hook BGI调用视频
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -1,2 +1,3 @@
|
|||||||
build/
|
build/
|
||||||
.vscode/
|
.vscode/
|
||||||
|
bin/
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ endif()
|
|||||||
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
|
include_directories("${CMAKE_CURRENT_SOURCE_DIR}/include")
|
||||||
|
|
||||||
set(DETOURS_LIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/detours.lib")
|
set(DETOURS_LIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/detours.lib")
|
||||||
|
set(PLAYER_LIB "${CMAKE_CURRENT_SOURCE_DIR}/lib/player.lib")
|
||||||
|
|
||||||
set(ENABLE_ICONV OFF CACHE BOOL "Libiconv is not needed.")
|
set(ENABLE_ICONV OFF CACHE BOOL "Libiconv is not needed.")
|
||||||
add_subdirectory(utils)
|
add_subdirectory(utils)
|
||||||
@@ -39,6 +40,7 @@ add_subdirectory("libzip")
|
|||||||
|
|
||||||
add_library(jewena_patch SHARED dllmain.cpp config.hpp config.cpp vfs.hpp vfs.cpp string_replace_file.hpp string_replace_file.cpp)
|
add_library(jewena_patch SHARED dllmain.cpp config.hpp config.cpp vfs.hpp vfs.cpp string_replace_file.hpp string_replace_file.cpp)
|
||||||
target_link_libraries(jewena_patch "${DETOURS_LIB}")
|
target_link_libraries(jewena_patch "${DETOURS_LIB}")
|
||||||
|
target_link_libraries(jewena_patch "${PLAYER_LIB}")
|
||||||
target_link_libraries(jewena_patch utils)
|
target_link_libraries(jewena_patch utils)
|
||||||
target_link_libraries(jewena_patch zip)
|
target_link_libraries(jewena_patch zip)
|
||||||
|
|
||||||
|
|||||||
37
config.cpp
37
config.cpp
@@ -2,6 +2,8 @@
|
|||||||
#include "fileop.h"
|
#include "fileop.h"
|
||||||
#include "file_reader.h"
|
#include "file_reader.h"
|
||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
|
#include "str_util.h"
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#if _WIN32
|
#if _WIN32
|
||||||
@@ -46,3 +48,38 @@ bool Config::Load(std::string path) {
|
|||||||
fileop::fclose(f);
|
fileop::fclose(f);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Config::IsAppendLogging() {
|
||||||
|
auto re = configs.find("appendLogging");
|
||||||
|
if (re == configs.end()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return str_util::parse_bool((*re).second);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Config::LoggingLevel() {
|
||||||
|
auto re = configs.find("loggingLevel");
|
||||||
|
if (re == configs.end()) {
|
||||||
|
return AV_LOG_INFO;
|
||||||
|
}
|
||||||
|
std::string level = str_util::tolower((*re).second);
|
||||||
|
if (level == "debug") {
|
||||||
|
return AV_LOG_DEBUG;
|
||||||
|
} else if (level == "verbose") {
|
||||||
|
return AV_LOG_VERBOSE;
|
||||||
|
} else if (level == "info") {
|
||||||
|
return AV_LOG_INFO;
|
||||||
|
} else if (level == "warning") {
|
||||||
|
return AV_LOG_WARNING;
|
||||||
|
} else if (level == "error") {
|
||||||
|
return AV_LOG_ERROR;
|
||||||
|
} else if (level == "fatal") {
|
||||||
|
return AV_LOG_FATAL;
|
||||||
|
} else if (level == "trace") {
|
||||||
|
return AV_LOG_TRACE;
|
||||||
|
} else if (level == "panic") {
|
||||||
|
return AV_LOG_PANIC;
|
||||||
|
} else {
|
||||||
|
return AV_LOG_INFO;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,6 +7,11 @@ class Config {
|
|||||||
Config() {
|
Config() {
|
||||||
configs["defaultFont"] = "微软雅黑";
|
configs["defaultFont"] = "微软雅黑";
|
||||||
configs["stringReplaceFile"] = "";
|
configs["stringReplaceFile"] = "";
|
||||||
|
configs["appendLogging"] = "false";
|
||||||
|
configs["loggingFile"] = "";
|
||||||
|
configs["loggingLevel"] = "info";
|
||||||
}
|
}
|
||||||
bool Load(std::string path);
|
bool Load(std::string path);
|
||||||
|
bool IsAppendLogging();
|
||||||
|
int LoggingLevel();
|
||||||
};
|
};
|
||||||
|
|||||||
127
dllmain.cpp
127
dllmain.cpp
@@ -8,6 +8,7 @@
|
|||||||
#include "fileop.h"
|
#include "fileop.h"
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include "string_replace_file.hpp"
|
#include "string_replace_file.hpp"
|
||||||
|
#include "player.h"
|
||||||
|
|
||||||
static HFONT(WINAPI *TrueCreateFontW)(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD dwItalic, DWORD dwUnderline, DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision, DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily, LPCWSTR lpFaceName) = CreateFontW;
|
static HFONT(WINAPI *TrueCreateFontW)(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD dwItalic, DWORD dwUnderline, DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision, DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily, LPCWSTR lpFaceName) = CreateFontW;
|
||||||
static HFONT(WINAPI *TrueCreateFontA)(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD dwItalic, DWORD dwUnderline, DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision, DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily, LPCSTR lpFaceName) = CreateFontA;
|
static HFONT(WINAPI *TrueCreateFontA)(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD dwItalic, DWORD dwUnderline, DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision, DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily, LPCSTR lpFaceName) = CreateFontA;
|
||||||
@@ -22,10 +23,21 @@ static decltype(GetFileType) *TrueGetFileType = GetFileType;
|
|||||||
static decltype(GetFileAttributesW) *TrueGetFileAttributesW = GetFileAttributesW;
|
static decltype(GetFileAttributesW) *TrueGetFileAttributesW = GetFileAttributesW;
|
||||||
static decltype(GetFileAttributesExW) *TrueGetFileAttributesExW = GetFileAttributesExW;
|
static decltype(GetFileAttributesExW) *TrueGetFileAttributesExW = GetFileAttributesExW;
|
||||||
|
|
||||||
|
typedef int64_t(*OpenMediaFileAndGetDuration)(DWORD* duration, const char* arcName, const char* videoName);
|
||||||
|
typedef int64_t(*IsPlaying)();
|
||||||
|
typedef int64_t(*IsMediaPlaying)();
|
||||||
|
typedef int64_t(*ReleaseDirectShowGraph)();
|
||||||
|
|
||||||
static Config config;
|
static Config config;
|
||||||
static std::wstring defaultFont;
|
static std::wstring defaultFont;
|
||||||
static VFS vfs;
|
static VFS vfs;
|
||||||
static StringReplaceFile replaceFile;
|
static StringReplaceFile replaceFile;
|
||||||
|
static PlayerSession* player = NULL;
|
||||||
|
static PlayerSettings* settings = NULL;
|
||||||
|
static OpenMediaFileAndGetDuration OpenMediaFileAndGetDurationFunc = NULL;
|
||||||
|
static IsPlaying IsPlayingFunc = NULL;
|
||||||
|
static IsMediaPlaying IsMediaPlayingFunc = NULL;
|
||||||
|
static ReleaseDirectShowGraph ReleaseDirectShowGraphFunc = NULL;
|
||||||
|
|
||||||
char* to_utf8(char* target, const char* source, UINT cp) {
|
char* to_utf8(char* target, const char* source, UINT cp) {
|
||||||
int count = MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, source, -1, NULL, 0);
|
int count = MultiByteToWideChar(cp, MB_ERR_INVALID_CHARS, source, -1, NULL, 0);
|
||||||
@@ -73,8 +85,108 @@ PVOID GetHandle() {
|
|||||||
return (char*)hModule + 0xf40e0;
|
return (char*)hModule + 0xf40e0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
HWND* GetHwndPointer() {
|
||||||
|
HMODULE hModule = GetModuleHandleA(NULL);
|
||||||
|
return (HWND*)((char*)hModule + 0x1e1620);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenMediaFileAndGetDuration GetOpenMediaFileAndGetDuration() {
|
||||||
|
HMODULE hModule = GetModuleHandleA(NULL);
|
||||||
|
return (OpenMediaFileAndGetDuration)((char*)hModule + 0xed3d0);
|
||||||
|
}
|
||||||
|
|
||||||
|
IsPlaying GetIsPlaying() {
|
||||||
|
HMODULE hModule = GetModuleHandleA(NULL);
|
||||||
|
return (IsPlaying)((char*)hModule + 0xed810);
|
||||||
|
}
|
||||||
|
|
||||||
|
IsMediaPlaying GetIsMediaPlaying() {
|
||||||
|
HMODULE hModule = GetModuleHandleA(NULL);
|
||||||
|
return (IsMediaPlaying)((char*)hModule + 0xed2f0);
|
||||||
|
}
|
||||||
|
|
||||||
|
ReleaseDirectShowGraph GetReleaseDirectShowGraph() {
|
||||||
|
HMODULE hModule = GetModuleHandleA(NULL);
|
||||||
|
return (ReleaseDirectShowGraph)((char*)hModule + 0xed610);
|
||||||
|
}
|
||||||
|
|
||||||
static PVOID h = nullptr;
|
static PVOID h = nullptr;
|
||||||
|
|
||||||
|
int64_t HookedOpenMediaFileAndGetDuration(DWORD* duration, const char* arcName, const char* videoName) {
|
||||||
|
player_free(&player);
|
||||||
|
player_log(AV_LOG_INFO, "BGI: Open Video: %s, %s\n", arcName, videoName);
|
||||||
|
int64_t ok = 0;
|
||||||
|
if (fileop::exists(videoName)) {
|
||||||
|
player_log(AV_LOG_INFO, "Video file exists: %s\n", videoName);
|
||||||
|
if (!settings) {
|
||||||
|
settings = player_settings_init();
|
||||||
|
if (!settings) {
|
||||||
|
player_log(AV_LOG_ERROR, "Failed to initialize player settings.\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
player_settings_set_hWnd(settings, (void**)GetHwndPointer());
|
||||||
|
if (player_create2(videoName, &player, settings)) {
|
||||||
|
player_log(AV_LOG_ERROR, "Failed to create player session.\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (wait_player_inited(player)) {
|
||||||
|
player_log(AV_LOG_ERROR, "Failed to initialize player.\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
if (player_play(player)) {
|
||||||
|
player_log(AV_LOG_ERROR, "Failed to play video.\n");
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
int64_t dur;
|
||||||
|
if (!player_get_duration(player, &dur)) {
|
||||||
|
if (duration) {
|
||||||
|
*duration = dur / 1000;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
player_log(AV_LOG_WARNING, "Failed to get video duration.\n");
|
||||||
|
}
|
||||||
|
goto works;
|
||||||
|
}
|
||||||
|
end:
|
||||||
|
ok = OpenMediaFileAndGetDurationFunc(duration, arcName, videoName);
|
||||||
|
works:
|
||||||
|
if (duration) {
|
||||||
|
char tmp[32];
|
||||||
|
int64_t dur = *duration * 1000;
|
||||||
|
player_ts_make_string(tmp, dur);
|
||||||
|
player_log(AV_LOG_INFO, "Video duration: %s\n", tmp);
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t HookedIsPlaying() {
|
||||||
|
if (player) {
|
||||||
|
return player_is_playing(player);
|
||||||
|
}
|
||||||
|
return IsPlayingFunc();
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t HookedIsMediaPlaying() {
|
||||||
|
if (player) {
|
||||||
|
int64_t re = player_is_playing(player);
|
||||||
|
// 释放播放器,BGI在播放完毕后不会手动释放
|
||||||
|
if (!re) {
|
||||||
|
player_log(AV_LOG_INFO, "Auto Close\n");
|
||||||
|
player_free(&player);
|
||||||
|
}
|
||||||
|
return re;
|
||||||
|
}
|
||||||
|
int64_t re = IsMediaPlayingFunc();
|
||||||
|
return re;
|
||||||
|
}
|
||||||
|
|
||||||
|
int64_t HookedReleaseDirectShowGraph() {
|
||||||
|
player_log(AV_LOG_INFO, "BGI: Close\n");
|
||||||
|
player_free(&player);
|
||||||
|
return ReleaseDirectShowGraphFunc();
|
||||||
|
}
|
||||||
|
|
||||||
HFONT WINAPI HookedCreateFontW(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD dwItalic, DWORD dwUnderline, DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision, DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily, LPCWSTR lpFaceName) {
|
HFONT WINAPI HookedCreateFontW(int nHeight, int nWidth, int nEscapement, int nOrientation, int fnWeight, DWORD dwItalic, DWORD dwUnderline, DWORD dwStrikeOut, DWORD dwCharSet, DWORD dwOutPrecision, DWORD dwClipPrecision, DWORD dwQuality, DWORD dwPitchAndFamily, LPCWSTR lpFaceName) {
|
||||||
std::wstring name(lpFaceName);
|
std::wstring name(lpFaceName);
|
||||||
if (name == L"Meiryo") {
|
if (name == L"Meiryo") {
|
||||||
@@ -183,11 +295,24 @@ extern "C" __declspec(dllexport) void Attach() {
|
|||||||
if (defaultFont.empty()) {
|
if (defaultFont.empty()) {
|
||||||
defaultFont = L"微软雅黑";
|
defaultFont = L"微软雅黑";
|
||||||
}
|
}
|
||||||
vfs.AddArchiveWithErrorMsg("jewena-chs.dat");
|
auto loggingFile = config.configs["loggingFile"];
|
||||||
|
if (!loggingFile.empty()) {
|
||||||
|
set_player_log_file(loggingFile.c_str(), config.IsAppendLogging() ? 1 : 0, config.LoggingLevel());
|
||||||
|
}
|
||||||
|
vfs.AddArchive("jewena-chs.dat");
|
||||||
|
vfs.AddArchive("video.dat");
|
||||||
DetourTransactionBegin();
|
DetourTransactionBegin();
|
||||||
DetourUpdateThread(GetCurrentThread());
|
DetourUpdateThread(GetCurrentThread());
|
||||||
h = GetHandle();
|
h = GetHandle();
|
||||||
DetourAttach(&h, (PVOID)jis_to_utf8);
|
DetourAttach(&h, (PVOID)jis_to_utf8);
|
||||||
|
OpenMediaFileAndGetDurationFunc = GetOpenMediaFileAndGetDuration();
|
||||||
|
DetourAttach(&OpenMediaFileAndGetDurationFunc, HookedOpenMediaFileAndGetDuration);
|
||||||
|
IsPlayingFunc = GetIsPlaying();
|
||||||
|
DetourAttach(&IsPlayingFunc, HookedIsPlaying);
|
||||||
|
IsMediaPlayingFunc = GetIsMediaPlaying();
|
||||||
|
DetourAttach(&IsMediaPlayingFunc, HookedIsMediaPlaying);
|
||||||
|
ReleaseDirectShowGraphFunc = GetReleaseDirectShowGraph();
|
||||||
|
DetourAttach(&ReleaseDirectShowGraphFunc, HookedReleaseDirectShowGraph);
|
||||||
DetourAttach(&TrueCreateFontW, HookedCreateFontW);
|
DetourAttach(&TrueCreateFontW, HookedCreateFontW);
|
||||||
DetourAttach(&TrueCreateFontA, HookedCreateFontA);
|
DetourAttach(&TrueCreateFontA, HookedCreateFontA);
|
||||||
DetourAttach(&TrueCreateFileW, HookedCreateFileW);
|
DetourAttach(&TrueCreateFileW, HookedCreateFileW);
|
||||||
|
|||||||
170
include/player.h
Normal file
170
include/player.h
Normal file
@@ -0,0 +1,170 @@
|
|||||||
|
#ifndef _PLAYER_H
|
||||||
|
#define _PLAYER_H
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#if _WIN32
|
||||||
|
#if BUILD_PLAYER
|
||||||
|
#define PLAYER_API __declspec(dllexport)
|
||||||
|
#else
|
||||||
|
#define PLAYER_API __declspec(dllimport)
|
||||||
|
#endif
|
||||||
|
#elif defined(__GNUC__)
|
||||||
|
#define PLAYER_API __attribute__((visibility("default")))
|
||||||
|
#else
|
||||||
|
#define PLAYER_API
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct PlayerSession PlayerSession;
|
||||||
|
typedef struct PlayerSettings PlayerSettings;
|
||||||
|
|
||||||
|
#ifndef BUILD_PLAYER
|
||||||
|
#define AV_LOG_QUIET -8
|
||||||
|
#define AV_LOG_PANIC 0
|
||||||
|
#define AV_LOG_FATAL 8
|
||||||
|
#define AV_LOG_ERROR 16
|
||||||
|
#define AV_LOG_WARNING 24
|
||||||
|
#define AV_LOG_INFO 32
|
||||||
|
#define AV_LOG_VERBOSE 40
|
||||||
|
#define AV_LOG_DEBUG 48
|
||||||
|
#define AV_LOG_TRACE 56
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define PLAYER_ERR_OK 0
|
||||||
|
#define PLAYER_ERR_NULLPTR 1
|
||||||
|
#define PLAYER_ERR_SDL 2
|
||||||
|
#define PLAYER_ERR_OOM 3
|
||||||
|
#define PLAYER_ERR_NO_STREAM_OR_DECODER 4
|
||||||
|
#define PLAYER_ERR_UNKNOWN_AUDIO_SAMPLE_FMT 5
|
||||||
|
#define PLAYER_ERR_FAILED_CREATE_MUTEX 6
|
||||||
|
#define PLAYER_ERR_WAIT_MUTEX_FAILED 7
|
||||||
|
#define PLAYER_ERR_FAILED_CREATE_THREAD 8
|
||||||
|
#define PLAYER_ERR_NO_DURATION 9
|
||||||
|
|
||||||
|
PLAYER_API const char* player_version_str();
|
||||||
|
PLAYER_API int32_t player_version();
|
||||||
|
/**
|
||||||
|
* @brief 设置播放器日志文件
|
||||||
|
*
|
||||||
|
* 如果之前设置过日志文件,会关闭之前的日志文件。
|
||||||
|
* @param filename 日志文件路径,如果为NULL则关闭之前的设置的日志文件
|
||||||
|
* @param append 是否追加到文件末尾
|
||||||
|
* @param max_level 最大日志级别,小于等于这个级别的日志会被记录
|
||||||
|
*/
|
||||||
|
PLAYER_API void set_player_log_file(const char* filename, unsigned char append, int max_level);
|
||||||
|
/**
|
||||||
|
* @brief 记录播放器日志
|
||||||
|
* @param level 日志级别
|
||||||
|
* @param fmt 日志格式
|
||||||
|
*/
|
||||||
|
PLAYER_API void player_log(int level, const char* fmt, ...);
|
||||||
|
PLAYER_API size_t player_ts_max_string_size();
|
||||||
|
/**
|
||||||
|
* @brief 将时间戳转换为字符串
|
||||||
|
* @param buf 用于接收字符串的缓冲区,至少需要 player_ts_max_string_size() 大小
|
||||||
|
* @param ts 时间戳(单位:微秒)
|
||||||
|
* @return 字符串指针
|
||||||
|
*/
|
||||||
|
PLAYER_API char* player_ts_make_string(char* buf, int64_t ts);
|
||||||
|
/**
|
||||||
|
* @brief 返回错误代码对应的错误消息
|
||||||
|
* @param err 错误代码
|
||||||
|
* @return 错误消息,需要调用free释放内存
|
||||||
|
*/
|
||||||
|
PLAYER_API char* player_get_err_msg(int err);
|
||||||
|
/**
|
||||||
|
* @brief 返回错误代码对应的错误消息
|
||||||
|
* @param err 错误代码(仅处理>=0的错误)
|
||||||
|
* @return 错误消息
|
||||||
|
*/
|
||||||
|
PLAYER_API const char* player_get_err_msg2(int err);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建一个播放器会话
|
||||||
|
* @param url 要播放的文件路径
|
||||||
|
* @param session 用于接收会话指针的指针
|
||||||
|
* @return 错误代码
|
||||||
|
*/
|
||||||
|
PLAYER_API int player_create(const char* url, PlayerSession** session);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 创建一个播放器会话
|
||||||
|
* @param url 要播放的文件路径
|
||||||
|
* @param session 用于接收会话指针的指针
|
||||||
|
* @param settings 播放器设置,如果为NULL会使用默认设置。注意,传入的settings需要在session销毁前保持有效,需要手动调用 player_settings_free 。
|
||||||
|
* @return 错误代码
|
||||||
|
*/
|
||||||
|
PLAYER_API int player_create2(const char* url, PlayerSession** session, PlayerSettings* settings);
|
||||||
|
/**
|
||||||
|
* @brief 等待播放器初始化完成
|
||||||
|
* @param session 播放器会话指针
|
||||||
|
* @return 错误代码
|
||||||
|
*/
|
||||||
|
PLAYER_API int wait_player_inited(PlayerSession* session);
|
||||||
|
/**
|
||||||
|
* @brief 开始播放
|
||||||
|
* @param session 播放器会话指针
|
||||||
|
* @return 错误代码
|
||||||
|
*/
|
||||||
|
PLAYER_API int player_play(PlayerSession* session);
|
||||||
|
/**
|
||||||
|
* @brief 暂停播放
|
||||||
|
* @param session 播放器会话指针
|
||||||
|
* @return 错误代码
|
||||||
|
*/
|
||||||
|
PLAYER_API int player_pause(PlayerSession* session);
|
||||||
|
/**
|
||||||
|
* @brief 判断播放器是否正在播放
|
||||||
|
* @param session 播放器会话指针
|
||||||
|
* @return 是否正在播放
|
||||||
|
*/
|
||||||
|
PLAYER_API int player_is_playing(PlayerSession* session);
|
||||||
|
/**
|
||||||
|
* @brief 获取当前播放时间
|
||||||
|
* @param session 播放器会话指针
|
||||||
|
* @param pos 用于接收当前播放时间的指针(单位:微秒)
|
||||||
|
* @return 错误代码
|
||||||
|
*/
|
||||||
|
PLAYER_API int player_get_duration(PlayerSession* session, int64_t* duration);
|
||||||
|
PLAYER_API void player_free(PlayerSession** session);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 初始化播放器设置,会自动设置为默认值
|
||||||
|
* @return 播放器设置指针
|
||||||
|
*/
|
||||||
|
PLAYER_API PlayerSettings* player_settings_init();
|
||||||
|
/**
|
||||||
|
* @brief 将播放器设置重置为默认值
|
||||||
|
* @param settings 播放器设置指针
|
||||||
|
*/
|
||||||
|
PLAYER_API void player_settings_default(PlayerSettings* settings);
|
||||||
|
/**
|
||||||
|
* @brief 设置是否自动调整窗口大小
|
||||||
|
* @param settings 播放器设置指针
|
||||||
|
* @param resize 是否自动调整窗口大小
|
||||||
|
*/
|
||||||
|
PLAYER_API void player_settings_set_resize(PlayerSettings* settings, unsigned char resize);
|
||||||
|
/**
|
||||||
|
* @brief 设置窗口句柄
|
||||||
|
* @param settings 播放器设置指针
|
||||||
|
* @param hWnd 指向窗口句柄的指针
|
||||||
|
*/
|
||||||
|
PLAYER_API void player_settings_set_hWnd(PlayerSettings* settings, void** hWnd);
|
||||||
|
PLAYER_API void player_settings_free(PlayerSettings** settings);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief 直接播放一个文件,会创建一个新的窗口并自动播放,播放结束后自动销毁。
|
||||||
|
*
|
||||||
|
* 会阻塞当前线程。
|
||||||
|
* @param filename 要播放的文件路径
|
||||||
|
* @param hWnd 指向窗口句柄的指针(可选)
|
||||||
|
*/
|
||||||
|
PLAYER_API void play(const char* filename, void** hWnd);
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
9
include/player_version.h
Normal file
9
include/player_version.h
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#ifndef _PLAYER_VERSION_H
|
||||||
|
#define _PLAYER_VERSION_H
|
||||||
|
#define PLAYER_VERSION_MAJOR 0
|
||||||
|
#define PLAYER_VERSION_MINOR 0
|
||||||
|
#define PLAYER_VERSION_MICRO 1
|
||||||
|
#define PLAYER_VERSION_REV 0
|
||||||
|
#define PLAYER_VERSION "0.0.1.0"
|
||||||
|
#define PLAYER_VERSION_INT (((int32_t)PLAYER_VERSION_MAJOR << 24) | ((int32_t)PLAYER_VERSION_MINOR << 16) | ((int32_t)PLAYER_VERSION_MICRO << 8) | (int32_t)PLAYER_VERSION_REV)
|
||||||
|
#endif
|
||||||
BIN
lib/player.lib
Normal file
BIN
lib/player.lib
Normal file
Binary file not shown.
2
utils
2
utils
Submodule utils updated: 5fde5e6e52...252c20d068
Reference in New Issue
Block a user