Dudy Kohen wrote:
> The problem is because I worked on a 0.99.12 tarball and not the
> SVN...
Ahh, yeah, there were a few conflicts trying to apply the patch to
SVN, though all except the the glade file ones were relatively minor.
I think the attached patch has all of your changes from the first
patch except the glade file, which as you say, is easier to regenerate
with glade than it is to manually merge. I attempted to do that, but
had issues when using glade 3.4, and Jorg wasn't around to find out
exactly which version he's been using recently.
> Lyrics can be marked as stored while an empty string is in the file
> itself, can you say what Picard or Kid3 show in the USLT section of
> the same file?
Oh, there are lyrics in the USLT tag, to be sure. I even added some
debug code to id3_lyrics_read() to verify that the lyrics were found.
They just didn't get displayed for me.
I'll try to update to your current patch and test again sometime over
the weekend.
> A new tab is too much in my opinion, and since the entire window is
> resizeable, the box is resizeable.
Though for many people, screen width is easier to come by than height,
which is what made me think that a separate tab would fit better in
the default size of the dialog.
--
Todd OpenPGP -> KeyID: 0xBEAF0CE3 | URL: www.pobox.com/~tmz/pgp
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Health is merely the slowest possible rate at which one can die.
diff --git a/src/display.h b/src/display.h
index 9b0f92e..3678f86 100644
--- a/src/display.h
+++ b/src/display.h
@@ -191,6 +191,7 @@ typedef enum {
TM_COLUMN_SORT_ALBUMARTIST, /* 45 */
TM_COLUMN_SORT_COMPOSER,
TM_COLUMN_SORT_TVSHOW,
+ TM_COLUMN_LYRICS,
TM_NUM_COLUMNS
} TM_item;
@@ -257,6 +258,7 @@ typedef enum {
T_SORT_COMPOSER,
T_SORT_TVSHOW,
T_GAPLESS_TRACK_FLAG,
+ T_LYRICS,
T_ITEM_NUM,
} T_item;
diff --git a/src/display_itdb.c b/src/display_itdb.c
index 83c7ca3..ce1715a 100644
--- a/src/display_itdb.c
+++ b/src/display_itdb.c
@@ -115,6 +115,7 @@ void gp_track_extra_destroy (ExtraTrackData *etrack)
g_free (etrack->hostname);
g_free (etrack->sha1_hash);
g_free (etrack->charset);
+ g_free (etrack->lyrics);
g_free (etrack);
}
}
@@ -137,6 +138,7 @@ ExtraTrackData *gp_track_extra_duplicate (ExtraTrackData *etr)
etr_dup->hostname = g_strdup (etr->hostname);
etr_dup->sha1_hash = g_strdup (etr->sha1_hash);
etr_dup->charset = g_strdup (etr->charset);
+ etr_dup->lyrics = g_strdup (etr->lyrics);
/* clear the pc_path_hashed flag */
etr_dup->pc_path_hashed = FALSE;
}
@@ -261,6 +263,7 @@ void gp_track_add_extra (Track *track)
{
ExtraTrackData *etr = g_new0 (ExtraTrackData, 1);
track->userdata = etr;
+ etr->lyrics=NULL;
track->userdata_destroy =
(ItdbUserDataDestroyFunc)gp_track_extra_destroy;
track->userdata_duplicate =
@@ -823,6 +826,7 @@ void gp_track_validate_entries (Track *track)
if (!etr->pc_path_locale) etr->pc_path_locale = g_strdup ("");
if (!etr->thumb_path_utf8) etr->thumb_path_utf8 = g_strdup ("");
if (!etr->thumb_path_locale) etr->thumb_path_locale = g_strdup ("");
+ if (!etr->lyrics) etr->lyrics = g_strdup ("");
/* Make sure year_str is identical to year */
g_free (etr->year_str);
etr->year_str = g_strdup_printf ("%d", track->year);
diff --git a/src/display_itdb.h b/src/display_itdb.h
index 817e8eb..b32c138 100644
--- a/src/display_itdb.h
+++ b/src/display_itdb.h
@@ -87,6 +87,8 @@ typedef struct
original itdb */
guint64 local_track_dbid; /* when using DND from local to iPod:
original track */
+ gchar *lyrics; /* Lyrics information as read from file or as
+ updated in the program */
} ExtraTrackData;
/* types for iTunesDB */
diff --git a/src/display_tracks.c b/src/display_tracks.c
index ad49d11..f920ca1 100644
--- a/src/display_tracks.c
+++ b/src/display_tracks.c
@@ -1077,6 +1077,7 @@ tm_cell_edited (GtkCellRendererText *renderer,
case TM_COLUMN_IPOD_PATH:
case TM_COLUMN_COMPILATION:
case TM_COLUMN_THUMB_PATH:
+ case TM_COLUMN_LYRICS:
case TM_NUM_COLUMNS:
/* These are not editable text fields */
break;
@@ -1138,7 +1139,12 @@ static void tm_cell_data_func (GtkTreeViewColumn *tree_column,
itdb = track->itdb;
g_return_if_fail (itdb);
- text = track_get_text (track, TM_to_T (column));
+ if (column!= TM_COLUMN_LYRICS)
+ {
+ text = track_get_text (track, TM_to_T (column));
+ }
+ text = g_strdup_printf ("%d", track->lyrics_flag);
+ }
switch (column)
{
@@ -1180,6 +1186,7 @@ static void tm_cell_data_func (GtkTreeViewColumn *tree_column,
"xalign", 0.0, NULL);
break;
case TM_COLUMN_MEDIA_TYPE:
+ case TM_COLUMN_LYRICS:
g_object_set (G_OBJECT (renderer),
"text", text,
"editable", FALSE,
@@ -1374,6 +1381,7 @@ tm_cell_toggled (GtkCellRendererToggle *renderer,
case TM_COLUMN_SORT_ALBUMARTIST:
case TM_COLUMN_SORT_COMPOSER:
case TM_COLUMN_SORT_TVSHOW:
+ case TM_COLUMN_LYRICS:
case TM_NUM_COLUMNS:
/* these are not toggle buttons */
break;
@@ -1798,6 +1806,9 @@ static gint tm_data_compare (Track *track1, Track *track2,
case TM_COLUMN_MEDIA_TYPE:
cmp = track1->mediatype - track2->mediatype;
break;
+ case TM_COLUMN_LYRICS:
+ cmp = track1->lyrics_flag - track2->lyrics_flag;
+ break;
case TM_NUM_COLUMNS:
break;
}
@@ -1879,6 +1890,7 @@ gboolean tm_search_equal_func (GtkTreeModel *model,
case TM_COLUMN_MEDIA_TYPE:
case TM_COLUMN_SEASON_NR:
case TM_COLUMN_EPISODE_NR:
+ case TM_COLUMN_LYRICS:
case TM_NUM_COLUMNS:
break;
}
@@ -2038,6 +2050,7 @@ static void tm_set_search_column (TM_item newcol)
case TM_COLUMN_MEDIA_TYPE:
case TM_COLUMN_SEASON_NR:
case TM_COLUMN_EPISODE_NR:
+ case TM_COLUMN_LYRICS:
case TM_NUM_COLUMNS:
gtk_tree_view_set_enable_search (GTK_TREE_VIEW (track_treeview), FALSE);
break;
@@ -2279,6 +2292,9 @@ static GtkTreeViewColumn *tm_add_column (TM_item tm_item, gint pos)
case TM_COLUMN_SOUNDCHECK:
text = _("Sndchk.");
break;
+ case TM_COLUMN_LYRICS:
+ text = _("Lyrics?");
+ break;
case TM_NUM_COLUMNS:
g_return_val_if_reached (NULL);
break;
diff --git a/src/file.c b/src/file.c
index f0682d0..12e2244 100644
--- a/src/file.c
+++ b/src/file.c
@@ -842,6 +842,7 @@ static gboolean copy_new_info (Track *from, Track *to)
case T_SEASON_NR:
case T_EPISODE_NR:
case T_GROUPING:
+ case T_LYRICS:
changed |= track_copy_item (from, to, item);
break;
case T_CATEGORY:
@@ -1400,6 +1401,7 @@ static Track *get_track_info_from_file (gchar *name, Track *orig_track)
/* set path file information */
enti->pc_path_utf8 = charset_to_utf8 (name);
enti->pc_path_locale = g_strdup (name);
+ enti->lyrics=NULL;
/* set length of file */
stat (name, &filestat);
nti->size = filestat.st_size; /* get the filesize in bytes */
@@ -2576,3 +2578,139 @@ gboolean read_soundcheck (Track *track)
return result;
}
+/* Get lyrics from file */
+gboolean get_lyrics_from_file (Track *track,gchar **lyrics)
+{
+ gchar *path;
+ gchar *buf;
+ gboolean result = FALSE;
+ ExtraTrackData *etr;
+
+ g_return_val_if_fail (track, FALSE);
+ etr = track->userdata;
+ g_return_val_if_fail (etr,FALSE);
+ path = get_file_name_from_source (track, SOURCE_PREFER_IPOD);
+ if (path)
+ {
+ switch (determine_file_type (path))
+ {
+ case FILE_TYPE_MP3:
+ result = id3_lyrics_read (path, lyrics);
+ break;
+ case FILE_TYPE_M4A:
+ case FILE_TYPE_M4P:
+ case FILE_TYPE_M4B:
+ case FILE_TYPE_M4V:
+ case FILE_TYPE_MP4:
+ result = TRUE;
+ *lyrics=g_strdup(
+ "File format unsupported now.");
+ break;
+ case FILE_TYPE_MOV:
+ case FILE_TYPE_MPG:
+ case FILE_TYPE_WAV: /* FIXME */
+ case FILE_TYPE_OGG: /* FIXME */
+ case FILE_TYPE_FLAC: /* FIXME */
+ case FILE_TYPE_UNKNOWN:
+ result = TRUE;
+ *lyrics=g_strdup(
+ "Lyrics not supported for this file format.");
+ break;
+ case FILE_TYPE_M3U:
+ case FILE_TYPE_PLS:
+ case FILE_TYPE_IMAGE:
+ case FILE_TYPE_DIRECTORY:
+ break;
+ }
+ g_free (path);
+ }
+ else
+ {
+ buf = get_track_info (track, FALSE);
+ gtkpod_warning (
+ _("Lyrics not found, file not availible (%s).\n\n"),
+ buf);
+ g_free (buf);
+ }
+ if (result)
+ {
+ if (!*lyrics) *lyrics=g_strdup("");
+ if (etr->lyrics) g_free(etr->lyrics);
+ etr->lyrics=g_strdup(*lyrics);
+ }
+ return result;
+}
+
+/* Write lyrics to file */
+gboolean write_lyrics_to_file (Track *track,const gchar *lyrics)
+{
+ gchar *path;
+ gchar *buf;
+ gboolean result = FALSE;
+ ExtraTrackData *etr;
+
+ g_return_val_if_fail (track, FALSE);
+ etr = track->userdata;
+ g_return_val_if_fail (etr,FALSE);
+ path = get_file_name_from_source (track, SOURCE_IPOD);
+ if (!path)
+ {
+ if (prefs_get_int("id3_write"))
+ {
+ path = get_file_name_from_source (track, SOURCE_LOCAL);
+ }
+ else
+ {
+ buf = get_track_info (track, FALSE);
+ gtkpod_warning (
+ _("iPod File not avalible and ID3 saving disabled in options, cannot save lyrics to: %s.\n\n"),
+ buf);
+ g_free (buf);
+ }
+ }
+ if (path!=NULL)
+ {
+ switch (determine_file_type (path))
+ {
+ case FILE_TYPE_MP3:
+ result = id3_lyrics_save (path, lyrics);
+ break;
+ case FILE_TYPE_M4A:
+ case FILE_TYPE_M4P:
+ case FILE_TYPE_M4B:
+ case FILE_TYPE_M4V:
+ case FILE_TYPE_MP4:
+ result = TRUE;
+ break;
+ case FILE_TYPE_MOV:
+ case FILE_TYPE_MPG:
+ case FILE_TYPE_WAV: /* FIXME */
+ case FILE_TYPE_OGG: /* FIXME */
+ case FILE_TYPE_FLAC: /* FIXME */
+ case FILE_TYPE_UNKNOWN:
+ result = TRUE;
+ break;
+ case FILE_TYPE_M3U:
+ case FILE_TYPE_PLS:
+ case FILE_TYPE_IMAGE:
+ case FILE_TYPE_DIRECTORY:
+ break;
+ }
+ g_free (path);
+ }
+ else
+ {
+ buf = get_track_info (track, FALSE);
+ gtkpod_warning (
+ _("Lyrics not found, file not availible (%s).\n\n"),
+ buf);
+ g_free (buf);
+ }
+ if ((lyrics == NULL) || (strlen(lyrics)==0))
+ {
+ if (lyrics == NULL) lyrics = g_strdup("");
+ etr->lyrics=g_strdup(lyrics);
+ track->lyrics_flag=0x00;
+ }
+ return result;
+}
diff --git a/src/file.h b/src/file.h
index cb565b5..845b7ee 100644
--- a/src/file.h
+++ b/src/file.h
@@ -124,6 +124,8 @@ GList *export_tracklist_when_necessary (iTunesDB *itdb_s,
GList *export_trackglist_when_necessary (iTunesDB *itdb_s,
iTunesDB *itdb_d,
GList *tracks);
+gboolean get_lyrics_from_file (Track *track,gchar **lyrics);
+gboolean write_lyrics_to_file (Track *track,const gchar *lyrics);
/* needed to adapt the prefs structure */
extern const gchar *EXPORT_FILES_SPECIAL_CHARSET;
extern const gchar *EXPORT_FILES_CHECK_EXISTING;
diff --git a/src/file_itunesdb.c b/src/file_itunesdb.c
index 9fd9cf7..63777b9 100644
--- a/src/file_itunesdb.c
+++ b/src/file_itunesdb.c
@@ -81,6 +81,7 @@ struct track_extended_info
guint64 local_itdb_id;
guint64 local_track_dbid;
gboolean transferred;
+ gchar *lyrics;
};
typedef struct {
@@ -147,6 +148,8 @@ void fill_in_extended_info (Track *track, gint32 total, gint32 num)
}
if (sei) /* found info for this id! */
{
+ etr->lyrics=NULL;
+ sei->lyrics=NULL;
if (sei->pc_path_locale && !etr->pc_path_locale)
{
etr->pc_path_locale = g_strdup (sei->pc_path_locale);
@@ -307,6 +310,7 @@ static gboolean read_extended_info (gchar *name, gchar *itunes)
{
if (sei->ipod_id != 0)
{ /* normal extended information */
+ sei->lyrics=NULL;
if (hash_matched)
{
if (!extendedinfohash)
@@ -347,6 +351,7 @@ static gboolean read_extended_info (gchar *name, gchar *itunes)
{
sei = g_malloc0 (sizeof (struct track_extended_info));
sei->ipod_id = atoi (arg);
+ sei->lyrics=NULL;
}
}
else if (g_ascii_strcasecmp (line, "version") == 0)
@@ -1618,6 +1623,7 @@ static void transfer_tracks_show_failed (iTunesDB *itdb, TransferData *td)
g_return_if_fail (tr && tr->userdata);
etr = tr->userdata;
+ etr->lyrics=NULL;
buf = get_track_info (tr, FALSE);
diff --git a/src/misc_conversion.c b/src/misc_conversion.c
index 0aedd20..c58e88a 100644
--- a/src/misc_conversion.c
+++ b/src/misc_conversion.c
@@ -111,6 +111,7 @@ static const gchar *t_strings[] = {
N_("Sort Composer"),
N_("Sort TV Show"),
N_("Gapless Track Flag"),
+ N_("Lyrics"),
NULL };
/* Tooltips for prefs window */
@@ -171,6 +172,7 @@ static const gchar *t_tooltips[] = {
N_("Used for sorting on the iPod"),
N_("Used for sorting on the iPod"),
N_("Used for sorting on the iPod"),
+ NULL,
NULL
};
@@ -230,6 +232,7 @@ T_item TM_to_T (TM_item tm)
case TM_COLUMN_SORT_ALBUMARTIST: return T_SORT_ALBUMARTIST;
case TM_COLUMN_SORT_COMPOSER: return T_SORT_COMPOSER;
case TM_COLUMN_SORT_TVSHOW: return T_SORT_TVSHOW;
+ case TM_COLUMN_LYRICS: return T_LYRICS;
case TM_NUM_COLUMNS: g_return_val_if_reached (-1);
}
return -1;
diff --git a/src/misc_track.c b/src/misc_track.c
index 5f36b21..820c5f2 100644
--- a/src/misc_track.c
+++ b/src/misc_track.c
@@ -882,6 +882,9 @@ gchar **track_get_item_pointer (Track *track, T_item t_item)
case T_SORT_TVSHOW:
result = &track->sort_tvshow;
break;
+ case T_LYRICS:
+ result = &etr->lyrics;
+ break;
case T_ALL:
case T_IPOD_ID:
case T_TRACK_NR:
@@ -989,6 +992,7 @@ gboolean track_copy_item (Track *frtrack, Track *totrack, T_item item)
case T_SORT_ALBUMARTIST:
case T_SORT_COMPOSER:
case T_SORT_TVSHOW:
+ case T_LYRICS:
fritem = track_get_item (frtrack, item);
toitem_ptr = track_get_item_pointer (totrack, item);
g_return_val_if_fail (fritem, FALSE);
@@ -1007,6 +1011,10 @@ gboolean track_copy_item (Track *frtrack, Track *totrack, T_item item)
changed = TRUE;
}
}
+ else if ((changed) && (item == T_LYRICS))
+ {
+ write_lyrics_to_file (totrack,etotr->lyrics);
+ }
/* handle items that have two entries */
if (item == T_PC_PATH)
{
@@ -1418,6 +1426,9 @@ gchar *track_get_text (Track *track, T_item item)
case T_ITEM_NUM:
case T_GAPLESS_TRACK_FLAG:
break;
+ case T_LYRICS:
+ get_lyrics_from_file (track,&text);
+ break;
}
return text;
}
@@ -1501,6 +1512,16 @@ gboolean track_set_text (Track *track, const gchar *new_text, T_item item)
changed = TRUE;
}
break;
+ case T_LYRICS:
+ if ((etr->lyrics == NULL) ||
+ (strcmp(etr->lyrics,new_text) != 0))
+ {
+ g_free(etr->lyrics);
+ etr->lyrics=g_strdup(new_text);
+ /*write_lyrics_to_file (track,new_text); */
+ changed = TRUE;
+ }
+ break;
case T_TRACK_NR:
nr = atoi (new_text);
if ((nr >= 0) && (nr != track->track_nr))
diff --git a/src/mp3file.c b/src/mp3file.c
index 181f648..ba8da64 100644
--- a/src/mp3file.c
+++ b/src/mp3file.c
@@ -1261,7 +1261,7 @@ static void id3_set_string (struct id3_tag *tag,
field = id3_frame_field (frame, 0);
id3_field_settextencoding(field, encoding);
- if (strcmp (frame_name, ID3_FRAME_COMMENT) == 0)
+ if ((strcmp (frame_name, ID3_FRAME_COMMENT) == 0) || (strcmp (frame_name, "USLT") == 0))
{
field = id3_frame_field (frame, 3);
field->type = ID3_FIELD_TYPE_STRINGFULL;
@@ -1332,7 +1332,7 @@ static void id3_set_string (struct id3_tag *tag,
}
#endif
- if (strcmp (frame_name, ID3_FRAME_COMMENT) == 0)
+ if ((strcmp (frame_name, ID3_FRAME_COMMENT) == 0) || (strcmp (frame_name, "USLT") == 0))
res = id3_field_setfullstring (field, ucs4);
else
res = id3_field_setstrings (field, 1, &ucs4);
@@ -2911,3 +2911,74 @@ Track *mp3_get_file_info (const gchar *name)
}
return track;
}
+/*
+ *
+ * @returns: TRUE on success, else FALSE.
+ */
+gboolean id3_lyrics_read (const gchar *filename,gchar **lyrics)
+{
+ struct id3_file *id3file;
+ struct id3_tag *id3tag;
+
+ g_return_val_if_fail (filename, FALSE);
+ g_return_val_if_fail (lyrics, FALSE);
+
+ if (!(id3file = id3_file_open (filename, ID3_FILE_MODE_READONLY)))
+ {
+ gchar *fbuf = charset_to_utf8 (filename);
+ g_print(_("ERROR while opening file: '%s' (%s).\n"),
+ fbuf, g_strerror(errno));
+ g_free (fbuf);
+ return FALSE;
+ }
+
+ if ((id3tag = id3_file_tag(id3file)))
+ {
+ *lyrics = id3_get_string (id3tag, "USLT");
+ }
+
+ id3_file_close (id3file);
+ return TRUE;
+}
+
+gboolean id3_lyrics_save (const gchar *filename,const gchar *lyrics)
+{
+ struct id3_file *id3file;
+ struct id3_tag *id3tag;
+ /* Using utf encoding because that's the only one iPod supports */
+ enum id3_field_textencoding encoding = ID3_FIELD_TEXTENCODING_UTF_8;
+
+
+ g_return_val_if_fail (filename, FALSE);
+
+
+ id3file = id3_file_open (filename, ID3_FILE_MODE_READWRITE);
+ if (!id3file)
+ {
+ gchar *fbuf = charset_to_utf8 (filename);
+ g_print(_("ERROR while opening file: '%s' (%s).\n"),
+ fbuf, g_strerror(errno));
+ g_free (fbuf);
+ return FALSE;
+ }
+
+ if ((id3tag = id3_file_tag(id3file)))
+ {
+ id3_set_string (id3tag, "USLT", lyrics, encoding);
+ }
+
+ if (id3_file_update(id3file) != 0)
+ {
+ gchar *fbuf = charset_to_utf8 (filename);
+ g_print(_("ERROR while writing tag to file: '%s' (%s).\n"),
+ fbuf, g_strerror(errno));
+ g_free (fbuf);
+ return FALSE;
+ }
+
+ id3_file_close (id3file);
+
+ return TRUE;
+}
+
+
diff --git a/src/mp3file.h b/src/mp3file.h
index 2895902..6a36516 100644
--- a/src/mp3file.h
+++ b/src/mp3file.h
@@ -38,4 +38,7 @@ gboolean mp3_read_soundcheck (const gchar *path, Track *track);
gboolean mp3_read_gapless (const gchar *path, Track *track);
gboolean id3_read_tags (const gchar *name, Track *track);
+gboolean id3_lyrics_read (const gchar *filename,gchar **lyrics);
+gboolean id3_lyrics_save (const gchar *filename,const gchar *lyrics);
+
#endif
-------------------------------------------------------------------------
This SF.Net email is sponsored by the Moblin Your Move Developer's challenge
Build the coolest Linux based applications with Moblin SDK & win great prizes
Grand prize is a trip for two to an Open Source event anywhere in the world
http://moblin-contest.org/redirect.php?banner_id=100&url=/_______________________________________________
Gtkpod-devel mailing list
Gtkpod-devel@...
https://lists.sourceforge.net/lists/listinfo/gtkpod-devel