Skip to content

Commit

Permalink
All - New Formats Selection
Browse files Browse the repository at this point in the history
  • Loading branch information
nlogozzo committed Jan 9, 2025
1 parent bb0fde7 commit 14df09d
Show file tree
Hide file tree
Showing 54 changed files with 2,395 additions and 2,056 deletions.
2 changes: 1 addition & 1 deletion docs/po/parabolic.pot
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2025-01-09 10:32-0500\n"
"POT-Creation-Date: 2025-01-09 14:20-0500\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <[email protected]>\n"
Expand Down
27 changes: 14 additions & 13 deletions libparabolic/include/controllers/adddownloaddialogcontroller.h
Original file line number Diff line number Diff line change
Expand Up @@ -77,16 +77,17 @@ namespace Nickvision::TubeConverter::Shared::Controllers
*/
std::vector<std::string> getFileTypeStrings() const;
/**
* @brief Gets the list of qualities as strings.
* @param fileTypeIndex The index of the selected file type
* @return The list of qualities as strings
* @brief Gets the list of video formats as strings.
* @param previousIndex An optional out parameter that will contain the previous selected video format index if available, else index will be 0
* @return The list of video formats as strings
*/
std::vector<std::string> getQualityStrings(size_t fileTypeIndex) const;
std::vector<std::string> getVideoFormatStrings(size_t* previousIndex = nullptr) const;
/**
* @brief Gets the list of audio languages as strings.
* @return The list of audio languages as strings
* @brief Gets the list of audio formats as strings.
* @param previousIndex An optional out parameter that will contain the previous selected audio format index if available, else index will be 0
* @return The list of audio formats as strings
*/
std::vector<std::string> getAudioLanguageStrings() const;
std::vector<std::string> getAudioFormatStrings(size_t* previousIndex = nullptr) const;
/**
* @brief Gets the list of subtitles languages as strings.
* @return The list of subtitles languages as strings
Expand Down Expand Up @@ -144,16 +145,16 @@ namespace Nickvision::TubeConverter::Shared::Controllers
* @param saveFolder The folder to save the download to
* @param filename The filename to save the download as
* @param fileTypeIndex The index of the selected file type
* @param qualityIndex The index of the selected quality
* @param audioLanguageIndex The index of the selected audio language
* @param videoFormatIndex The index of the selected video format
* @param audioFormatIndex The index of the selected audio format
* @param subtitleLanguages The list of selected subtitle languages
* @param splitChapters Whether or not to split the video by chapters
* @param limitSpeed Whether or not to limit the download speed
* @param exportDescription Whether or not to export the media description to a file
* @param startTime The start time of the download
* @param endTime The end time of the download
*/
void addSingleDownload(const std::filesystem::path& saveFolder, const std::string& filename, size_t fileTypeIndex, size_t qualityIndex, size_t audioLanguageIndex, const std::vector<std::string>& subtitleLanguages, bool splitChapters, bool limitSpeed, bool exportDescription, const std::string& startTime, const std::string& endTime);
void addSingleDownload(const std::filesystem::path& saveFolder, const std::string& filename, size_t fileTypeIndex, size_t videoFormatIndex, size_t audioFormatIndex, const std::vector<std::string>& subtitleLanguages, bool splitChapters, bool limitSpeed, bool exportDescription, const std::string& startTime, const std::string& endTime);
/**
* @brief Adds a playlist download to the download manager.
* @param saveFolder The folder to save the downloads to
Expand All @@ -172,10 +173,10 @@ namespace Nickvision::TubeConverter::Shared::Controllers
std::optional<Models::UrlInfo> m_urlInfo;
std::optional<Keyring::Credential> m_credential;
bool m_downloadImmediatelyAfterValidation;
mutable std::unordered_map<size_t, Models::Format> m_qualityFormatMap;
mutable std::unordered_map<size_t, Models::Format> m_audioLanguageFormatMap;
mutable std::unordered_map<size_t, size_t> m_videoFormatMap;
mutable std::unordered_map<size_t, size_t> m_audioFormatMap;
Nickvision::Events::Event<Nickvision::Events::ParamEventArgs<bool>> m_urlValidated;
};
}

#endif //ADDDOWNLOADDIALOGCONTROLLER_H
#endif //ADDDOWNLOADDIALOGCONTROLLER_H
39 changes: 34 additions & 5 deletions libparabolic/include/models/format.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ namespace Nickvision::TubeConverter::Shared::Models
* @return The type of the format
*/
MediaType getType() const;
/**
* @brief Gets the bitrate of the format in kbps.
* @return The bitrate bitrate of the format in kbps
*/
const std::optional<double>& getBitrate() const;
/**
* @brief Gets the audio language of the format.
* @return The audio language of the format
Expand All @@ -63,28 +68,52 @@ namespace Nickvision::TubeConverter::Shared::Models
*/
const std::optional<VideoResolution>& getVideoResolution() const;
/**
* @brief Gets the audio bitrate of the format.
* @return The audio bitrate of the format
* @brief Gets the string representation of the format.
* @return The string representation of the format
*/
const std::optional<double>& getAudioBitrate() const;
std::string str() const;
/**
* @brief Converts the Format to a JSON object.
* @brief The json object will not be in yt-dlp json format.
* @return The JSON object
*/
boost::json::object toJson() const;
/**
* @brief Compares two Format via ==.
* @param other The other Format to compare
* @return True if this == other
*/
bool operator==(const Format& other) const;
/**
* @brief Compares two Format via !=.
* @param other The other Format to compare
* @return True if this != other
*/
bool operator!=(const Format& other) const;
/**
* @brief Compares two Format via <.
* @param other The other Format to compare
* @return True if this < other
*/
bool operator<(const Format& other) const;
/**
* @brief Compares two Format via >.
* @param other The other Format to compare
* @return True if this > other
*/
bool operator>(const Format& other) const;

private:
std::string m_id;
std::string m_protocol;
std::string m_extension;
MediaType m_type;
std::optional<double> m_bitrate;
std::optional<std::string> m_audioLanguage;
bool m_hasAudioDescription;
std::optional<VideoCodec> m_videoCodec;
std::optional<VideoResolution> m_videoResolution;
std::optional<double> m_audioBitrate;
};
}

#endif //FORMAT_H
#endif //FORMAT_H
24 changes: 17 additions & 7 deletions libparabolic/include/models/previousdownloadoptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,25 @@ namespace Nickvision::TubeConverter::Shared::Models
*/
void setFileType(const MediaFileType& previousMediaFileType);
/**
* @brief Gets the previous quality.
* @return The previous quality
* @brief Gets the previous video format id.
* @return The previous video format id
*/
std::string getQuality() const;
std::string getVideoFormatId() const;
/**
* @brief Sets the previous quality.
* @param quality The new previous quality
* @brief Sets the previous video format id.
* @param videoFormatId The new previous video format id
*/
void setQuality(const std::string& quality);
void setVideoFormatId(const std::string& videoFormatId);
/**
* @brief Gets the previous audio format id.
* @return The previous audio format id
*/
std::string getAudioFormatId() const;
/**
* @brief Sets the previous audio format id.
* @param audioFormatId The new previous audio format id
*/
void setAudioFormatId(const std::string& audioFormatId);
/**
* @brief Gets the previous split chapters state.
* @return The previous split chapters state
Expand Down Expand Up @@ -105,4 +115,4 @@ namespace Nickvision::TubeConverter::Shared::Models
};
}

#endif //PREVIOUSDOWNLOADOPTIONS_H
#endif //PREVIOUSDOWNLOADOPTIONS_H
104 changes: 40 additions & 64 deletions libparabolic/src/controllers/adddownloaddialogcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -59,21 +59,17 @@ namespace Nickvision::TubeConverter::Shared::Controllers

bool AddDownloadDialogController::isUrlValid() const
{
return m_urlInfo.has_value() && m_urlInfo->count() > 0;
return m_urlInfo && m_urlInfo->count() > 0;
}

bool AddDownloadDialogController::isUrlPlaylist() const
{
return m_urlInfo.has_value() && m_urlInfo->isPlaylist();
return m_urlInfo && m_urlInfo->isPlaylist();
}

size_t AddDownloadDialogController::getMediaCount() const
{
if(!m_urlInfo)
{
return 0;
}
return m_urlInfo->count();
return !m_urlInfo ? 0 : m_urlInfo->count();
}

std::vector<std::string> AddDownloadDialogController::getFileTypeStrings() const
Expand Down Expand Up @@ -120,75 +116,62 @@ namespace Nickvision::TubeConverter::Shared::Controllers
return fileTypes;
}

std::vector<std::string> AddDownloadDialogController::getQualityStrings(size_t fileTypeIndex) const
std::vector<std::string> AddDownloadDialogController::getVideoFormatStrings(size_t* previousIndex) const
{
std::vector<std::string> qualities;
m_qualityFormatMap.clear();
std::vector<std::string> formats;
m_videoFormatMap.clear();
if(!m_urlInfo)
{
return qualities;
return formats;
}
MediaFileType type{ static_cast<MediaFileType::MediaFileTypeValue>(fileTypeIndex) };
qualities.push_back(_("Best"));
formats.push_back(_("Best"));
if(!m_urlInfo->isPlaylist())
{
const Media& media{ m_urlInfo->get(0) };
if(media.getType() == MediaType::Audio)
for(size_t i = 0; i < media.getFormats().size(); i++)
{
fileTypeIndex += MediaFileType::getVideoFileTypeCount();
type = static_cast<MediaFileType::MediaFileTypeValue>(fileTypeIndex);
}
for(const Format& format : media.getFormats())
{
if(type.isAudio() && format.getAudioBitrate() && std::find(qualities.begin(), qualities.end(), std::to_string(format.getAudioBitrate().value())) == qualities.end())
const Format& format{ media.getFormats()[i] };
if(format.getType() == MediaType::Video)
{
m_qualityFormatMap.emplace(qualities.size(), format);
qualities.push_back(std::to_string(format.getAudioBitrate().value()));
}
else if(type.isVideo() && format.getVideoResolution() && std::find(qualities.begin(), qualities.end(), format.getVideoResolution().value().str()) == qualities.end())
{
m_qualityFormatMap.emplace(qualities.size(), format);
qualities.push_back(format.getVideoResolution().value().str());
m_videoFormatMap[formats.size()] = i;
if(previousIndex && format.getId() == m_previousOptions.getVideoFormatId())
{
*previousIndex = formats.size();
}
formats.push_back(format.str());
}
}
}
return qualities;
return formats;
}

std::vector<std::string> AddDownloadDialogController::getAudioLanguageStrings() const
std::vector<std::string> AddDownloadDialogController::getAudioFormatStrings(size_t* previousIndex) const
{
std::vector<std::string> languages;
m_audioLanguageFormatMap.clear();
std::vector<std::string> formats;
m_audioFormatMap.clear();
if(!m_urlInfo)
{
return languages;
return formats;
}
languages.push_back(_("Default"));
formats.push_back(_("Best"));
if(!m_urlInfo->isPlaylist())
{
const Media& media{ m_urlInfo->get(0) };
for(const Format& format : media.getFormats())
for(size_t i = 0; i < media.getFormats().size(); i++)
{
if(format.getAudioLanguage())
const Format& format{ media.getFormats()[i] };
if(format.getType() == MediaType::Audio)
{
std::string language;
if(format.hasAudioDescription())
m_audioFormatMap[formats.size()] = i;
if(previousIndex && format.getId() == m_previousOptions.getAudioFormatId())
{
language = std::format("{} ({})", format.getAudioLanguage().value(), _("Audio Description"));
}
else
{
language = format.getAudioLanguage().value();
}
if(std::find(languages.begin(), languages.end(), language) == languages.end())
{
m_audioLanguageFormatMap.emplace(languages.size(), format);
languages.push_back(language);
*previousIndex = formats.size();
}
formats.push_back(format.str());
}
}
}
return languages;
return formats;
}

std::vector<std::string> AddDownloadDialogController::getSubtitleLanguageStrings() const
Expand Down Expand Up @@ -287,7 +270,7 @@ namespace Nickvision::TubeConverter::Shared::Controllers
}
}

void AddDownloadDialogController::addSingleDownload(const std::filesystem::path& saveFolder, const std::string& filename, size_t fileTypeIndex, size_t qualityIndex, size_t audioLanguageIndex, const std::vector<std::string>& subtitleLanguages, bool splitChapters, bool limitSpeed, bool exportDescription, const std::string& startTime, const std::string& endTime)
void AddDownloadDialogController::addSingleDownload(const std::filesystem::path& saveFolder, const std::string& filename, size_t fileTypeIndex, size_t videoFormatIndex, size_t audioFormatIndex, const std::vector<std::string>& subtitleLanguages, bool splitChapters, bool limitSpeed, bool exportDescription, const std::string& startTime, const std::string& endTime)
{
const Media& media{ m_urlInfo->get(0) };
//Get Subtitle Languages
Expand All @@ -308,20 +291,13 @@ namespace Nickvision::TubeConverter::Shared::Controllers
options.setAvailableFormats(m_urlInfo->get(0).getFormats());
options.setSaveFolder(std::filesystem::exists(saveFolder) ? saveFolder : m_previousOptions.getSaveFolder());
options.setSaveFilename(!filename.empty() ? StringHelpers::normalizeForFilename(filename, m_downloadManager.getDownloaderOptions().getLimitCharacters()) : media.getTitle());
if(qualityIndex != 0)
if(videoFormatIndex != 0)
{
if(options.getFileType().isVideo())
{
options.setVideoFormat(m_qualityFormatMap.at(qualityIndex));
}
else
{
options.setAudioFormat(m_qualityFormatMap.at(qualityIndex));
}
options.setVideoFormat(media.getFormats()[m_videoFormatMap[videoFormatIndex]]);
}
if(audioLanguageIndex != 0)
if(audioFormatIndex != 0)
{
options.setAudioFormat(m_audioLanguageFormatMap.at(audioLanguageIndex));
options.setAudioFormat(media.getFormats()[m_audioFormatMap[audioFormatIndex]]);
}
options.setSubtitleLanguages(subtitles);
options.setSplitChapters(splitChapters);
Expand All @@ -335,13 +311,13 @@ namespace Nickvision::TubeConverter::Shared::Controllers
//Save Previous Options
m_previousOptions.setSaveFolder(options.getSaveFolder());
m_previousOptions.setFileType(options.getFileType());
if(qualityIndex != 0)
if(options.getVideoFormat())
{
m_previousOptions.setQuality(options.getFileType().isVideo() ? m_qualityFormatMap.at(qualityIndex).getVideoResolution().value().str() : std::to_string(m_qualityFormatMap.at(qualityIndex).getAudioBitrate().value()));
m_previousOptions.setVideoFormatId(options.getVideoFormat()->getId());
}
else
if(options.getAudioFormat())
{
m_previousOptions.setQuality(_("Best"));
m_previousOptions.setAudioFormatId(options.getAudioFormat()->getId());
}
m_previousOptions.setSplitChapters(options.getSplitChapters());
m_previousOptions.setLimitSpeed(options.getLimitSpeed());
Expand Down
2 changes: 1 addition & 1 deletion libparabolic/src/controllers/mainwindowcontroller.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ namespace Nickvision::TubeConverter::Shared::Controllers
m_appInfo.setVersion({ "2025.1.0-next" });
m_appInfo.setShortName(_("Parabolic"));
m_appInfo.setDescription(_("Download web video and audio"));
m_appInfo.setChangelog("- Fixed an issue where some video downloads contained no audio\n- Fixed an issue where progress was incorrectly reported for some downloads\n- Fixed an issue where downloads would not stop on Windows\n- Fixed an issue where paths with accent marks were not handled correctly on Windows\n- Fixed an issue where the bundled ffmpeg did not work correctly on some Windows systems");
m_appInfo.setChangelog("- Parabolic will now display all available video and audio formats for selection by the user when downloading a single media\n- Fixed an issue where some video downloads contained no audio\n- Fixed an issue where progress was incorrectly reported for some downloads\n- Fixed an issue where downloads would not stop on Windows\n- Fixed an issue where paths with accent marks were not handled correctly on Windows\n- Fixed an issue where the bundled ffmpeg did not work correctly on some Windows systems");
m_appInfo.setSourceRepo("https://github.com/NickvisionApps/Parabolic");
m_appInfo.setIssueTracker("https://github.com/NickvisionApps/Parabolic/issues/new");
m_appInfo.setSupportUrl("https://github.com/NickvisionApps/Parabolic/discussions");
Expand Down
9 changes: 6 additions & 3 deletions libparabolic/src/models/download.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -106,17 +106,20 @@ namespace Nickvision::TubeConverter::Shared::Models
m_process->exited() += [this](const ProcessExitedEventArgs& args) { onProcessExit(args); };
m_process->start();
m_status = DownloadStatus::Running;
std::thread watcher{ &Download::watch, this };
watcher.detach();
lock.unlock();
if(m_options.getTimeFrame())
{
m_progressChanged.invoke({ m_id, std::nan(""), 0.0, _("WARNING: Using ffmpeg to download. Progress will not be shown.") });
}
if(downloaderOptions.getUseAria())
else if(downloaderOptions.getUseAria())
{
m_progressChanged.invoke({ m_id, std::nan(""), 0.0, _("WARNING: Using aria2 to download. Progress will not be shown.") });
}
else
{
std::thread watcher{ &Download::watch, this };
watcher.detach();
}
}

void Download::stop()
Expand Down
Loading

0 comments on commit 14df09d

Please sign in to comment.