--- /dev/null
+#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 "xinema.h"
+
+using namespace std;
+using namespace Msp;
+
+Xinema::EarlyInit::EarlyInit()
+{
+ XInitThreads();
+}
+
+
+Xinema::Xinema(int argc, char **argv):
+ window(display, 1920, 1080)
+{
+ GetOpt getopt;
+ getopt.add_argument("filename", filename, GetOpt::REQUIRED_ARG);
+ getopt(argc, argv);
+
+ window.signal_close.connect(sigc::bind(sigc::mem_fun(this, &Xinema::exit), 0));
+}
+
+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);
+
+ xine_queue = xine_event_new_queue(xine_stream);
+
+ 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);
+
+ 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;
+ }
+ }
+}
+
+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;
+}
--- /dev/null
+#ifndef XINEMA_H_
+#define XINEMA_H_
+
+#include <msp/core/application.h>
+#include <msp/graphics/display.h>
+#include <msp/graphics/window.h>
+#include <xine.h>
+
+class Xinema: public Msp::RegisteredApplication<Xinema>
+{
+private:
+ struct EarlyInit
+ {
+ EarlyInit();
+ };
+
+ EarlyInit early_init;
+ std::string filename;
+ Msp::Graphics::Display display;
+ 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;
+
+public:
+ Xinema(int, char **);
+
+ virtual int main();
+
+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