Revision: 1979
          http://gtkpod.svn.sourceforge.net/gtkpod/?rev=1979&view=rev
Author:   teuf
Date:     2008-05-25 02:07:13 -0700 (Sun, 25 May 2008)

Log Message:
-----------
Add jump table support (mhod53)

Modified Paths:
--------------
    libgpod/trunk/ChangeLog
    libgpod/trunk/src/itdb_itunesdb.c

Modified: libgpod/trunk/ChangeLog
===================================================================
--- libgpod/trunk/ChangeLog     2008-05-24 13:53:52 UTC (rev 1978)
+++ libgpod/trunk/ChangeLog     2008-05-25 09:07:13 UTC (rev 1979)
@@ -1,3 +1,9 @@
+2008-05-25  Christophe Fergeau <teuf at gnome.org>
+
+       Patch from Ian Stewart <ian.stewart at ozemail.com.au>
+
+       * src/itdb_itunesdb.c: add jump letter support (mhod53)
+
 2008-05-24  Christophe Fergeau <teuf at gnome.org>
 
        * src/ithumb-writer.c: factor some code out of

Modified: libgpod/trunk/src/itdb_itunesdb.c
===================================================================
--- libgpod/trunk/src/itdb_itunesdb.c   2008-05-24 13:53:52 UTC (rev 1978)
+++ libgpod/trunk/src/itdb_itunesdb.c   2008-05-25 09:07:13 UTC (rev 1979)
@@ -219,6 +219,7 @@
   MHOD_ID_SPLPREF = 50,  /* settings for smart playlist */
   MHOD_ID_SPLRULES = 51, /* rules for smart playlist     */
   MHOD_ID_LIBPLAYLISTINDEX = 52,  /* Library Playlist Index */
+  MHOD_ID_LIBPLAYLISTJUMPTABLE=53,
   MHOD_ID_PLAYLIST = 100
 };
 
@@ -250,8 +251,20 @@
     gint cd_nr;
     gint index;
     gint numtracks;
+    gunichar2 letter_album;
+    gunichar2 letter_title;
+    gunichar2 letter_artist;
+    gunichar2 letter_genre;
+    gunichar2 letter_composer;
 };
 
+struct mhod53_entry
+{
+    gunichar2 letter;
+    gint32 start;
+    gint32 count;
+};
+
 struct _MHODData
 {
     gboolean valid;
@@ -265,10 +278,8 @@
        Itdb_SPLRules *splrules;
        GList *mhod52coltracks;
     } data;
-    union
-    {
-       enum MHOD52_SORTTYPE mhod52sorttype;
-    } data2;
+    enum MHOD52_SORTTYPE mhod52sorttype;
+    GList *mhod53_list;
 };
 
 typedef struct _MHODData MHODData;
@@ -1663,6 +1674,7 @@
     case MHOD_ID_LIBPLAYLISTINDEX:
     case MHOD_ID_PLAYLIST:
     case MHOD_ID_CHAPTERDATA:
+    case MHOD_ID_LIBPLAYLISTJUMPTABLE:
        /* these do not have a string entry */
        return NULL;
     }
@@ -2124,6 +2136,7 @@
          case MHOD_ID_SORT_ALBUMARTIST:
          case MHOD_ID_SORT_COMPOSER:
          case MHOD_ID_SORT_TVSHOW:
+         case MHOD_ID_LIBPLAYLISTJUMPTABLE:
              /* these are not expected here */
              break;
          case MHOD_ID_LIBPLAYLISTINDEX:
@@ -2432,6 +2445,7 @@
          case MHOD_ID_SPLPREF:
          case MHOD_ID_SPLRULES:
          case MHOD_ID_LIBPLAYLISTINDEX:
+         case MHOD_ID_LIBPLAYLISTJUMPTABLE:
          case MHOD_ID_PLAYLIST:
          case MHOD_ID_CHAPTERDATA:
              g_free (entry_utf8);
@@ -3749,6 +3763,57 @@
 }
 
 
+/* Return the first alpha-numeric character in the string
+   Return upper-case for alpha, return 0 for all numbers */
+
+static gunichar2 jump_table_letter (gchar *p)
+{
+    gunichar chr = 0;
+    gboolean found_alnum_chars = FALSE;
+
+    g_assert (g_utf8_validate (p, -1, NULL));
+
+    while (*p != '\0') {
+        chr = g_utf8_get_char (p);
+        if (g_unichar_isalnum (chr)) 
+        {
+           found_alnum_chars = TRUE;
+            break;        
+        }
+        p = g_utf8_find_next_char (p, NULL);
+    }
+
+    if (!found_alnum_chars) {
+        /* Return number 0 if no alphanumerics in string */
+        return '0';
+    }
+
+    if (g_unichar_isalpha(chr))
+    {
+        gunichar2 utf16chr;
+        gunichar upperchr;
+        gunichar2 *str;
+        GError *err = NULL;
+
+       upperchr = g_unichar_toupper (chr);
+        str = g_ucs4_to_utf16 (&upperchr, 1, NULL, NULL, &err);
+       if (err != NULL) {
+           fprintf (stderr, "Error in UCS4 to UTF16 conversion: %s, original 
unichar: %x, toupper unichar: %x\n", err->message, chr, upperchr);
+           g_error_free (err);
+           return '0';
+       }
+       else
+        {
+           utf16chr = str[0];
+           g_free (str);
+           return utf16chr;
+       }
+    }      
+
+    return '0';                /* Return number 0 for any digit */
+}
+
+
 /* Create a new list containing all tracks but with collate keys
    instead of the actual strings (title, artist, album, genre,
    composer) */
@@ -3772,28 +3837,34 @@
        if (tr->sort_album && *tr->sort_album)
        {
            ct->album = g_utf8_collate_key (tr->sort_album, -1);
+           ct->letter_album = jump_table_letter (tr->sort_album);
        }
        else if (tr->album)
        {
            ct->album = g_utf8_collate_key (tr->album, -1);
+           ct->letter_album = jump_table_letter (tr->album);
        }
        else
        {
            ct->album = g_strdup ("");
+           ct->letter_album = '0';
        }
 
        /* title */
        if (tr->sort_title && *tr->sort_title)
        {
            ct->title = g_utf8_collate_key (tr->sort_title, -1);
+           ct->letter_title = jump_table_letter (tr->sort_title);
        }
        else if (tr->title)
        {
            ct->title = g_utf8_collate_key (tr->title, -1);
+           ct->letter_title = jump_table_letter (tr->title);
        }
        else
        {
            ct->title = g_strdup ("");
+           ct->letter_title = '0';
        }
 
        /* artist */
@@ -3801,39 +3872,47 @@
        if (str)
        {
            ct->artist = g_utf8_collate_key (str, -1);
+           ct->letter_artist = jump_table_letter (str);
            g_free (str);
        }
        else if (tr->artist)
        {
            ct->artist = g_utf8_collate_key (tr->artist, -1);
+           ct->letter_artist = jump_table_letter (tr->artist);
        }
        else
        {
            ct->artist = g_strdup ("");
+           ct->letter_artist = '0';
        }
 
        /* genre */
        if (tr->genre)
        {
            ct->genre = g_utf8_collate_key (tr->genre, -1);
+           ct->letter_genre = jump_table_letter (tr->genre);
        }
        else
        {
            ct->genre = g_strdup ("");
+           ct->letter_genre = '0';
        }
 
        /* composer */
        if (tr->sort_composer && *tr->sort_composer)
        {
            ct->composer = g_utf8_collate_key (tr->sort_composer, -1);
+           ct->letter_composer = jump_table_letter (tr->sort_composer);
        }
        else if (tr->composer)
        {
            ct->composer = g_utf8_collate_key (tr->composer, -1);
+           ct->letter_composer = jump_table_letter (tr->sort_composer);
        }
        else
        {
            ct->composer = g_strdup ("");
+           ct->letter_composer = jump_table_letter (tr->composer);
        }
 
        ct->track_nr = tr->track_nr;
@@ -3864,7 +3943,6 @@
     g_list_free (coltracks);
 }
 
-
 /* Write out one mhod header.
      type: see enum of MHMOD_IDs;
      data: utf8 string for text items
@@ -4150,9 +4228,13 @@
          gint numtracks = ct->numtracks;
          GList *gl;
          gpointer compfunc = NULL;
+         gunichar2 sortkey = 0;
+          gunichar2 lastsortkey = 0;
+         guint32 mhod53index = 0;
+         struct mhod53_entry *m53 = NULL;
 
          /* sort list */
-         switch (mhod->data2.mhod52sorttype)
+         switch (mhod->mhod52sorttype)
          {
          case MHOD52_SORTTYPE_TITLE:
              compfunc = mhod52_sort_title;
@@ -4182,7 +4264,7 @@
          put32lint (cts, mhod->type);      /* type of the mhod           */
          put32_n0 (cts, 2);                /* unknown                    */
          /* end of header, start of data */
-         put32lint (cts, mhod->data2.mhod52sorttype);   /* sort type     */
+         put32lint (cts, mhod->mhod52sorttype);   /* sort type     */
          put32lint (cts, numtracks);       /* number of entries          */
          put32_n0 (cts, 10);               /* unknown                    */
          for (gl=mhod->data.mhod52coltracks; gl; gl=gl->next)
@@ -4190,9 +4272,66 @@
              ct = gl->data;
              g_return_if_fail (ct);
              put32lint (cts, ct->index);
+
+             /* This is for the type 53s */
+             switch (mhod->mhod52sorttype)
+             {
+               case MHOD52_SORTTYPE_TITLE:
+               sortkey = ct->letter_title;
+               break;
+             case MHOD52_SORTTYPE_ALBUM:
+               sortkey = ct->letter_album;
+               break;
+             case MHOD52_SORTTYPE_ARTIST:
+               sortkey = ct->letter_artist;
+               break;
+             case MHOD52_SORTTYPE_GENRE:
+               sortkey = ct->letter_genre;
+               break;
+             case MHOD52_SORTTYPE_COMPOSER:
+               sortkey = ct->letter_composer;
+               break;
+             }
+
+           if (sortkey != lastsortkey) {
+             m53 = g_new0 (struct mhod53_entry, 1);
+             m53->letter = sortkey;
+             m53->start = mhod53index;
+             m53->count = 0;
+             mhod->mhod53_list = g_list_append (mhod->mhod53_list, m53);
+             lastsortkey = sortkey; 
+           }
+           mhod53index++;
+           m53->count++;
          }
       }
       break;
+  case MHOD_ID_LIBPLAYLISTJUMPTABLE:
+      {
+          GList *gl;
+          guint32 numentries;
+          struct mhod53_entry *m53;
+
+          numentries = g_list_length (mhod->mhod53_list);
+          put_header (cts, "mhod");                            /* header */
+          put32lint (cts, 24);                         /* size of header */
+          put32lint (cts, 12*numentries+40);           /* size of header + 
body */
+          put32lint (cts, mhod->type);                 /* type of the mhod */
+          put32_n0 (cts, 2);                           /* unknown */
+          put32lint (cts, mhod->mhod52sorttype);       /* sort type */
+          put32lint (cts, numentries);                 /* number of entries */
+          put32_n0 (cts, 2);                           /* unknown */
+
+          for (gl=mhod->mhod53_list; gl; gl=gl->next)
+          {
+              m53 = gl->data;
+              put16lint (cts, m53->letter);
+              put16lint (cts, 0);
+              put32lint (cts, m53->start);
+              put32lint (cts, m53->count);
+          }
+      }
+      break;
   }
 }
 
@@ -4684,7 +4823,26 @@
     return TRUE;
 }
 
+/* Write one type 52 and the corresponding type 53 mhod */
+static void mk_mhod52 (enum MHOD52_SORTTYPE mhod52sorttype, FExport *fexp, 
+                       MHODData *mhod)
+{
+    mhod->mhod52sorttype = mhod52sorttype;
+    mhod->type = MHOD_ID_LIBPLAYLISTINDEX;
+    mk_mhod (fexp, mhod);
+}
 
+static void mk_mhod53 (enum MHOD52_SORTTYPE mhod52sorttype, FExport *fexp, 
+                       MHODData *mhod)
+{
+    mhod->type = MHOD_ID_LIBPLAYLISTJUMPTABLE;
+    mk_mhod (fexp, mhod);
+    g_list_foreach (mhod->mhod53_list, (GFunc)g_free, NULL);
+    g_list_free (mhod->mhod53_list);
+    mhod->mhod53_list = NULL;
+}
+
+
 /* corresponds to mk_mhyp */
 /* mhsd_type: 2: write normal playlists
               3: write podcast playlist in special format */
@@ -4722,8 +4880,8 @@
     else
     {
        if ((pl->type == ITDB_PL_TYPE_MPL) && pl->members)
-       {   /* 5 more MHOD 52 lists */
-           mhodnum += 5;
+       {   /* 5 more MHOD 52 lists and 5 more MHOD 53 lists*/
+           mhodnum += 10;
        }
     }
     put32lint (cts, mhodnum);      /* nr of mhods               */
@@ -4749,23 +4907,25 @@
     mk_long_mhod_id_playlist (fexp, pl);
 
     if ((pl->type == ITDB_PL_TYPE_MPL) && pl->members)
-    {   /* write out the MHOD 52 lists */
+    {   /* write out the MHOD 52 and MHOD 53 lists */
        /* We have to sort all tracks five times. To speed this up,
           translate the utf8 keys into collate_keys and use the
           faster strcmp() for comparison */
        mhod.valid = TRUE;
-       mhod.type = MHOD_ID_LIBPLAYLISTINDEX;
        mhod.data.mhod52coltracks = mhod52_make_collate_keys (pl->members);
-       mhod.data2.mhod52sorttype = MHOD52_SORTTYPE_TITLE;
-       mk_mhod (fexp, &mhod);
-       mhod.data2.mhod52sorttype = MHOD52_SORTTYPE_ARTIST;
-       mk_mhod (fexp, &mhod);
-       mhod.data2.mhod52sorttype = MHOD52_SORTTYPE_ALBUM;
-       mk_mhod (fexp, &mhod);
-       mhod.data2.mhod52sorttype = MHOD52_SORTTYPE_GENRE;
-       mk_mhod (fexp, &mhod);
-       mhod.data2.mhod52sorttype = MHOD52_SORTTYPE_COMPOSER;
-       mk_mhod (fexp, &mhod);
+       mhod.mhod53_list = NULL;        
+
+       mk_mhod52 (MHOD52_SORTTYPE_TITLE, fexp, &mhod); 
+       mk_mhod53 (MHOD52_SORTTYPE_TITLE, fexp, &mhod); 
+       mk_mhod52 (MHOD52_SORTTYPE_ARTIST, fexp, &mhod);
+       mk_mhod53 (MHOD52_SORTTYPE_ARTIST, fexp, &mhod);
+       mk_mhod52 (MHOD52_SORTTYPE_ALBUM, fexp, &mhod);
+       mk_mhod53 (MHOD52_SORTTYPE_ALBUM, fexp, &mhod);
+       mk_mhod52 (MHOD52_SORTTYPE_GENRE, fexp, &mhod);
+       mk_mhod53 (MHOD52_SORTTYPE_GENRE, fexp, &mhod);
+       mk_mhod52 (MHOD52_SORTTYPE_COMPOSER, fexp, &mhod);
+       mk_mhod53 (MHOD52_SORTTYPE_COMPOSER, fexp, &mhod);
+
        mhod52_free_collate_keys (mhod.data.mhod52coltracks);
     }
     else  if (pl->is_spl)


This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.

-------------------------------------------------------------------------
This SF.net email is sponsored by: Microsoft
Defy all challenges. Microsoft(R) Visual Studio 2008.
http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2

Reply via email to