aboutsummaryrefslogtreecommitdiff
path: root/include/Downloader.hpp
blob: cc15e5d83172093c9ce54360258c6a56c072d8d8 (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
#pragma once

#include "../plugins/youtube/YoutubeMediaProxy.hpp"
#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;
        size_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;
    };

    class YoutubeDownloader : public Downloader {
    public:
        YoutubeDownloader(const MediaMetadata &video_metadata, const MediaMetadata &audio_metadata, const std::string &output_filepath);
        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:
        CurlDownloader* get_min_progress_downloader();
    private:
        MediaMetadata video_metadata;
        MediaMetadata audio_metadata;
        std::string video_output_filepath;
        std::string audio_output_filepath;
        std::unique_ptr<CurlDownloader> downloaders[2];
        AsyncTask<void> downloader_task;
        std::unique_ptr<YoutubeMediaProxy> youtube_video_media_proxy;
        std::unique_ptr<YoutubeMediaProxy> youtube_audio_media_proxy;
    };
}