Skip to content
This repository has been archived by the owner on May 7, 2020. It is now read-only.

Youtube-dl integration #196

Open
wants to merge 27 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
e4829e5
isYoutubeURL()
nparkanyi Sep 10, 2017
bb275f1
update copyright
nparkanyi Sep 10, 2017
583dabc
simplified isYoutubeURL, fixed typo
nparkanyi Sep 10, 2017
dbdb2d2
Moved youtube-dl stuff to MainFrm, initial GetYoutubeHttpsStreams tes…
nparkanyi Sep 12, 2017
fae6b34
properly wait for process completion
nparkanyi Sep 12, 2017
d1389a5
initial youtube-dl pipe buffer implementation
nparkanyi Sep 13, 2017
2ff8d86
youtube-dl pipe buffering relegated to worker threads to prevent I/O …
nparkanyi Sep 14, 2017
deafa66
load youtube videos and playlists through the Open File dialogue.
nparkanyi Sep 15, 2017
b78a429
clear playlist when not appending
nparkanyi Sep 15, 2017
3c3615a
some proper error handling for youtube-dl stuff
nparkanyi Sep 15, 2017
6f7fa18
Use video title instead of unwieldy raw youtube stream urls.
nparkanyi Sep 18, 2017
e936772
add normal youtube url to recent files list instead of raw https stre…
nparkanyi Sep 22, 2017
b1baada
only call youtube-dl once
nparkanyi Sep 22, 2017
404ab86
load Youtube links from command line
nparkanyi Sep 24, 2017
e6589a9
post to status bar when calling youtube-dl
nparkanyi Sep 24, 2017
c4fbbfe
fixed signed/unsigned mismatch
nparkanyi Sep 24, 2017
3319262
Don't call OpenCurPlaylistItem() when appending youtube video to play…
nparkanyi Sep 27, 2017
30784b8
using -f option in youtube-dl allows us to get audio and video in one…
nparkanyi Sep 27, 2017
aff39e1
Call youtube-dl -J and parse JSON with rapidjson (CYoutubeDLInstance)
nparkanyi Nov 5, 2017
7796822
updated project files to include YoutubeDL.{cpp,h}.
nparkanyi Nov 6, 2017
8e3ec16
drag-n-drop support for youtube-dl urls
nparkanyi Nov 8, 2017
34fd985
removed leftover crap
nparkanyi Nov 24, 2017
1dd4a5c
fixed typos
nparkanyi Jan 26, 2018
b60bd35
Merge https://github.com/mpc-hc/mpc-hc into youtube-dl
nparkanyi Feb 11, 2018
c3b496b
added maximum video height option under advanced settings
nparkanyi Feb 11, 2018
ed39301
Use original URL when loading youtube-dl videos from Favorites.
nparkanyi Mar 3, 2018
6ef0b8b
obey youtube-dl audio-only flag on videos with split audio/video stre…
nparkanyi Apr 5, 2018
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/mpc-hc/AppSettings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,8 @@ CAppSettings::CAppSettings()
, iLAVGPUDevice(DWORD_MAX)
, nCmdVolume(0)
, eSubtitleRenderer(SubtitleRenderer::INTERNAL)
, iYDLMaxHeight(0)
, bYDLAudioOnly(false)
{
// Internal source filter
#if INTERNAL_SOURCEFILTER_CDDA
Expand Down Expand Up @@ -1089,6 +1091,9 @@ void CAppSettings::SaveSettings()
pApp->WriteProfileInt(IDS_R_SANEAR, IDS_RS_SANEAR_CROSSFEED_LEVEL, uCrossfeedLevel);
}

pApp->WriteProfileInt(IDS_R_SETTINGS, IDS_RS_YDL_MAX_HEIGHT, iYDLMaxHeight);
pApp->WriteProfileInt(IDS_R_SETTINGS, IDS_RS_YDL_AUDIO_ONLY, bYDLAudioOnly);

pApp->FlushProfile();
}

Expand Down Expand Up @@ -1826,6 +1831,9 @@ void CAppSettings::LoadSettings()
pApp->GetProfileInt(IDS_R_SANEAR, IDS_RS_SANEAR_CROSSFEED_LEVEL,
SaneAudioRenderer::ISettings::CROSSFEED_LEVEL_CMOY));

iYDLMaxHeight = pApp->GetProfileInt(IDS_R_SETTINGS, IDS_RS_YDL_MAX_HEIGHT, 0);
bYDLAudioOnly = pApp->GetProfileInt(IDS_R_SETTINGS, IDS_RS_YDL_AUDIO_ONLY, FALSE);

bInitialized = true;
}

Expand Down
38 changes: 30 additions & 8 deletions src/mpc-hc/AppSettings.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,9 @@ struct wmcmd_base : public ACCEL {
};

wmcmd_base()
: ACCEL( { 0, 0, 0 })
: ACCEL( {
0, 0, 0
})
, mouse(NONE)
, mouseFS(NONE)
, dwname(0)
Expand Down Expand Up @@ -316,7 +318,9 @@ class wmcmd : public wmcmd_base
return cmd > 0 && cmd == wc.cmd;
}

CString GetName() const { return ResStr(dwname); }
CString GetName() const {
return ResStr(dwname);
}

void Restore() {
ASSERT(default_cmd);
Expand Down Expand Up @@ -364,7 +368,9 @@ class CRemoteCtrlClient : public CAsyncSocket
void SetHWND(HWND hWnd);
void Connect(CString addr);
void DisConnect();
int GetStatus() const { return m_nStatus; }
int GetStatus() const {
return m_nStatus;
}
};

class CWinLircClient : public CRemoteCtrlClient
Expand Down Expand Up @@ -416,7 +422,9 @@ class CAppSettings
DVD_HMSF_TIMECODE DVDPosition;

CSize sizeFixedWindow;
bool HasFixedWindowSize() const { return sizeFixedWindow.cx > 0 || sizeFixedWindow.cy > 0; }
bool HasFixedWindowSize() const {
return sizeFixedWindow.cx > 0 || sizeFixedWindow.cy > 0;
}
//int iFixedWidth, iFixedHeight;
int iMonitor;

Expand Down Expand Up @@ -722,7 +730,9 @@ class CAppSettings
};

SubtitleRenderer GetSubtitleRenderer() const;
void SetSubtitleRenderer(SubtitleRenderer renderer) { eSubtitleRenderer = renderer; }
void SetSubtitleRenderer(SubtitleRenderer renderer) {
eSubtitleRenderer = renderer;
}

static bool IsSubtitleRendererRegistered(SubtitleRenderer eSubtitleRenderer);

Expand All @@ -732,7 +742,13 @@ class CAppSettings
ASSERT(fKeepAspectRatio && "Keep Aspect Ratio option have to be enabled if override value is used.");
return sizeAspectRatio;
};
void SetAspectRatioOverride(const CSize& ar) { sizeAspectRatio = ar; }
void SetAspectRatioOverride(const CSize& ar) {
sizeAspectRatio = ar;
}

//YoutubeDL settings
int iYDLMaxHeight;
bool bYDLAudioOnly;

private:
struct FilterKey {
Expand Down Expand Up @@ -779,10 +795,16 @@ class CAppSettings

void SaveSettings();
void LoadSettings();
void SaveExternalFilters() { if (bInitialized) { SaveExternalFilters(m_filters); } };
void SaveExternalFilters() {
if (bInitialized) {
SaveExternalFilters(m_filters);
}
};
void UpdateSettings();

void SetAsUninitialized() { bInitialized = false; };
void SetAsUninitialized() {
bInitialized = false;
};

void GetFav(favtype ft, CAtlList<CString>& sl) const;
void SetFav(favtype ft, CAtlList<CString>& sl);
Expand Down
138 changes: 122 additions & 16 deletions src/mpc-hc/MainFrm.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/*
* (C) 2003-2006 Gabest
* (C) 2006-2017 see Authors.txt
* (C) 2006-2018 see Authors.txt
*
* This file is part of MPC-HC.
*
Expand Down Expand Up @@ -105,6 +105,9 @@
#include <initguid.h>
#include <qnetwork.h>

#include "YoutubeDL.h"


// IID_IAMLine21Decoder
DECLARE_INTERFACE_IID_(IAMLine21Decoder_2, IAMLine21Decoder, "6E8D4A21-310C-11d0-B79A-00AA003767A7") {};

Expand Down Expand Up @@ -3830,6 +3833,15 @@ void CMainFrame::OnFileOpenmedia()
SetForegroundWindow();

CAtlList<CString> filenames;

if (dlg.GetFileNames().GetHead().Left(4) == _T("http")
&& ProcessYoutubeDLURL(dlg.GetFileNames().GetHead(), dlg.GetAppendToPlaylist())) {
if (!dlg.GetAppendToPlaylist()) {
OpenCurPlaylistItem();
}
return;
}

filenames.AddHeadList(&dlg.GetFileNames());

if (!dlg.HasMultipleFiles()) {
Expand Down Expand Up @@ -3991,6 +4003,7 @@ BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCDS)
PathUtils::ParseDirs(sl);

bool fMulti = sl.GetCount() > 1;
bool fYoutubeDL = sl.GetHead().Left(4) == _T("http");

if (!fMulti) {
sl.AddTailList(&s.slDubs);
Expand All @@ -4015,7 +4028,13 @@ BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCDS)
m_dwLastRun = GetTickCount64();

if ((s.nCLSwitches & CLSW_ADD) && !IsPlaylistEmpty()) {
m_wndPlaylistBar.Append(sl, fMulti, &s.slSubs);
bool r = false;
if (fYoutubeDL) {
r = ProcessYoutubeDLURL(sl.GetHead(), true);
}
if (!r) { //not an http link, or youtube-dl unavailable
m_wndPlaylistBar.Append(sl, fMulti, &s.slSubs);
}
applyRandomizeSwitch();

if (s.nCLSwitches & (CLSW_OPEN | CLSW_PLAY)) {
Expand All @@ -4026,8 +4045,15 @@ BOOL CMainFrame::OnCopyData(CWnd* pWnd, COPYDATASTRUCT* pCDS)
//SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
fSetForegroundWindow = true;

m_wndPlaylistBar.Open(sl, fMulti, &s.slSubs);
bool r = false;
if (fYoutubeDL) {
r = ProcessYoutubeDLURL(sl.GetHead(), false);
}
if (!r) { //not an http link or youtube-dl unavailable
m_wndPlaylistBar.Open(sl, fMulti, &s.slSubs);
}
applyRandomizeSwitch();
m_wndPlaylistBar.SetFirst();
OpenCurPlaylistItem((s.nCLSwitches & CLSW_STARTVALID) ? s.rtStart : 0);

s.nCLSwitches &= ~CLSW_STARTVALID;
Expand Down Expand Up @@ -4246,6 +4272,7 @@ void CMainFrame::OnDropFiles(CAtlList<CString>& slFiles, DROPEFFECT dropEffect)
}
}

bool bAppend = !!(dropEffect & DROPEFFECT_APPEND);
// Use the first subtitle file that was just loaded
if (subInputSelected.pSubStream) {
AfxGetAppSettings().fEnableSubtitles = true;
Expand All @@ -4260,7 +4287,17 @@ void CMainFrame::OnDropFiles(CAtlList<CString>& slFiles, DROPEFFECT dropEffect)
}
SendStatusMessage(filenames + ResStr(IDS_SUB_LOADED_SUCCESS), 3000);
} else {
if (dropEffect & DROPEFFECT_APPEND) {
//load http url with youtube-dl, if available
if (slFiles.GetHead().Left(4) == _T("http")) {
if (ProcessYoutubeDLURL(slFiles.GetHead(), bAppend)) {
if (!bAppend) {
OpenCurPlaylistItem();
}
return;
}
}

if (bAppend) {
m_wndPlaylistBar.Append(slFiles, true);
} else {
m_wndPlaylistBar.Open(slFiles, true);
Expand Down Expand Up @@ -6936,7 +6973,7 @@ void CMainFrame::OnPlayPlay()
strOSD.LoadString(IDS_PLAY_BD);
} else {
strOSD = GetFileName();
if (!strOSD.IsEmpty()) {
if (!strOSD.IsEmpty() && !m_wndPlaylistBar.GetCur()->m_bYoutubeDL) {
strOSD.TrimRight('/');
strOSD.Replace('\\', '/');
strOSD = strOSD.Mid(strOSD.ReverseFind('/') + 1);
Expand Down Expand Up @@ -8825,9 +8862,13 @@ void CMainFrame::AddFavorite(bool fDisplayMessage, bool fShowDialog)
} else {
CPlaylistItem pli;
if (m_wndPlaylistBar.GetCur(pli)) {
POSITION pos = pli.m_fns.GetHeadPosition();
while (pos) {
args.AddTail(pli.m_fns.GetNext(pos));
if (pli.m_bYoutubeDL) {
args.AddTail(pli.m_ydlSourceURL);
} else {
POSITION pos = pli.m_fns.GetHeadPosition();
while (pos) {
args.AddTail(pli.m_fns.GetNext(pos));
}
}
}
}
Expand Down Expand Up @@ -9021,7 +9062,13 @@ void CMainFrame::PlayFavoriteFile(CString fav)
}
}

m_wndPlaylistBar.Open(args, false);
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);

if (args.GetHead().Left(4) != _T("http")
|| !ProcessYoutubeDLURL(args.GetHead(), false)) {
m_wndPlaylistBar.Open(args, false);
}

if (GetPlaybackMode() == PM_FILE && args.GetHead() == m_lastOMD->title) {
m_pMS->SetPositions(&rtStart, AM_SEEKING_AbsolutePositioning, nullptr, AM_SEEKING_NoPositioning);
OnPlayPlay();
Expand All @@ -9040,6 +9087,15 @@ void CMainFrame::OnRecentFile(UINT nID)
nID -= ID_RECENT_FILE_START;
CString fn;
m_recentFilesMenu.GetMenuString(nID + 2, fn, MF_BYPOSITION);

if (fn.Left(4) == _T("http")) {
SendMessage(WM_COMMAND, ID_FILE_CLOSEMEDIA);
if (ProcessYoutubeDLURL(fn, false)) {
OpenCurPlaylistItem();
return;
}
}

if (!m_wndPlaylistBar.SelectFileInPlaylist(fn)) {
CAtlList<CString> fns;
fns.AddTail(fn);
Expand Down Expand Up @@ -10570,7 +10626,7 @@ void CMainFrame::OpenFile(OpenFileData* pOFD)
}

// We don't keep track of piped inputs since that hardly makes any sense
if (s.fKeepHistory && fn.Find(_T("pipe:")) != 0) {
if (s.fKeepHistory && fn.Find(_T("pipe:")) != 0 && pOFD->bAddToRecent) {
CRecentFileList* pMRU = bMainFile ? &s.MRU : &s.MRUDub;
pMRU->ReadList();
pMRU->Add(fn);
Expand Down Expand Up @@ -12231,7 +12287,7 @@ void CMainFrame::SendNowPlayingToSkype()

if (GetPlaybackMode() == PM_FILE) {
CString fn = label;
if (fn.Find(_T("://")) >= 0) {
if (!pli.m_bYoutubeDL && fn.Find(_T("://")) >= 0) {
int i = fn.Find('?');
if (i >= 0) {
fn = fn.Left(i);
Expand Down Expand Up @@ -12616,7 +12672,7 @@ void CMainFrame::SetupAudioSubMenu()
ATR.bQuantization,
ATR.bNumberOfChannels,
ResStr(ATR.bNumberOfChannels > 1 ? IDS_MAINFRM_13 : IDS_MAINFRM_12).GetString()
);
);
}
}

Expand Down Expand Up @@ -16652,14 +16708,14 @@ CString CMainFrame::GetFileName()
{
CString path(m_wndPlaylistBar.GetCurFileName());

if (m_pFSF) {
if (!m_wndPlaylistBar.GetCur()->m_bYoutubeDL && m_pFSF) {
CComHeapPtr<OLECHAR> pFN;
if (SUCCEEDED(m_pFSF->GetCurFile(&pFN, nullptr))) {
path = pFN;
}
}

return PathUtils::StripPathOrUrl(path);
return m_wndPlaylistBar.GetCur()->m_bYoutubeDL ? path : PathUtils::StripPathOrUrl(path);
}

CString CMainFrame::GetCaptureTitle()
Expand Down Expand Up @@ -16728,10 +16784,11 @@ void CMainFrame::UpdateDXVAStatus()
bool CMainFrame::GetDecoderType(CString& type) const
{
if (!m_fAudioOnly) {
if (m_bUsingDXVA)
if (m_bUsingDXVA) {
type = m_HWAccelType;
else
} else {
type.LoadString(IDS_TOOLTIP_SOFTWARE_DECODING);
}
return true;
}
return false;
Expand Down Expand Up @@ -16982,3 +17039,52 @@ LRESULT CMainFrame::OnGetSubtitles(WPARAM, LPARAM lParam)
pSubtitlesInfo->fileContents = UTF16To8(content);
return TRUE;
}


bool CMainFrame::ProcessYoutubeDLURL(CString url, bool append)
{
auto& s = AfxGetAppSettings();
CAtlList<CString> vstreams;
CAtlList<CString> astreams;
CAtlList<CString> names;
CAtlList<CString> filenames;
CYoutubeDLInstance ydl;

m_wndStatusBar.SetStatusMessage(ResStr(IDS_CONTROLS_YOUTUBEDL));

if (!ydl.Run(url)) {
return false;
}
if (!ydl.GetHttpStreams(vstreams, astreams, names)) {
return false;
}

if (!append) {
m_wndPlaylistBar.Empty();
}
for (unsigned int i = 0; i < vstreams.GetCount(); i++) {
filenames.RemoveAll();

//only respect the Audio Only flag for sources that actually have separate audio streams (i.e. youtube)
if (astreams.IsEmpty() || !s.bYDLAudioOnly) {
filenames.AddTail(vstreams.GetAt(vstreams.FindIndex(i)));
}

if (!astreams.IsEmpty()) {
filenames.AddTail(astreams.GetAt(astreams.FindIndex(i)));
}
m_wndPlaylistBar.Append(filenames, false, nullptr,
names.GetAt(names.FindIndex(i))
+ " (" + url + ")", url);
}

CRecentFileList* mru = &s.MRU;
mru->ReadList();
mru->Add(url);
mru->WriteList();

if (!append) {
m_wndPlaylistBar.SetFirst();
}
return true;
}