aboutsummaryrefslogtreecommitdiff
path: root/include/Downloader.hpp
blob: cb70f2e338a09af37ebd81f03cac5d6a6191f059 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
#pragma once

#include "Path.hpp"
#include "AsyncTask.hpp"
#include <string>

namespace QuickMedia {
    enum class DownloadUpdateStatus {
        DOWNLOADING,
        FINISHED,
        ERROR
    };

    class Downloader {
    public:
        Downloader(const std::string &url, const std::string &output_filepath) : url(url), output_filepath(output_filepath) {}
        virtual ~Downloader() = default;

        virtual bool start() = 0;
        virtual bool stop(bool download_completed) = 0;
        virtual DownloadUpdateStatus update() = 0;

        virtual float get_progress() = 0;
        virtual std::string get_progress_text() = 0;
        virtual std::string get_download_speed_text() = 0;

        const std::string& get_output_filepath() { return output_filepath; }
    protected:
        std::string url;
        std::string output_filepath;
    };

    class CurlDownloader : public Downloader {
    public:
        CurlDownloader(const std::string &url, const std::string &output_filepath, int64_t content_length = -1);
        bool start() override;
        bool stop(bool download_completed) override;
        DownloadUpdateStatus update() override;
        float get_progress() override;
        std::string get_progress_text() override;
        std::string get_download_speed_text() override;
    private:
        Path output_filepath_tmp;
        ReadProgram read_program;
        AsyncTask<bool> header_reader;
        std::string header;
        int64_t content_length = -1;
        int64_t downloaded_since_last_check = 0;
        float progress = 0.0f;
        std::mutex content_length_mutex;
        std::string progress_text;
        std::string download_speed_text;
        bool finished = false;
    };

    class YoutubeDlDownloader : public Downloader {
    public:
        YoutubeDlDownloader(const std::string &url, const std::string &output_filepath, bool no_video);
        bool start() override;
        bool stop(bool download_completed) override;
        DownloadUpdateStatus update() override;
        float get_progress() override;
        std::string get_progress_text() override;
        std::string get_download_speed_text() override;
    private:
        ReadProgram read_program;
        FILE *read_program_file = nullptr;
        AsyncTask<bool> youtube_dl_output_reader;
        std::mutex progress_update_mutex;
        float progress = 0.0f;
        std::string progress_text;
        std::string download_speed_text;
        bool no_video;
        bool finished = false;
    };

    struct MediaMetadata {
        std::string url;
        int64_t content_length;
    };

    struct YoutubeReadProgram {
        ReadProgram read_program;
        int64_t offset = 0;
        int64_t content_length = -1;
        int64_t bytes_downloaded = 0;
        int64_t downloaded_since_last_check = 0;
        char *url = nullptr;
        std::string output_filepath;
        std::string output_filepath_tmp;
        double progress = 0.0;
        std::string progress_text;
        std::string download_speed_text;
        bool finished = false;
    };

    class YoutubeDownloader : public Downloader {
    public:
        YoutubeDownloader(const MediaMetadata &video_metadata, const MediaMetadata &audio_metadata, const std::string &output_filepath);
        ~YoutubeDownloader();

        bool start() override;
        bool stop(bool download_completed) override;
        DownloadUpdateStatus update() override;
        float get_progress() override;
        std::string get_progress_text() override;
        std::string get_download_speed_text() override;
    private:
        YoutubeReadProgram* get_min_progress_downloader();
        DownloadUpdateStatus update(size_t program_index);
    private:
        MediaMetadata video_metadata;
        MediaMetadata audio_metadata;
        std::string video_output_filepath;
        std::string audio_output_filepath;
        YoutubeReadProgram *program[2];
        AsyncTask<bool> downloader_tasks[2];
    };
}