]> git.tdb.fi Git - xinema.git/blob - source/xineengine.cpp
Refactor code to have the engine tick any streams
[xinema.git] / source / xineengine.cpp
1 #include <algorithm>
2 #include <stdexcept>
3 #include <msp/fs/dir.h>
4 #include <msp/graphics/display_private.h>
5 #include <msp/graphics/window_private.h>
6 #include "xineengine.h"
7 #include "xinestream.h"
8
9 using namespace std;
10 using namespace Msp;
11
12 XineEngine::XineEngine(Graphics::Window &w, Mutex *m):
13         window(w),
14         display_mutex(m),
15         locked_thread(0),
16         lock_count(0),
17         pending_expose(0)
18 {
19         engine = xine_new();
20
21         FS::Path config_fn = FS::get_home_dir()/".xine"/"config";
22         xine_config_load(engine, config_fn.c_str());
23
24         xine_init(engine);
25
26         audio_driver = xine_open_audio_driver(engine, "auto", 0);
27         if(!audio_driver)
28                 throw runtime_error("Could not open audio driver");
29
30         visual.display = window.get_display().get_private().display;
31         visual.screen = 0;
32         visual.d = window.get_private().window;
33         visual.user_data = this;
34         visual.dest_size_cb = &dest_size_cb;
35         visual.frame_output_cb = &frame_output_cb;
36         if(display_mutex)
37         {
38                 visual.lock_display = &lock_cb;
39                 visual.unlock_display = &unlock_cb;
40         }
41         else
42         {
43                 visual.lock_display = 0;
44                 visual.unlock_display = 0;
45         }
46
47         video_driver = xine_open_video_driver(engine, "auto", XINE_VISUAL_TYPE_X11_2, &visual);
48         if(!video_driver)
49                 throw runtime_error("Could not open video driver");
50
51         window.signal_expose.connect(sigc::mem_fun(this, &XineEngine::window_exposed));
52 }
53
54 XineEngine::~XineEngine()
55 {
56         xine_close_video_driver(engine, video_driver);
57         xine_close_audio_driver(engine, audio_driver);
58         xine_exit(engine);
59 }
60
61 void XineEngine::add_stream(XineStream &stream)
62 {
63         streams.push_back(&stream);
64 }
65
66 void XineEngine::remove_stream(XineStream &stream)
67 {
68         list<XineStream *>::iterator i = find(streams.begin(), streams.end(), &stream);
69         if(i!=streams.end())
70                 streams.erase(i);
71 }
72
73 void XineEngine::tick()
74 {
75         if(pending_expose)
76         {
77                 xine_port_send_gui_data(video_driver, XINE_GUI_SEND_EXPOSE_EVENT, &pending_expose->xevent);
78                 delete pending_expose;
79                 pending_expose = 0;
80         }
81
82         for(list<XineStream *>::const_iterator i=streams.begin(); i!=streams.end(); ++i)
83                 (*i)->tick();
84 }
85
86 void XineEngine::window_exposed(unsigned, unsigned, unsigned, unsigned, const Graphics::Window::Event &event)
87 {
88         delete pending_expose;
89         pending_expose = new Graphics::Window::Event(event);
90 }
91
92 void XineEngine::dest_size_cb(void *user_data, int, int, double, int *dest_width, int *dest_height, double *dest_pixel_aspect)
93 {
94         XineEngine &engine = *reinterpret_cast<XineEngine *>(user_data);
95         *dest_width = engine.window.get_width();
96         *dest_height = engine.window.get_height();
97         *dest_pixel_aspect = 1.0;
98 }
99
100 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)
101 {
102         XineEngine &engine = *reinterpret_cast<XineEngine *>(user_data);
103         *dest_x = 0;
104         *dest_y = 0;
105         *dest_width = engine.window.get_width();
106         *dest_height = engine.window.get_height();
107         *dest_pixel_aspect = 1.0;
108         *win_x = 0;
109         *win_y = 0;
110 }
111
112 void XineEngine::lock_cb(void *user_data)
113 {
114         XineEngine &engine = *reinterpret_cast<XineEngine *>(user_data);
115         pthread_t tid = pthread_self();
116         if(tid==engine.locked_thread)
117                 ++engine.lock_count;
118         else
119         {
120                 engine.display_mutex->lock();
121                 engine.locked_thread = tid;
122                 engine.lock_count = 1;
123         }
124 }
125
126 void XineEngine::unlock_cb(void *user_data)
127 {
128         XineEngine &engine = *reinterpret_cast<XineEngine *>(user_data);
129         pthread_t tid = pthread_self();
130         if(tid!=engine.locked_thread)
131                 throw logic_error("Unlock from non-locked thread");
132         if(!--engine.lock_count)
133         {
134                 engine.locked_thread = 0;
135                 engine.display_mutex->unlock();
136         }
137 }