Update of /cvsroot/gtkpod/gtkpod/src
In directory sc8-pr-cvs2.sourceforge.net:/tmp/cvs-serv19794/src

Modified Files:
        display_itdb.c display_itdb.h file_itunesdb.c main.c 
        misc_track.c misc_track.h sha1.c 
Log Message:
        * misc_track.c: when adding a duplicate keep the original
          filename information if it's still valid.

        * file_itunesdb.c: removed rating and playcount completely
          from extended info hash routines. Added local_itdb_id and
          local_track_dbid.

        * src/display_itdb.c
          src/display_itdb.h
          src/file_itunesdb.c
          src/main.c
          src/misc_track.c
          src/misc_track.h: introduced and maintain a filename hash
          for each repository. Will be used to cross-reference between
          repositories for playcounts and on-the-fly conversion.




Index: display_itdb.c
===================================================================
RCS file: /cvsroot/gtkpod/gtkpod/src/display_itdb.c,v
retrieving revision 1.64
retrieving revision 1.65
diff -u -d -r1.64 -r1.65
--- display_itdb.c      7 Apr 2007 04:43:15 -0000       1.64
+++ display_itdb.c      7 Apr 2007 14:55:49 -0000       1.65
@@ -1,5 +1,5 @@
 /*
-|  Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+|  Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
 |  Part of the gtkpod project.
 | 
 |  URL: http://www.gtkpod.org/
@@ -63,6 +63,7 @@
     if (eitdb)
     {
        sha1_free_eitdb (eitdb);
+       gp_itdb_pc_path_hash_destroy (eitdb);
        g_free (eitdb);
     }
 }
@@ -168,12 +169,13 @@
            (ItdbUserDataDuplicateFunc)gp_itdb_extra_duplicate;
        eitdb->data_changed = FALSE;
        eitdb->itdb_imported = FALSE;
+       gp_itdb_pc_path_hash_init (eitdb);
     }
 }
 
 
 /* Validate a complete @itdb (including tracks and playlists),
- * i.e. add the Extra*Data and validate the track entries */
+ * i.e. add the Extra*Data */
 void gp_itdb_add_extra_full (iTunesDB *itdb)
 {
     GList *gl;
@@ -276,6 +278,7 @@
        /* exception: sha1_hash, hostname, charset: these may be NULL. */
        gp_track_validate_entries (track);
        itdb_track_add (itdb, track, -1);
+       gp_itdb_pc_path_hash_add_track (track);
        result = track;
     }
     data_changed (itdb);
@@ -291,6 +294,10 @@
 {
     /* currently only the details window may be accessing the tracks */
     details_remove_track (track);
+    /* remove from SHA1 hash */
+    sha1_track_remove (track);
+    /* remove from pc_path_hash */
+    gp_itdb_pc_path_hash_remove_track (track);
     /* remove from database */
     itdb_track_remove (track);
 }
@@ -304,6 +311,10 @@
 {
     /* currently only the details window may be accessing the tracks */
     details_remove_track (track);
+    /* remove from SHA1 hash */
+    sha1_track_remove (track);
+    /* remove from pc_path_hash */
+    gp_itdb_pc_path_hash_remove_track (track);
     /* remove from database */
     itdb_track_unlink (track);
 }
@@ -674,7 +685,6 @@
 
     if (remove_track)
     {
-       sha1_track_remove (track);
        if (itdb->usertype & GP_ITDB_TYPE_IPOD)
        {
            switch (deleteaction)

Index: display_itdb.h
===================================================================
RCS file: /cvsroot/gtkpod/gtkpod/src/display_itdb.h,v
retrieving revision 1.40
retrieving revision 1.41
diff -u -d -r1.40 -r1.41
--- display_itdb.h      7 Apr 2007 04:43:15 -0000       1.40
+++ display_itdb.h      7 Apr 2007 14:55:49 -0000       1.41
@@ -1,5 +1,5 @@
 /*
-|  Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+|  Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
 |  Part of the gtkpod project.
 | 
 |  URL: http://www.gtkpod.org/
@@ -46,6 +46,7 @@
 {
     struct itdbs_head *itdbs_head; /* pointer to the master itdbs_head */
     GHashTable *sha1hash;          /* sha1 hash information            */
+    GHashTable *pc_path_hash;      /* hash with local filenames        */
     GList *pending_deletion;       /* tracks marked for removal from
                                      media                            */
     gchar *offline_filename;       /* filename for offline database
@@ -71,10 +72,14 @@
   gchar   *thumb_path_locale; /* same for thumbnail                  */
   gchar   *thumb_path_utf8;   /* same for thumbnail                  */
   gchar   *hostname;      /* name of host this file has been imported on*/
-  gchar   *sha1_hash;     /* sha1 hash of file (or NULL)              */
+  gchar   *sha1_hash;     /* sha1 hash of file (or NULL)             */
   gchar   *charset;       /* charset used for ID3 tags               */
   gint32  sortindex;      /* used for stable sorting (current order) */
   gboolean tchanged;      /* temporary use, e.g. in detail.c         */
+  guint64 local_itdb_id;  /* when using DND from local to iPod: original itdb  
 */
+  guint64 local_track_dbid;/* when using DND from local to iPod: original 
track */
+  gboolean pc_path_hashed;/* for programming error detection (see    */
+                         /* gp_itdb_local_path_hash_add_track()     */
 } ExtraTrackData;
 
 /* types for iTunesDB */

Index: file_itunesdb.c
===================================================================
RCS file: /cvsroot/gtkpod/gtkpod/src/file_itunesdb.c,v
retrieving revision 1.115
retrieving revision 1.116
diff -u -d -r1.115 -r1.116
--- file_itunesdb.c     7 Apr 2007 04:43:15 -0000       1.115
+++ file_itunesdb.c     7 Apr 2007 14:55:49 -0000       1.116
@@ -1,5 +1,5 @@
 /*
-|  Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+|  Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
 |  Part of the gtkpod project.
 | 
 |  URL: http://www.gtkpod.org/
@@ -75,8 +75,8 @@
     gchar *hostname;
     gchar *ipod_path;
     gint32 oldsize;
-    guint32 playcount;
-    guint32 rating;        /* still read but never written */
+    guint64 local_itdb_id;
+    guint64 local_track_dbid;
     gboolean transferred;
 };
 
@@ -203,12 +203,9 @@
          etr->charset = g_strdup (sei->charset);
       if (sei->hostname && !etr->hostname)
          etr->hostname = g_strdup (sei->hostname);
+      etr->local_itdb_id = sei->local_itdb_id;
+      etr->local_track_dbid = sei->local_track_dbid;
       etr->oldsize = sei->oldsize;
-      track->playcount += sei->playcount;
-      /* FIXME: This means that the rating can never be reset to 0
-       * by the iPod */
-      if (track->rating == 0)
-         track->rating = sei->rating;
       track->transferred = sei->transferred;
       /* don't remove the sha1-hash -- there may be duplicates... */
       if (extendedinfohash)
@@ -414,18 +411,16 @@
                sei->charset = g_strdup (arg);
            else if (g_ascii_strcasecmp (line, "oldsize") == 0)
                sei->oldsize = atoi (arg);
-           else if (g_ascii_strcasecmp (line, "playcount") == 0)
-               sei->playcount = atoi (arg);
-           else if (g_ascii_strcasecmp (line, "rating") == 0)
-               sei->rating = atoi (arg);
            else if (g_ascii_strcasecmp (line, "transferred") == 0)
                sei->transferred = atoi (arg);
            else if (g_ascii_strcasecmp (line, "filename_ipod") == 0)
                sei->ipod_path = g_strdup (arg);
            else if (g_ascii_strcasecmp (line, "pc_mtime") == 0)
-           {
                sei->mtime = (time_t)g_ascii_strtoull (arg, NULL, 10);
-           }
+           else if (g_ascii_strcasecmp (line, "local_itdb_id") == 0)
+               sei->local_itdb_id = (guint64)g_ascii_strtoull (arg, NULL, 10);
+           else if (g_ascii_strcasecmp (line, "local_track_dbid") == 0)
+               sei->local_track_dbid = (guint64)g_ascii_strtoull (arg, NULL, 
10);
     }
     g_free (sha1);
     fclose (fp);
@@ -630,9 +625,9 @@
     {
        Track *track = gl->data;
    
-    /* Send eligible tracks to last.fm cache */
-    if (track->recent_playcount > 0)
-        lastfm_add_track(track);
+       /* Send eligible tracks to last.fm cache */
+       if (track->recent_playcount > 0)
+           lastfm_add_track(track);
 
        ExtraTrackData *etr;
        g_return_val_if_fail (track, (release_widgets(), NULL));
@@ -667,6 +662,10 @@
            gp_track_set_thumbnails (track, filename);
            g_free (filename);
        }
+
+       /* add to filename hash */
+       gp_itdb_pc_path_hash_add_track (track);
+
        ++num;
     }
     /* take over the pending deletion information */
@@ -681,7 +680,8 @@
 
     /* delete hash information (if present) */
     destroy_extendedinfohash ();
-    /* find duplicates */
+
+    /* find duplicates and create sha1 hash*/
     gp_sha1_hash_tracks_itdb (itdb);
 
     /* mark the data as unchanged */
@@ -1198,6 +1198,12 @@
          fprintf (fp, "oldsize=%d\n", etr->oldsize);
       if (etr->mtime)
          fprintf (fp, "pc_mtime=%llu\n", (unsigned long long)etr->mtime);
+      if (etr->local_itdb_id)
+         fprintf (fp, "local_itdb_id=%" G_GUINT64_FORMAT "\n",
+                  etr->local_itdb_id);
+      if (etr->local_track_dbid)
+         fprintf (fp, "local_track_dbid=%" G_GUINT64_FORMAT "\n",
+                  etr->local_track_dbid);
       fprintf (fp, "transferred=%d\n", track->transferred);
       while (widgets_blocked && gtk_events_pending ())  gtk_main_iteration ();
   }

Index: main.c
===================================================================
RCS file: /cvsroot/gtkpod/gtkpod/src/main.c,v
retrieving revision 1.60
retrieving revision 1.61
diff -u -d -r1.60 -r1.61
--- main.c      22 Feb 2007 15:05:53 -0000      1.60
+++ main.c      7 Apr 2007 14:55:49 -0000       1.61
@@ -1,6 +1,5 @@
-/* Time-stamp: <2007-02-23 00:05:25 jcs>
-|
-|  Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+/*
+|  Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
 |  Part of the gtkpod project.
 | 
 |  URL: http://www.gtkpod.org/
@@ -130,7 +129,8 @@
        
        gtk_widget_show (gtkpod_window);
 
-  init_data (gtkpod_window);   /* setup base data */
+  init_data (gtkpod_window);   /* setup base data, importing all local
+                               * repositories */
 
   /* stuff to be done before starting gtkpod */
   call_script ("gtkpod.in", NULL);

Index: misc_track.c
===================================================================
RCS file: /cvsroot/gtkpod/gtkpod/src/misc_track.c,v
retrieving revision 1.61
retrieving revision 1.62
diff -u -d -r1.61 -r1.62
--- misc_track.c        7 Apr 2007 04:43:15 -0000       1.61
+++ misc_track.c        7 Apr 2007 14:55:49 -0000       1.62
@@ -1,5 +1,5 @@
 /*
-|  Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+|  Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
 |  Part of the gtkpod project.
 | 
 |  URL: http://www.gtkpod.org/
@@ -280,13 +280,18 @@
        oldtrack->time_added =  MIN (oldtrack->time_added, track->time_added);
 
        /* Update filename if new track has filename set (should be
-       * always!?) */
+         always!?) and old filename is not available or no longer
+         valid */
        if (etr->pc_path_locale)
        {
-          g_free (oldetr->pc_path_locale);
-          g_free (oldetr->pc_path_utf8);
-          oldetr->pc_path_locale = g_strdup (etr->pc_path_locale);
-          oldetr->pc_path_utf8 = g_strdup (etr->pc_path_utf8);
+          if (!oldetr->pc_path_locale ||
+              !g_file_test (oldetr->pc_path_locale, G_FILE_TEST_IS_REGULAR))
+          {
+              g_free (oldetr->pc_path_locale);
+              g_free (oldetr->pc_path_utf8);
+              oldetr->pc_path_locale = g_strdup (etr->pc_path_locale);
+              oldetr->pc_path_utf8 = g_strdup (etr->pc_path_utf8);
+          }
        }
        if (itdb_playlist_contains_track (itdb_playlist_mpl (itdb),
                                         track))
@@ -380,7 +385,7 @@
 
 
 /* Returns the track with the filename @name or NULL, if none can be
- * found. This function also works if @name is on the iPod. */
+ * found. This function also works if @filename is on the iPod. */
 Track *gp_track_by_filename (iTunesDB *itdb, gchar *filename)
 {
     gchar *musicdir = NULL;
@@ -445,6 +450,278 @@
 }
 
 
+/* Find @track in repository @itdb by the following methods and return
+   the matches:
+
+   1) DND origin data
+   2) filename matches
+   3) SHA1 match 
+
+   If DND origin data is available and valid only one track is
+   returned. Otherwise all tracks matching the filename and the SHA1
+   are returned.
+
+   If DND origin data is found to be invalid it is deleted.
+
+   Return value: a GList with matching tracks. You must call
+   g_list_free() on the list when it is no longer needed.
+*/
+GList *gp_itdb_find_same_tracks (iTunesDB *itdb, Track *track)
+{
+    ExtraTrackData *etr;
+    Track *itr;
+    GList *tracks = NULL;
+
+    g_return_val_if_fail (itdb, NULL);
+    g_return_val_if_fail (track, NULL);
+
+    etr = track->userdata;
+    g_return_val_if_fail (etr, NULL);
+
+    if (itdb->id == etr->local_itdb_id)
+    {   /* we can probably find the original track from the DND data */
+       GList *gl;
+       for (gl=itdb->tracks; gl; gl=gl->next)
+       {
+           itr = gl->data;
+           g_return_val_if_fail (itr, NULL);
+           if (itr->dbid == etr->local_track_dbid)
+           {   /* found track */
+               tracks = g_list_prepend (tracks, itr);
+               return tracks;
+           }
+       }
+       /* DND origin data is no longer valid */
+       etr->local_itdb_id = 0;
+       etr->local_track_dbid = 0;
+    }
+
+    /* No luck so far -- let's get filename matches */
+    tracks = gp_itdb_pc_path_hash_find_tracks (itdb, etr->pc_path_utf8);
+
+    /* And also try SHA1 match */
+    itr = sha1_sha1_exists (itdb, etr->sha1_hash);
+
+    if (itr)
+    {   /* insert into tracks list if not already present */
+       if (!g_list_find (tracks, itr))
+       {
+           tracks = g_list_prepend (tracks, itr);
+       }
+    }
+
+    return tracks;
+}
+
+
+
+/* ------------------------------------------------------------ *\
+|                                                                |
+|         functions for local path hashtable                     |
+|                                                                |
+\* ------------------------------------------------------------ */
+
+/* set up hash table for local filenames */
+void gp_itdb_pc_path_hash_init (ExtraiTunesDBData *eitdb)
+{
+    g_return_if_fail (eitdb);
+
+    if (!eitdb->pc_path_hash)
+    {
+       eitdb->pc_path_hash = g_hash_table_new_full (
+           g_str_hash, g_str_equal,
+           g_free, NULL);
+    }
+}
+
+
+/* function for destroying hash value, used when destroying the hash
+ * table in gp_itdb_local_path_hash_destroy() below. */
+static void pc_path_hash_free_value (gpointer key,
+                                       gpointer value,
+                                       gpointer userdata)
+{
+    g_list_free (value);
+}
+
+
+/* free all memory associated with the local_path_hash */
+void gp_itdb_pc_path_hash_destroy (ExtraiTunesDBData *eitdb)
+{
+    g_return_if_fail (eitdb);
+
+    if (eitdb->pc_path_hash)
+    {
+       g_hash_table_foreach (eitdb->pc_path_hash,
+                             pc_path_hash_free_value,
+                             NULL);
+       g_hash_table_destroy (eitdb->pc_path_hash);
+       eitdb->pc_path_hash = NULL;
+    }
+}
+
+
+/* Add track to filehash. This function must only be called once for
+ * each track. */
+void gp_itdb_pc_path_hash_add_track (Track *track)
+{
+    iTunesDB *itdb;
+    ExtraTrackData *etr;
+    ExtraiTunesDBData *eitdb;
+
+    g_return_if_fail (track);
+    etr = track->userdata;
+    g_return_if_fail (etr);
+
+    itdb = track->itdb;
+    g_return_if_fail (itdb);
+
+    eitdb = itdb->userdata;
+    g_return_if_fail (eitdb);
+    g_return_if_fail (eitdb->pc_path_hash);
+
+    g_return_if_fail (track);
+    etr = track->userdata;
+    g_return_if_fail (etr);
+
+    /* This is only to detect programming errors */
+    g_return_if_fail (!etr->pc_path_hashed);
+
+    if (etr->pc_path_utf8 && *etr->pc_path_utf8)
+    {   /* add to hash table */
+       GList *tracks;
+       tracks = g_hash_table_lookup (eitdb->pc_path_hash, etr->pc_path_utf8);
+       tracks = g_list_prepend (tracks, track);
+       g_hash_table_replace (eitdb->pc_path_hash,
+                             g_strdup (etr->pc_path_utf8),
+                             tracks);
+       /* This is only to detect programming errors */
+       etr->pc_path_hashed = TRUE;
+    }
+}
+
+/* used in the next two functions */
+struct pc_path_hash_find_track_data
+{
+    Track *track;
+    gchar *key;
+};
+
+
+/* Used in the next function. Return TRUE and the current key if
+   td->track is contained in the list for key */
+static gboolean pc_path_hash_find_track (gpointer key,
+                                        gpointer value,
+                                        gpointer user_data)
+{
+    GList *tracks = value;
+    struct pc_path_hash_find_track_data *td = user_data;
+
+    if (g_list_find (tracks, td->track))
+    {
+       td->key = g_strdup (key);
+       return TRUE;
+    }
+    return FALSE;
+}
+
+
+
+/* remove track from filehash */
+void gp_itdb_pc_path_hash_remove_track (Track *track)
+{
+    struct pc_path_hash_find_track_data td;
+    ExtraTrackData *etr;
+    iTunesDB *itdb;
+    ExtraiTunesDBData *eitdb;
+    GList *tracks;
+
+    g_return_if_fail (track);
+    etr = track->userdata;
+    g_return_if_fail (etr);
+
+    itdb = track->itdb;
+    g_return_if_fail (itdb);
+
+    eitdb = itdb->userdata;
+    g_return_if_fail (eitdb);
+    g_return_if_fail (eitdb->pc_path_hash);
+
+    if (!etr->pc_path_hashed)  return;
+
+    if (etr->pc_path_utf8 && *etr->pc_path_utf8)
+    {   /* try lookup with filename */
+       GList *tracks;
+       tracks = g_hash_table_lookup (eitdb->pc_path_hash, etr->pc_path_utf8);
+       if (tracks)
+       {   /* filename exists */
+           GList *link = g_list_find (tracks, track);
+           if (link)
+           {   /* track found */
+               tracks = g_list_remove_link (tracks, link);
+               if (tracks)
+               {   /* still tracks left under this filename */
+                   g_hash_table_replace (eitdb->pc_path_hash,
+                                         g_strdup (etr->pc_path_utf8),
+                                         tracks);
+               }
+               else
+               {   /* no more tracks left under this filename */
+                   g_hash_table_remove (eitdb->pc_path_hash,
+                                        etr->pc_path_utf8);
+               }
+               etr->pc_path_hashed = FALSE;
+               return;
+           }
+       }
+    }
+
+    /* We didn't find the track by filename, or now filename is
+     * available any more) -> search through the list */
+    td.track = track;
+    td.key = NULL;
+    tracks = g_hash_table_find (eitdb->pc_path_hash,
+                               pc_path_hash_find_track,
+                               &td);
+    if (tracks)
+    {
+       tracks = g_list_remove (tracks, track);
+       if (tracks)
+       {   /* still tracks left under this filename */
+           g_hash_table_replace (eitdb->pc_path_hash,
+                                 g_strdup (td.key),
+                                 tracks);
+       }
+       else
+       {   /* no more tracks left under this filename */
+           g_hash_table_remove (eitdb->pc_path_hash,
+                                td.key);
+       }
+       etr->pc_path_hashed = FALSE;
+       g_free (td.key);
+    }
+}
+
+
+/* Return all tracks with @filename (@filename in UTF8).
+   You must g_list_free the returned list when it is not longer needed. */
+GList *gp_itdb_pc_path_hash_find_tracks (iTunesDB *itdb, const gchar *filename)
+{
+    ExtraiTunesDBData *eitdb;
+    GList *tracks = NULL;
+
+    g_return_val_if_fail (itdb, NULL);
+    eitdb = itdb->userdata;
+    g_return_val_if_fail (eitdb, NULL);
+    g_return_val_if_fail (eitdb->pc_path_hash, NULL);
+
+    if (filename && *filename)
+       tracks = g_hash_table_lookup (eitdb->pc_path_hash, filename);
+
+    return g_list_copy (tracks);
+}
+
+
 
 /* ------------------------------------------------------------ *\
 |                                                                |

Index: misc_track.h
===================================================================
RCS file: /cvsroot/gtkpod/gtkpod/src/misc_track.h,v
retrieving revision 1.16
retrieving revision 1.17
diff -u -d -r1.16 -r1.17
--- misc_track.h        17 Nov 2006 07:40:47 -0000      1.16
+++ misc_track.h        7 Apr 2007 14:55:49 -0000       1.17
@@ -1,6 +1,5 @@
-/* Time-stamp: <2006-11-17 16:36:11 jcs>
-|
-|  Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+/*
+|  Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
 |  Part of the gtkpod project.
 | 
 |  URL: http://www.gtkpod.org/
@@ -41,6 +40,14 @@
 void gp_sha1_hash_tracks (void);
 void gp_sha1_free_hash (void);
 Track *gp_track_by_filename (iTunesDB *itdb, gchar *filename);
+
+void gp_itdb_pc_path_hash_init (ExtraiTunesDBData *eitdb);
+void gp_itdb_pc_path_hash_destroy (ExtraiTunesDBData *eitdb);
+void gp_itdb_pc_path_hash_add_track (Track *track);
+void gp_itdb_pc_path_hash_remove_track (Track *track);
+GList *gp_itdb_pc_path_hash_find_tracks (iTunesDB *itdb, const gchar 
*filename);
+GList *gp_itdb_find_same_tracks (iTunesDB *itdb, Track *track);
+
 gchar **track_get_item_pointer (Track *track, T_item t_item);
 const gchar *track_get_item (Track *track, T_item t_item);
 guint32 *track_get_timestamp_ptr (Track *track, T_item t_item);

Index: sha1.c
===================================================================
RCS file: /cvsroot/gtkpod/gtkpod/src/sha1.c,v
retrieving revision 1.47
retrieving revision 1.48
diff -u -d -r1.47 -r1.48
--- sha1.c      7 Apr 2007 04:43:15 -0000       1.47
+++ sha1.c      7 Apr 2007 14:55:49 -0000       1.48
@@ -1,6 +1,6 @@
 /*
 |  Copyright (C) 2002 Corey Donohoe <atmos at atmos.org>
-|  Copyright (C) 2002-2005 Jorg Schuler <jcsjcs at users sourceforge net>
+|  Copyright (C) 2002-2007 Jorg Schuler <jcsjcs at users sourceforge net>
 |  Part of the gtkpod project.
 | 
 |  URL: http://www.gtkpod.org/


-------------------------------------------------------------------------
Take Surveys. Earn Cash. Influence the Future of IT
Join SourceForge.net's Techsay panel and you'll get the chance to share your
opinions on IT & business topics through brief surveys-and earn cash
http://www.techsay.com/default.php?page=join.php&p=sourceforge&CID=DEVDEV
_______________________________________________
gtkpod-cvs2 mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/gtkpod-cvs2

Reply via email to