2
* arch-tag: Implementation of ipod source object
4
* Copyright (C) 2004 Christophe Fergeau <teuf@gnome.org>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
21
#include <gtk/gtktreeview.h>
25
#include <libgnome/gnome-i18n.h>
26
#include "eel-gconf-extensions.h"
27
#include "rb-ipod-source.h"
28
#include "rb-stock-icons.h"
29
#define DEFAULT_MOUNT_PATH "/mnt/ipod"
30
#define GCONF_MOUNT_PATH "/apps/qahog/mount_path"
33
static void rb_ipod_source_init (RBiPodSource *source);
34
static void rb_ipod_source_finalize (GObject *object);
35
static void rb_ipod_source_class_init (RBiPodSourceClass *klass);
37
static gboolean ipod_itunesdb_monitor_cb (RBiPodSource *source);
41
struct RBiPodSourcePrivate
43
guint ipod_polling_id;
48
rb_ipod_source_get_type (void)
50
static GType rb_ipod_source_type = 0;
52
if (rb_ipod_source_type == 0)
54
static const GTypeInfo our_info =
56
sizeof (RBiPodSourceClass),
59
(GClassInitFunc) rb_ipod_source_class_init,
62
sizeof (RBiPodSource),
64
(GInstanceInitFunc) rb_ipod_source_init
67
rb_ipod_source_type = g_type_register_static (RB_TYPE_LIBRARY_SOURCE,
73
return rb_ipod_source_type;
77
rb_ipod_source_class_init (RBiPodSourceClass *klass)
79
GObjectClass *object_class = G_OBJECT_CLASS (klass);
81
object_class->finalize = rb_ipod_source_finalize;
85
rb_ipod_source_init (RBiPodSource *source)
87
source->priv = g_new0 (RBiPodSourcePrivate, 1);
88
source->priv->ipod_polling_id = g_timeout_add (1000, (GSourceFunc)ipod_itunesdb_monitor_cb, source);
93
rb_ipod_source_finalize (GObject *object)
95
RBiPodSource *source = RB_IPOD_SOURCE (object);
97
if (source->priv->ipod_polling_id) {
98
g_source_remove (source->priv->ipod_polling_id);
104
rb_ipod_source_new (RBShell *shell, RhythmDB *db, BonoboUIComponent *component)
107
GtkWidget *dummy = gtk_tree_view_new ();
110
icon = gtk_widget_render_icon (dummy, RB_STOCK_IPOD,
111
GTK_ICON_SIZE_LARGE_TOOLBAR,
113
gtk_widget_destroy (dummy);
115
/* FIXME: need to set icon */
116
source = RB_SOURCE (g_object_new (RB_TYPE_IPOD_SOURCE,
118
"entry-type", RHYTHMDB_ENTRY_TYPE_IPOD,
119
"internal-name", "<ipod>",
122
"component", component,
125
rb_shell_register_entry_type_for_source (shell, source,
126
RHYTHMDB_ENTRY_TYPE_IPOD);
134
ipod_get_mount_path (void)
138
path = eel_gconf_get_string (GCONF_MOUNT_PATH);
139
if (path == NULL || strcmp (path, "") == 0)
140
return g_strdup (DEFAULT_MOUNT_PATH);
146
ipod_get_itunesdb_path (void)
149
gchar *mount_path = ipod_get_mount_path ();
151
result = g_build_filename (mount_path,
152
"iPod_Control/iTunes/iTunesDB",
159
entry_set_locked (RhythmDB *db, RhythmDBEntry *entry,
160
RhythmDBPropType propid, GValue *value)
162
rhythmdb_write_lock (RHYTHMDB (db));
163
rhythmdb_entry_set (RHYTHMDB (db), entry, propid, value);
164
rhythmdb_write_unlock (RHYTHMDB (db));
168
entry_set_string_prop (RhythmDB *db, RhythmDBEntry *entry,
169
RhythmDBPropType propid, const char *str)
175
tmp = g_strdup (_("Unknown"));
177
tmp = g_strdup (str);
180
g_value_init (&value, G_TYPE_STRING);
181
g_value_set_string_take_ownership (&value, tmp);
182
entry_set_locked (RHYTHMDB (db), entry, propid, &value);
183
g_value_unset (&value);
187
#define MAX_SONGS_LOADED_AT_ONCE 250
192
} RBiPodSongAdderCtxt;
196
load_ipod_db_idle_cb (RBiPodSongAdderCtxt *ctxt)
198
RhythmDBTreeEntry *entry;
201
for (i = 0; i < MAX_SONGS_LOADED_AT_ONCE; i++) {
207
item = ipod_get_next_item (ctxt->parser);
208
if ((item == NULL) || (item->type != IPOD_ITEM_SONG)) {
209
ipod_item_destroy (item);
212
song = (iPodSong *)item->data;
215
mount_path = ipod_get_mount_path ();
216
pc_path = itunesdb_get_track_name_on_ipod (mount_path, song);
218
rhythmdb_write_lock (RHYTHMDB (ctxt->db));
219
entry = rhythmdb_entry_new (RHYTHMDB (ctxt->db),
220
RHYTHMDB_ENTRY_TYPE_IPOD,
222
rhythmdb_write_unlock (RHYTHMDB (ctxt->db));
225
/* Set track number */
226
if (song->track_nr != 0) {
227
GValue value = {0, };
228
g_value_init (&value, G_TYPE_INT);
229
g_value_set_int (&value, song->track_nr);
230
entry_set_locked (RHYTHMDB (ctxt->db), entry,
231
RHYTHMDB_PROP_TRACK_NUMBER,
233
g_value_unset (&value);
236
/* Set disc number */
237
if (song->cd_nr != 0) {
238
GValue value = {0, };
239
g_value_init (&value, G_TYPE_ULONG);
240
g_value_set_ulong (&value, song->cd_nr);
241
rhythmdb_entry_set (RHYTHMDB (ctxt->db), entry,
242
RHYTHMDB_PROP_DISC_NUMBER,
244
g_value_unset (&value);
248
if (song->bitrate != 0) {
249
GValue value = {0, };
250
g_value_init (&value, G_TYPE_INT);
251
g_value_set_int (&value, song->bitrate);
252
entry_set_locked (RHYTHMDB (ctxt->db), entry,
253
RHYTHMDB_PROP_BITRATE,
255
g_value_unset (&value);
259
if (song->tracklen != 0) {
260
GValue value = {0, };
261
g_value_init (&value, G_TYPE_LONG);
262
g_value_set_long (&value, song->tracklen/1000);
263
entry_set_locked (RHYTHMDB (ctxt->db), entry,
264
RHYTHMDB_PROP_DURATION,
266
g_value_unset (&value);
270
if (song->size != 0) {
271
GValue value = {0, };
272
g_value_init (&value, G_TYPE_UINT64);
273
g_value_set_uint64 (&value, song->size);
274
entry_set_locked (RHYTHMDB (ctxt->db), entry,
275
RHYTHMDB_PROP_FILE_SIZE,
277
g_value_unset (&value);
282
entry_set_string_prop (RHYTHMDB (ctxt->db), entry,
283
RHYTHMDB_PROP_TITLE, song->title);
285
/* Set album, artist and genre from iTunesDB */
286
entry_set_string_prop (RHYTHMDB (ctxt->db), entry,
287
RHYTHMDB_PROP_ARTIST, song->artist);
289
entry_set_string_prop (RHYTHMDB (ctxt->db), entry,
290
RHYTHMDB_PROP_ALBUM, song->album);
292
entry_set_string_prop (RHYTHMDB (ctxt->db), entry,
293
RHYTHMDB_PROP_GENRE, song->genre);
295
ipod_item_destroy (item);
297
/* FIXME: item is leaked */
302
context_free (gpointer data)
304
RBiPodSongAdderCtxt *ctxt = (RBiPodSongAdderCtxt *)data;
308
if (ctxt->parser != NULL) {
309
ipod_parser_destroy (ctxt->parser);
314
/* We need to be locked to use this function */
315
static GnomeVFSResult
316
add_ipod_songs_to_db (RhythmDB *db)
320
RBiPodSongAdderCtxt *ctxt;
322
ctxt = g_new0 (RBiPodSongAdderCtxt, 1);
324
return GNOME_VFS_ERROR_NO_MEMORY;
327
path = ipod_get_mount_path ();
328
parser = ipod_parser_new (path);
332
ctxt->parser = parser;
334
g_idle_add_full (G_PRIORITY_DEFAULT_IDLE,
335
(GSourceFunc)load_ipod_db_idle_cb,
343
ipod_load_songs (RhythmDB *rdb)
347
res = add_ipod_songs_to_db (rdb);
349
if (res != GNOME_VFS_OK) {
350
g_warning ("Error loading iPod database");
355
ipod_unload_songs (RhythmDB *db)
357
rhythmdb_write_lock (db);
358
rhythmdb_entry_delete_by_type (db, RHYTHMDB_ENTRY_TYPE_IPOD);
359
rhythmdb_write_unlock (db);
363
ipod_itunesdb_monitor_cb (RBiPodSource *source)
366
gchar *itunesdb_path;
367
static gboolean was_present = FALSE;
369
itunesdb_path = ipod_get_itunesdb_path ();
370
g_assert (itunesdb_path != NULL);
371
is_present = g_file_test (itunesdb_path, G_FILE_TEST_EXISTS);
373
if (is_present && !was_present) {
376
g_print ("iPod plugged\n");
378
g_object_get (G_OBJECT (source), "db", &db, NULL);
379
ipod_load_songs (db);
380
/* FIXME: should we suspend this monitor until the iPod
381
* database has been read and fed to rhythmbox?
383
} else if (!is_present && was_present) {
386
g_print ("iPod unplugged\n");
388
g_object_get (G_OBJECT (source), "db", &db, NULL);
389
ipod_unload_songs (db);
391
g_free (itunesdb_path);
395
RhythmDBEntryType rhythmdb_entry_ipod_get_type (void)
397
static RhythmDBEntryType ipod_type = -1;
399
if (ipod_type == -1) {
400
ipod_type = rhythmdb_entry_register_type ();