hythmbox-2.98/lib/libmediaplayerid/mpid-util.c

No issues found

  1 /*
  2  * Copyright (C) 2009 Jonathan Matthew  <jonathan@d14n.org>
  3  *
  4  * This library is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2 of the License, or (at your option) any later version.
  8  *
  9  * This library is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with this library; if not, write to the
 16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 17  * Boston, MA 02111-1307, USA.
 18  */
 19 
 20 #include <string.h>
 21 #include <glib.h>
 22 #include <glib/gprintf.h>
 23 #include <glib-object.h>
 24 
 25 #include "mediaplayerid.h"
 26 #include "mpid-private.h"
 27 
 28 static gboolean debug_enabled = FALSE;
 29 
 30 #define ENUM_ENTRY(name, nick) { name, "" #name "", nick }
 31 
 32 /**
 33  * MPIDError:
 34  * @MPID_ERROR_NONE: Indicates no error has occurred
 35  * @MPID_ERROR_NO_DEVICE_PATH: Unable to find the device path
 36  * @MPID_ERROR_MECHANISM_FAILED: The device detection mechanism (e.g. udev or HAL) failed
 37  * @MPID_ERROR_NOT_MEDIA_PLAYER: The device is not a media player
 38  * @MPID_ERROR_DEVICE_INFO_MISSING: The device detection mechanism identified the device
 39  *   but was unable to locate its device information
 40  */
 41 
 42 GType
 43 mpid_error_get_type (void)
 44 {
 45 	static GType etype = 0;
 46 
 47 	if (etype == 0) {
 48 		static const GEnumValue values[] = {
 49 			ENUM_ENTRY(MPID_ERROR_NONE, "OK"),
 50 			ENUM_ENTRY(MPID_ERROR_NO_DEVICE_PATH, "no-such-device"),
 51 			ENUM_ENTRY(MPID_ERROR_MECHANISM_FAILED, "device-db-failed"),
 52 			ENUM_ENTRY(MPID_ERROR_NOT_MEDIA_PLAYER, "not-media-player"),
 53 			ENUM_ENTRY(MPID_ERROR_DEVICE_INFO_MISSING, "device-info-missing"),
 54 			{ 0, 0, 0 }
 55 		};
 56 
 57 		etype = g_enum_register_static ("MPIDError", values);
 58 	}
 59 
 60 	return etype;
 61 }
 62 
 63 /**
 64  * MPIDSource:
 65  * @MPID_SOURCE_NONE: No device information is available
 66  * @MPID_SOURCE_SYSTEM: Device information provided by the operating system (e.g. udev or HAL)
 67  * @MPID_SOURCE_OVERRIDE: Device information provided by an override file on the device itself.
 68  */
 69 
 70 GType
 71 mpid_source_get_type (void)
 72 {
 73 	static GType etype = 0;
 74 
 75 	if (etype == 0) {
 76 		static const GEnumValue values[] = {
 77 			ENUM_ENTRY(MPID_SOURCE_NONE, "no-device-info"),
 78 			ENUM_ENTRY(MPID_SOURCE_SYSTEM, "system-device-info"),
 79 			ENUM_ENTRY(MPID_SOURCE_OVERRIDE, "override-device-info"),
 80 			{ 0, 0, 0 }
 81 		};
 82 
 83 		etype = g_enum_register_static ("MPIDSourceType", values);
 84 	}
 85 
 86 	return etype;
 87 }
 88 
 89 /**
 90  * mpid_enable_debug:
 91  * @debug: whether to enable debug output
 92  *
 93  * Enables or disables debug output from the MPID library
 94  */
 95 void
 96 mpid_enable_debug (gboolean debug)
 97 {
 98 	debug_enabled = debug;
 99 }
100 
101 void
102 mpid_debug (const char *format, ...)
103 {
104 	va_list args;
105 	va_start (args, format);
106 	if (debug_enabled)
107 		g_vprintf (format, args);
108 	va_end (args);
109 }
110 
111 void
112 mpid_debug_strv (const char *what, char **strv)
113 {
114 	int i;
115 	if (strv != NULL) {
116 		mpid_debug ("%s:\n", what);
117 		for (i = 0; strv[i] != NULL; i++) {
118 			mpid_debug ("\t%s\n", strv[i]);
119 		}
120 	} else {
121 		mpid_debug ("%s: (none)\n", what);
122 	}
123 }
124 
125 void
126 mpid_debug_str (const char *what, const char *str)
127 {
128 	if (str != NULL) {
129 		mpid_debug ("%s: %s\n", what, str);
130 	} else {
131 		mpid_debug ("%s: (none)\n", what);
132 	}
133 }
134 
135 static GKeyFile *
136 read_fake_keyfile (const char *path)
137 {
138 	const char *fake_group = "[mpid-data]\n";
139 	char *data;
140 	char *munged;
141 	gsize data_size;
142 	gsize munged_data_size;
143 	GKeyFile *keyfile;
144 	GError *error = NULL;
145 
146 	if (g_file_get_contents (path, &data, &data_size, &error) == FALSE) {
147 		mpid_debug ("unable to read contents of file %s: %s\n", path, error->message);
148 		g_clear_error (&error);
149 		return NULL;
150 	}
151 
152 	/* prepend a group name to the file contents */
153 	munged_data_size = data_size + strlen (fake_group);
154 	munged = g_malloc0 (munged_data_size + 1);
155 	strcpy (munged, fake_group);
156 	memcpy (munged + strlen (fake_group), data, data_size);
157 
158 	keyfile = g_key_file_new ();
159 	if (g_key_file_load_from_data (keyfile, munged, munged_data_size, G_KEY_FILE_NONE, &error) == FALSE) {
160 		mpid_debug ("unable to parse contents of file %s: %s\n", path, error->message);
161 		g_key_file_free (keyfile);
162 		keyfile = NULL;
163 
164 		/* probably do something with this error too */
165 		g_clear_error (&error);
166 	}
167 
168 	g_free (munged);
169 	return keyfile;
170 }
171 
172 void
173 mpid_override_string_from_keyfile (char **str, GKeyFile *keyfile, const char *group, const char *key)
174 {
175 	char *v;
176 	v = g_key_file_get_string (keyfile, group, key, NULL);
177 	if (v != NULL) {
178 		g_free (*str);
179 		*str = v;
180 	}
181 }
182 
183 void
184 mpid_override_strv_from_keyfile (char ***strv, GKeyFile *keyfile, const char *group, const char *key)
185 {
186 	char **v;
187 	v = g_key_file_get_string_list (keyfile, group, key, NULL, NULL);
188 	if (v != NULL) {
189 		g_strfreev (*strv);
190 		*strv = v;
191 	}
192 }
193 
194 void
195 mpid_device_read_override_file (MPIDDevice *device)
196 {
197 	GKeyFile *keyfile;
198 	GError *error = NULL;
199 	char *mountpoint;
200 	char *override_path;
201 	char *start_group;
202 	char *str;
203 	int val;
204 
205 	mountpoint = mpid_device_get_mount_point (device);
206 	if (mountpoint == NULL) {
207 		/* maybe set an error if not already set? */
208 		return;
209 	}
210 
211 	override_path = g_build_filename (mountpoint, ".audio_player.mpi", NULL);
212 	if (g_file_test (override_path, G_FILE_TEST_EXISTS)) {
213 		mpid_debug ("found override file %s on mount %s\n", override_path, mountpoint);
214 
215 		device->error = MPID_ERROR_NONE;
216 		mpid_read_device_file (device, override_path);
217 		device->source = MPID_SOURCE_OVERRIDE;
218 		g_free (override_path);
219 		g_free (mountpoint);
220 		return;
221 	}
222 
223 	override_path = g_build_filename (mountpoint, ".is_audio_player", NULL);
224 	if (g_file_test (override_path, G_FILE_TEST_EXISTS) == FALSE) {
225 		mpid_debug ("override file %s not found on mount %s\n", override_path, mountpoint);
226 		g_free (override_path);
227 		g_free (mountpoint);
228 		return;
229 	}
230 
231 	keyfile = read_fake_keyfile (override_path);
232 	g_free (override_path);
233 	g_free (mountpoint);
234 
235 	if (keyfile == NULL) {
236 		/* maybe set an error? */
237 		return;
238 	}
239 
240 	/* forget any previous error */
241 	device->error = MPID_ERROR_NONE;
242 	device->source = MPID_SOURCE_OVERRIDE;
243 
244 	/* ensure we at least have 'storage' protocol and mp3 output.
245 	 * for mp3-only devices with no playlists, an empty override file should suffice.
246 	 */
247 	if (device->access_protocols == NULL) {
248 		char *p[] = { MPID_PROTOCOL_GENERIC, NULL };
249 		device->access_protocols = g_strdupv (p);
250 	}
251 
252 	if (device->output_formats == NULL) {
253 		char *f[] = { "audio/mpeg", NULL };
254 		device->output_formats = g_strdupv (f);
255 	}
256 
257 	/* now apply information from the override file */
258 	start_group = g_key_file_get_start_group (keyfile);
259 	g_key_file_set_list_separator (keyfile, ',');
260 
261 	mpid_override_strv_from_keyfile (&device->output_formats, keyfile, start_group, "output_formats");
262 	mpid_override_strv_from_keyfile (&device->input_formats, keyfile, start_group, "input_formats");
263 	mpid_override_strv_from_keyfile (&device->playlist_formats, keyfile, start_group, "playlist_formats");
264 	mpid_override_strv_from_keyfile (&device->audio_folders, keyfile, start_group, "audio_folders");
265 
266 	str = g_key_file_get_string (keyfile, start_group, "playlist_path", NULL);
267 	if (str != NULL) {
268 		g_free (device->playlist_path);
269 		device->playlist_path = str;
270 	}
271 
272 	val = g_key_file_get_integer (keyfile, start_group, "folder_depth", &error);
273 	if (error == NULL) {
274 		device->folder_depth = val;
275 	} else {
276 		g_clear_error (&error);
277 	}
278 
279 	g_key_file_free (keyfile);
280 }