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];
};
}
|