2016-08-28 12:07:43 +00:00
|
|
|
#ifdef _WIN32
|
|
|
|
#include <windows.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#include <util/platform.h>
|
|
|
|
#include "vlc-video-plugin.h"
|
|
|
|
|
|
|
|
OBS_DECLARE_MODULE()
|
|
|
|
OBS_MODULE_USE_DEFAULT_LOCALE("vlc-video", "en-US")
|
2019-07-27 12:47:10 +00:00
|
|
|
MODULE_EXPORT const char *obs_module_description(void)
|
|
|
|
{
|
|
|
|
return "VLC playlist source";
|
|
|
|
}
|
2016-08-28 12:07:43 +00:00
|
|
|
|
|
|
|
/* libvlc core */
|
|
|
|
LIBVLC_NEW libvlc_new_;
|
|
|
|
LIBVLC_RELEASE libvlc_release_;
|
|
|
|
LIBVLC_CLOCK libvlc_clock_;
|
|
|
|
LIBVLC_EVENT_ATTACH libvlc_event_attach_;
|
|
|
|
|
|
|
|
/* libvlc media */
|
|
|
|
LIBVLC_MEDIA_NEW_PATH libvlc_media_new_path_;
|
2016-10-10 19:01:40 +00:00
|
|
|
LIBVLC_MEDIA_NEW_LOCATION libvlc_media_new_location_;
|
|
|
|
LIBVLC_MEDIA_ADD_OPTION libvlc_media_add_option_;
|
2016-08-28 12:07:43 +00:00
|
|
|
LIBVLC_MEDIA_RELEASE libvlc_media_release_;
|
|
|
|
LIBVLC_MEDIA_RELEASE libvlc_media_retain_;
|
|
|
|
|
|
|
|
/* libvlc media player */
|
|
|
|
LIBVLC_MEDIA_PLAYER_NEW libvlc_media_player_new_;
|
|
|
|
LIBVLC_MEDIA_PLAYER_NEW_FROM_MEDIA libvlc_media_player_new_from_media_;
|
|
|
|
LIBVLC_MEDIA_PLAYER_RELEASE libvlc_media_player_release_;
|
|
|
|
LIBVLC_VIDEO_SET_CALLBACKS libvlc_video_set_callbacks_;
|
|
|
|
LIBVLC_VIDEO_SET_FORMAT_CALLBACKS libvlc_video_set_format_callbacks_;
|
|
|
|
LIBVLC_AUDIO_SET_CALLBACKS libvlc_audio_set_callbacks_;
|
|
|
|
LIBVLC_AUDIO_SET_FORMAT_CALLBACKS libvlc_audio_set_format_callbacks_;
|
|
|
|
LIBVLC_MEDIA_PLAYER_PLAY libvlc_media_player_play_;
|
|
|
|
LIBVLC_MEDIA_PLAYER_STOP libvlc_media_player_stop_;
|
|
|
|
LIBVLC_MEDIA_PLAYER_GET_TIME libvlc_media_player_get_time_;
|
2020-03-25 08:07:22 +00:00
|
|
|
LIBVLC_MEDIA_PLAYER_SET_TIME libvlc_media_player_set_time_;
|
2016-08-28 12:07:43 +00:00
|
|
|
LIBVLC_VIDEO_GET_SIZE libvlc_video_get_size_;
|
|
|
|
LIBVLC_MEDIA_PLAYER_EVENT_MANAGER libvlc_media_player_event_manager_;
|
2020-03-25 08:07:22 +00:00
|
|
|
LIBVLC_MEDIA_PLAYER_GET_STATE libvlc_media_player_get_state_;
|
|
|
|
LIBVLC_MEDIA_PLAYER_GET_LENGTH libvlc_media_player_get_length_;
|
2016-08-28 12:07:43 +00:00
|
|
|
|
|
|
|
/* libvlc media list */
|
|
|
|
LIBVLC_MEDIA_LIST_NEW libvlc_media_list_new_;
|
|
|
|
LIBVLC_MEDIA_LIST_RELEASE libvlc_media_list_release_;
|
|
|
|
LIBVLC_MEDIA_LIST_ADD_MEDIA libvlc_media_list_add_media_;
|
|
|
|
LIBVLC_MEDIA_LIST_LOCK libvlc_media_list_lock_;
|
|
|
|
LIBVLC_MEDIA_LIST_UNLOCK libvlc_media_list_unlock_;
|
|
|
|
LIBVLC_MEDIA_LIST_EVENT_MANAGER libvlc_media_list_event_manager_;
|
|
|
|
|
|
|
|
/* libvlc media list player */
|
|
|
|
LIBVLC_MEDIA_LIST_PLAYER_NEW libvlc_media_list_player_new_;
|
|
|
|
LIBVLC_MEDIA_LIST_PLAYER_RELEASE libvlc_media_list_player_release_;
|
|
|
|
LIBVLC_MEDIA_LIST_PLAYER_PLAY libvlc_media_list_player_play_;
|
|
|
|
LIBVLC_MEDIA_LIST_PLAYER_PAUSE libvlc_media_list_player_pause_;
|
|
|
|
LIBVLC_MEDIA_LIST_PLAYER_STOP libvlc_media_list_player_stop_;
|
2019-09-22 21:19:10 +00:00
|
|
|
LIBVLC_MEDIA_LIST_PLAYER_SET_MEDIA_PLAYER
|
|
|
|
libvlc_media_list_player_set_media_player_;
|
2016-08-28 12:07:43 +00:00
|
|
|
LIBVLC_MEDIA_LIST_PLAYER_SET_MEDIA_LIST libvlc_media_list_player_set_media_list_;
|
|
|
|
LIBVLC_MEDIA_LIST_PLAYER_EVENT_MANAGER libvlc_media_list_player_event_manager_;
|
2019-09-22 21:19:10 +00:00
|
|
|
LIBVLC_MEDIA_LIST_PLAYER_SET_PLAYBACK_MODE
|
|
|
|
libvlc_media_list_player_set_playback_mode_;
|
2018-02-19 19:54:37 +00:00
|
|
|
LIBVLC_MEDIA_LIST_PLAYER_NEXT libvlc_media_list_player_next_;
|
|
|
|
LIBVLC_MEDIA_LIST_PLAYER_PREVIOUS libvlc_media_list_player_previous_;
|
2016-08-28 12:07:43 +00:00
|
|
|
|
|
|
|
void *libvlc_module = NULL;
|
2018-12-16 16:14:58 +00:00
|
|
|
#ifdef __APPLE__
|
|
|
|
void *libvlc_core_module = NULL;
|
|
|
|
#endif
|
|
|
|
|
2016-08-28 12:07:43 +00:00
|
|
|
libvlc_instance_t *libvlc = NULL;
|
|
|
|
uint64_t time_start = 0;
|
|
|
|
|
|
|
|
static bool load_vlc_funcs(void)
|
|
|
|
{
|
2019-09-22 21:19:10 +00:00
|
|
|
#define LOAD_VLC_FUNC(func) \
|
|
|
|
do { \
|
|
|
|
func##_ = os_dlsym(libvlc_module, #func); \
|
|
|
|
if (!func##_) { \
|
|
|
|
blog(LOG_WARNING, \
|
|
|
|
"Could not func VLC function %s, " \
|
|
|
|
"VLC loading failed", \
|
|
|
|
#func); \
|
|
|
|
return false; \
|
|
|
|
} \
|
2016-08-28 12:07:43 +00:00
|
|
|
} while (false)
|
|
|
|
|
|
|
|
/* libvlc core */
|
|
|
|
LOAD_VLC_FUNC(libvlc_new);
|
|
|
|
LOAD_VLC_FUNC(libvlc_release);
|
|
|
|
LOAD_VLC_FUNC(libvlc_clock);
|
|
|
|
LOAD_VLC_FUNC(libvlc_event_attach);
|
|
|
|
|
|
|
|
/* libvlc media */
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_new_path);
|
2016-10-10 19:01:40 +00:00
|
|
|
LOAD_VLC_FUNC(libvlc_media_new_location);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_add_option);
|
2016-08-28 12:07:43 +00:00
|
|
|
LOAD_VLC_FUNC(libvlc_media_release);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_retain);
|
|
|
|
|
|
|
|
/* libvlc media player */
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_player_new);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_player_new_from_media);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_player_release);
|
|
|
|
LOAD_VLC_FUNC(libvlc_video_set_callbacks);
|
|
|
|
LOAD_VLC_FUNC(libvlc_video_set_format_callbacks);
|
|
|
|
LOAD_VLC_FUNC(libvlc_audio_set_callbacks);
|
|
|
|
LOAD_VLC_FUNC(libvlc_audio_set_format_callbacks);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_player_play);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_player_stop);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_player_get_time);
|
2020-03-25 08:07:22 +00:00
|
|
|
LOAD_VLC_FUNC(libvlc_media_player_set_time);
|
2016-08-28 12:07:43 +00:00
|
|
|
LOAD_VLC_FUNC(libvlc_video_get_size);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_player_event_manager);
|
2020-03-25 08:07:22 +00:00
|
|
|
LOAD_VLC_FUNC(libvlc_media_player_get_state);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_player_get_length);
|
2016-08-28 12:07:43 +00:00
|
|
|
|
|
|
|
/* libvlc media list */
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_new);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_release);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_add_media);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_lock);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_unlock);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_event_manager);
|
|
|
|
|
|
|
|
/* libvlc media list player */
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_new);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_release);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_play);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_pause);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_stop);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_set_media_player);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_set_media_list);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_event_manager);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_set_playback_mode);
|
2018-02-19 19:54:37 +00:00
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_next);
|
|
|
|
LOAD_VLC_FUNC(libvlc_media_list_player_previous);
|
2016-08-28 12:07:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
static bool load_libvlc_module(void)
|
|
|
|
{
|
|
|
|
#ifdef _WIN32
|
2019-09-22 21:19:10 +00:00
|
|
|
char *path_utf8 = NULL;
|
2016-08-28 12:07:43 +00:00
|
|
|
wchar_t path[1024];
|
|
|
|
LSTATUS status;
|
2019-09-22 21:19:10 +00:00
|
|
|
DWORD size;
|
|
|
|
HKEY key;
|
2016-08-28 12:07:43 +00:00
|
|
|
|
|
|
|
memset(path, 0, 1024 * sizeof(wchar_t));
|
|
|
|
|
2019-09-22 21:19:10 +00:00
|
|
|
status = RegOpenKeyW(HKEY_LOCAL_MACHINE, L"SOFTWARE\\VideoLAN\\VLC",
|
|
|
|
&key);
|
2016-08-28 12:07:43 +00:00
|
|
|
if (status != ERROR_SUCCESS)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
size = 1024;
|
2019-09-22 21:19:10 +00:00
|
|
|
status = RegQueryValueExW(key, L"InstallDir", NULL, NULL, (LPBYTE)path,
|
|
|
|
&size);
|
2016-08-28 12:07:43 +00:00
|
|
|
if (status == ERROR_SUCCESS) {
|
|
|
|
wcscat(path, L"\\libvlc.dll");
|
|
|
|
os_wcs_to_utf8_ptr(path, 0, &path_utf8);
|
|
|
|
libvlc_module = os_dlopen(path_utf8);
|
|
|
|
bfree(path_utf8);
|
|
|
|
}
|
|
|
|
|
|
|
|
RegCloseKey(key);
|
|
|
|
#else
|
|
|
|
|
|
|
|
#ifdef __APPLE__
|
|
|
|
#define LIBVLC_DIR "/Applications/VLC.app/Contents/MacOS/"
|
2018-12-16 16:14:58 +00:00
|
|
|
/* According to otoolo -L, this is what libvlc.dylib wants. */
|
|
|
|
#define LIBVLC_CORE_FILE LIBVLC_DIR "lib/libvlccore.dylib"
|
2016-08-28 12:07:43 +00:00
|
|
|
#define LIBVLC_FILE LIBVLC_DIR "lib/libvlc.5.dylib"
|
|
|
|
setenv("VLC_PLUGIN_PATH", LIBVLC_DIR "plugins", false);
|
2018-12-16 16:14:58 +00:00
|
|
|
libvlc_core_module = os_dlopen(LIBVLC_CORE_FILE);
|
|
|
|
|
|
|
|
if (!libvlc_core_module)
|
|
|
|
return false;
|
2016-08-28 12:07:43 +00:00
|
|
|
#else
|
|
|
|
#define LIBVLC_FILE "libvlc.so.5"
|
|
|
|
#endif
|
|
|
|
libvlc_module = os_dlopen(LIBVLC_FILE);
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return libvlc_module != NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
extern struct obs_source_info vlc_source_info;
|
|
|
|
|
|
|
|
bool load_libvlc(void)
|
|
|
|
{
|
|
|
|
if (libvlc)
|
|
|
|
return true;
|
|
|
|
|
|
|
|
libvlc = libvlc_new_(0, 0);
|
|
|
|
if (!libvlc) {
|
|
|
|
blog(LOG_INFO, "Couldn't create libvlc instance");
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
time_start = (uint64_t)libvlc_clock_() * 1000ULL;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool obs_module_load(void)
|
|
|
|
{
|
|
|
|
if (!load_libvlc_module()) {
|
|
|
|
blog(LOG_INFO, "Couldn't find VLC installation, VLC video "
|
2019-09-22 21:19:10 +00:00
|
|
|
"source disabled");
|
2016-08-28 12:07:43 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!load_vlc_funcs())
|
|
|
|
return true;
|
|
|
|
|
|
|
|
blog(LOG_INFO, "VLC found, VLC video source enabled");
|
|
|
|
|
|
|
|
obs_register_source(&vlc_source_info);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
void obs_module_unload(void)
|
|
|
|
{
|
|
|
|
if (libvlc)
|
|
|
|
libvlc_release_(libvlc);
|
2018-12-16 16:14:58 +00:00
|
|
|
#ifdef __APPLE__
|
|
|
|
if (libvlc_core_module)
|
|
|
|
os_dlclose(libvlc_core_module);
|
|
|
|
#endif
|
2016-08-28 12:07:43 +00:00
|
|
|
if (libvlc_module)
|
|
|
|
os_dlclose(libvlc_module);
|
|
|
|
}
|