]> git.sesse.net Git - vlc/blob - bindings/phonon/vlc/mediaobject.cpp
Add some locking.
[vlc] / bindings / phonon / vlc / mediaobject.cpp
1 /*****************************************************************************
2  * VLC backend for the Phonon library                                        *
3  * Copyright (C) 2007-2008 Tanguy Krotoff <tkrotoff@gmail.com>               *
4  * Copyright (C) 2008 Lukas Durfina <lukas.durfina@gmail.com>                *
5  * Copyright (C) 2009 Fathi Boudra <fabo@kde.org>                            *
6  *                                                                           *
7  * This program is free software; you can redistribute it and/or             *
8  * modify it under the terms of the GNU Lesser General Public                *
9  * License as published by the Free Software Foundation; either              *
10  * version 3 of the License, or (at your option) any later version.          *
11  *                                                                           *
12  * This program is distributed in the hope that it will be useful,           *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of            *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU         *
15  * Lesser General Public License for more details.                           *
16  *                                                                           *
17  * You should have received a copy of the GNU Lesser General Public          *
18  * License along with this package; if not, write to the Free Software       *
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA *
20  *****************************************************************************/
21
22 #include "mediaobject.h"
23
24 #include "seekstack.h"
25
26 #include <QtCore/QUrl>
27 #include <QtCore/QMetaType>
28 #include <QtCore/QTimer>
29
30 //Time in milliseconds before sending aboutToFinish() signal
31 //2 seconds
32 static const int ABOUT_TO_FINISH_TIME = 2000;
33
34 namespace Phonon
35 {
36 namespace VLC {
37
38 MediaObject::MediaObject(QObject *p_parent)
39         : QObject(p_parent)
40 {
41     currentState = Phonon::LoadingState;
42     i_video_widget_id = 0;
43     b_prefinish_mark_reached_emitted = false;
44     b_about_to_finish_emitted = false;
45     i_transition_time = 0;
46
47     // By default, no tick() signal
48     // FIXME: Not implemented yet
49     i_tick_interval = 0;
50
51     qRegisterMetaType<QMultiMap<QString, QString> >("QMultiMap<QString, QString>");
52
53     connect(this, SIGNAL(stateChanged(Phonon::State)),
54             SLOT(stateChangedInternal(Phonon::State)));
55
56     connect(this, SIGNAL(tickInternal(qint64)),
57             SLOT(tickInternalSlot(qint64)));
58 }
59
60 MediaObject::~MediaObject()
61 {
62 }
63
64 void MediaObject::setVideoWidgetId(WId i_widget_id)
65 {
66     i_video_widget_id = i_widget_id;
67 }
68
69 void MediaObject::play()
70 {
71     qDebug() << __FUNCTION__;
72
73     if (currentState == Phonon::PausedState) {
74         resume();
75     } else {
76         // Play the file
77         playInternal();
78     }
79 }
80
81 void MediaObject::seek(qint64 milliseconds)
82 {
83     static SeekStack *p_stack = new SeekStack(this);
84
85     p_stack->pushSeek(milliseconds);
86
87     qint64 currentTime = this->currentTime();
88     qint64 totalTime = this->totalTime();
89
90     if (currentTime < totalTime - i_prefinish_mark) {
91         b_prefinish_mark_reached_emitted = false;
92     }
93     if (currentTime < totalTime - ABOUT_TO_FINISH_TIME) {
94         b_about_to_finish_emitted = false;
95     }
96 }
97
98 void MediaObject::tickInternalSlot(qint64 currentTime)
99 {
100     qint64 totalTime = this->totalTime();
101
102     if (i_tick_interval > 0) {
103         // If _tickInternal == 0 means tick() signal is disabled
104         // Default is _tickInternal = 0
105         emit tick(currentTime);
106     }
107
108     if (currentState == Phonon::PlayingState) {
109         if (currentTime >= totalTime - i_prefinish_mark) {
110             if (!b_prefinish_mark_reached_emitted) {
111                 b_prefinish_mark_reached_emitted = true;
112                 emit prefinishMarkReached(totalTime - currentTime);
113             }
114         }
115         if (currentTime >= totalTime - ABOUT_TO_FINISH_TIME) {
116             if (!b_about_to_finish_emitted) {
117                 // Track is about to finish
118                 b_about_to_finish_emitted = true;
119                 emit aboutToFinish();
120             }
121         }
122     }
123 }
124
125 void MediaObject::loadMedia(const QString & filename)
126 {
127     // Default MediaObject state is Phonon::LoadingState
128     currentState = Phonon::LoadingState;
129
130     // Load the media
131     loadMediaInternal(filename);
132 }
133
134 void MediaObject::resume()
135 {
136     pause();
137 }
138
139 qint32 MediaObject::tickInterval() const
140 {
141     return i_tick_interval;
142 }
143
144 void MediaObject::setTickInterval(qint32 tickInterval)
145 {
146     i_tick_interval = tickInterval;
147 //    if (_tickInterval <= 0) {
148 //        _tickTimer->setInterval(50);
149 //    } else {
150 //        _tickTimer->setInterval(_tickInterval);
151 //    }
152 }
153
154 qint64 MediaObject::currentTime() const
155 {
156     qint64 time = -1;
157     Phonon::State st = state();
158
159     switch (st) {
160     case Phonon::PausedState:
161         time = currentTimeInternal();
162         break;
163     case Phonon::BufferingState:
164         time = currentTimeInternal();
165         break;
166     case Phonon::PlayingState:
167         time = currentTimeInternal();
168         break;
169     case Phonon::StoppedState:
170         time = 0;
171         break;
172     case Phonon::LoadingState:
173         time = 0;
174         break;
175     case Phonon::ErrorState:
176         time = -1;
177         break;
178     default:
179         qCritical() << __FUNCTION__ << "Error: unsupported Phonon::State:" << st;
180     }
181
182     return time;
183 }
184
185 Phonon::State MediaObject::state() const
186 {
187     return currentState;
188 }
189
190 Phonon::ErrorType MediaObject::errorType() const
191 {
192     return Phonon::NormalError;
193 }
194
195 MediaSource MediaObject::source() const
196 {
197     return mediaSource;
198 }
199
200 void MediaObject::setSource(const MediaSource & source)
201 {
202     qDebug() << __FUNCTION__;
203
204     mediaSource = source;
205
206     switch (source.type()) {
207     case MediaSource::Invalid:
208         break;
209     case MediaSource::LocalFile:
210         loadMedia(mediaSource.fileName());
211         break;
212     case MediaSource::Url:
213         loadMedia(mediaSource.url().toString());
214         break;
215     case MediaSource::Disc:
216         switch (source.discType()) {
217         case Phonon::NoDisc:
218             qCritical() << __FUNCTION__
219             << "Error: the MediaSource::Disc doesn't specify which one (Phonon::NoDisc)";
220             return;
221         case Phonon::Cd:
222             loadMedia(mediaSource.deviceName());
223             break;
224         case Phonon::Dvd:
225             loadMedia("dvd://" + mediaSource.deviceName());
226             break;
227         case Phonon::Vcd:
228             loadMedia(mediaSource.deviceName());
229             break;
230         default:
231             qCritical() << __FUNCTION__ << "Error: unsupported MediaSource::Disc:" << source.discType();
232             break;
233         }
234         break;
235     case MediaSource::Stream:
236         break;
237     default:
238         qCritical() << __FUNCTION__
239         << "Error: unsupported MediaSource:"
240         << source.type();
241         break;
242     }
243
244     emit currentSourceChanged(mediaSource);
245 }
246
247 void MediaObject::setNextSource(const MediaSource & source)
248 {
249     setSource(source);
250 }
251
252 qint32 MediaObject::prefinishMark() const
253 {
254     return i_prefinish_mark;
255 }
256
257 void MediaObject::setPrefinishMark(qint32 msecToEnd)
258 {
259     i_prefinish_mark = msecToEnd;
260     if (currentTime() < totalTime() - i_prefinish_mark) {
261         // Not about to finish
262         b_prefinish_mark_reached_emitted = false;
263     }
264 }
265
266 qint32 MediaObject::transitionTime() const
267 {
268     return i_transition_time;
269 }
270
271 void MediaObject::setTransitionTime(qint32 time)
272 {
273     i_transition_time = time;
274 }
275
276 void MediaObject::stateChangedInternal(Phonon::State newState)
277 {
278     qDebug() << __FUNCTION__ << "newState:" << newState
279     << "previousState:" << currentState ;
280
281     if (newState == currentState) {
282         // State not changed
283         return;
284     }
285
286     // State changed
287     Phonon::State previousState = currentState;
288     currentState = newState;
289     emit stateChanged(currentState, previousState);
290 }
291
292 }
293 } // Namespace Phonon::VLC