]> git.tdb.fi Git - xinema.git/blob - source/xinestream.cpp
Implement basic playback controls
[xinema.git] / source / xinestream.cpp
1 #include <msp/io/print.h>
2 #include "xineengine.h"
3 #include "xinestream.h"
4
5 using namespace std;
6 using namespace Msp;
7
8 XineStream::XineStream(XineEngine &e, const string &mrl):
9         engine(e),
10         state(STOPPED)
11 {
12         stream = xine_stream_new(engine.get_engine(), engine.get_audio_driver(), engine.get_video_driver());
13         xine_open(stream, mrl.c_str());
14
15         queue = xine_event_new_queue(stream);
16
17         check_info();
18
19         engine.add_stream(*this);
20 }
21
22 XineStream::~XineStream()
23 {
24         engine.remove_stream(*this);
25
26         xine_close(stream);
27         xine_event_dispose_queue(queue);
28         xine_dispose(stream);
29 }
30
31 void XineStream::play()
32 {
33         if(state==STOPPED)
34                 xine_play(stream, 0, 0);
35         else if(state==PAUSED)
36                 xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_NORMAL);
37
38         set_state(PLAYING);
39 }
40
41 void XineStream::seek(const Time::TimeDelta &time)
42 {
43         xine_play(stream, 0, time/Time::msec);
44         if(state!=PLAYING)
45         {
46                 xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
47                 set_state(PAUSED);
48         }
49 }
50
51 void XineStream::pause()
52 {
53         if(state==PLAYING)
54         {
55                 xine_set_param(stream, XINE_PARAM_SPEED, XINE_SPEED_PAUSE);
56                 set_state(PAUSED);
57         }
58 }
59
60 void XineStream::stop()
61 {
62         xine_stop(stream);
63         set_state(STOPPED);
64 }
65
66 void XineStream::set_state(State s)
67 {
68         if(s==state)
69                 return;
70
71         state = s;
72         signal_state_changed.emit(state);
73 }
74
75 void XineStream::tick()
76 {
77         while(xine_event_t *event = xine_event_get(queue))
78         {
79                 handle_event(*event);
80                 xine_event_free(event);
81         }
82
83         check_info();
84 }
85
86 void XineStream::check_info()
87 {
88         const char *xt = xine_get_meta_info(stream, XINE_META_INFO_TITLE);
89         if(xt)
90         {
91                 if(title.compare(xt))
92                 {
93                         title = xt;
94                         signal_title_changed.emit(title);
95                 }
96         }
97         else if(!title.empty())
98         {
99                 title.clear();
100                 signal_title_changed.emit(title);
101         }
102
103         int dur_msec, pos_msec;
104         xine_get_pos_length(stream, 0, &pos_msec, &dur_msec);
105         Time::TimeDelta dur = dur_msec*Time::msec;
106         Time::TimeDelta pos = pos_msec*Time::msec;
107         if(dur!=duration)
108         {
109                 duration = dur;
110                 signal_duration_changed.emit(duration);
111         }
112         if(pos!=position)
113         {
114                 position = pos;
115                 signal_position_changed.emit(position);
116         }
117 }
118
119 void XineStream::handle_event(const xine_event_t &event)
120 {
121         switch(event.type)
122         {
123         case XINE_EVENT_UI_PLAYBACK_FINISHED:
124                 set_state(STOPPED);
125                 break;
126         case XINE_EVENT_PROGRESS:
127                 {
128                         xine_progress_data_t *data = reinterpret_cast<xine_progress_data_t *>(event.data);
129                         IO::print("%s [%d%%]\n", data->description, data->percent);
130                 }
131                 break;
132         }
133 }
134
135
136 void operator<<(LexicalConverter &conv, XineStream::State state)
137 {
138         switch(state)
139         {
140         case XineStream::STOPPED: conv.result("STOPPED"); return;
141         case XineStream::PAUSED: conv.result("PAUSED"); return;
142         case XineStream::PLAYING: conv.result("PLAYING"); return;
143         default: conv.result(format("State(%d)", static_cast<int>(state))); return;
144         }
145 }
146
147 void operator>>(const LexicalConverter &conv, XineStream::State &state)
148 {
149         const string &str = conv.get();
150         if(str=="STOPPED")
151                 state = XineStream::STOPPED;
152         else if(str=="PAUSED")
153                 state = XineStream::PAUSED;
154         else if(str=="PLAYING")
155                 state = XineStream::PLAYING;
156         else
157                 throw lexical_error(format("Conversion of '%s' to XineStream::State", str));
158 }