2009-12-03 Jeffrey Stedfast <fejj@novell.com>
[moon.git] / src / playlist.h
blobbce6d302e187d7a5546754f904e2ece947ce0ea5
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * playlist.h:
5 * Contact:
6 * Moonlight List (moonlight-list@lists.ximian.com)
8 * Copyright 2007 Novell, Inc. (http://www.novell.com)
10 * See the LICENSE file included with the distribution for details.
13 #ifndef __PLAYLIST_H__
14 #define __PLAYLIST_H__
16 class PlaylistEntry;
17 class Playlist;
18 class PlaylistRoot;
20 #include <expat.h>
22 #include "value.h"
23 #include "error.h"
24 #include "dependencyobject.h"
25 #include "uri.h"
26 #include "pipeline.h"
28 class PlaylistKind {
29 public:
30 enum Kind {
31 /* ASX3 playlists */
32 Unknown = 0,
33 Root = 1 << 0,
34 Abstract = 1 << 1,
35 Asx = 1 << 2,
36 Author = 1 << 3,
37 Banner = 1 << 4,
38 Base = 1 << 5,
39 Copyright = 1 << 6,
40 Duration = 1 << 7,
41 Entry = 1 << 8,
42 EntryRef = 1 << 9,
43 LogUrl = 1 << 10,
44 MoreInfo = 1 << 11,
45 Ref = 1 << 12,
46 StartTime = 1 << 13,
47 Title = 1 << 14,
48 StartMarker = 1 << 15,
49 Repeat = 1 << 16,
50 EndMarker = 1 << 17,
51 Param = 1 << 18,
52 Event = 1 << 19,
55 public:
56 const char *str;
57 Kind kind;
58 PlaylistKind (const char *str, Kind kind)
60 this->str = str;
61 this->kind = kind;
65 class PlaylistNode : public List::Node {
66 private:
67 PlaylistEntry *entry;
69 public:
70 PlaylistNode (PlaylistEntry *entry);
71 virtual ~PlaylistNode ();
72 PlaylistEntry *GetEntry () { return entry; }
75 class PlaylistEntry : public EventObject {
76 private:
77 // ASX Properties
78 Uri *base;
79 char *title;
80 char *author;
81 char *abstract;
82 char *copyright;
83 Uri *source_name;
84 char *info_target;
85 char *info_url;
86 bool client_skip;
87 TimeSpan start_time;
88 Duration *duration;
89 GHashTable *params;
91 PlaylistKind::Kind set_values;
93 // Non ASX properties
94 char *full_source_name;
95 bool is_live;
96 bool play_when_available;
97 Playlist *parent;
98 Media *media;
99 bool opened; // if OpenCompleted event has been received
101 void Init (Playlist *parent);
102 void OpenMediaPlayer ();
104 protected:
105 PlaylistEntry (Type::Kind kind);
106 PlaylistEntry (Type::Kind kind, Playlist *parent);
107 virtual ~PlaylistEntry () {}
109 public:
110 PlaylistEntry (Playlist *parent);
112 void Initialize (Media *media);
113 void InitializeWithUri (const char *uri);
114 void InitializeWithDownloader (Downloader *dl, const char *PartName);
115 void InitializeWithDemuxer (IMediaDemuxer *demuxer);
116 void InitializeWithStream (ManagedStreamCallbacks *callbacks);
117 void InitializeWithSource (IMediaSource *source);
119 Media * CreateMedia ();
121 virtual void Dispose ();
123 // ASX properties
125 Uri *GetBase ();
126 Uri *GetBaseInherited ();
127 void SetBase (Uri *base);
129 const char *GetTitle ();
130 void SetTitle (const char *title);
132 const char *GetAuthor ();
133 void SetAuthor (const char *author);
135 const char *GetAbstract ();
136 void SetAbstract (const char *abstract);
138 const char *GetCopyright ();
139 void SetCopyright (const char *copyright);
141 Uri *GetSourceName ();
142 void SetSourceName (Uri *source_name);
144 TimeSpan GetStartTime ();
145 void SetStartTime (TimeSpan start_time);
147 Duration *GetDuration ();
148 Duration *GetInheritedDuration ();
149 void SetDuration (Duration *duration);
150 bool HasDuration () { return (set_values & PlaylistKind::Duration); }
151 bool HasInheritedDuration ();
153 const char *GetInfoTarget ();
154 void SetInfoTarget (const char *info_target);
156 const char *GetInfoURL ();
157 void SetInfoURL (const char *info_url);
159 bool GetClientSkip ();
160 void SetClientSkip (bool value);
162 void AddParams (const char *name, const char *value);
164 // non-ASX properties
166 Playlist *GetParent () { return parent; }
167 void SetParent (Playlist *value) { parent = value; }
168 PlaylistRoot *GetRoot ();
170 Media *GetMedia ();
171 void ClearMedia ();
173 virtual MediaElement *GetElement ();
174 MediaPlayer *GetMediaPlayer ();
176 const char *GetFullSourceName ();
177 virtual bool IsPlaylist () { return false; }
179 bool GetIsLive () { return is_live; }
180 void SetIsLive (bool value) { is_live = value; }
182 // Playback methods
184 virtual void Play ();
185 virtual void Pause ();
186 virtual void Stop ();
187 virtual void Seek (guint64 pts);
188 virtual void Open ();
189 virtual void PopulateMediaAttributes ();
191 virtual PlaylistEntry *GetCurrentPlaylistEntry () { return this; }
192 virtual bool IsSingleFile ();
194 void Print (int depth);
196 EVENTHANDLER (PlaylistEntry, Opening, Media, EventArgs);
197 EVENTHANDLER (PlaylistEntry, OpenCompleted, Media, EventArgs);
198 EVENTHANDLER (PlaylistEntry, Seeking, Media, EventArgs);
199 EVENTHANDLER (PlaylistEntry, SeekCompleted, Media, EventArgs);
200 EVENTHANDLER (PlaylistEntry, CurrentStateChanged, Media, EventArgs);
201 EVENTHANDLER (PlaylistEntry, MediaError, Media, ErrorEventArgs);
202 EVENTHANDLER (PlaylistEntry, DownloadProgressChanged, Media, EventArgs);
203 EVENTHANDLER (PlaylistEntry, BufferingProgressChanged, Media, EventArgs);
205 #if DEBUG
206 virtual void DumpInternal (int tabs);
207 #endif
210 class Playlist : public PlaylistEntry {
211 private:
212 List *entries;
213 PlaylistNode *current_node;
214 IMediaSource *source;
215 bool is_single_file;
216 bool waiting;
217 bool opened;
219 void Init ();
221 bool HasMediaSource ();
222 void OnMediaDownloaded ();
224 void MergeWith (PlaylistEntry *entry);
225 bool PlayNext (); // returns false if nothing more to play
227 protected:
228 Playlist (Type::Kind kind);
229 virtual ~Playlist () {}
232 public:
233 Playlist (Playlist *parent, IMediaSource *source);
235 virtual void Dispose ();
237 virtual void Play ();
238 virtual void Pause ();
239 virtual void Stop ();
240 virtual void Seek (guint64 to);
241 virtual void Open ();
242 virtual void PopulateMediaAttributes ();
244 virtual void AddEntry (PlaylistEntry *entry);
246 PlaylistEntry *GetCurrentEntry () { return current_node ? current_node->GetEntry () : NULL; }
247 virtual PlaylistEntry *GetCurrentPlaylistEntry ();
248 bool ReplaceCurrentEntry (Playlist *entry);
250 virtual bool IsPlaylist () { return true; }
251 virtual bool IsSingleFile () { return is_single_file; }
252 void SetWaiting (bool value) { waiting = value; }
253 bool GetWaiting (void) { return waiting; }
255 bool IsCurrentEntryLastEntry ();
256 void OnEntryEnded ();
257 void OnEntryFailed (ErrorEventArgs *args);
259 void Print (int depth);
261 gint32 GetCount () { return entries ? entries->Length () : 0; }
263 #if DEBUG
264 virtual void DumpInternal (int tabs);
265 #endif
268 /* @Namespace=None,ManagedEvents=Manual */
269 class PlaylistRoot : public Playlist {
270 private:
271 class PtsNode : public List::Node {
272 public:
273 guint64 pts;
274 PtsNode (guint64 pts)
276 this->pts = pts;
279 MediaElement *element;
280 MediaPlayer *mplayer;
282 List seeks; // the pts to seek to when SeekCallback is called. Main thread only.
284 static void EmitBufferUnderflowEvent (EventObject *obj);
285 static void StopCallback (EventObject *obj);
286 static void PlayCallback (EventObject *obj);
287 static void PauseCallback (EventObject *obj);
288 static void OpenCallback (EventObject *obj);
289 static void SeekCallback (EventObject *obj);
291 protected:
292 virtual ~PlaylistRoot () {}
294 virtual void Stop ();
296 public:
297 PlaylistRoot (MediaElement *element);
298 virtual void Dispose (); // not thread-safe
299 virtual MediaElement *GetElement ();
301 void StopAsync ();
302 void OpenAsync ();
303 void PlayAsync ();
304 void PauseAsync ();
305 void SeekAsync (guint64 pts);
307 virtual bool IsSingleFile ();
309 Media *GetCurrentMedia ();
310 MediaPlayer *GetMediaPlayer ();
312 // Events
313 const static int OpeningEvent;
314 const static int OpenCompletedEvent;
315 const static int SeekingEvent;
316 const static int SeekCompletedEvent;
317 const static int CurrentStateChangedEvent;
318 const static int PlayEvent;
319 const static int PauseEvent;
320 const static int StopEvent;
321 const static int MediaErrorEvent;
322 const static int MediaEndedEvent;
323 const static int DownloadProgressChangedEvent;
324 const static int BufferingProgressChangedEvent;
325 const static int BufferUnderflowEvent;
326 const static int EntryChangedEvent;
328 // Event handlers
329 EVENTHANDLER (PlaylistRoot, MediaEnded, MediaPlayer, EventArgs);
330 EVENTHANDLER (PlaylistRoot, BufferUnderflow, MediaPlayer, EventArgs);
332 #if DEBUG
333 void Dump ();
334 #endif
337 class PlaylistParserInternal {
338 public:
339 XML_Parser parser;
340 gint32 bytes_read;
341 bool reparse;
343 PlaylistParserInternal ();
344 ~PlaylistParserInternal ();
347 class PlaylistParser {
348 private:
349 PlaylistRoot *root;
350 Playlist *playlist;
351 PlaylistEntry *current_entry;
352 PlaylistParserInternal *internal;
353 IMediaSource *source;
354 bool was_playlist;
355 ErrorEventArgs *error_args;
356 // For <ASX* files, this is 3 (or 0 if no version attribute was found).
357 // for [Ref* files, this is 2.
358 // The presence of a version does not guarantee that the playlist
359 // was parsed correctly.
360 int playlist_version;
362 enum XmlType {
363 XML_TYPE_NONE,
364 XML_TYPE_ASX3,
368 char *current_text;
370 class KindNode : public List::Node {
371 public:
372 PlaylistKind::Kind kind;
374 KindNode (PlaylistKind::Kind kind)
376 this->kind = kind;
380 static PlaylistKind playlist_kinds [];
381 List *kind_stack;
383 void OnASXStartElement (const char *name, const char **attrs);
384 void OnASXEndElement (const char *name);
385 void OnASXText (const char *text, int len);
387 static void on_asx_start_element (gpointer user_data, const char *name, const char **attrs);
388 static void on_asx_end_element (gpointer user_data, const char *name);
389 static void on_asx_text (gpointer user_data, const char *text, int len);
391 void EndEntry ();
392 PlaylistEntry *GetCurrentEntry ();
394 PlaylistEntry *GetCurrentContent ();
396 void PushCurrentKind (PlaylistKind::Kind kind);
397 void PopCurrentKind ();
398 PlaylistKind::Kind GetCurrentKind ();
399 PlaylistKind::Kind GetParentKind ();
400 bool AssertParentKind (int kind);
402 void Setup (XmlType type);
403 void Cleanup ();
404 void SetSource (IMediaSource *source);
405 bool TryFixError (gint8 *buffer, int bytes_read, int total_bytes_read);
406 public:
408 PlaylistParser (PlaylistRoot *root, IMediaSource *source);
409 ~PlaylistParser ();
411 Playlist *GetPlaylist () { return playlist; }
413 MediaResult Parse ();
414 bool ParseASX2 ();
415 bool ParseASX3 ();
416 static bool Is (IMediaSource *source, const char *header);
417 static bool IsASX2 (IMediaSource *source);
418 static bool IsASX3 (IMediaSource *source);
420 // This value determines if the data we parsed
421 // actually was a playlist. It may be true even
422 // if the playlist wasn't parsed correctly.
423 bool WasPlaylist () { return was_playlist; }
424 void ParsingError (ErrorEventArgs *args = NULL);
426 ErrorEventArgs *GetErrorEventArgs () { return error_args; }
428 static PlaylistKind::Kind StringToKind (const char *str);
429 static const char *KindToString (PlaylistKind::Kind kind);
432 #endif /* __PLAYLIST_H__ */