No issues found
1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*-
2 *
3 * Copyright (C) 2006 James Livingston <doclivingston@gmail.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * The Rhythmbox authors hereby grant permission for non-GPL compatible
11 * GStreamer plugins to be used and distributed together with GStreamer
12 * and Rhythmbox. This permission is above and beyond the permissions granted
13 * by the GPL license by which Rhythmbox is covered. If you modify this code
14 * you may extend this exception to your version of the code, but you are not
15 * obligated to do so. If you do not wish to do so, delete this exception
16 * statement from your version.
17 *
18 * This program is distributed in the hope that it will be useful,
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 * GNU General Public License for more details.
22 *
23 * You should have received a copy of the GNU General Public License
24 * along with this program; if not, write to the Free Software
25 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
26 *
27 */
28
29 #define __EXTENSIONS__
30
31 #include "config.h"
32
33 #include <string.h>
34
35 #include <glib/gi18n.h>
36 #include <gtk/gtk.h>
37
38 #include "mediaplayerid.h"
39
40 #include "rb-psp-source.h"
41 #include "rb-debug.h"
42 #include "rb-util.h"
43 #include "rb-file-helpers.h"
44 #include "rb-auto-playlist-source.h"
45 #include "rhythmdb.h"
46
47
48 static void rb_psp_source_create_playlists (RBGenericPlayerSource *source);
49
50 G_DEFINE_DYNAMIC_TYPE (RBPspSource, rb_psp_source, RB_TYPE_GENERIC_PLAYER_SOURCE)
51
52
53 static void
54 rb_psp_source_class_init (RBPspSourceClass *klass)
55 {
56 RBGenericPlayerSourceClass *generic_class = RB_GENERIC_PLAYER_SOURCE_CLASS (klass);
57 generic_class->impl_load_playlists = rb_psp_source_create_playlists;
58 }
59
60 static void
61 rb_psp_source_class_finalize (RBPspSourceClass *klass)
62 {
63 }
64
65 static void
66 rb_psp_source_init (RBPspSource *source)
67 {
68 }
69
70 RBSource *
71 rb_psp_source_new (GObject *plugin, RBShell *shell, GMount *mount, MPIDDevice *device_info)
72 {
73 RBPspSource *source;
74 RhythmDBEntryType *entry_type;
75 RhythmDB *db;
76 char *name;
77 char *path;
78 GVolume *volume;
79
80 g_assert (rb_psp_is_mount_player (mount, device_info));
81
82 volume = g_mount_get_volume (mount);
83
84 g_object_get (G_OBJECT (shell), "db", &db, NULL);
85 path = g_volume_get_identifier (volume, G_VOLUME_IDENTIFIER_KIND_UNIX_DEVICE);
86 name = g_strdup_printf ("psp: %s", path);
87 entry_type = g_object_new (RHYTHMDB_TYPE_ENTRY_TYPE,
88 "db", db,
89 "name", name,
90 "save-to-disk", FALSE,
91 "category", RHYTHMDB_ENTRY_NORMAL,
92 NULL);
93 rhythmdb_register_entry_type (db, entry_type);
94 g_object_unref (db);
95 g_free (name);
96 g_free (path);
97 g_object_unref (volume);
98
99 source = RB_PSP_SOURCE (g_object_new (RB_TYPE_PSP_SOURCE,
100 "plugin", plugin,
101 "entry-type", entry_type,
102 "mount", mount,
103 "shell", shell,
104 "device-info", device_info,
105 NULL));
106
107 rb_shell_register_entry_type_for_source (shell, RB_SOURCE (source), entry_type);
108
109 return RB_SOURCE (source);
110 }
111
112 static GFile *
113 find_dir_no_case (GFile *root, gboolean look_for_psp)
114 {
115 GFileEnumerator *e;
116 GFileInfo *info;
117 GFile *ret;
118 GFile *music_dir;
119
120 ret = music_dir = NULL;
121 e = g_file_enumerate_children (root, G_FILE_ATTRIBUTE_STANDARD_NAME","G_FILE_ATTRIBUTE_STANDARD_TYPE,
122 G_FILE_QUERY_INFO_NONE, NULL, NULL);
123 if (e == NULL)
124 return ret;
125
126 while ((info = g_file_enumerator_next_file (e, NULL, NULL)) != NULL) {
127 const char *name;
128
129 name = g_file_info_get_name (info);
130 if (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY) {
131 g_object_unref (info);
132 continue;
133 }
134
135 if (g_ascii_strcasecmp (name, "MUSIC") == 0) {
136 music_dir = g_file_resolve_relative_path (root, name);
137 g_object_unref (info);
138 if (look_for_psp)
139 continue;
140 else
141 break;
142 }
143
144 if (look_for_psp) {
145 if (g_ascii_strcasecmp (name, "PSP") == 0) {
146 GFile *psp_dir;
147
148 psp_dir = g_file_resolve_relative_path (root, name);
149 ret = find_dir_no_case (psp_dir, FALSE);
150 g_object_unref (psp_dir);
151
152 if (ret != NULL) {
153 g_object_unref (info);
154 if (music_dir != NULL)
155 g_object_unref (music_dir);
156 music_dir = NULL;
157 break;
158 }
159 }
160 }
161 g_object_unref (info);
162 }
163 g_object_unref (e);
164
165 if (ret == NULL)
166 ret = music_dir;
167
168 return ret;
169 }
170
171 static GFile *
172 find_music_dir (GMount *mount)
173 {
174 GFile *root;
175 GFile *music_dir = NULL;
176
177 root = g_mount_get_root (mount);
178 if (root != NULL) {
179 music_dir = find_dir_no_case (root, TRUE);
180 /* FIXME create directories if they don't exist */
181 g_object_unref (root);
182 }
183
184 return music_dir;
185 }
186
187 static void
188 visit_playlist_dirs (RBPspSource *source,
189 GFile *file)
190 {
191 RBShell *shell;
192 RhythmDB *db;
193 RhythmDBEntryType *entry_type;
194 char *playlist_path;
195 char *playlist_name;
196 RBSource *playlist;
197 GPtrArray *query;
198
199 playlist_path = g_file_get_uri (file); /* or _get_path? */
200
201 g_object_get (source,
202 "shell", &shell,
203 "entry-type", &entry_type,
204 NULL);
205 g_object_get (shell,
206 "db", &db,
207 NULL);
208
209 /* FIXME this isn't good enough, we only need the files directly under the playlist directory,
210 * not sub-dirs */
211 query = rhythmdb_query_parse (db,
212 RHYTHMDB_QUERY_PROP_EQUALS, RHYTHMDB_PROP_TYPE, entry_type,
213 RHYTHMDB_QUERY_PROP_PREFIX, RHYTHMDB_PROP_LOCATION, playlist_path,
214 RHYTHMDB_QUERY_END);
215 g_free (playlist_path);
216 g_object_unref (entry_type);
217
218 playlist_name = g_file_get_basename (file);
219 playlist = rb_auto_playlist_source_new (shell, playlist_name, FALSE);
220 g_free (playlist_name);
221
222 rb_auto_playlist_source_set_query (RB_AUTO_PLAYLIST_SOURCE (playlist), query,
223 RHYTHMDB_QUERY_MODEL_LIMIT_NONE, NULL,
224 NULL, 0);
225 rb_generic_player_source_add_playlist (RB_GENERIC_PLAYER_SOURCE (source), shell, RB_SOURCE (playlist));
226 rhythmdb_query_free (query);
227
228 g_object_unref (shell);
229 g_object_unref (db);
230 }
231
232
233 static void
234 rb_psp_source_create_playlists (RBGenericPlayerSource *source)
235 {
236 GMount *mount;
237 GFile *music_dir;
238
239 g_object_get (source, "mount", &mount, NULL);
240 music_dir = find_music_dir (mount);
241 g_object_unref (mount);
242
243 if (music_dir != NULL) {
244 GFileEnumerator *e;
245 GFileInfo *info;
246
247 e = g_file_enumerate_children (music_dir, G_FILE_ATTRIBUTE_STANDARD_NAME","G_FILE_ATTRIBUTE_STANDARD_TYPE,
248 G_FILE_QUERY_INFO_NONE, NULL, NULL);
249 if (e != NULL) {
250 while ((info = g_file_enumerator_next_file (e, NULL, NULL)) != NULL) {
251 GFile *file;
252 const char *name;
253 if (g_file_info_get_file_type (info) != G_FILE_TYPE_DIRECTORY) {
254 g_object_unref (info);
255 continue;
256 }
257 name = g_file_info_get_name (info);
258 file = g_file_resolve_relative_path (music_dir, name);
259 visit_playlist_dirs (RB_PSP_SOURCE (source), file);
260 g_object_unref (file);
261 g_object_unref (info);
262 }
263 g_object_unref (e);
264 }
265 g_object_unref (music_dir);
266 }
267 }
268
269 gboolean
270 rb_psp_is_mount_player (GMount *mount, MPIDDevice *device_info)
271 {
272 char *model;
273 gboolean result = FALSE;
274
275 g_object_get (device_info, "model", &model, NULL);
276 if (model != NULL && (g_str_equal (model, "PSP") || g_str_equal (model, "\"PSP\" MS"))) {
277 result = TRUE;
278 }
279 g_free (model);
280
281 return result;
282 }
283
284 void
285 _rb_psp_source_register_type (GTypeModule *module)
286 {
287 rb_psp_source_register_type (module);
288 }