]> git.tdb.fi Git - xinema.git/commitdiff
Refactor the libxine interface into classes
authorMikko Rasa <tdb@tdb.fi>
Wed, 14 Oct 2015 09:07:27 +0000 (12:07 +0300)
committerMikko Rasa <tdb@tdb.fi>
Wed, 14 Oct 2015 09:07:27 +0000 (12:07 +0300)
source/xineengine.cpp [new file with mode: 0644]
source/xineengine.h [new file with mode: 0644]
source/xinema.cpp
source/xinema.h
source/xinestream.cpp [new file with mode: 0644]
source/xinestream.h [new file with mode: 0644]

diff --git a/source/xineengine.cpp b/source/xineengine.cpp
new file mode 100644 (file)
index 0000000..4175381
--- /dev/null
@@ -0,0 +1,101 @@
+#include <stdexcept>
+#include <msp/fs/dir.h>
+#include <msp/graphics/display_private.h>
+#include <msp/graphics/window_private.h>
+#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<XineEngine *>(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<XineEngine *>(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<XineEngine *>(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<XineEngine *>(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 (file)
index 0000000..8acb1a5
--- /dev/null
@@ -0,0 +1,38 @@
+#ifndef XINEENGINE_H_
+#define XINEENGINE_H_
+
+#include <pthread.h>
+#include <xine.h>
+#include <msp/core/mutex.h>
+#include <msp/graphics/window.h>
+
+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
index 953310ad93cd868f4763ac85585a603298381e0a..e4051cda3f15d5bb35bee8f474667d03d59f7190 100644 (file)
@@ -1,20 +1,12 @@
 #include <sigc++/bind.h>
 #include <msp/core/getopt.h>
-#include <msp/fs/dir.h>
-#include <msp/graphics/display_private.h>
-#include <msp/graphics/window_private.h>
-#include <msp/io/print.h>
+#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<xine_progress_data_t *>(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<Xinema *>(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<Xinema *>(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();
 }
index ce9e92af666ab7f71c7c42e9f8e85fcfef5102b1..3c3f75a0eb610746433343778157b39998686bcc 100644 (file)
@@ -2,28 +2,22 @@
 #define XINEMA_H_
 
 #include <msp/core/application.h>
+#include <msp/core/mutex.h>
 #include <msp/graphics/display.h>
 #include <msp/graphics/window.h>
-#include <xine.h>
+
+class XineEngine;
+class XineStream;
 
 class Xinema: public Msp::RegisteredApplication<Xinema>
 {
 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 (file)
index 0000000..fd2c622
--- /dev/null
@@ -0,0 +1,53 @@
+#include <msp/io/print.h>
+#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<xine_progress_data_t *>(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 (file)
index 0000000..885797d
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef XINESTREAM_H_
+#define XINESTREAM_H_
+
+#include <string>
+#include <xine.h>
+
+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