From 4157ae2c48c539a3bbe609ab143d4c1454fd1748 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Wed, 14 Oct 2015 12:07:27 +0300 Subject: [PATCH] Refactor the libxine interface into classes --- source/xineengine.cpp | 101 ++++++++++++++++++++++++++++++++++++++++++ source/xineengine.h | 38 ++++++++++++++++ source/xinema.cpp | 86 +++++------------------------------ source/xinema.h | 23 +++------- source/xinestream.cpp | 53 ++++++++++++++++++++++ source/xinestream.h | 27 +++++++++++ 6 files changed, 237 insertions(+), 91 deletions(-) create mode 100644 source/xineengine.cpp create mode 100644 source/xineengine.h create mode 100644 source/xinestream.cpp create mode 100644 source/xinestream.h diff --git a/source/xineengine.cpp b/source/xineengine.cpp new file mode 100644 index 0000000..4175381 --- /dev/null +++ b/source/xineengine.cpp @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include "xineengine.h" + +using namespace std; +using namespace Msp; + +XineEngine::XineEngine(const Graphics::Window &w, Mutex *m): + window(w), + display_mutex(m), + locked_thread(0), + lock_count(0) +{ + engine = xine_new(); + + FS::Path config_fn = FS::get_home_dir()/".xine"/"config"; + xine_config_load(engine, config_fn.c_str()); + + xine_init(engine); + + audio_driver = xine_open_audio_driver(engine, "auto", 0); + if(!audio_driver) + throw runtime_error("Could not open audio driver"); + + visual.display = window.get_display().get_private().display; + visual.screen = 0; + visual.d = window.get_private().window; + visual.user_data = this; + visual.dest_size_cb = &dest_size_cb; + visual.frame_output_cb = &frame_output_cb; + if(display_mutex) + { + visual.lock_display = &lock_cb; + visual.unlock_display = &unlock_cb; + } + else + { + visual.lock_display = 0; + visual.unlock_display = 0; + } + + video_driver = xine_open_video_driver(engine, "auto", XINE_VISUAL_TYPE_X11_2, &visual); + if(!video_driver) + throw runtime_error("Could not open video driver"); +} + +XineEngine::~XineEngine() +{ + xine_close_video_driver(engine, video_driver); + xine_close_audio_driver(engine, audio_driver); + xine_exit(engine); +} + +void XineEngine::dest_size_cb(void *user_data, int, int, double, int *dest_width, int *dest_height, double *dest_pixel_aspect) +{ + XineEngine &engine = *reinterpret_cast(user_data); + *dest_width = engine.window.get_width(); + *dest_height = engine.window.get_height(); + *dest_pixel_aspect = 1.0; +} + +void XineEngine::frame_output_cb(void *user_data, int, int, double, int *dest_x, int *dest_y, int *dest_width, int *dest_height, double *dest_pixel_aspect, int *win_x, int *win_y) +{ + XineEngine &engine = *reinterpret_cast(user_data); + *dest_x = 0; + *dest_y = 0; + *dest_width = engine.window.get_width(); + *dest_height = engine.window.get_height(); + *dest_pixel_aspect = 1.0; + *win_x = 0; + *win_y = 0; +} + +void XineEngine::lock_cb(void *user_data) +{ + XineEngine &engine = *reinterpret_cast(user_data); + pthread_t tid = pthread_self(); + if(tid==engine.locked_thread) + ++engine.lock_count; + else + { + engine.display_mutex->lock(); + engine.locked_thread = tid; + engine.lock_count = 1; + } +} + +void XineEngine::unlock_cb(void *user_data) +{ + XineEngine &engine = *reinterpret_cast(user_data); + pthread_t tid = pthread_self(); + if(tid!=engine.locked_thread) + throw logic_error("Unlock from non-locked thread"); + if(!--engine.lock_count) + { + engine.locked_thread = 0; + engine.display_mutex->unlock(); + } +} diff --git a/source/xineengine.h b/source/xineengine.h new file mode 100644 index 0000000..8acb1a5 --- /dev/null +++ b/source/xineengine.h @@ -0,0 +1,38 @@ +#ifndef XINEENGINE_H_ +#define XINEENGINE_H_ + +#include +#include +#include +#include + +class XineStream; + +class XineEngine +{ +private: + const Msp::Graphics::Window &window; + Msp::Mutex *display_mutex; + pthread_t locked_thread; + unsigned lock_count; + xine_t *engine; + xine_audio_port_t *audio_driver; + x11_visual_t visual; + xine_video_port_t *video_driver; + +public: + XineEngine(const Msp::Graphics::Window &, Msp::Mutex * = 0); + ~XineEngine(); + + xine_t *get_engine() { return engine; } + xine_audio_port_t *get_audio_driver() { return audio_driver; } + xine_video_port_t *get_video_driver() { return video_driver; } + +private: + static void dest_size_cb(void *, int, int, double, int *, int *, double *); + static void frame_output_cb(void *, int, int, double, int *, int *, int *, int *, double *, int *, int *); + static void lock_cb(void *); + static void unlock_cb(void *); +}; + +#endif diff --git a/source/xinema.cpp b/source/xinema.cpp index 953310a..e4051cd 100644 --- a/source/xinema.cpp +++ b/source/xinema.cpp @@ -1,20 +1,12 @@ #include #include -#include -#include -#include -#include +#include "xineengine.h" #include "xinema.h" +#include "xinestream.h" using namespace std; using namespace Msp; -Xinema::EarlyInit::EarlyInit() -{ - XInitThreads(); -} - - Xinema::Xinema(int argc, char **argv): window(display, 1920, 1080) { @@ -27,83 +19,27 @@ Xinema::Xinema(int argc, char **argv): int Xinema::main() { - xine = xine_new(); - - FS::Path config_fn = FS::get_home_dir()/".xine"/"config"; - xine_config_load(xine, config_fn.c_str()); - - xine_init(xine); - - xine_audio = xine_open_audio_driver(xine, "auto", 0); - - XLockDisplay(display.get_private().display); window.show(); - XSync(display.get_private().display, false); - XUnlockDisplay(display.get_private().display); - - xine_visual.display = display.get_private().display; - xine_visual.screen = 0; - xine_visual.d = window.get_private().window; - xine_visual.user_data = this; - xine_visual.dest_size_cb = &dest_size_cb; - xine_visual.frame_output_cb = &frame_output_cb; - - xine_video = xine_open_video_driver(xine, "auto", XINE_VISUAL_TYPE_X11, &xine_visual); - - xine_stream = xine_stream_new(xine, xine_audio, xine_video); - xine_open(xine_stream, filename.c_str()); - xine_play(xine_stream, 0, 0); + display.tick(); - xine_queue = xine_event_new_queue(xine_stream); + engine = new XineEngine(window, &display_mutex); + stream = new XineStream(*engine, filename); + stream->play(); Application::main(); - xine_close(xine_stream); - xine_event_dispose_queue(xine_queue); - xine_dispose(xine_stream); - xine_close_video_driver(xine, xine_video); - xine_close_audio_driver(xine, xine_audio); - xine_exit(xine); + delete stream; + delete engine; return exit_code; } void Xinema::tick() { - XLockDisplay(display.get_private().display); - display.tick(); - XUnlockDisplay(display.get_private().display); - - while(xine_event_t *event = xine_event_get(xine_queue)) { - switch(event->type) - { - case XINE_EVENT_PROGRESS: - { - xine_progress_data_t *data = reinterpret_cast(event->data); - IO::print("%s [%d%%]\n", data->description, data->percent); - } - break; - } + MutexLock lock(display_mutex); + display.tick(); } -} -void Xinema::dest_size_cb(void *user_data, int, int, double, int *dest_width, int *dest_height, double *dest_pixel_aspect) -{ - Xinema &xinema = *reinterpret_cast(user_data); - *dest_width = xinema.window.get_width(); - *dest_height = xinema.window.get_height(); - *dest_pixel_aspect = 1.0; -} - -void Xinema::frame_output_cb(void *user_data, int, int, double, int *dest_x, int *dest_y, int *dest_width, int *dest_height, double *dest_pixel_aspect, int *win_x, int *win_y) -{ - Xinema &xinema = *reinterpret_cast(user_data); - *dest_x = 0; - *dest_y = 0; - *dest_width = xinema.window.get_width(); - *dest_height = xinema.window.get_height(); - *dest_pixel_aspect = 1.0; - *win_x = 0; - *win_y = 0; + stream->tick(); } diff --git a/source/xinema.h b/source/xinema.h index ce9e92a..3c3f75a 100644 --- a/source/xinema.h +++ b/source/xinema.h @@ -2,28 +2,22 @@ #define XINEMA_H_ #include +#include #include #include -#include + +class XineEngine; +class XineStream; class Xinema: public Msp::RegisteredApplication { private: - struct EarlyInit - { - EarlyInit(); - }; - - EarlyInit early_init; std::string filename; Msp::Graphics::Display display; + Msp::Mutex display_mutex; Msp::Graphics::Window window; - xine_t *xine; - xine_audio_port_t *xine_audio; - x11_visual_t xine_visual; - xine_video_port_t *xine_video; - xine_stream_t *xine_stream; - xine_event_queue_t *xine_queue; + XineEngine *engine; + XineStream *stream; public: Xinema(int, char **); @@ -32,9 +26,6 @@ public: private: virtual void tick(); - - static void dest_size_cb(void *, int, int, double, int *, int *, double *); - static void frame_output_cb(void *, int, int, double, int *, int *, int *, int *, double *, int *, int *); }; #endif diff --git a/source/xinestream.cpp b/source/xinestream.cpp new file mode 100644 index 0000000..fd2c622 --- /dev/null +++ b/source/xinestream.cpp @@ -0,0 +1,53 @@ +#include +#include "xineengine.h" +#include "xinestream.h" + +using namespace std; +using namespace Msp; + +XineStream::XineStream(XineEngine &engine, const string &mrl) +{ + stream = xine_stream_new(engine.get_engine(), engine.get_audio_driver(), engine.get_video_driver()); + xine_open(stream, mrl.c_str()); + + queue = xine_event_new_queue(stream); +} + +XineStream::~XineStream() +{ + xine_close(stream); + xine_event_dispose_queue(queue); + xine_dispose(stream); +} + +void XineStream::play() +{ + xine_play(stream, 0, 0); +} + +void XineStream::stop() +{ + xine_stop(stream); +} + +void XineStream::tick() +{ + while(xine_event_t *event = xine_event_get(queue)) + { + handle_event(*event); + xine_event_free(event); + } +} + +void XineStream::handle_event(const xine_event_t &event) +{ + switch(event.type) + { + case XINE_EVENT_PROGRESS: + { + xine_progress_data_t *data = reinterpret_cast(event.data); + IO::print("%s [%d%%]\n", data->description, data->percent); + } + break; + } +} diff --git a/source/xinestream.h b/source/xinestream.h new file mode 100644 index 0000000..885797d --- /dev/null +++ b/source/xinestream.h @@ -0,0 +1,27 @@ +#ifndef XINESTREAM_H_ +#define XINESTREAM_H_ + +#include +#include + +class XineEngine; + +class XineStream +{ +private: + xine_stream_t *stream; + xine_event_queue_t *queue; + +public: + XineStream(XineEngine &, const std::string &); + ~XineStream(); + + void play(); + void stop(); + + void tick(); +private: + void handle_event(const xine_event_t &); +}; + +#endif -- 2.43.0