~ubuntu-branches/ubuntu/utopic/rhythmbox/utopic-proposed

« back to all changes in this revision

Viewing changes to sources/rb-ipod-source.c

Tags: upstream-0.9.2
ImportĀ upstreamĀ versionĀ 0.9.2

Show diffs side-by-side

added added

removed removed

Lines of Context:
18
18
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19
19
 *
20
20
 */
 
21
 
 
22
#include <config.h>
 
23
#if defined(HAVE_HAL_0_5) || defined(HAVE_HAL_0_2)
 
24
#define HAVE_HAL 1
 
25
#endif
 
26
 
 
27
 
21
28
#include <gtk/gtktreeview.h>
22
29
#include <string.h>
23
 
#include "itunesdb.h"
24
30
#include "rhythmdb.h"
25
31
#include <libgnome/gnome-i18n.h>
 
32
#ifdef HAVE_HAL
 
33
#include <libhal.h>
 
34
#include <dbus/dbus.h>
 
35
#endif
 
36
#include <libgnomevfs/gnome-vfs-volume.h>
 
37
#include <libgnomevfs/gnome-vfs-volume-monitor.h>
 
38
#include <gpod/itdb.h>
26
39
#include "eel-gconf-extensions.h"
27
40
#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"
31
 
 
32
 
 
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);
36
 
 
37
 
static gboolean ipod_itunesdb_monitor_cb (RBiPodSource *source);
38
 
 
39
 
 
40
 
 
41
 
struct RBiPodSourcePrivate
42
 
{
43
 
        guint ipod_polling_id;
44
 
};
45
 
 
46
 
 
47
 
GType
48
 
rb_ipod_source_get_type (void)
49
 
{
50
 
        static GType rb_ipod_source_type = 0;
51
 
 
52
 
        if (rb_ipod_source_type == 0)
53
 
        {
54
 
                static const GTypeInfo our_info =
55
 
                {
56
 
                        sizeof (RBiPodSourceClass),
57
 
                        NULL,
58
 
                        NULL,
59
 
                        (GClassInitFunc) rb_ipod_source_class_init,
60
 
                        NULL,
61
 
                        NULL,
62
 
                        sizeof (RBiPodSource),
63
 
                        0,
64
 
                        (GInstanceInitFunc) rb_ipod_source_init
65
 
                };
66
 
 
67
 
                rb_ipod_source_type = g_type_register_static (RB_TYPE_LIBRARY_SOURCE,
68
 
                                                              "RBiPodSource",
69
 
                                                              &our_info, 0);
70
 
 
71
 
        }
72
 
 
73
 
        return rb_ipod_source_type;
74
 
}
 
41
#include "rb-debug.h"
 
42
#include "rb-playlist-source.h"
 
43
#include "rb-util.h"
 
44
#include "rhythmdb.h"
 
45
 
 
46
static GObject *rb_ipod_source_constructor (GType type, guint n_construct_properties,
 
47
                               GObjectConstructParam *construct_properties);
 
48
static void rb_ipod_source_dispose (GObject *object);
 
49
 
 
50
static GObject *rb_ipod_source_constructor (GType type, guint n_construct_properties,
 
51
                               GObjectConstructParam *construct_properties);
 
52
static void rb_ipod_source_dispose (GObject *object);
 
53
 
 
54
static gboolean impl_show_popup (RBSource *source);
 
55
static void rb_ipod_load_songs (RBiPodSource *source);
 
56
static gchar *rb_ipod_get_mount_path (GnomeVFSVolume *volume);
 
57
static void impl_delete_thyself (RBSource *source);
 
58
 
 
59
#ifdef HAVE_HAL
 
60
static gboolean hal_udi_is_ipod (const char *udi);
 
61
#endif
 
62
 
 
63
typedef struct
 
64
{
 
65
        Itdb_iTunesDB *ipod_db;
 
66
        gchar *ipod_mount_path;
 
67
} RBiPodSourcePrivate;
 
68
 
 
69
 
 
70
G_DEFINE_TYPE (RBiPodSource, rb_ipod_source, RB_TYPE_REMOVABLE_MEDIA_SOURCE)
 
71
#define IPOD_SOURCE_GET_PRIVATE(o)   (G_TYPE_INSTANCE_GET_PRIVATE ((o), RB_TYPE_IPOD_SOURCE, RBiPodSourcePrivate))
 
72
 
75
73
 
76
74
static void
77
75
rb_ipod_source_class_init (RBiPodSourceClass *klass)
78
76
{
79
77
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
80
 
 
81
 
        object_class->finalize = rb_ipod_source_finalize;
 
78
        RBSourceClass *source_class = RB_SOURCE_CLASS (klass);
 
79
 
 
80
        object_class->constructor = rb_ipod_source_constructor;
 
81
        object_class->dispose = rb_ipod_source_dispose;
 
82
 
 
83
        source_class->impl_show_popup = impl_show_popup;
 
84
        source_class->impl_delete_thyself = impl_delete_thyself;
 
85
 
 
86
        g_type_class_add_private (klass, sizeof (RBiPodSourcePrivate));
82
87
}
83
88
 
84
89
static void
85
90
rb_ipod_source_init (RBiPodSource *source)
86
91
{
87
 
        source->priv = g_new0 (RBiPodSourcePrivate, 1); 
88
 
        source->priv->ipod_polling_id = g_timeout_add (1000, (GSourceFunc)ipod_itunesdb_monitor_cb, source);
89
 
}
90
 
 
 
92
 
 
93
}
 
94
 
 
95
static GObject *
 
96
rb_ipod_source_constructor (GType type, guint n_construct_properties,
 
97
                               GObjectConstructParam *construct_properties)
 
98
{
 
99
        GObjectClass *klass, *parent_class; 
 
100
        RBiPodSource *source; 
 
101
 
 
102
        klass = G_OBJECT_CLASS (g_type_class_peek (type));
 
103
        parent_class = G_OBJECT_CLASS (g_type_class_peek_parent (klass));
 
104
        source = RB_IPOD_SOURCE (parent_class->constructor (type, n_construct_properties, construct_properties));
 
105
 
 
106
        rb_ipod_load_songs (source);
 
107
 
 
108
        return G_OBJECT (source);
 
109
}
91
110
 
92
111
static void 
93
 
rb_ipod_source_finalize (GObject *object)
 
112
rb_ipod_source_dispose (GObject *object)
94
113
{
95
 
        RBiPodSource *source = RB_IPOD_SOURCE (object);
96
 
 
97
 
        if (source->priv->ipod_polling_id) {
98
 
                g_source_remove (source->priv->ipod_polling_id);
 
114
        RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (object);
 
115
 
 
116
        if (priv->ipod_db != NULL) {
 
117
                itdb_free (priv->ipod_db);
 
118
                priv->ipod_db = NULL;
 
119
        }
 
120
 
 
121
        if (priv->ipod_mount_path) {
 
122
                g_free (priv->ipod_mount_path);
 
123
                priv->ipod_mount_path = NULL;
99
124
        }
 
125
 
 
126
        G_OBJECT_CLASS (rb_ipod_source_parent_class)->dispose (object);
100
127
}
101
128
 
102
 
 
103
 
RBSource *
104
 
rb_ipod_source_new (RBShell *shell, RhythmDB *db, BonoboUIComponent *component)
 
129
RBRemovableMediaSource *
 
130
rb_ipod_source_new (RBShell *shell, GnomeVFSVolume *volume)
105
131
{
106
 
        RBSource *source;
107
 
        GtkWidget *dummy = gtk_tree_view_new ();
108
 
        GdkPixbuf *icon;
109
 
 
110
 
        icon = gtk_widget_render_icon (dummy, RB_STOCK_IPOD,
111
 
                                       GTK_ICON_SIZE_LARGE_TOOLBAR,
112
 
                                       NULL);
113
 
        gtk_widget_destroy (dummy);
114
 
 
115
 
        /* FIXME: need to set icon */
116
 
        source = RB_SOURCE (g_object_new (RB_TYPE_IPOD_SOURCE,
 
132
        RBiPodSource *source;
 
133
        RhythmDBEntryType entry_type;
 
134
 
 
135
        g_assert (rb_ipod_is_volume_ipod (volume));
 
136
 
 
137
        entry_type =  rhythmdb_entry_register_type ();
 
138
 
 
139
        source = RB_IPOD_SOURCE (g_object_new (RB_TYPE_IPOD_SOURCE,
117
140
                                          "name", _("iPod"),
118
 
                                          "entry-type", RHYTHMDB_ENTRY_TYPE_IPOD,
119
 
                                          "internal-name", "<ipod>",
120
 
                                          "icon", icon,
121
 
                                          "db", db,
122
 
                                          "component", component,
 
141
                                          "entry-type", entry_type,
 
142
                                          "volume", volume,
 
143
                                          "shell", shell,
123
144
                                          NULL));
124
145
 
125
 
        rb_shell_register_entry_type_for_source (shell, source, 
126
 
                                                 RHYTHMDB_ENTRY_TYPE_IPOD);
127
 
 
128
 
 
129
 
        return source;
130
 
}
131
 
 
132
 
 
133
 
static char *
134
 
ipod_get_mount_path (void)
135
 
{
136
 
        gchar *path;
137
 
 
138
 
        path = eel_gconf_get_string (GCONF_MOUNT_PATH);
139
 
        if (path == NULL || strcmp (path, "") == 0)
140
 
                return g_strdup (DEFAULT_MOUNT_PATH);
141
 
        else
142
 
                return path;
143
 
}
144
 
 
145
 
static char *
146
 
ipod_get_itunesdb_path (void)
147
 
{
148
 
        gchar *result;
149
 
        gchar *mount_path = ipod_get_mount_path ();
150
 
 
151
 
        result = g_build_filename (mount_path,
152
 
                                   "iPod_Control/iTunes/iTunesDB", 
153
 
                                   NULL);
154
 
        g_free (mount_path);
155
 
        return result;
156
 
}
157
 
 
158
 
static void
159
 
entry_set_locked (RhythmDB *db, RhythmDBEntry *entry,
160
 
                  RhythmDBPropType propid, GValue *value) 
161
 
{
162
 
        rhythmdb_write_lock (RHYTHMDB (db));
163
 
        rhythmdb_entry_set (RHYTHMDB (db), entry, propid, value);
164
 
        rhythmdb_write_unlock (RHYTHMDB (db));
 
146
        rb_shell_register_entry_type_for_source (shell, RB_SOURCE (source), entry_type);
 
147
 
 
148
        return RB_REMOVABLE_MEDIA_SOURCE (source);
165
149
}
166
150
 
167
151
static void 
169
153
                       RhythmDBPropType propid, const char *str)
170
154
{
171
155
        GValue value = {0,};
172
 
        gchar *tmp;
173
156
 
174
 
        if (str == NULL) {
175
 
                tmp = g_strdup (_("Unknown"));
176
 
        } else {
177
 
                tmp = g_strdup (str);
178
 
        }
 
157
        if (!str)
 
158
                str = _("Unknown");
179
159
 
180
160
        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);
 
161
        g_value_set_static_string (&value, str);
 
162
        rhythmdb_entry_set_uninserted (RHYTHMDB (db), entry, propid, &value);
183
163
        g_value_unset (&value);
184
164
}
185
165
 
186
166
 
187
 
#define MAX_SONGS_LOADED_AT_ONCE 250
188
 
 
189
 
typedef struct  {
 
167
static char *
 
168
ipod_path_to_uri (const char *mount_point, const char *ipod_path)
 
169
{
 
170
        char *rel_pc_path;
 
171
        char *full_pc_path;
 
172
        char *uri;
 
173
        
 
174
        rel_pc_path = g_strdup (ipod_path);     
 
175
        itdb_filename_ipod2fs (rel_pc_path);
 
176
        full_pc_path = g_build_filename (mount_point, rel_pc_path, NULL);
 
177
        g_free (rel_pc_path);
 
178
        uri = g_filename_to_uri (full_pc_path, NULL, NULL);
 
179
        g_free (full_pc_path);
 
180
        return uri;
 
181
}
 
182
 
 
183
static void
 
184
add_rb_playlist (RBiPodSource *source, Itdb_Playlist *playlist)
 
185
{
 
186
        RBShell *shell;
 
187
        RBSource *playlist_source;
 
188
        GList *it;
 
189
        RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
 
190
        RhythmDBEntryType entry_type;
 
191
 
 
192
        g_object_get (G_OBJECT (source), 
 
193
                      "shell", &shell, 
 
194
                      "entry-type", &entry_type,
 
195
                      NULL);
 
196
 
 
197
        playlist_source = RB_SOURCE (g_object_new (RB_TYPE_PLAYLIST_SOURCE,
 
198
                                                   "name", playlist->name,
 
199
                                                   "shell", shell,
 
200
                                                   "visibility", TRUE,
 
201
                                                   "is-local", FALSE,
 
202
                                                   "entry-type", entry_type,
 
203
                                                   NULL));
 
204
 
 
205
        for (it = playlist->members; it != NULL; it = it->next) {
 
206
                Itdb_Track *song;
 
207
                char *filename;
 
208
 
 
209
                song = (Itdb_Track *)it->data;
 
210
                filename = ipod_path_to_uri (priv->ipod_mount_path, 
 
211
                                            song->ipod_path);
 
212
                rb_playlist_source_add_location (RB_PLAYLIST_SOURCE (playlist_source),
 
213
                                                 filename);
 
214
                g_free (filename);
 
215
        }
 
216
 
 
217
        rb_shell_append_source (shell, playlist_source, RB_SOURCE (source));
 
218
        g_object_unref (G_OBJECT (shell));
 
219
}
 
220
 
 
221
 
 
222
static void
 
223
load_ipod_playlists (RBiPodSource *source)
 
224
{
 
225
        RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
 
226
        GList *it;
 
227
 
 
228
        for (it = priv->ipod_db->playlists; it != NULL; it = it->next) {
 
229
                Itdb_Playlist *playlist;
 
230
 
 
231
                playlist = (Itdb_Playlist *)it->data;
 
232
                if (itdb_playlist_is_mpl (playlist)) {
 
233
                        continue;
 
234
                }
 
235
                if (playlist->is_spl) {
 
236
                        continue;
 
237
                }
 
238
 
 
239
                add_rb_playlist (source, playlist);
 
240
        }
 
241
 
 
242
}
 
243
 
 
244
static gboolean
 
245
load_ipod_db_idle_cb (RBiPodSource *source)
 
246
{
 
247
        RBShell *shell;
190
248
        RhythmDB *db;
191
 
        iPodParser *parser;
192
 
} RBiPodSongAdderCtxt;
193
 
 
194
 
 
195
 
static gboolean
196
 
load_ipod_db_idle_cb (RBiPodSongAdderCtxt *ctxt)
197
 
{
198
 
        RhythmDBTreeEntry *entry;
199
 
        int i;
200
 
 
201
 
        for (i = 0; i < MAX_SONGS_LOADED_AT_ONCE; i++) {
202
 
                gchar *pc_path;
203
 
                gchar *mount_path;
204
 
                iPodItem *item;
205
 
                iPodSong *song;
206
 
                
207
 
                item = ipod_get_next_item (ctxt->parser);
208
 
                if ((item == NULL) || (item->type != IPOD_ITEM_SONG)) {
209
 
                        ipod_item_destroy (item);
210
 
                        return FALSE;
211
 
                }
212
 
                song = (iPodSong *)item->data;
213
 
                                
214
 
                /* Set URI */
215
 
                mount_path = ipod_get_mount_path ();
216
 
                pc_path = itunesdb_get_track_name_on_ipod (mount_path, song);
217
 
                g_free (mount_path);
218
 
                rhythmdb_write_lock (RHYTHMDB (ctxt->db));
219
 
                entry = rhythmdb_entry_new (RHYTHMDB (ctxt->db), 
220
 
                                            RHYTHMDB_ENTRY_TYPE_IPOD,
221
 
                                            pc_path);
222
 
                rhythmdb_write_unlock (RHYTHMDB (ctxt->db));
223
 
                g_free (pc_path);
 
249
        GList *it;
 
250
        RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
 
251
  
 
252
        g_object_get (G_OBJECT (source), "shell", &shell, NULL);
 
253
        g_object_get (G_OBJECT (shell), "db", &db, NULL);
 
254
        g_object_unref (G_OBJECT (shell));
 
255
  
 
256
        g_assert (db != NULL);
 
257
        for (it = priv->ipod_db->tracks; it != NULL; it = it->next) {
 
258
                Itdb_Track *song;
 
259
                RhythmDBEntry *entry;
 
260
                RhythmDBEntryType entry_type;
 
261
                char *pc_path;
 
262
 
 
263
                song = (Itdb_Track *)it->data;
 
264
                
 
265
                /* Set URI */
 
266
                g_object_get (G_OBJECT (source), "entry-type", &entry_type, 
 
267
                              NULL);
 
268
 
 
269
                pc_path = ipod_path_to_uri (priv->ipod_mount_path, 
 
270
                                            song->ipod_path);
 
271
                entry = rhythmdb_entry_new (RHYTHMDB (db), entry_type,
 
272
                                            pc_path);
 
273
                g_free (pc_path);
 
274
  
 
275
                rb_debug ("Adding %s from iPod", pc_path);
224
276
 
225
277
                /* Set track number */
226
278
                if (song->track_nr != 0) {
227
279
                        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, 
232
 
                                          &value);
 
280
                        g_value_init (&value, G_TYPE_ULONG);
 
281
                        g_value_set_ulong (&value, song->track_nr);
 
282
                        rhythmdb_entry_set_uninserted (RHYTHMDB (db), entry, 
 
283
                                                       RHYTHMDB_PROP_TRACK_NUMBER, 
 
284
                                                       &value);
233
285
                        g_value_unset (&value);
234
286
                }
235
287
 
238
290
                        GValue value = {0, };
239
291
                        g_value_init (&value, G_TYPE_ULONG);
240
292
                        g_value_set_ulong (&value, song->cd_nr);
241
 
                        rhythmdb_entry_set (RHYTHMDB (ctxt->db), entry, 
242
 
                                            RHYTHMDB_PROP_DISC_NUMBER, 
243
 
                                            &value);
 
293
                        rhythmdb_entry_set_uninserted (RHYTHMDB (db), entry, 
 
294
                                                       RHYTHMDB_PROP_DISC_NUMBER, 
 
295
                                                       &value);
244
296
                        g_value_unset (&value);
245
297
                }
246
298
                
247
299
                /* Set bitrate */
248
300
                if (song->bitrate != 0) {
249
301
                        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, 
254
 
                                          &value);
 
302
                        g_value_init (&value, G_TYPE_ULONG);
 
303
                        g_value_set_ulong (&value, song->bitrate);
 
304
                        rhythmdb_entry_set_uninserted (RHYTHMDB (db), entry, 
 
305
                                                       RHYTHMDB_PROP_BITRATE, 
 
306
                                                       &value);
255
307
                        g_value_unset (&value);
256
308
                }
257
309
                
258
310
                /* Set length */
259
311
                if (song->tracklen != 0) {
260
312
                        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, 
265
 
                                          &value);
 
313
                        g_value_init (&value, G_TYPE_ULONG);
 
314
                        g_value_set_ulong (&value, song->tracklen/1000);
 
315
                        rhythmdb_entry_set_uninserted (RHYTHMDB (db), entry, 
 
316
                                                       RHYTHMDB_PROP_DURATION, 
 
317
                                                       &value);
266
318
                        g_value_unset (&value);
267
319
                }
268
320
                
271
323
                        GValue value = {0, };
272
324
                        g_value_init (&value, G_TYPE_UINT64);
273
325
                        g_value_set_uint64 (&value, song->size);
274
 
                        entry_set_locked (RHYTHMDB (ctxt->db), entry, 
275
 
                                          RHYTHMDB_PROP_FILE_SIZE, 
276
 
                                          &value);
 
326
                        rhythmdb_entry_set_uninserted (RHYTHMDB (db), entry, 
 
327
                                                       RHYTHMDB_PROP_FILE_SIZE, 
 
328
                                                       &value);
277
329
                        g_value_unset (&value);
278
330
                }
279
331
                
280
 
                /* Set title */
281
 
                
282
 
                entry_set_string_prop (RHYTHMDB (ctxt->db), entry, 
 
332
                /* Set title */         
 
333
                entry_set_string_prop (RHYTHMDB (db), entry, 
283
334
                                       RHYTHMDB_PROP_TITLE, song->title);
284
335
                
285
336
                /* Set album, artist and genre from iTunesDB */
286
 
                entry_set_string_prop (RHYTHMDB (ctxt->db), entry, 
 
337
                entry_set_string_prop (RHYTHMDB (db), entry, 
287
338
                                       RHYTHMDB_PROP_ARTIST, song->artist);
288
339
                
289
 
                entry_set_string_prop (RHYTHMDB (ctxt->db), entry, 
 
340
                entry_set_string_prop (RHYTHMDB (db), entry, 
290
341
                                       RHYTHMDB_PROP_ALBUM, song->album);
291
342
                
292
 
                entry_set_string_prop (RHYTHMDB (ctxt->db), entry, 
 
343
                entry_set_string_prop (RHYTHMDB (db), entry, 
293
344
                                       RHYTHMDB_PROP_GENRE, song->genre);
294
345
                
295
 
                ipod_item_destroy (item);
296
 
        }
297
 
        /* FIXME: item is leaked */
298
 
        return TRUE;
299
 
}
300
 
 
301
 
static void
302
 
context_free (gpointer data)
303
 
{
304
 
        RBiPodSongAdderCtxt *ctxt = (RBiPodSongAdderCtxt *)data;
305
 
        if (ctxt == NULL) {
306
 
                return;
307
 
        }
308
 
        if (ctxt->parser != NULL) {
309
 
                ipod_parser_destroy (ctxt->parser);
310
 
        }
311
 
        g_free (ctxt);
312
 
}
313
 
 
314
 
/* We need to be locked to use this function */
315
 
static GnomeVFSResult
316
 
add_ipod_songs_to_db (RhythmDB *db)
317
 
{
318
 
        char *path;
319
 
        iPodParser *parser;
320
 
        RBiPodSongAdderCtxt *ctxt;
321
 
 
322
 
        ctxt = g_new0 (RBiPodSongAdderCtxt, 1);
323
 
        if (ctxt == NULL) {
324
 
                return GNOME_VFS_ERROR_NO_MEMORY;
325
 
        }
326
 
 
327
 
        path = ipod_get_mount_path ();
328
 
        parser = ipod_parser_new (path);
329
 
        g_free (path);
330
 
 
331
 
        ctxt->db = db;
332
 
        ctxt->parser = parser;
333
 
 
334
 
        g_idle_add_full (G_PRIORITY_DEFAULT_IDLE, 
335
 
                         (GSourceFunc)load_ipod_db_idle_cb,
336
 
                         ctxt, context_free);
337
 
 
338
 
        return GNOME_VFS_OK;
339
 
}
340
 
 
341
 
 
342
 
static void
343
 
ipod_load_songs (RhythmDB *rdb)
344
 
{
345
 
        GnomeVFSResult res;
346
 
 
347
 
        res = add_ipod_songs_to_db (rdb);
348
 
 
349
 
        if (res != GNOME_VFS_OK) {
350
 
                g_warning ("Error loading iPod database");
351
 
        }
352
 
}
353
 
 
354
 
static void
355
 
ipod_unload_songs (RhythmDB *db)
356
 
{
357
 
        rhythmdb_write_lock (db);
358
 
        rhythmdb_entry_delete_by_type (db, RHYTHMDB_ENTRY_TYPE_IPOD);
359
 
        rhythmdb_write_unlock (db);
360
 
}
361
 
 
362
 
static gboolean
363
 
ipod_itunesdb_monitor_cb (RBiPodSource *source)
364
 
{
365
 
        gboolean is_present;
 
346
                rhythmdb_commit (RHYTHMDB (db));
 
347
        
 
348
        }
 
349
 
 
350
        load_ipod_playlists (source);
 
351
 
 
352
        g_object_unref (G_OBJECT (db));
 
353
        return FALSE;
 
354
}
 
355
 
 
356
static void
 
357
rb_ipod_load_songs (RBiPodSource *source)
 
358
{
 
359
        RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
 
360
        GnomeVFSVolume *volume;
 
361
 
 
362
        g_object_get (G_OBJECT (source), "volume", &volume, NULL);
 
363
        priv->ipod_mount_path = rb_ipod_get_mount_path (volume);
 
364
 
 
365
        priv->ipod_db = itdb_parse (priv->ipod_mount_path, NULL);
 
366
        if (priv->ipod_db != NULL) {
 
367
                g_idle_add ((GSourceFunc)load_ipod_db_idle_cb, source);
 
368
        }
 
369
}
 
370
 
 
371
static gchar *
 
372
rb_ipod_get_mount_path (GnomeVFSVolume *volume)
 
373
{
 
374
        gchar *path;
 
375
        gchar *uri;
 
376
 
 
377
        uri = gnome_vfs_volume_get_activation_uri (volume);
 
378
        path = g_filename_from_uri (uri, NULL, NULL);
 
379
        g_assert (path != NULL);
 
380
        g_free (uri);
 
381
 
 
382
        return path;
 
383
}
 
384
 
 
385
static gchar *
 
386
rb_ipod_get_itunesdb_path (GnomeVFSVolume *volume)
 
387
{
 
388
        gchar *mount_point_uri;
 
389
        gchar *mount_point;
 
390
        gchar *result;
 
391
 
 
392
        mount_point_uri = gnome_vfs_volume_get_activation_uri (volume);
 
393
        if (mount_point_uri == NULL) {
 
394
                return NULL;
 
395
        }
 
396
        mount_point = g_filename_from_uri (mount_point_uri, NULL, NULL);
 
397
        g_free (mount_point_uri);
 
398
        if (mount_point == NULL) {
 
399
                return NULL;
 
400
        }
 
401
        result = g_build_filename (mount_point, 
 
402
                                   "iPod_Control/iTunes/iTunesDB",
 
403
                                   NULL);
 
404
        g_free (mount_point);
 
405
        return result;
 
406
}
 
407
 
 
408
gboolean
 
409
rb_ipod_is_volume_ipod (GnomeVFSVolume *volume)
 
410
{
366
411
        gchar *itunesdb_path;
367
 
        static gboolean was_present = FALSE;
368
 
 
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);
372
 
 
373
 
        if (is_present && !was_present) {
374
 
                RhythmDB *db;
375
 
 
376
 
                g_print ("iPod plugged\n");
377
 
                was_present = TRUE;
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?
382
 
                 */
383
 
        } else if (!is_present && was_present) {
384
 
                RhythmDB *db;
385
 
 
386
 
                g_print ("iPod unplugged\n");
387
 
                was_present = FALSE;
388
 
                g_object_get (G_OBJECT (source), "db", &db, NULL);
389
 
                ipod_unload_songs (db);
390
 
        }
391
 
        g_free (itunesdb_path);
 
412
        gboolean result = FALSE;
 
413
#ifdef HAVE_HAL
 
414
        gchar *udi;
 
415
#endif
 
416
        if (gnome_vfs_volume_get_volume_type (volume) != GNOME_VFS_VOLUME_TYPE_MOUNTPOINT) {
 
417
                return FALSE;
 
418
        }
 
419
 
 
420
#ifdef HAVE_HAL
 
421
        udi = gnome_vfs_volume_get_hal_udi (volume);
 
422
        if (udi != NULL) {
 
423
                gboolean result;
 
424
 
 
425
                result = hal_udi_is_ipod (udi);
 
426
                g_free (udi);
 
427
                return result;
 
428
        }
 
429
#endif
 
430
        
 
431
        itunesdb_path = rb_ipod_get_itunesdb_path (volume);
 
432
        if (itunesdb_path != NULL) {
 
433
                result = g_file_test (itunesdb_path, G_FILE_TEST_EXISTS);
 
434
                g_free (itunesdb_path);
 
435
        }
 
436
 
 
437
        return result;
 
438
}
 
439
 
 
440
#ifdef HAVE_HAL_0_5
 
441
 
 
442
static gboolean
 
443
hal_udi_is_ipod (const char *udi)
 
444
{
 
445
        LibHalContext *ctx;
 
446
        DBusConnection *conn;
 
447
        char *parent_udi, *parent_name;
 
448
        gboolean result;
 
449
        DBusError error;
 
450
 
 
451
        result = FALSE;
 
452
        dbus_error_init (&error);
 
453
        conn = NULL;
 
454
        ctx = libhal_ctx_new ();
 
455
        if (ctx == NULL) {
 
456
                /* FIXME: should we return an error somehow so that we can 
 
457
                 * fall back to a check for iTunesDB presence instead ?
 
458
                 */
 
459
                g_print ("Error: %s\n", error.message);
 
460
                goto end;
 
461
        }
 
462
        conn = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
 
463
        if (conn == NULL) {
 
464
                g_print ("Error: %s\n", error.message);
 
465
                goto end;
 
466
        }
 
467
        libhal_ctx_set_dbus_connection (ctx, conn);
 
468
        if (!libhal_ctx_init (ctx, &error)) {
 
469
                g_print ("Error: %s\n", error.message);
 
470
                goto end;
 
471
        }
 
472
 
 
473
        parent_udi = libhal_device_get_property_string (ctx, udi,
 
474
                        "info.parent", &error);
 
475
        parent_name = libhal_device_get_property_string (ctx, parent_udi,
 
476
                        "storage.model", &error);
 
477
        g_free (parent_udi);
 
478
        if (parent_name != NULL && strcmp (parent_name, "iPod") == 0) {
 
479
                result = TRUE;
 
480
        }
 
481
 
 
482
        g_free (parent_name);
 
483
end:
 
484
        if (ctx) {
 
485
                libhal_ctx_shutdown (ctx, &error);
 
486
                libhal_ctx_free(ctx);
 
487
        }
 
488
        dbus_error_free (&error);
 
489
 
 
490
        return result;
 
491
}
 
492
 
 
493
#elif HAVE_HAL_0_2
 
494
 
 
495
static gboolean
 
496
hal_udi_is_ipod (const char *udi)
 
497
{
 
498
        LibHalContext *ctx;
 
499
        char *parent_udi, *parent_name;
 
500
        gboolean result;
 
501
 
 
502
        result = FALSE;
 
503
        ctx = hal_initialize (NULL, FALSE);
 
504
        if (ctx == NULL) {
 
505
                /* FIXME: should we return an error somehow so that we can 
 
506
                 * fall back to a check for iTunesDB presence instead ?
 
507
                 */
 
508
                return FALSE;
 
509
        }
 
510
        parent_udi = hal_device_get_property_string (ctx, udi,
 
511
                        "info.parent");
 
512
        parent_name = hal_device_get_property_string (ctx, parent_udi,
 
513
                        "storage.model");
 
514
        g_free (parent_udi);
 
515
 
 
516
        if (parent_name != NULL && strcmp (parent_name, "iPod") == 0) {
 
517
                result = TRUE;
 
518
        }
 
519
 
 
520
        g_free (parent_name);
 
521
        hal_shutdown (ctx);
 
522
 
 
523
        return result;
 
524
}
 
525
 
 
526
#endif
 
527
 
 
528
static gboolean
 
529
impl_show_popup (RBSource *source)
 
530
{
 
531
        _rb_source_show_popup (RB_SOURCE (source), "/iPodSourcePopup");
392
532
        return TRUE;
393
533
}
394
534
 
395
 
RhythmDBEntryType rhythmdb_entry_ipod_get_type (void) 
 
535
static void
 
536
impl_delete_thyself (RBSource *source)
396
537
{
397
 
        static RhythmDBEntryType ipod_type = -1;
398
 
       
399
 
        if (ipod_type == -1) {
400
 
                ipod_type = rhythmdb_entry_register_type ();
401
 
        }
402
 
 
403
 
        return ipod_type;
 
538
        RBiPodSourcePrivate *priv = IPOD_SOURCE_GET_PRIVATE (source);
 
539
 
 
540
        itdb_free (priv->ipod_db);
 
541
        priv->ipod_db = NULL;
 
542
 
 
543
        RB_SOURCE_CLASS (rb_ipod_source_parent_class)->impl_delete_thyself (source);
404
544
}