2009-08-26 Chris Toshok <toshok@ximian.com>
[moon.git] / src / playlist.h
blob1e156822fe91f3e1a3236a558246f60dc44fd30d
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 class PlaylistRoot : public Playlist {
269 private:
270 MediaElement *element;
271 MediaPlayer *mplayer;
273 guint64 seek_pts; // the pts to seek to when SeekCallback is called.
275 static void EmitBufferUnderflowEvent (EventObject *obj);
276 static void StopCallback (EventObject *obj);
277 static void PlayCallback (EventObject *obj);
278 static void PauseCallback (EventObject *obj);
279 static void OpenCallback (EventObject *obj);
280 static void SeekCallback (EventObject *obj);
282 protected:
283 virtual ~PlaylistRoot () {}
285 virtual void Stop ();
287 public:
288 PlaylistRoot (MediaElement *element);
289 virtual void Dispose (); // not thread-safe
290 virtual MediaElement *GetElement ();
292 void StopAsync ();
293 void OpenAsync ();
294 void PlayAsync ();
295 void PauseAsync ();
296 void SeekAsync (guint64 pts);
298 virtual bool IsSingleFile ();
300 Media *GetCurrentMedia ();
301 MediaPlayer *GetMediaPlayer ();
303 // Events
304 const static int OpeningEvent;
305 const static int OpenCompletedEvent;
306 const static int SeekingEvent;
307 const static int SeekCompletedEvent;
308 const static int CurrentStateChangedEvent;
309 const static int PlayEvent;
310 const static int PauseEvent;
311 const static int StopEvent;
312 const static int MediaErrorEvent;
313 const static int MediaEndedEvent;
314 const static int DownloadProgressChangedEvent;
315 const static int BufferingProgressChangedEvent;
316 const static int BufferUnderflowEvent;
317 const static int EntryChangedEvent;
319 // Event handlers
320 EVENTHANDLER (PlaylistRoot, MediaEnded, MediaPlayer, EventArgs);
321 EVENTHANDLER (PlaylistRoot, BufferUnderflow, MediaPlayer, EventArgs);
323 #if DEBUG
324 void Dump ();
325 #endif
328 class PlaylistParserInternal {
329 public:
330 XML_Parser parser;
331 gint32 bytes_read;
332 bool reparse;
334 PlaylistParserInternal ();
335 ~PlaylistParserInternal ();
338 class PlaylistParser {
339 private:
340 PlaylistRoot *root;
341 Playlist *playlist;
342 PlaylistEntry *current_entry;
343 PlaylistParserInternal *internal;
344 IMediaSource *source;
345 bool was_playlist;
346 ErrorEventArgs *error_args;
347 // For <ASX* files, this is 3 (or 0 if no version attribute was found).
348 // for [Ref* files, this is 2.
349 // The presence of a version does not guarantee that the playlist
350 // was parsed correctly.
351 int playlist_version;
353 enum XmlType {
354 XML_TYPE_NONE,
355 XML_TYPE_ASX3,
359 char *current_text;
361 class KindNode : public List::Node {
362 public:
363 PlaylistKind::Kind kind;
365 KindNode (PlaylistKind::Kind kind)
367 this->kind = kind;
371 static PlaylistKind playlist_kinds [];
372 List *kind_stack;
374 void OnASXStartElement (const char *name, const char **attrs);
375 void OnASXEndElement (const char *name);
376 void OnASXText (const char *text, int len);
378 static void on_asx_start_element (gpointer user_data, const char *name, const char **attrs);
379 static void on_asx_end_element (gpointer user_data, const char *name);
380 static void on_asx_text (gpointer user_data, const char *text, int len);
382 void EndEntry ();
383 PlaylistEntry *GetCurrentEntry ();
385 PlaylistEntry *GetCurrentContent ();
387 void PushCurrentKind (PlaylistKind::Kind kind);
388 void PopCurrentKind ();
389 PlaylistKind::Kind GetCurrentKind ();
390 PlaylistKind::Kind GetParentKind ();
391 bool AssertParentKind (int kind);
393 void Setup (XmlType type);
394 void Cleanup ();
395 void SetSource (IMediaSource *source);
396 bool TryFixError (gint8 *buffer, int bytes_read);
397 public:
399 PlaylistParser (PlaylistRoot *root, IMediaSource *source);
400 ~PlaylistParser ();
402 Playlist *GetPlaylist () { return playlist; }
404 MediaResult Parse ();
405 bool ParseASX2 ();
406 bool ParseASX3 ();
407 static bool Is (IMediaSource *source, const char *header);
408 static bool IsASX2 (IMediaSource *source);
409 static bool IsASX3 (IMediaSource *source);
411 // This value determines if the data we parsed
412 // actually was a playlist. It may be true even
413 // if the playlist wasn't parsed correctly.
414 bool WasPlaylist () { return was_playlist; }
415 void ParsingError (ErrorEventArgs *args = NULL);
417 ErrorEventArgs *GetErrorEventArgs () { return error_args; }
419 static PlaylistKind::Kind StringToKind (const char *str);
420 static const char *KindToString (PlaylistKind::Kind kind);
423 #endif /* __PLAYLIST_H__ */