Author: jbevain
Date: 2007-09-05 05:30:15 -0400 (Wed, 05 Sep 2007)
New Revision: 85340

Modified:
   trunk/moon/src/ChangeLog
   trunk/moon/src/playlist.cpp
   trunk/moon/src/playlist.h
Log:
2007-09-05  Jb Evain  <[EMAIL PROTECTED]>

        * playlist.cpp, playlist.h: work on playlist parsing.


Modified: trunk/moon/src/ChangeLog
===================================================================
--- trunk/moon/src/ChangeLog    2007-09-05 09:28:43 UTC (rev 85339)
+++ trunk/moon/src/ChangeLog    2007-09-05 09:30:15 UTC (rev 85340)
@@ -1,5 +1,9 @@
 2007-09-05  Jb Evain  <[EMAIL PROTECTED]>
 
+       * playlist.cpp, playlist.h: work on playlist parsing.
+
+2007-09-05  Jb Evain  <[EMAIL PROTECTED]>
+
        * xaml.h: export timespan_from_str.
 
 2007-09-05  Jb Evain  <[EMAIL PROTECTED]>

Modified: trunk/moon/src/playlist.cpp
===================================================================
--- trunk/moon/src/playlist.cpp 2007-09-05 09:28:43 UTC (rev 85339)
+++ trunk/moon/src/playlist.cpp 2007-09-05 09:30:15 UTC (rev 85340)
@@ -11,14 +11,17 @@
 #include <glib.h>
 #include <gtk/gtk.h>
 #include <expat.h>
+#include <string.h>
 
 #include "playlist.h"
 #include "downloader.h"
+#include "xaml.h"
 
 // PlaylistContent
 
 PlaylistContent::PlaylistContent ()
 {
+       base = NULL;
        title = NULL;
        author = NULL;
        abstract = NULL;
@@ -26,12 +29,25 @@
 
 PlaylistContent::~PlaylistContent ()
 {
+       g_free (base);
        g_free (title);
        g_free (author);
        g_free (abstract);
 }
 
 const char *
+PlaylistContent::GetBase ()
+{
+       return base;
+}
+
+void
+PlaylistContent::SetBase (char *base)
+{
+       this->base = base;
+}
+
+const char *
 PlaylistContent::GetTitle ()
 {
        return title;
@@ -116,13 +132,16 @@
        this->start_time = start_time;
 }
 
-bool
-playlist_entry_free (List::Node *node, gpointer data)
+gint64
+PlaylistEntry::GetDuration ()
 {
-       PlaylistEntry *entry = dynamic_cast<PlaylistEntry *> (node);
-       delete entry;
+       return duration;
+}
 
-       return true;
+void
+PlaylistEntry::SetDuration (gint64 duration)
+{
+       this->duration = duration;
 }
 
 // Playlist
@@ -130,14 +149,13 @@
 Playlist::Playlist (MediaElement *element, char *source_name)
        : MediaSource (element, source_name)
 {
-       items = new List ();
+       entries = new List ();
 }
 
 Playlist::~Playlist ()
 {
-       items->ForEach (playlist_entry_free, NULL);
-
-       delete items;
+       entries->Clear (true);
+       delete entries;
 }
 
 bool
@@ -162,6 +180,12 @@
        return false;
 }
 
+void
+Playlist::AddEntry (PlaylistEntry *entry)
+{
+       entries->Append (entry);
+}
+
 bool
 Playlist::Parse ()
 {
@@ -173,7 +197,8 @@
                return false;
 
        PlaylistParser *parser = new PlaylistParser (this);
-       parser->Parse (text, len);
+       if (!parser->Parse (text, len))
+               error = true;
 
        delete parser;
        g_free (text);
@@ -186,43 +211,178 @@
 PlaylistParser::PlaylistParser (Playlist *playlist)
 {
        this->playlist = playlist;
+       entry = NULL;
 
        parser = XML_ParserCreate (NULL);
+       kind_stack = new List ();
+       PushCurrentKind (Root);
 
+       XML_SetUserData (parser, this);
        XML_SetElementHandler (parser, on_start_element, on_end_element);
        XML_SetCharacterDataHandler (parser, on_text);
 }
 
 PlaylistParser::~PlaylistParser ()
 {
+       kind_stack->Clear (true);
+       delete kind_stack;
        XML_ParserFree (parser);
-
-       g_free (base);
 }
 
 void
 PlaylistParser::on_start_element (gpointer user_data, const char *name, const 
char **attrs)
 {
-//     PlaylistParser *parser = reinterpret_cast<PlaylistParser *> (user_data);
+       PlaylistParser *parser = reinterpret_cast<PlaylistParser *> (user_data);
+       PlaylistNodeKind kind;
+       //printf ("on_start_element, name: %s\n", name);
+       if (!strcmp (name, "Abstract")) {
+               kind = Abstract;
+       } else if (!strcmp (name, "ASX")) {
+               kind = Asx;
+       } else if (!strcmp (name, "AUTHOR")) {
+               kind = Author;
+       } else if (!strcmp (name, "BANNER")) {
+               kind = Banner;
+       } else if (!strcmp (name, "BASE")) {
+               kind = Base;
+       } else if (!strcmp (name, "COPYRIGHT")) {
+               kind = Copyright;
+       } else if (!strcmp (name, "DURATION")) {
+               kind = Duration;
+       } else if (!strcmp (name, "ENTRY")) {
+               kind = Entry;
+       } else if (!strcmp (name, "ENTRYREF")) {
+               kind = EntryRef;
+       } else if (!strcmp (name, "LOGURL")) {
+               kind = LogUrl;
+       } else if (!strcmp (name, "MOREINFO")) {
+               kind = MoreInfo;
+       } else if (!strcmp (name, "STARTTIME")) {
+               kind = StartTime;
+       } else if (!strcmp (name, "REF")) {
+               kind = Ref;
+               parser->GetCurrentEntry ()->SetSource (NULL); // get source 
from href attribute
+       } else if (!strcmp (name, "TITLE")) {
+               kind = Title;
+       } else {
+               kind = Unknown;
+       }
+
+       parser->PushCurrentKind (kind);
 }
 
 void
 PlaylistParser::on_end_element (gpointer user_data, const char *name)
 {
-//     PlaylistParser *parser = reinterpret_cast<PlaylistParser *> (user_data);
+       PlaylistParser *parser = reinterpret_cast<PlaylistParser *> (user_data);
+       parser->PopCurrentKind ();
 }
 
 void
-PlaylistParser::on_text (gpointer user_data, const char *text, int len)
+PlaylistParser::on_text (gpointer user_data, const char *data, int len)
 {
-//     PlaylistParser *parser = reinterpret_cast<PlaylistParser *> (user_data);
+       PlaylistParser *parser = reinterpret_cast<PlaylistParser *> (user_data);
+       //printf ("on_text, text: %s\n", g_strndup (data, len));
+       switch (parser->GetCurrentKind ()) {
+       case Abstract:
+               parser->AssertParentKind (Asx | Entry);
+               parser->GetCurrentContent ()->SetAbstract (g_strndup (data, 
len));
+               break;
+       case Author:
+               parser->AssertParentKind (Asx | Entry);
+               parser->GetCurrentContent ()->SetAuthor (g_strndup (data, len));
+               break;
+       case Base:
+               parser->AssertParentKind (Asx | Entry);
+               parser->GetCurrentContent ()->SetBase (g_strndup (data, len));
+               break;
+       case Copyright:
+               parser->AssertParentKind (Asx | Entry);
+               parser->GetCurrentContent ()->SetCopyright (g_strndup (data, 
len));
+               break;
+       case Duration:
+               parser->AssertParentKind (Entry);
+               parser->GetCurrentEntry ()->SetDuration (timespan_from_str 
(g_strndup (data, len)));
+               break;
+       case Entry:
+               parser->AssertParentKind (Asx);
+               parser->AddEntry ();
+               break;
+       case StartTime:
+               parser->AssertParentKind (Entry);
+               parser->GetCurrentEntry ()->SetStartTime (timespan_from_str 
(g_strndup (data, len)));
+               break;
+       case Title:
+               parser->AssertParentKind (Asx | Entry);
+               parser->GetCurrentContent ()->SetTitle (g_strndup (data, len));
+               break;
+       default:
+               break;
+       }
 }
 
-void
+bool
 PlaylistParser::Parse (const char *text, int len)
 {
        if (XML_Parse (parser, text, len, TRUE))
-               return;
+               return true;
 
        g_warning ("parsing error: %s\n", XML_ErrorString (XML_GetErrorCode 
(parser)));
+       return false;
 }
+
+PlaylistContent *
+PlaylistParser::GetCurrentContent ()
+{
+       if (entry != NULL)
+               return entry;
+
+       return playlist;
+}
+
+PlaylistEntry *
+PlaylistParser::GetCurrentEntry ()
+{
+       return entry;
+}
+
+void
+PlaylistParser::AddEntry ()
+{
+       PlaylistEntry *entry = new PlaylistEntry ();
+       playlist->AddEntry (entry);
+       this->entry = entry;
+}
+
+void
+PlaylistParser::PushCurrentKind (PlaylistParser::PlaylistNodeKind kind)
+{
+       kind_stack->Append (new KindNode (kind));
+}
+
+void
+PlaylistParser::PopCurrentKind ()
+{
+       kind_stack->Remove (kind_stack->Last ());
+}
+
+PlaylistParser::PlaylistNodeKind
+PlaylistParser::GetCurrentKind ()
+{
+       KindNode *node = dynamic_cast<KindNode *> (kind_stack->Last ());
+       return node->kind;
+}
+
+PlaylistParser::PlaylistNodeKind
+PlaylistParser::GetParentKind ()
+{
+       KindNode *node = dynamic_cast<KindNode *> (kind_stack->Last ()->prev);
+       return node->kind;
+}
+
+void
+PlaylistParser::AssertParentKind (int kind)
+{
+       printf ("AssertParentKind, current: %d kind %d\n", GetParentKind (), 
kind);
+       g_assert (GetParentKind () & kind);
+}

Modified: trunk/moon/src/playlist.h
===================================================================
--- trunk/moon/src/playlist.h   2007-09-05 09:28:43 UTC (rev 85339)
+++ trunk/moon/src/playlist.h   2007-09-05 09:30:15 UTC (rev 85340)
@@ -20,6 +20,7 @@
 
 class PlaylistContent {
 private:
+       char *base;
        char *title;
        char *author;
        char *abstract;
@@ -28,6 +29,9 @@
        PlaylistContent ();
        ~PlaylistContent ();
 
+       const char *GetBase ();
+       void SetBase (char *base);
+
        const char *GetTitle ();
        void SetTitle (char *title);
 
@@ -45,6 +49,7 @@
 private:
        char *source;
        gint64 start_time;
+       gint64 duration;
 public:
        PlaylistEntry ();
        ~PlaylistEntry ();
@@ -54,35 +59,84 @@
 
        gint64 GetStartTime ();
        void SetStartTime (gint64 start_time);
+
+       gint64 GetDuration ();
+       void SetDuration (gint64 duration);
 };
 
 class Playlist : public MediaSource, public PlaylistContent {
-       List *items; // list of PlaylistEntries
+private:
+       List *entries;
+
+       bool Parse ();
 public:
        Playlist (MediaElement *element, char *source_name);
        virtual ~Playlist ();
 
        virtual bool Open ();
 
+       void AddEntry (PlaylistEntry *entry);
+
        static bool IsPlaylistFile (const char *file_name);
-private:
-       bool Parse ();
 };
 
 class PlaylistParser {
 private:
        Playlist *playlist;
+       PlaylistEntry *entry;
        XML_Parser parser;
-       char *base;
 
+       enum PlaylistNodeKind {
+               Unknown         = 0,
+               Root            = 1 << 0,
+               Abstract        = 1 << 1,
+               Asx                     = 1 << 2,
+               Author          = 1 << 3,
+               Banner          = 1 << 4,
+               Base            = 1 << 5,
+               Copyright       = 1 << 6,
+               Duration        = 1 << 7,
+               Entry           = 1 << 8,
+               EntryRef        = 1 << 9,
+               LogUrl          = 1 << 10,
+               MoreInfo        = 1 << 11,
+               Ref                     = 1 << 12,
+               StartTime       = 1 << 13,
+               Title           = 1 << 14,
+       };
+
+       class KindNode : public List::Node {
+       public:
+               PlaylistNodeKind kind;
+               
+               KindNode (PlaylistNodeKind kind)
+               {
+                       this->kind = kind;
+               }
+       };
+
+       List *kind_stack;
+
        static void on_start_element (gpointer user_data, const char *name, 
const char **attrs);
        static void on_end_element (gpointer user_data, const char *name);
        static void on_text (gpointer user_data, const char *text, int len);
+
+       void AddEntry ();
+       PlaylistEntry *GetCurrentEntry ();
+
+       PlaylistContent *GetCurrentContent ();
+
+       void PushCurrentKind (PlaylistNodeKind kind);
+       void PopCurrentKind ();
+       PlaylistNodeKind GetCurrentKind ();
+       PlaylistNodeKind GetParentKind ();
+       void AssertParentKind (int kind);
+
 public:
        PlaylistParser (Playlist *list);
        ~PlaylistParser ();
 
-       void Parse (const char *text, int len);
+       bool Parse (const char *text, int len);
 };
 
 G_END_DECLS

_______________________________________________
Mono-patches maillist  -  [email protected]
http://lists.ximian.com/mailman/listinfo/mono-patches

Reply via email to