Skip to content
This repository has been archived by the owner on Jul 31, 2022. It is now read-only.

Commit

Permalink
Added mpv video playback
Browse files Browse the repository at this point in the history
  • Loading branch information
tkashkin committed Mar 24, 2017
1 parent 2cd11cd commit 9c9644b
Show file tree
Hide file tree
Showing 8 changed files with 234 additions and 23 deletions.
5 changes: 5 additions & 0 deletions include/Process.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ using namespace std;

#include "Utils.h"

struct WindowHandle {
DWORD pid;
HWND handle;
};

class Process
{
public:
Expand Down
3 changes: 3 additions & 0 deletions include/Utils.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ class Utils
static str filename(str path);

static TCHAR* chars(str s);

static wstring s2ws(string str);
static string ws2s(wstring wstr);
};

#endif // UTILS_H
16 changes: 16 additions & 0 deletions include/VideoPlayback.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using namespace std;

#ifndef VIDEOPLAYBACK_H
#define VIDEOPLAYBACK_H

#include "ZLauncher.h"

class VideoPlayback
{
public:
static void start();

static void playVideo(string video);
};

#endif // VIDEOPLAYBACK_H
9 changes: 8 additions & 1 deletion include/ZLauncher.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

#include <string>
#include <sstream>
#include <fstream>
#include <windows.h>
#include <tlhelp32.h>
#include <psapi.h>
Expand All @@ -15,6 +16,7 @@

#include "Process.h"
#include "Utils.h"
#include "VideoPlayback.h"

using namespace std;

Expand All @@ -34,10 +36,13 @@ typedef stringstream sstream;
#define ERR_STEAM_ELEVATION 5
#define ERR_STEAM_GAME 6

#define STEAM_RUNNING_ELEVATED -1
#define STEAM_RUNNING -1
#define STEAM_RUNNING_ELEVATED -2

#define c(s) Utils::chars(s)

#define VP_LOG_CHECK_INTERVAL 30

#ifndef ZLAUNCHER_H
#define ZLAUNCHER_H

Expand All @@ -56,6 +61,8 @@ class ZLauncher

static bool restartElevated(bool launched = true);

static void wait();

static void showError();

static str getConfigFile();
Expand Down
9 changes: 9 additions & 0 deletions src/Utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,3 +67,12 @@ TCHAR* Utils::chars(str s)
{
return const_cast<TCHAR *>(s.c_str());
}

wstring Utils::s2ws(string str)
{
return wstring(str.begin(), str.end());
}
string Utils::ws2s(wstring wstr)
{
return string(wstr.begin(), wstr.end());
}
143 changes: 143 additions & 0 deletions src/VideoPlayback.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
#include "ZLauncher.h"

#include <fstream>
#include <iostream>

string vp_log_pattern = "/vol/content/Movie/";
string vp_log_pattern_ext = ".mp4";
string vp_video, vp_last_video;
long long vp_last_video_time;

extern HANDLE job;

extern str cemu_path, game_path;

static void attach(HWND child, HWND parent)
{
SetParent(child, parent);
DWORD style = GetWindowLong(child, GWL_STYLE);
style &= ~(WS_POPUP | WS_CAPTION);
style |= WS_CHILD;
SetWindowLong(child, GWL_STYLE, style);
RECT rc;
GetClientRect(parent, &rc);
MoveWindow(child, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, true);
UpdateWindow(parent);
}

static long long getTimeMS()
{
static LARGE_INTEGER s_frequency;
static BOOL s_use_qpc = QueryPerformanceFrequency(&s_frequency);
if (s_use_qpc) {
LARGE_INTEGER now;
QueryPerformanceCounter(&now);
return (1000LL * now.QuadPart) / s_frequency.QuadPart;
} else {
return GetTickCount();
}
}
static long long getTime()
{
return getTimeMS() / 1000LL;
}

static HWND waitForWindow(LPCWSTR cls, LPCWSTR title)
{
HWND hwnd = 0;
while(!IsWindow(hwnd))
{
hwnd = FindWindow(cls, title);
Sleep(50);
}
return hwnd;
}

static HWND waitForChildWindow(HWND parent, LPCWSTR cls, LPCWSTR title)
{
HWND hwnd = 0;
while(!IsWindow(hwnd))
{
hwnd = FindWindowEx(parent, NULL, cls, title);
Sleep(50);
}
return hwnd;
}

void VideoPlayback::playVideo(string video)
{
if(getTime() - vp_last_video_time < 30) return;

HWND hCemuWnd = waitForWindow(L"wxWindowNR", NULL);
HWND hCemuRender = waitForChildWindow(hCemuWnd, NULL, L"Render");

str vp_window_title = L"The Legend of Zelda: Breath of the Wild cutscene player";

PROCESS_INFORMATION vp_process;
Process::start(&vp_process, L".\\mpv.exe", L"mpv --no-osc --keep-open=no --cursor-autohide=always --no-border --no-window-dragging --title=\"" + vp_window_title + L"\" \"" + game_path + L"\\content\\Movie\\" + Utils::s2ws(video) + L".mp4\"",
Utils::getCurrentDir(), job, false);

HWND hVPWnd = waitForWindow(NULL, c(vp_window_title));

ShowWindow(hCemuRender, SW_HIDE);
attach(hVPWnd, hCemuWnd);
ShowWindow(hVPWnd, SW_SHOW);

WaitForSingleObject(vp_process.hProcess, INFINITE);

ShowWindow(hCemuRender, SW_SHOW);

UpdateWindow(hCemuWnd);

vp_last_video_time = getTime();
}

static void processLogLine(string line)
{
size_t pos = line.find(vp_log_pattern);
if(pos != string::npos)
{
size_t endpos = line.find(vp_log_pattern_ext);

string video = line.substr(pos + vp_log_pattern.length(), 9);

VideoPlayback::playVideo(video);
}
}

static DWORD WINAPI logWatcherThread(LPVOID arg)
{
str filename = cemu_path + L"\\log.txt";
#ifdef UNICODE
string fn = Utils::ws2s(filename);
#else
string fn = filename;
#endif

ifstream ifs(fn, ios::ate);
streamoff p;

string line;
while(true)
{
//ifs.seekg(p);

while(getline(ifs, line))
{
processLogLine(line);
p = ifs.tellg();
}

ifs.clear();

Sleep(VP_LOG_CHECK_INTERVAL);
}

return 0;
}

void VideoPlayback::start()
{
DWORD threadId;
HANDLE hThread = CreateThread(NULL, NULL, &logWatcherThread, NULL, NULL, &threadId);
}
68 changes: 47 additions & 21 deletions src/ZLauncher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ bool elevated, gameIsLaunched, launchedFromSteam;
str cfg = L"zlauncher.ini";

str cemu, cemu_path, cemu_cmdline, cemu_cores, game_path, speedhack_path, steam_path, steam_gameid, steam_cmdline;
bool cemu_fullscreen, game_elevate, speedhack_enabled, steam_enabled, steam_elevate;
bool cemu_fullscreen, game_elevate, speedhack_enabled, steam_enabled, steam_elevate, vp_enabled;

static void mb(LPTSTR msg, LPTSTR title = L"Error", UINT flags = MB_ICONERROR)
{
Expand Down Expand Up @@ -70,48 +70,68 @@ int ZLauncher::launch()
{
if(!this->parseConfig()) return 1;

if(!elevated)
{
str log = cemu_path + L"\\log.txt";
DeleteFile(c(log));
CloseHandle(CreateFile(c(log), GENERIC_READ, 0, NULL, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, NULL));
}

int steam_res = ERR_SUCCESS;
if(steam_enabled && !steam_path.empty()) steam_res = ZLauncher::launchWithSteam();

if(steam_res >= ERR_SUCCESS) return steam_res;
if(steam_enabled && steam_res >= ERR_SUCCESS) return steam_res;

if(game_elevate && !elevated) return ZLauncher::restartElevated(false) ? ERR_SUCCESS : ERR_ELEVATION;

if(!gameIsLaunched && !this->launchGame(elevated ? job : nullptr)) return ERR_GAME;

if(elevated)
if(speedhack_enabled)
{
if(speedhack_enabled && !launchSpeedhack(job)) return ERR_SPEEDHACK;

if(pemu.hProcess)
{
WaitForSingleObject(pemu.hProcess, INFINITE);
CloseHandle(pemu.hProcess);
CloseHandle(pemu.hThread);
}
else
if(elevated)
{
if(HANDLE cemu = Process::find(L"Cemu.exe"))
if(!this->launchSpeedhack(job)) return ERR_SPEEDHACK;

ZLauncher::wait();

if(psh.hProcess)
{
WaitForSingleObject(cemu, INFINITE);
CloseHandle(cemu);
CloseHandle(psh.hProcess);
CloseHandle(psh.hThread);
}
}

if(psh.hProcess)
else
{
CloseHandle(psh.hProcess);
CloseHandle(psh.hThread);
ZLauncher::restartElevated();
}
}
else
{
ZLauncher::restartElevated();
ZLauncher::wait();
}

return ERR_SUCCESS;
}

void ZLauncher::wait()
{
if(vp_enabled) VideoPlayback::start();

if(pemu.hProcess)
{
WaitForSingleObject(pemu.hProcess, INFINITE);
CloseHandle(pemu.hProcess);
CloseHandle(pemu.hThread);
}
else
{
if(HANDLE cemu = Process::find(L"Cemu.exe"))
{
WaitForSingleObject(cemu, INFINITE);
CloseHandle(cemu);
}
}
}

int ZLauncher::launchWithSteam()
{
if(steam_elevate)
Expand All @@ -136,6 +156,10 @@ int ZLauncher::launchWithSteam()
return Process::startElevated(steam_path, steam_cmdline, Utils::getCurrentDir(), nullptr, false) ? ERR_SUCCESS : ERR_STEAM_ELEVATION;
}
}
else if(launchedFromSteam)
{
return STEAM_RUNNING;
}

return Process::start(NULL, steam_path, steam_cmdline, Utils::getCurrentDir(), nullptr, false) ? ERR_SUCCESS : ERR_STEAM_GAME;
}
Expand Down Expand Up @@ -164,6 +188,8 @@ bool ZLauncher::parseConfig()
steam_cmdline = L"\"" + steam_path + L"\" \"steam://rungameid/" + steam_gameid + L"\"";
}

vp_enabled = Utils::getConfigBool(L"video", L"enabled", false);

if(cemu_path.empty() || game_path.empty()) return false;

cemu = cemu_path + L"\\Cemu.exe";
Expand Down
4 changes: 3 additions & 1 deletion zlauncher.cbp
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<Add option="-fexpensive-optimizations" />
<Add option="-O3" />
<Add option="-std=c++11" />
<Add option="-mwindows" />
<Add option="-mwindows -lpthread -mthreads -pthread" />
<Add directory="include" />
</Compiler>
<Linker>
Expand All @@ -31,13 +31,15 @@
</Compiler>
<Unit filename="include/Process.h" />
<Unit filename="include/Utils.h" />
<Unit filename="include/VideoPlayback.h" />
<Unit filename="include/ZLauncher.h" />
<Unit filename="main.cpp" />
<Unit filename="resources.rc">
<Option compilerVar="WINDRES" />
</Unit>
<Unit filename="src/Process.cpp" />
<Unit filename="src/Utils.cpp" />
<Unit filename="src/VideoPlayback.cpp" />
<Unit filename="src/ZLauncher.cpp" />
<Unit filename="zlauncher.ico" />
<Unit filename="zlauncher.manifest" />
Expand Down

0 comments on commit 9c9644b

Please sign in to comment.