1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
3 * arch-tag: Implementation of local song properties dialog
5 * Copyright (C) 2002 Olivier Martin <omartin@ifrance.com>
6 * Copyright (C) 2003 Colin Walters <walters@verbum.org>
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
25 * Yes, this code is ugly.
34 #define EPSILON 0.0001
36 #include <glib/gi18n.h>
38 #include <glade/glade.h>
39 #include <libgnomevfs/gnome-vfs.h>
40 #include <libgnomevfs/gnome-vfs-utils.h>
43 #include "rhythmdb-property-model.h"
44 #include "rb-song-info.h"
45 #include "rb-glade-helpers.h"
46 #include "rb-dialog.h"
47 #include "rb-rating.h"
48 #include "rb-preferences.h"
49 #include "eel-gconf-extensions.h"
50 #include "rb-source.h"
53 static void rb_song_info_class_init (RBSongInfoClass
*klass
);
54 static void rb_song_info_init (RBSongInfo
*song_info
);
55 static GObject
*rb_song_info_constructor (GType type
, guint n_construct_properties
,
56 GObjectConstructParam
*construct_properties
);
58 static void rb_song_info_show (GtkWidget
*widget
);
59 static void rb_song_info_finalize (GObject
*object
);
60 static void rb_song_info_set_property (GObject
*object
,
64 static void rb_song_info_get_property (GObject
*object
,
68 static void rb_song_info_response_cb (GtkDialog
*dialog
,
70 RBSongInfo
*song_info
);
71 static void rb_song_info_populate_dialog (RBSongInfo
*song_info
);
72 static void rb_song_info_populate_dialog_multiple (RBSongInfo
*song_info
);
73 static void rb_song_info_update_duration (RBSongInfo
*song_info
);
74 static void rb_song_info_update_location (RBSongInfo
*song_info
);
75 static void rb_song_info_update_filesize (RBSongInfo
*song_info
);
76 static void rb_song_info_update_play_count (RBSongInfo
*song_info
);
77 static void rb_song_info_update_last_played (RBSongInfo
*song_info
);
78 static void rb_song_info_update_bitrate (RBSongInfo
*song_info
);
79 static void rb_song_info_update_buttons (RBSongInfo
*song_info
);
80 static void rb_song_info_update_rating (RBSongInfo
*song_info
);
81 static void rb_song_info_update_year (RBSongInfo
*song_info
);
82 static void rb_song_info_update_playback_error (RBSongInfo
*song_info
);
84 static void rb_song_info_backward_clicked_cb (GtkWidget
*button
,
85 RBSongInfo
*song_info
);
86 static void rb_song_info_forward_clicked_cb (GtkWidget
*button
,
87 RBSongInfo
*song_info
);
88 static void rb_song_info_query_model_changed_cb (GObject
*source
,
90 RBSongInfo
*song_info
);
91 static void rb_song_info_rated_cb (RBRating
*rating
,
93 RBSongInfo
*song_info
);
94 static void rb_song_info_mnemonic_cb (GtkWidget
*target
);
95 static void rb_song_info_sync_entries (RBSongInfo
*dialog
);
97 struct RBSongInfoPrivate
101 RBEntryView
*entry_view
;
102 RhythmDBQueryModel
*query_model
;
104 /* information on the displayed song */
105 RhythmDBEntry
*current_entry
;
106 GList
*selected_entries
;
110 /* the dialog widgets */
119 GtkWidget
*track_cur
;
122 GtkWidget
*playback_error_box
;
123 GtkWidget
*playback_error_label
;
130 GtkWidget
*play_count
;
131 GtkWidget
*last_played
;
134 RhythmDBPropertyModel
* albums
;
135 RhythmDBPropertyModel
* artists
;
136 RhythmDBPropertyModel
* genres
;
139 #define RB_SONG_INFO_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_SONG_INFO, RBSongInfoPrivate))
144 POST_METADATA_CHANGE
,
156 static guint rb_song_info_signals
[LAST_SIGNAL
] = { 0 };
158 G_DEFINE_TYPE (RBSongInfo
, rb_song_info
, GTK_TYPE_DIALOG
)
161 rb_song_info_class_init (RBSongInfoClass
*klass
)
163 GObjectClass
*object_class
= G_OBJECT_CLASS (klass
);
164 GtkWidgetClass
*widget_class
= GTK_WIDGET_CLASS (klass
);
166 object_class
->set_property
= rb_song_info_set_property
;
167 object_class
->get_property
= rb_song_info_get_property
;
168 object_class
->constructor
= rb_song_info_constructor
;
170 widget_class
->show
= rb_song_info_show
;
172 g_object_class_install_property (object_class
,
174 g_param_spec_object ("source",
178 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
179 g_object_class_install_property (object_class
,
181 g_param_spec_object ("entry-view",
183 "RBEntryView object",
185 G_PARAM_READWRITE
| G_PARAM_CONSTRUCT_ONLY
));
186 g_object_class_install_property (object_class
,
188 g_param_spec_boxed ("current-entry",
190 "RhythmDBEntry object",
194 object_class
->finalize
= rb_song_info_finalize
;
196 rb_song_info_signals
[PRE_METADATA_CHANGE
] =
197 g_signal_new ("pre-metadata-change",
198 G_OBJECT_CLASS_TYPE (object_class
),
200 G_STRUCT_OFFSET (RBSongInfoClass
, pre_metadata_change
),
202 g_cclosure_marshal_VOID__BOXED
,
205 RHYTHMDB_TYPE_ENTRY
);
207 rb_song_info_signals
[POST_METADATA_CHANGE
] =
208 g_signal_new ("post-metadata-change",
209 G_OBJECT_CLASS_TYPE (object_class
),
211 G_STRUCT_OFFSET (RBSongInfoClass
, post_metadata_change
),
213 g_cclosure_marshal_VOID__BOXED
,
216 RHYTHMDB_TYPE_ENTRY
);
218 g_type_class_add_private (klass
, sizeof (RBSongInfoPrivate
));
222 rb_song_info_init (RBSongInfo
*song_info
)
224 /* create the dialog and some buttons backward - forward - close */
225 song_info
->priv
= RB_SONG_INFO_GET_PRIVATE (song_info
);
227 g_signal_connect_object (G_OBJECT (song_info
),
229 G_CALLBACK (rb_song_info_response_cb
),
232 gtk_dialog_set_has_separator (GTK_DIALOG (song_info
), FALSE
);
234 gtk_container_set_border_width (GTK_CONTAINER (song_info
), 5);
235 gtk_window_set_resizable (GTK_WINDOW (song_info
), TRUE
);
236 gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (song_info
)->vbox
), 2);
240 rb_song_info_show (GtkWidget
*widget
)
242 if (GTK_WIDGET_CLASS (rb_song_info_parent_class
)->show
)
243 GTK_WIDGET_CLASS (rb_song_info_parent_class
)->show (widget
);
245 rb_song_info_update_playback_error (RB_SONG_INFO (widget
));
249 rb_song_info_construct_single (RBSongInfo
*song_info
, GladeXML
*xml
,
252 song_info
->priv
->backward
= gtk_dialog_add_button (GTK_DIALOG (song_info
),
256 g_signal_connect_object (G_OBJECT (song_info
->priv
->backward
),
258 G_CALLBACK (rb_song_info_backward_clicked_cb
),
261 song_info
->priv
->forward
= gtk_dialog_add_button (GTK_DIALOG (song_info
),
262 GTK_STOCK_GO_FORWARD
,
265 g_signal_connect_object (G_OBJECT (song_info
->priv
->forward
),
267 G_CALLBACK (rb_song_info_forward_clicked_cb
),
270 gtk_window_set_title (GTK_WINDOW (song_info
), _("Song Properties"));
272 /* get the widgets from the XML */
273 song_info
->priv
->notebook
= glade_xml_get_widget (xml
, "song_info_vbox");
274 song_info
->priv
->title
= glade_xml_get_widget (xml
, "song_info_title");
275 song_info
->priv
->track_cur
= glade_xml_get_widget (xml
, "song_info_track_cur");
276 song_info
->priv
->bitrate
= glade_xml_get_widget (xml
, "song_info_bitrate");
277 song_info
->priv
->duration
= glade_xml_get_widget (xml
, "song_info_duration");
278 song_info
->priv
->location
= glade_xml_get_widget (xml
, "song_info_location");
279 song_info
->priv
->filesize
= glade_xml_get_widget (xml
, "song_info_filesize");
280 song_info
->priv
->play_count
= glade_xml_get_widget (xml
, "song_info_playcount");
281 song_info
->priv
->last_played
= glade_xml_get_widget (xml
, "song_info_lastplayed");
282 song_info
->priv
->name
= glade_xml_get_widget (xml
, "song_info_name");
284 rb_glade_boldify_label (xml
, "title_label");
285 rb_glade_boldify_label (xml
, "trackn_label");
286 rb_glade_boldify_label (xml
, "name_label");
287 rb_glade_boldify_label (xml
, "location_label");
288 rb_glade_boldify_label (xml
, "filesize_label");
289 rb_glade_boldify_label (xml
, "last_played_label");
290 rb_glade_boldify_label (xml
, "play_count_label");
291 rb_glade_boldify_label (xml
, "duration_label");
292 rb_glade_boldify_label (xml
, "bitrate_label");
294 /* whenever you press a mnemonic, the associated GtkEntry's text gets highlighted */
295 g_signal_connect_object (G_OBJECT (song_info
->priv
->title
),
297 G_CALLBACK (rb_song_info_mnemonic_cb
),
299 g_signal_connect_object (G_OBJECT (song_info
->priv
->track_cur
),
301 G_CALLBACK (rb_song_info_mnemonic_cb
),
304 gtk_editable_set_editable (GTK_EDITABLE (song_info
->priv
->title
), editable
);
305 gtk_editable_set_editable (GTK_EDITABLE (song_info
->priv
->track_cur
), editable
);
308 gtk_widget_grab_focus (song_info
->priv
->title
);
313 rb_song_info_construct_multiple (RBSongInfo
*song_info
, GladeXML
*xml
,
316 gtk_window_set_title (GTK_WINDOW (song_info
),
317 _("Multiple Song Properties"));
318 gtk_widget_grab_focus (song_info
->priv
->artist
);
320 song_info
->priv
->notebook
= glade_xml_get_widget (xml
, "song_info_notebook");
324 rb_song_info_add_completion (GtkEntry
*entry
, RhythmDBPropertyModel
*propmodel
)
326 GtkEntryCompletion
* completion
;
328 completion
= gtk_entry_completion_new();
329 gtk_entry_completion_set_model (completion
, GTK_TREE_MODEL (propmodel
));
330 gtk_entry_completion_set_text_column (completion
, RHYTHMDB_PROPERTY_MODEL_COLUMN_TITLE
);
331 gtk_entry_set_completion (entry
, completion
);
332 g_object_unref (completion
);
336 rb_song_info_constructor (GType type
, guint n_construct_properties
,
337 GObjectConstructParam
*construct_properties
)
339 RBSongInfo
*song_info
;
340 RBSongInfoClass
*klass
;
342 GList
*selected_entries
;
344 gboolean editable
= TRUE
;
347 klass
= RB_SONG_INFO_CLASS (g_type_class_peek (RB_TYPE_SONG_INFO
));
349 song_info
= RB_SONG_INFO (G_OBJECT_CLASS (rb_song_info_parent_class
)
350 ->constructor (type
, n_construct_properties
, construct_properties
));
352 selected_entries
= rb_entry_view_get_selected_entries (song_info
->priv
->entry_view
);
354 g_return_val_if_fail (selected_entries
!= NULL
, NULL
);
356 for (tem
= selected_entries
; tem
; tem
= tem
->next
) {
357 if (!rhythmdb_entry_is_editable (song_info
->priv
->db
,
358 selected_entries
->data
)) {
364 song_info
->priv
->editable
= editable
;
366 if (selected_entries
->next
== NULL
) {
367 song_info
->priv
->current_entry
= selected_entries
->data
;
368 song_info
->priv
->selected_entries
= NULL
;
370 g_list_foreach (selected_entries
, (GFunc
)rhythmdb_entry_unref
, NULL
);
371 g_list_free (selected_entries
);
373 song_info
->priv
->current_entry
= NULL
;
374 song_info
->priv
->selected_entries
= selected_entries
;
377 if (song_info
->priv
->current_entry
) {
378 xml
= rb_glade_xml_new ("song-info.glade",
381 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (song_info
)->vbox
),
382 glade_xml_get_widget (xml
, "song_info_vbox"));
384 xml
= rb_glade_xml_new ("song-info-multiple.glade",
385 "song_info_notebook",
387 gtk_container_add (GTK_CONTAINER (GTK_DIALOG (song_info
)->vbox
),
388 glade_xml_get_widget (xml
, "song_info_notebook"));
391 glade_xml_signal_autoconnect (xml
);
393 song_info
->priv
->artist
= glade_xml_get_widget (xml
, "song_info_artist");
394 song_info
->priv
->album
= glade_xml_get_widget (xml
, "song_info_album");
395 song_info
->priv
->genre
= glade_xml_get_widget (xml
, "song_info_genre");
396 song_info
->priv
->year
= glade_xml_get_widget (xml
, "song_info_year");
397 song_info
->priv
->playback_error_box
= glade_xml_get_widget (xml
, "song_info_error_box");
398 song_info
->priv
->playback_error_label
= glade_xml_get_widget (xml
, "song_info_error_label");
399 song_info
->priv
->disc_cur
= glade_xml_get_widget (xml
, "song_info_disc_cur");
401 rb_song_info_add_completion (GTK_ENTRY (song_info
->priv
->genre
), song_info
->priv
->genres
);
402 rb_song_info_add_completion (GTK_ENTRY (song_info
->priv
->artist
), song_info
->priv
->artists
);
403 rb_song_info_add_completion (GTK_ENTRY (song_info
->priv
->album
), song_info
->priv
->albums
);
405 rb_glade_boldify_label (xml
, "album_label");
406 rb_glade_boldify_label (xml
, "artist_label");
407 rb_glade_boldify_label (xml
, "genre_label");
408 rb_glade_boldify_label (xml
, "year_label");
409 rb_glade_boldify_label (xml
, "rating_label");
410 rb_glade_boldify_label (xml
, "discn_label");
412 g_signal_connect_object (G_OBJECT (song_info
->priv
->artist
),
414 G_CALLBACK (rb_song_info_mnemonic_cb
),
416 g_signal_connect_object (G_OBJECT (song_info
->priv
->album
),
418 G_CALLBACK (rb_song_info_mnemonic_cb
),
420 g_signal_connect_object (G_OBJECT (song_info
->priv
->genre
),
422 G_CALLBACK (rb_song_info_mnemonic_cb
),
424 g_signal_connect_object (G_OBJECT (song_info
->priv
->year
),
426 G_CALLBACK (rb_song_info_mnemonic_cb
),
428 g_signal_connect_object (G_OBJECT (song_info
->priv
->disc_cur
),
430 G_CALLBACK (rb_song_info_mnemonic_cb
),
433 /* this widget has to be customly created */
434 song_info
->priv
->rating
= GTK_WIDGET (rb_rating_new ());
435 g_signal_connect_object (song_info
->priv
->rating
, "rated",
436 G_CALLBACK (rb_song_info_rated_cb
),
437 G_OBJECT (song_info
), 0);
438 gtk_container_add (GTK_CONTAINER (glade_xml_get_widget (xml
, "song_info_rating_container")),
439 song_info
->priv
->rating
);
441 gtk_editable_set_editable (GTK_EDITABLE (song_info
->priv
->artist
), editable
);
442 gtk_editable_set_editable (GTK_EDITABLE (song_info
->priv
->album
), editable
);
443 gtk_editable_set_editable (GTK_EDITABLE (song_info
->priv
->genre
), editable
);
444 gtk_editable_set_editable (GTK_EDITABLE (song_info
->priv
->year
), editable
);
445 gtk_editable_set_editable (GTK_EDITABLE (song_info
->priv
->disc_cur
), editable
);
447 /* Finish construction */
448 if (song_info
->priv
->current_entry
) {
449 rb_song_info_construct_single (song_info
, xml
, editable
);
450 rb_song_info_populate_dialog (song_info
);
452 rb_song_info_construct_multiple (song_info
, xml
, editable
);
453 rb_song_info_populate_dialog_multiple (song_info
);
455 g_object_get (G_OBJECT (song_info
->priv
->source
), "shell", &shell
, NULL
);
456 g_signal_emit_by_name (G_OBJECT (shell
), "create_song_info", song_info
, (song_info
->priv
->current_entry
== NULL
));
457 g_object_unref (G_OBJECT (shell
));
459 gtk_dialog_add_button (GTK_DIALOG (song_info
),
463 gtk_dialog_set_default_response (GTK_DIALOG (song_info
),
466 g_object_unref (G_OBJECT (xml
));
467 return G_OBJECT (song_info
);
471 rb_song_info_finalize (GObject
*object
)
473 RBSongInfo
*song_info
;
475 g_return_if_fail (object
!= NULL
);
476 g_return_if_fail (RB_IS_SONG_INFO (object
));
478 song_info
= RB_SONG_INFO (object
);
480 g_return_if_fail (song_info
->priv
!= NULL
);
482 g_signal_handlers_disconnect_by_func (song_info
->priv
->source
,
483 G_CALLBACK (rb_song_info_query_model_changed_cb
),
486 g_object_unref (song_info
->priv
->albums
);
487 g_object_unref (song_info
->priv
->artists
);
488 g_object_unref (song_info
->priv
->genres
);
490 g_object_unref (song_info
->priv
->db
);
491 g_object_unref (song_info
->priv
->source
);
492 g_object_unref (song_info
->priv
->query_model
);
494 if (song_info
->priv
->selected_entries
!= NULL
) {
495 g_list_foreach (song_info
->priv
->selected_entries
, (GFunc
)rhythmdb_entry_unref
, NULL
);
496 g_list_free (song_info
->priv
->selected_entries
);
499 G_OBJECT_CLASS (rb_song_info_parent_class
)->finalize (object
);
503 rb_song_info_set_source_internal (RBSongInfo
*song_info
,
506 RhythmDB
*old_db
= song_info
->priv
->db
;
508 if (song_info
->priv
->source
!= NULL
) {
509 g_signal_handlers_disconnect_by_func (song_info
->priv
->source
,
510 rb_song_info_query_model_changed_cb
,
512 g_object_unref (song_info
->priv
->source
);
513 g_object_unref (song_info
->priv
->query_model
);
514 g_object_unref (song_info
->priv
->db
);
517 song_info
->priv
->source
= source
;
519 g_object_ref (song_info
->priv
->source
);
521 g_object_get (G_OBJECT (song_info
->priv
->source
), "query-model", &song_info
->priv
->query_model
, NULL
);
523 g_signal_connect_object (G_OBJECT (song_info
->priv
->source
),
524 "notify::query-model",
525 G_CALLBACK (rb_song_info_query_model_changed_cb
),
528 g_object_get (G_OBJECT (song_info
->priv
->query_model
), "db", &song_info
->priv
->db
, NULL
);
530 if (old_db
!= song_info
->priv
->db
) {
531 if (song_info
->priv
->albums
) {
532 g_object_unref (song_info
->priv
->albums
);
534 if (song_info
->priv
->artists
) {
535 g_object_unref (song_info
->priv
->artists
);
537 if (song_info
->priv
->genres
) {
538 g_object_unref (song_info
->priv
->genres
);
541 song_info
->priv
->albums
= rhythmdb_property_model_new (song_info
->priv
->db
, RHYTHMDB_PROP_ALBUM
);
542 song_info
->priv
->artists
= rhythmdb_property_model_new (song_info
->priv
->db
, RHYTHMDB_PROP_ARTIST
);
543 song_info
->priv
->genres
= rhythmdb_property_model_new (song_info
->priv
->db
, RHYTHMDB_PROP_GENRE
);
545 g_object_set (song_info
->priv
->albums
, "query-model", song_info
->priv
->query_model
, NULL
);
546 g_object_set (song_info
->priv
->artists
, "query-model", song_info
->priv
->query_model
, NULL
);
547 g_object_set (song_info
->priv
->genres
, "query-model", song_info
->priv
->query_model
, NULL
);
549 if(song_info
->priv
->album
) {
550 GtkEntryCompletion
*comp
= gtk_entry_get_completion (GTK_ENTRY (song_info
->priv
->album
));
551 gtk_entry_completion_set_model (comp
, GTK_TREE_MODEL (song_info
->priv
->albums
));
554 if(song_info
->priv
->artist
) {
555 GtkEntryCompletion
*comp
= gtk_entry_get_completion (GTK_ENTRY (song_info
->priv
->artist
));
556 gtk_entry_completion_set_model (comp
, GTK_TREE_MODEL (song_info
->priv
->artist
));
559 if(song_info
->priv
->genre
) {
560 GtkEntryCompletion
*comp
= gtk_entry_get_completion (GTK_ENTRY (song_info
->priv
->genre
));
561 gtk_entry_completion_set_model (comp
, GTK_TREE_MODEL (song_info
->priv
->genre
));
567 rb_song_info_set_property (GObject
*object
,
572 RBSongInfo
*song_info
= RB_SONG_INFO (object
);
576 rb_song_info_set_source_internal (song_info
, g_value_get_object (value
));
578 case PROP_ENTRY_VIEW
:
579 song_info
->priv
->entry_view
= g_value_get_object (value
);
582 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
588 rb_song_info_get_property (GObject
*object
,
593 RBSongInfo
*song_info
= RB_SONG_INFO (object
);
597 g_value_set_object (value
, song_info
->priv
->source
);
599 case PROP_ENTRY_VIEW
:
600 g_value_set_object (value
, song_info
->priv
->entry_view
);
602 case PROP_CURRENT_ENTRY
:
603 g_value_set_boxed (value
, song_info
->priv
->current_entry
);
606 G_OBJECT_WARN_INVALID_PROPERTY_ID (object
, prop_id
, pspec
);
612 rb_song_info_new (RBSource
*source
, RBEntryView
*entry_view
)
614 RBSongInfo
*song_info
;
616 g_return_val_if_fail (RB_IS_SOURCE (source
), NULL
);
618 entry_view
= rb_source_get_entry_view (source
);
620 if (rb_entry_view_have_selection (entry_view
) == FALSE
)
623 /* create the dialog */
624 song_info
= g_object_new (RB_TYPE_SONG_INFO
,
626 "entry-view", entry_view
,
629 g_return_val_if_fail (song_info
->priv
!= NULL
, NULL
);
631 return GTK_WIDGET (song_info
);
635 rb_song_info_append_page (RBSongInfo
*info
, const char *title
, GtkWidget
*page
)
640 label
= gtk_label_new (title
);
641 page_num
= gtk_notebook_append_page (GTK_NOTEBOOK (info
->priv
->notebook
),
644 gtk_notebook_set_show_tabs (GTK_NOTEBOOK (info
->priv
->notebook
), TRUE
);
649 typedef void (*RBSongInfoSelectionFunc
)(RBSongInfo
*info
,
650 RhythmDBEntry
*entry
,
654 rb_song_info_selection_for_each (RBSongInfo
*info
, RBSongInfoSelectionFunc func
,
657 if (info
->priv
->current_entry
)
658 func (info
, info
->priv
->current_entry
, data
);
661 for (tem
= info
->priv
->selected_entries
; tem
; tem
= tem
->next
)
662 func (info
, tem
->data
, data
);
667 rb_song_info_response_cb (GtkDialog
*dialog
,
669 RBSongInfo
*song_info
)
671 if (response_id
== GTK_RESPONSE_CLOSE
) {
672 rb_song_info_sync_entries (RB_SONG_INFO (dialog
));
673 gtk_widget_destroy (GTK_WIDGET (dialog
));
678 rb_song_info_set_entry_rating (RBSongInfo
*info
,
679 RhythmDBEntry
*entry
,
682 GValue value
= {0, };
683 double trouble
= *((double*) data
);
685 /* set the new value for the song */
686 g_value_init (&value
, G_TYPE_DOUBLE
);
687 g_value_set_double (&value
, trouble
);
688 rhythmdb_entry_set (info
->priv
->db
, entry
, RHYTHMDB_PROP_RATING
, &value
);
689 g_value_unset (&value
);
693 rb_song_info_rated_cb (RBRating
*rating
,
695 RBSongInfo
*song_info
)
697 g_return_if_fail (RB_IS_RATING (rating
));
698 g_return_if_fail (RB_IS_SONG_INFO (song_info
));
699 g_return_if_fail (score
>= 0 && score
<= 5 );
701 rb_song_info_selection_for_each (song_info
,
702 rb_song_info_set_entry_rating
,
704 rhythmdb_commit (song_info
->priv
->db
);
706 g_object_set (G_OBJECT (song_info
->priv
->rating
),
712 rb_song_info_mnemonic_cb (GtkWidget
*target
)
714 g_return_if_fail (GTK_IS_EDITABLE (target
) || GTK_IS_TEXT_VIEW (target
));
716 gtk_widget_grab_focus (target
);
718 if (GTK_IS_EDITABLE (target
)) {
719 gtk_editable_select_region (GTK_EDITABLE (target
), 0, -1);
720 } else { /* GtkTextViews need special treatment */
721 g_signal_emit_by_name (G_OBJECT (target
), "select-all");
726 rb_song_info_populate_num_field (GtkEntry
*field
, gulong num
)
730 tmp
= g_strdup_printf ("%.2ld", num
);
732 tmp
= g_strdup (_("Unknown"));
733 gtk_entry_set_text (field
, tmp
);
738 rb_song_info_populate_dialog_multiple (RBSongInfo
*song_info
)
740 gboolean mixed_artists
= FALSE
;
741 gboolean mixed_albums
= FALSE
;
742 gboolean mixed_genres
= FALSE
;
743 gboolean mixed_years
= FALSE
;
744 gboolean mixed_disc_numbers
= FALSE
;
745 gboolean mixed_ratings
= FALSE
;
746 const char *artist
= NULL
;
747 const char *album
= NULL
;
748 const char *genre
= NULL
;
751 double rating
= 0.0; /* Zero is used for both "unrated" and "mixed ratings" too */
754 g_assert (song_info
->priv
->selected_entries
);
756 for (l
= song_info
->priv
->selected_entries
; l
!= NULL
; l
= g_list_next (l
)) {
757 RhythmDBEntry
*entry
;
758 const char *entry_artist
;
759 const char *entry_album
;
760 const char *entry_genre
;
762 int entry_disc_number
;
765 entry
= (RhythmDBEntry
*)l
->data
;
766 entry_artist
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_ARTIST
);
767 entry_album
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_ALBUM
);
768 entry_genre
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_GENRE
);
769 entry_year
= rhythmdb_entry_get_ulong (entry
, RHYTHMDB_PROP_YEAR
);
770 entry_disc_number
= rhythmdb_entry_get_ulong (entry
, RHYTHMDB_PROP_DISC_NUMBER
);
771 entry_rating
= rhythmdb_entry_get_double (entry
, RHYTHMDB_PROP_RATING
);
773 /* grab first valid values */
775 artist
= entry_artist
;
782 if (disc_number
== 0)
783 disc_number
= entry_disc_number
;
784 if (fabs(rating
) < EPSILON
)
785 rating
= entry_rating
;
787 /* locate mixed values */
788 if (artist
!= entry_artist
)
789 mixed_artists
= TRUE
;
790 if (album
!= entry_album
)
792 if (genre
!= entry_genre
)
794 if (year
!= entry_year
)
796 if (disc_number
!= entry_disc_number
)
797 mixed_disc_numbers
= TRUE
;
798 if (fabs(rating
- entry_rating
) >= EPSILON
)
799 mixed_ratings
= TRUE
;
801 /* don't continue search if everything is mixed */
802 if (mixed_artists
&& mixed_albums
&& mixed_genres
&&
803 mixed_years
&& mixed_disc_numbers
&& mixed_ratings
)
807 if (!mixed_artists
&& artist
!= NULL
)
808 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->artist
), artist
);
809 if (!mixed_albums
&& album
!= NULL
)
810 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->album
), album
);
811 if (!mixed_genres
&& genre
!= NULL
)
812 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->genre
), genre
);
813 if (!mixed_years
&& year
!= 0)
814 rb_song_info_populate_num_field (GTK_ENTRY (song_info
->priv
->year
), year
);
815 if (!mixed_disc_numbers
&& disc_number
!= 0)
816 rb_song_info_populate_num_field (GTK_ENTRY (song_info
->priv
->disc_cur
), disc_number
);
817 if (!mixed_ratings
&& fabs(rating
) >= EPSILON
)
818 g_object_set (G_OBJECT (song_info
->priv
->rating
), "rating", rating
, NULL
);
822 rb_song_info_populate_dialog (RBSongInfo
*song_info
)
828 g_assert (song_info
->priv
->current_entry
);
830 /* update the buttons sensitivity */
831 rb_song_info_update_buttons (song_info
);
833 text
= rhythmdb_entry_get_string (song_info
->priv
->current_entry
, RHYTHMDB_PROP_TITLE
);
834 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->title
), text
);
836 tmp
= g_strdup_printf (_("%s Properties"), text
);
837 gtk_window_set_title (GTK_WINDOW (song_info
), tmp
);
840 text
= rhythmdb_entry_get_string (song_info
->priv
->current_entry
, RHYTHMDB_PROP_ARTIST
);
841 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->artist
), text
);
842 text
= rhythmdb_entry_get_string (song_info
->priv
->current_entry
, RHYTHMDB_PROP_ALBUM
);
843 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->album
), text
);
844 text
= rhythmdb_entry_get_string (song_info
->priv
->current_entry
, RHYTHMDB_PROP_GENRE
);
845 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->genre
), text
);
847 num
= rhythmdb_entry_get_ulong (song_info
->priv
->current_entry
, RHYTHMDB_PROP_TRACK_NUMBER
);
848 rb_song_info_populate_num_field (GTK_ENTRY (song_info
->priv
->track_cur
), num
);
849 num
= rhythmdb_entry_get_ulong (song_info
->priv
->current_entry
, RHYTHMDB_PROP_DISC_NUMBER
);
850 rb_song_info_populate_num_field (GTK_ENTRY (song_info
->priv
->disc_cur
), num
);
852 rb_song_info_update_duration (song_info
);
853 rb_song_info_update_location (song_info
);
854 rb_song_info_update_filesize (song_info
);
855 rb_song_info_update_play_count (song_info
);
856 rb_song_info_update_last_played (song_info
);
857 rb_song_info_update_bitrate (song_info
);
858 rb_song_info_update_rating (song_info
);
859 rb_song_info_update_year (song_info
);
860 rb_song_info_update_playback_error (song_info
);
864 rb_song_info_update_playback_error (RBSongInfo
*song_info
)
866 char *message
= NULL
;
868 if (!song_info
->priv
->current_entry
)
871 message
= rhythmdb_entry_dup_string (song_info
->priv
->current_entry
, RHYTHMDB_PROP_PLAYBACK_ERROR
);
874 gtk_label_set_text (GTK_LABEL (song_info
->priv
->playback_error_label
),
876 gtk_widget_show (song_info
->priv
->playback_error_box
);
878 gtk_label_set_text (GTK_LABEL (song_info
->priv
->playback_error_label
),
880 gtk_widget_hide (song_info
->priv
->playback_error_box
);
887 rb_song_info_update_bitrate (RBSongInfo
*song_info
)
891 bitrate
= rhythmdb_entry_get_ulong (song_info
->priv
->current_entry
, RHYTHMDB_PROP_BITRATE
);
894 tmp
= g_strdup_printf (_("%lu kbps"), bitrate
);
896 tmp
= g_strdup (_("Unknown"));
897 gtk_label_set_text (GTK_LABEL (song_info
->priv
->bitrate
),
903 rb_song_info_update_duration (RBSongInfo
*song_info
)
907 int minutes
, seconds
;
908 duration
= rhythmdb_entry_get_ulong (song_info
->priv
->current_entry
, RHYTHMDB_PROP_DURATION
);
909 minutes
= duration
/ 60;
910 seconds
= duration
% 60;
911 text
= g_strdup_printf ("%d:%02d", minutes
, seconds
);
912 gtk_label_set_text (GTK_LABEL (song_info
->priv
->duration
), text
);
917 rb_song_info_update_filesize (RBSongInfo
*song_info
)
920 guint64 filesize
= 0;
921 filesize
= rhythmdb_entry_get_uint64 (song_info
->priv
->current_entry
, RHYTHMDB_PROP_FILE_SIZE
);
922 text
= gnome_vfs_format_file_size_for_display (filesize
);
923 gtk_label_set_text (GTK_LABEL (song_info
->priv
->filesize
), text
);
928 rb_song_info_update_location (RBSongInfo
*song_info
)
932 g_return_if_fail (song_info
!= NULL
);
934 text
= rhythmdb_entry_get_string (song_info
->priv
->current_entry
, RHYTHMDB_PROP_LOCATION
);
937 char *tmp
, *tmp_utf8
;
938 char *basename
, *dir
, *desktopdir
;
940 basename
= g_path_get_basename (text
);
941 tmp
= gnome_vfs_unescape_string_for_display (basename
);
943 tmp_utf8
= g_filename_to_utf8 (tmp
, -1, NULL
, NULL
, NULL
);
945 if (tmp_utf8
!= NULL
) {
946 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->name
),
949 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->name
),
950 _("Unknown file name"));
955 tmp
= gnome_vfs_get_local_path_from_uri (text
);
957 tmp
= g_strdup (text
);
958 dir
= g_path_get_dirname (tmp
);
960 tmp
= gnome_vfs_unescape_string_for_display (dir
);
962 tmp_utf8
= g_filename_to_utf8 (tmp
, -1, NULL
, NULL
, NULL
);
965 desktopdir
= g_build_filename (g_get_home_dir (), "Desktop", NULL
);
966 if ((tmp_utf8
!= NULL
) && (strcmp (tmp_utf8
, desktopdir
) == 0))
969 tmp_utf8
= g_strdup (_("On the desktop"));
973 if (tmp_utf8
!= NULL
) {
974 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->location
),
977 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->location
),
978 _("Unknown location"));
985 rb_song_info_backward_clicked_cb (GtkWidget
*button
,
986 RBSongInfo
*song_info
)
988 RhythmDBEntry
*new_entry
;
990 rb_song_info_sync_entries (RB_SONG_INFO (song_info
));
991 new_entry
= rhythmdb_query_model_get_previous_from_entry (song_info
->priv
->query_model
,
992 song_info
->priv
->current_entry
);
993 g_return_if_fail (new_entry
!= NULL
);
995 song_info
->priv
->current_entry
= new_entry
;
996 rb_entry_view_select_entry (song_info
->priv
->entry_view
, new_entry
);
997 rb_entry_view_scroll_to_entry (song_info
->priv
->entry_view
, new_entry
);
999 rb_song_info_populate_dialog (song_info
);
1000 g_object_notify (G_OBJECT (song_info
), "current-entry");
1001 rhythmdb_entry_unref (new_entry
);
1005 rb_song_info_forward_clicked_cb (GtkWidget
*button
,
1006 RBSongInfo
*song_info
)
1008 RhythmDBEntry
*new_entry
;
1010 rb_song_info_sync_entries (RB_SONG_INFO (song_info
));
1011 new_entry
= rhythmdb_query_model_get_next_from_entry (song_info
->priv
->query_model
,
1012 song_info
->priv
->current_entry
);
1013 g_return_if_fail (new_entry
!= NULL
);
1015 song_info
->priv
->current_entry
= new_entry
;
1016 rb_entry_view_select_entry (song_info
->priv
->entry_view
, new_entry
);
1017 rb_entry_view_scroll_to_entry (song_info
->priv
->entry_view
, new_entry
);
1019 rb_song_info_populate_dialog (song_info
);
1020 g_object_notify (G_OBJECT (song_info
), "current-entry");
1022 rhythmdb_entry_unref (new_entry
);
1026 * rb_song_info_update_buttons: update back/forward sensitivity
1029 rb_song_info_update_buttons (RBSongInfo
*song_info
)
1031 RhythmDBEntry
*entry
= NULL
;
1033 g_return_if_fail (song_info
!= NULL
);
1034 g_return_if_fail (song_info
->priv
->query_model
!= NULL
);
1036 if (!song_info
->priv
->current_entry
)
1040 entry
= rhythmdb_query_model_get_previous_from_entry (song_info
->priv
->query_model
,
1041 song_info
->priv
->current_entry
);
1043 gtk_widget_set_sensitive (song_info
->priv
->backward
, entry
!= NULL
);
1045 rhythmdb_entry_unref (entry
);
1048 entry
= rhythmdb_query_model_get_next_from_entry (song_info
->priv
->query_model
,
1049 song_info
->priv
->current_entry
);
1051 gtk_widget_set_sensitive (song_info
->priv
->forward
, entry
!= NULL
);
1053 rhythmdb_entry_unref (entry
);
1057 rb_song_info_query_model_inserted_cb (RhythmDBQueryModel
*model
,
1060 RBSongInfo
*song_info
)
1062 rb_song_info_update_buttons (song_info
);
1066 rb_song_info_query_model_deleted_cb (RhythmDBQueryModel
*model
,
1067 RhythmDBEntry
*entry
,
1068 RBSongInfo
*song_info
)
1070 rb_song_info_update_buttons (song_info
);
1074 rb_song_info_query_model_reordered_cb (RhythmDBQueryModel
*model
,
1078 RBSongInfo
*song_info
)
1080 rb_song_info_update_buttons (song_info
);
1084 rb_song_info_query_model_changed_cb (GObject
*source
,
1085 GParamSpec
*whatever
,
1086 RBSongInfo
*song_info
)
1088 if (song_info
->priv
->query_model
) {
1089 g_signal_handlers_disconnect_by_func (G_OBJECT (song_info
->priv
->query_model
),
1090 G_CALLBACK (rb_song_info_query_model_inserted_cb
),
1092 g_signal_handlers_disconnect_by_func (G_OBJECT (song_info
->priv
->query_model
),
1093 G_CALLBACK (rb_song_info_query_model_deleted_cb
),
1095 g_signal_handlers_disconnect_by_func (G_OBJECT (song_info
->priv
->query_model
),
1096 G_CALLBACK (rb_song_info_query_model_reordered_cb
),
1099 g_object_unref (G_OBJECT (song_info
->priv
->query_model
));
1102 g_object_get (source
, "query-model", &song_info
->priv
->query_model
, NULL
);
1104 g_signal_connect_object (G_OBJECT (song_info
->priv
->query_model
),
1105 "row-inserted", G_CALLBACK (rb_song_info_query_model_inserted_cb
),
1107 g_signal_connect_object (G_OBJECT (song_info
->priv
->query_model
),
1108 "row-changed", G_CALLBACK (rb_song_info_query_model_inserted_cb
),
1110 g_signal_connect_object (G_OBJECT (song_info
->priv
->query_model
),
1111 "entry-deleted", G_CALLBACK (rb_song_info_query_model_deleted_cb
),
1113 g_signal_connect_object (G_OBJECT (song_info
->priv
->query_model
),
1114 "rows-reordered", G_CALLBACK (rb_song_info_query_model_reordered_cb
),
1117 /* update next button sensitivity */
1118 rb_song_info_update_buttons (song_info
);
1122 rb_song_info_update_play_count (RBSongInfo
*song_info
)
1127 num
= rhythmdb_entry_get_ulong (song_info
->priv
->current_entry
, RHYTHMDB_PROP_PLAY_COUNT
);
1128 text
= g_strdup_printf ("%ld", num
);
1129 gtk_label_set_text (GTK_LABEL (song_info
->priv
->play_count
), text
);
1134 rb_song_info_update_last_played (RBSongInfo
*song_info
)
1137 str
= rhythmdb_entry_get_string (song_info
->priv
->current_entry
, RHYTHMDB_PROP_LAST_PLAYED_STR
);
1138 if (!strcmp ("", str
))
1140 gtk_label_set_text (GTK_LABEL (song_info
->priv
->last_played
), str
);
1144 rb_song_info_update_rating (RBSongInfo
*song_info
)
1148 g_return_if_fail (RB_IS_SONG_INFO (song_info
));
1150 rating
= rhythmdb_entry_get_double (song_info
->priv
->current_entry
, RHYTHMDB_PROP_RATING
);
1151 g_object_set (song_info
->priv
->rating
,
1157 rb_song_info_update_year (RBSongInfo
*song_info
)
1162 year
= rhythmdb_entry_get_ulong (song_info
->priv
->current_entry
, RHYTHMDB_PROP_YEAR
);
1164 text
= g_strdup_printf ("%lu", year
);
1166 text
= g_strdup (_("Unknown"));
1168 gtk_entry_set_text (GTK_ENTRY (song_info
->priv
->year
), text
);
1173 rb_song_info_sync_entries_multiple (RBSongInfo
*dialog
)
1175 const char *genre
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->genre
));
1176 const char *artist
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->artist
));
1177 const char *album
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->album
));
1178 const char *year_str
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->year
));
1179 const char *discn_str
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->disc_cur
));
1186 gboolean changed
= FALSE
;
1187 RhythmDBEntry
*entry
;
1189 if (strlen (album
) > 0) {
1190 g_value_init (&val
, G_TYPE_STRING
);
1191 g_value_set_string (&val
, album
);
1192 for (tem
= dialog
->priv
->selected_entries
; tem
; tem
= tem
->next
) {
1193 const char *entry_album
;
1195 entry
= (RhythmDBEntry
*)tem
->data
;
1196 entry_album
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_ALBUM
);
1198 if (strcmp (album
, entry_album
) == 0)
1200 rhythmdb_entry_set (dialog
->priv
->db
, entry
,
1201 RHYTHMDB_PROP_ALBUM
, &val
);
1204 g_value_unset (&val
);
1207 if (strlen (artist
) > 0) {
1208 g_value_init (&val
, G_TYPE_STRING
);
1209 g_value_set_string (&val
, artist
);
1210 for (tem
= dialog
->priv
->selected_entries
; tem
; tem
= tem
->next
) {
1211 const char *entry_artist
;
1213 entry
= (RhythmDBEntry
*)tem
->data
;
1214 entry_artist
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_ARTIST
);
1216 if (strcmp (artist
, entry_artist
) == 0)
1218 rhythmdb_entry_set (dialog
->priv
->db
, entry
,
1219 RHYTHMDB_PROP_ARTIST
, &val
);
1222 g_value_unset (&val
);
1225 if (strlen (genre
) > 0) {
1226 g_value_init (&val
, G_TYPE_STRING
);
1227 g_value_set_string (&val
, genre
);
1228 for (tem
= dialog
->priv
->selected_entries
; tem
; tem
= tem
->next
) {
1229 const char *entry_genre
;
1231 entry
= (RhythmDBEntry
*)tem
->data
;
1232 entry_genre
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_GENRE
);
1234 if (strcmp (genre
, entry_genre
) == 0)
1236 rhythmdb_entry_set (dialog
->priv
->db
, entry
,
1237 RHYTHMDB_PROP_GENRE
, &val
);
1240 g_value_unset (&val
);
1243 if (strlen (year_str
) > 0) {
1247 /* note: this will reset the day-of-year to Jan 1 for all entries */
1248 year
= g_ascii_strtoull (year_str
, &endptr
, 10);
1250 date
= g_date_new_dmy (1, G_DATE_JANUARY
, year
);
1252 type
= rhythmdb_get_property_type (dialog
->priv
->db
,
1253 RHYTHMDB_PROP_DATE
);
1255 g_value_init (&val
, type
);
1256 g_value_set_ulong (&val
, (date
? g_date_get_julian (date
) : 0));
1258 for (tem
= dialog
->priv
->selected_entries
; tem
; tem
= tem
->next
) {
1259 entry
= (RhythmDBEntry
*)tem
->data
;
1260 rhythmdb_entry_set (dialog
->priv
->db
, entry
,
1261 RHYTHMDB_PROP_DATE
, &val
);
1264 g_value_unset (&val
);
1270 discn
= g_ascii_strtoull (discn_str
, &endptr
, 10);
1271 if (endptr
!= discn_str
) {
1273 type
= rhythmdb_get_property_type (dialog
->priv
->db
,
1274 RHYTHMDB_PROP_DISC_NUMBER
);
1275 g_value_init (&val
, type
);
1276 g_value_set_ulong (&val
, discn
);
1278 for (tem
= dialog
->priv
->selected_entries
; tem
; tem
= tem
->next
) {
1279 gulong entry_disc_num
;
1281 entry
= (RhythmDBEntry
*)tem
->data
;
1282 entry_disc_num
= rhythmdb_entry_get_ulong (entry
, RHYTHMDB_PROP_DISC_NUMBER
);
1284 if (discn
!= entry_disc_num
) {
1285 rhythmdb_entry_set (dialog
->priv
->db
, entry
,
1286 RHYTHMDB_PROP_DISC_NUMBER
, &val
);
1290 g_value_unset (&val
);
1294 rhythmdb_commit (dialog
->priv
->db
);
1298 rb_song_info_sync_entry_single (RBSongInfo
*dialog
)
1304 const char *tracknum_str
;
1305 const char *discnum_str
;
1306 const char *year_str
;
1307 const char *entry_string
;
1315 gboolean changed
= FALSE
;
1316 RhythmDBEntry
*entry
= dialog
->priv
->current_entry
;
1318 title
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->title
));
1319 genre
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->genre
));
1320 artist
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->artist
));
1321 album
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->album
));
1322 tracknum_str
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->track_cur
));
1323 discnum_str
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->disc_cur
));
1324 year_str
= gtk_entry_get_text (GTK_ENTRY (dialog
->priv
->year
));
1326 g_signal_emit (dialog
, rb_song_info_signals
[PRE_METADATA_CHANGE
], 0,
1329 tracknum
= g_ascii_strtoull (tracknum_str
, &endptr
, 10);
1330 entry_val
= rhythmdb_entry_get_ulong (entry
, RHYTHMDB_PROP_TRACK_NUMBER
);
1331 if ((endptr
!= tracknum_str
) && (tracknum
!= entry_val
)) {
1332 type
= rhythmdb_get_property_type (dialog
->priv
->db
,
1333 RHYTHMDB_PROP_TRACK_NUMBER
);
1334 g_value_init (&val
, type
);
1335 g_value_set_ulong (&val
, tracknum
);
1336 rhythmdb_entry_set (dialog
->priv
->db
, entry
, RHYTHMDB_PROP_TRACK_NUMBER
, &val
);
1337 g_value_unset (&val
);
1341 discnum
= g_ascii_strtoull (discnum_str
, &endptr
, 10);
1342 entry_val
= rhythmdb_entry_get_ulong (entry
, RHYTHMDB_PROP_DISC_NUMBER
);
1343 if ((endptr
!= discnum_str
) && (discnum
!= entry_val
)) {
1344 type
= rhythmdb_get_property_type (dialog
->priv
->db
,
1345 RHYTHMDB_PROP_DISC_NUMBER
);
1346 g_value_init (&val
, type
);
1347 g_value_set_ulong (&val
, discnum
);
1348 rhythmdb_entry_set (dialog
->priv
->db
, entry
, RHYTHMDB_PROP_DISC_NUMBER
, &val
);
1349 g_value_unset (&val
);
1353 year
= g_ascii_strtoull (year_str
, &endptr
, 10);
1354 entry_val
= rhythmdb_entry_get_ulong (entry
, RHYTHMDB_PROP_YEAR
);
1355 if ((endptr
!= year_str
) &&
1356 (year
!= entry_val
||
1357 (entry_val
== 0 && year
> 0))) {
1361 if (entry_val
> 0) {
1364 julian
= rhythmdb_entry_get_ulong (entry
, RHYTHMDB_PROP_DATE
);
1365 date
= g_date_new_julian (julian
);
1366 g_date_set_year (date
, year
);
1368 date
= g_date_new_dmy (1, G_DATE_JANUARY
, year
);
1372 type
= rhythmdb_get_property_type (dialog
->priv
->db
,
1373 RHYTHMDB_PROP_DATE
);
1374 g_value_init (&val
, type
);
1375 g_value_set_ulong (&val
, (date
? g_date_get_julian (date
) : 0));
1376 rhythmdb_entry_set (dialog
->priv
->db
, entry
, RHYTHMDB_PROP_DATE
, &val
);
1379 g_value_unset (&val
);
1384 entry_string
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_TITLE
);
1385 if (strcmp (title
, entry_string
)) {
1386 type
= rhythmdb_get_property_type (dialog
->priv
->db
,
1387 RHYTHMDB_PROP_TITLE
);
1388 g_value_init (&val
, type
);
1389 g_value_set_string (&val
, title
);
1390 rhythmdb_entry_set (dialog
->priv
->db
, entry
,
1391 RHYTHMDB_PROP_TITLE
, &val
);
1392 g_value_unset (&val
);
1396 entry_string
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_ALBUM
);
1397 if (strcmp (album
, entry_string
)) {
1398 type
= rhythmdb_get_property_type (dialog
->priv
->db
,
1399 RHYTHMDB_PROP_ALBUM
);
1400 g_value_init (&val
, type
);
1401 g_value_set_string (&val
, album
);
1402 rhythmdb_entry_set (dialog
->priv
->db
, entry
,
1403 RHYTHMDB_PROP_ALBUM
, &val
);
1404 g_value_unset (&val
);
1408 entry_string
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_ARTIST
);
1409 if (strcmp (artist
, entry_string
)) {
1410 type
= rhythmdb_get_property_type (dialog
->priv
->db
,
1411 RHYTHMDB_PROP_ARTIST
);
1412 g_value_init (&val
, type
);
1413 g_value_set_string (&val
, artist
);
1414 rhythmdb_entry_set (dialog
->priv
->db
, entry
,
1415 RHYTHMDB_PROP_ARTIST
, &val
);
1416 g_value_unset (&val
);
1420 entry_string
= rhythmdb_entry_get_string (entry
, RHYTHMDB_PROP_GENRE
);
1421 if (strcmp (genre
, entry_string
)) {
1422 type
= rhythmdb_get_property_type (dialog
->priv
->db
,
1423 RHYTHMDB_PROP_GENRE
);
1424 g_value_init (&val
, type
);
1425 g_value_set_string (&val
, genre
);
1426 rhythmdb_entry_set (dialog
->priv
->db
, entry
,
1427 RHYTHMDB_PROP_GENRE
, &val
);
1428 g_value_unset (&val
);
1432 /* FIXME: when an entry is SYNCed, a changed signal is emitted, and
1433 * this signal is also emitted, aren't they redundant?
1435 g_signal_emit (G_OBJECT (dialog
), rb_song_info_signals
[POST_METADATA_CHANGE
], 0,
1439 rhythmdb_commit (dialog
->priv
->db
);
1443 rb_song_info_sync_entries (RBSongInfo
*dialog
)
1445 if (!dialog
->priv
->editable
)
1448 if (dialog
->priv
->current_entry
)
1449 rb_song_info_sync_entry_single (dialog
);
1451 rb_song_info_sync_entries_multiple (dialog
);