static char * get_prop_string_array(LibHalContext *hal_ctx, const char *udi, const char *prop) { char **props, *ret, *str; int i, len = 0; props = libhal_device_get_property_strlist(hal_ctx, udi, prop, NULL); if (props) { for (i = 0; props[i]; i++) len += strlen(props[i]); ret = xcalloc(sizeof(char), len + i); /* i - 1 commas, 1 NULL */ if (!ret) { libhal_free_string_array(props); return NULL; } str = ret; for (i = 0; props[i]; i++) { strcpy(str, props[i]); str += strlen(props[i]); *str++ = ','; } *(str-1) = '\0'; libhal_free_string_array(props); } else { return NULL; } return ret; }
static int gather_capabilities(LibHalContext *ctx, const char *udi, virNodeDevCapsDefPtr *caps_p) { char *bus_name = NULL; virNodeDevCapsDefPtr caps = NULL; char **hal_cap_names = NULL; int rv; size_t i; if (STREQ(udi, "/org/freedesktop/Hal/devices/computer")) { rv = gather_capability(ctx, udi, "system", &caps); if (rv != 0) goto failure; } if (get_str_prop(ctx, udi, "info.subsystem", &bus_name) == 0 || get_str_prop(ctx, udi, "linux.subsystem", &bus_name) == 0) { rv = gather_capability(ctx, udi, bus_name, &caps); if (rv != 0) goto failure; } hal_cap_names = libhal_device_get_property_strlist(ctx, udi, "info.capabilities", NULL); if (hal_cap_names) { for (i = 0; hal_cap_names[i]; i++) { if (! (bus_name && STREQ(hal_cap_names[i], bus_name))) { rv = gather_capability(ctx, udi, hal_cap_names[i], &caps); if (rv != 0) goto failure; } } for (i = 0; hal_cap_names[i]; i++) VIR_FREE(hal_cap_names[i]); VIR_FREE(hal_cap_names); } VIR_FREE(bus_name); *caps_p = caps; return 0; failure: VIR_FREE(bus_name); if (hal_cap_names) { for (i = 0; hal_cap_names[i]; i++) VIR_FREE(hal_cap_names[i]); VIR_FREE(hal_cap_names); } while (caps) { virNodeDevCapsDefPtr next = caps->next; virNodeDevCapsDefFree(caps); caps = next; } return rv; }
void CHALManager::HandleNewVolume(CStorageDevice *dev) { if (g_advancedSettings.m_handleMounting) { /* Here it can be checked if the device isn't mounted and then mount */ //TODO Have mountpoints be other than in /media/* if (!dev->Mounted && (dev->HotPlugged || dev->Type == 2) && dev->Approved) { char **capability; capability =libhal_device_get_property_strlist (m_Context, dev->UDI.c_str(), "info.capabilities", NULL); bool Mountable = false; if (dev->Type == 2 && (strcmp(capability[0], "volume.disc") == 0 && strcmp(capability[1], "volume") == 0)) // CD/DVD Mountable = true; else if ((strcmp(capability[0], "volume") == 0 && strcmp(capability[1], "block") == 0)) // HDD Mountable = true; if (Mountable) { CLog::Log(LOGNOTICE, "HAL: Trying to mount %s", dev->FriendlyName.c_str()); CStdString MountPoint; CStdString TestPath; if (dev->Label.size() > 0) { MountPoint = dev->Label.c_str(); TestPath.Format("/media/%s", MountPoint.c_str()); struct stat St; if (stat("/media", &St) != 0) return; //If /media doesn't exist something is wrong. while(stat (TestPath.c_str(), &St) == 0 && S_ISDIR (St.st_mode)) { CLog::Log(LOGDEBUG, "HAL: Proposed Mountpoint already existed"); MountPoint.append("_"); TestPath.Format("/media/%s", MountPoint.c_str()); } } else { MountPoint = StorageTypeToString(dev->Type); TestPath.Format("/media/%s", MountPoint.c_str()); int Nbr = 0; struct stat St; if (stat("/media", &St) != 0) return; //If /media doesn't exist something is wrong. while(stat (TestPath.c_str(), &St) == 0 && S_ISDIR (St.st_mode)) { CLog::Log(LOGDEBUG, "HAL: Proposed Mountpoint already existed"); Nbr++; MountPoint.Format("%s%i", StorageTypeToString(dev->Type), Nbr); TestPath.Format("/media/%s", MountPoint.c_str()); } } if (Mount(dev, MountPoint)) { CLog::Log(LOGINFO, "HAL: mounted %s on %s", dev->FriendlyName.c_str(), dev->MountPoint.c_str()); if (m_Notifications) CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(13021), dev->FriendlyName.c_str(), TOAST_DISPLAY_TIME, false); } } libhal_free_string_array(capability); } } }
/* Parse newly found device and add it to our remembered devices */ void CHALManager::AddDevice(const char *udi) { CSingleLock lock(m_lock); char *category; category = libhal_device_get_property_string(m_Context, udi, "info.category", NULL); if (category == NULL) return; if (strcmp(category, "volume") == 0) { CStorageDevice dev(udi); if (DeviceFromVolumeUdi(udi, &dev)) { CLog::Log(LOGDEBUG, "HAL: Added - %s | %s", CHALManager::StorageTypeToString(dev.Type), dev.toString().c_str()); HandleNewVolume(&dev); m_Volumes.push_back(dev); } } #if defined(HAS_SDL_JOYSTICK) // Scan input devices else if (strcmp(category, "input") == 0) { DBusError dbusError; dbus_error_init(&dbusError); char **capability; capability =libhal_device_get_property_strlist (m_Context, udi, "info.capabilities", &dbusError); for(char **ptr = capability; *ptr != NULL;ptr++) { // Reload joysticks if(strcmp(*ptr, "input.joystick") == 0) { CLog::Log(LOGINFO, "HAL: Joystick plugged in"); CHALDevice dev = CHALDevice(udi); dev.FriendlyName = libhal_device_get_property_string(m_Context, udi, "info.product", &m_Error); m_Joysticks.push_back(dev); if(m_Joysticks.size() < 2 || m_bMultipleJoysticksSupport) { // Restart SDL joystick subsystem if (!g_Joystick.Reinitialize()) break; if (m_Notifications) CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(13024), dev.FriendlyName.c_str(), TOAST_DISPLAY_TIME, false); } } } libhal_free_string_array(capability); } #endif /* else if (strcmp(category, "camera") == 0) { // PTP-Devices } else if (strcmp(category, "bluetooth_hci") == 0) { // Bluetooth-Devices } else if (strcmp(category, "portable audio player") == 0) { // MTP-Devices } else if (strcmp(category, "alsa") == 0) { //Alsa Devices } */ libhal_free_string(category); }
/** Entry point * * @param argc Number of arguments given to program * @param argv Arguments given to program * @return Return code */ int main (int argc, char *argv[]) { char *udi = NULL; char *key = NULL; int type; dbus_bool_t is_hex = FALSE; dbus_bool_t is_verbose = FALSE; dbus_bool_t is_version = FALSE; char *str; DBusError error; if (argc <= 1) { usage (argc, argv); return 1; } while (1) { int c; int option_index = 0; const char *opt; static struct option long_options[] = { {"udi", 1, NULL, 0}, {"key", 1, NULL, 0}, {"hex", 0, NULL, 0}, {"verbose", 0, NULL, 0}, {"version", 0, NULL, 0}, {"help", 0, NULL, 0}, {NULL, 0, NULL, 0} }; c = getopt_long (argc, argv, "", long_options, &option_index); if (c == -1) break; switch (c) { case 0: opt = long_options[option_index].name; if (strcmp (opt, "help") == 0) { usage (argc, argv); return 0; } else if (strcmp (opt, "hex") == 0) { is_hex = TRUE; } else if (strcmp (opt, "verbose") == 0) { is_verbose = TRUE; } else if (strcmp (opt, "version") == 0) { is_version = TRUE; } else if (strcmp (opt, "key") == 0) { key = strdup (optarg); } else if (strcmp (opt, "udi") == 0) { udi = strdup (optarg); } break; default: usage (argc, argv); return 1; break; } } if (is_version) { printf ("hal-get-property " PACKAGE_VERSION "\n"); return 0; } if (udi == NULL || key == NULL) { usage (argc, argv); return 1; } dbus_error_init (&error); if ((hal_ctx = libhal_ctx_new ()) == NULL) { fprintf (stderr, "error: libhal_ctx_new\n"); return 1; } if (!libhal_ctx_set_dbus_connection (hal_ctx, dbus_bus_get (DBUS_BUS_SYSTEM, &error))) { fprintf (stderr, "error: libhal_ctx_set_dbus_connection: %s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); return 1; } if (!libhal_ctx_init (hal_ctx, &error)) { if (dbus_error_is_set(&error)) { fprintf (stderr, "error: libhal_ctx_init: %s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); } fprintf (stderr, "Could not initialise connection to hald.\n" "Normally this means the HAL daemon (hald) is not running or not ready.\n"); return 1; } type = libhal_device_get_property_type (hal_ctx, udi, key, &error); if (type == LIBHAL_PROPERTY_TYPE_INVALID) { fprintf (stderr, "error: libhal_device_get_property_type: %s: %s\n", error.name, error.message); LIBHAL_FREE_DBUS_ERROR (&error); return 1; } /* emit the value to stdout */ switch (type) { case LIBHAL_PROPERTY_TYPE_STRING: str = libhal_device_get_property_string (hal_ctx, udi, key, &error); if (is_verbose) printf ("Type is string\n"); printf ("%s\n", str); libhal_free_string (str); break; case LIBHAL_PROPERTY_TYPE_INT32: if (is_verbose) printf ("Type is integer (shown in %s)\n", (is_hex ? "hexadecimal" : "decimal")); printf ((is_hex ? "%x\n" : "%d\n"), libhal_device_get_property_int (hal_ctx, udi, key, &error)); break; case LIBHAL_PROPERTY_TYPE_UINT64: if (is_verbose) printf ("Type is uint64 (shown in %s)\n", (is_hex ? "hexadecimal" : "decimal")); printf ((is_hex ? "%llx\n" : "%llu\n"), (long long unsigned int) libhal_device_get_property_uint64 (hal_ctx, udi, key, &error)); break; case LIBHAL_PROPERTY_TYPE_DOUBLE: if (is_verbose) printf ("Type is double\n"); printf ("%f\n", libhal_device_get_property_double (hal_ctx, udi, key, &error)); break; case LIBHAL_PROPERTY_TYPE_BOOLEAN: if (is_verbose) printf ("Type is boolean\n"); printf ("%s\n", libhal_device_get_property_bool (hal_ctx, udi, key, &error) ? "true" : "false"); break; case LIBHAL_PROPERTY_TYPE_STRLIST: { unsigned int i; char **strlist; if ((strlist = libhal_device_get_property_strlist (hal_ctx, udi, key, &error)) != NULL) { for (i = 0; strlist[i] != 0; i++) { printf ("%s", strlist[i]); if (strlist[i+1] != NULL) printf (" "); } } break; } default: printf ("Unknown type %d='%c'\n", type, type); return 1; break; } if (dbus_error_is_set (&error)) { fprintf (stderr, "error: %s: %s\n", error.name, error.message); dbus_error_free (&error); return 1; } return 0; }
gboolean check_libhal (const char *server_addr) { pid_t child_pid; child_pid = fork (); if (child_pid == -1) { printf ("Cannot fork\n"); exit (1); } else if (child_pid == 0) { DBusError error; DBusConnection *conn; LibHalContext *ctx; dbus_bool_t passed; printf ("server address='%s'\n", server_addr); dbus_error_init (&error); if ((conn = dbus_connection_open (server_addr, &error)) == NULL) { printf ("Error connecting to server: %s\n", error.message); goto fail; } dbus_connection_setup_with_g_main (conn, NULL); if ((ctx = libhal_ctx_new ()) == NULL) { printf ("Error getting libhal context\n"); goto fail; } libhal_ctx_set_dbus_connection (ctx, conn); libhal_ctx_init (ctx, &error); if (dbus_error_is_set (&error)) { printf ("FAILED98: %s\n", error.message); goto fail; } printf ("SUCCESS98\n"); libhal_device_print (ctx, "/org/freedesktop/Hal/devices/testobj1", &error); if (dbus_error_is_set (&error)) { printf ("FAILED99: %s\n", error.message); goto fail; } printf ("SUCCESS99\n"); passed = FALSE; { char *val; val = libhal_device_get_property_string (ctx, "/org/freedesktop/Hal/devices/testobj1", "test.string", &error); if (val == NULL || strcmp (val, "fooooobar22") != 0 || dbus_error_is_set (&error)) { libhal_free_string (val); printf ("FAILED100\n"); goto fail; } printf ("SUCCESS100\n"); libhal_free_string (val); } { char *val; val = libhal_device_get_property_string (ctx, "/org/freedesktop/Hal/devices/testobj1", "test.string2", &error); if (val == NULL || strcmp (val, "fooøةמ") != 0 || dbus_error_is_set (&error)) { libhal_free_string (val); printf ("FAILED101: %s\n", error.message); goto fail; } libhal_free_string (val); printf ("SUCCESS101\n"); } { dbus_bool_t b; b = libhal_device_get_property_bool ( ctx, "/org/freedesktop/Hal/devices/testobj1", "test.bool", &error); if (!b || dbus_error_is_set (&error)) { printf ("FAILED102: %s, %i\n", error.message, b); goto fail; } printf ("SUCCESS102\n"); } { double val; double expected_val = 0.53434343; val = libhal_device_get_property_double (ctx, "/org/freedesktop/Hal/devices/testobj1", "test.double", &error); if ( memcmp (&val, &expected_val, sizeof (double)) != 0 || dbus_error_is_set (&error)) { printf ("FAILED103\n"); goto fail; } printf ("SUCCESS103\n"); } if (libhal_device_get_property_uint64 ( ctx, "/org/freedesktop/Hal/devices/testobj1", "test.uint64", &error) != ((((dbus_uint64_t)1)<<35) + 5) || dbus_error_is_set (&error)) { printf ("FAILED104: %s\n", error.message); goto fail; } printf ("SUCCESS104\n"); { char **val; val = libhal_device_get_property_strlist (ctx, "/org/freedesktop/Hal/devices/testobj1", "test.strlist", &error); if (val == NULL || dbus_error_is_set (&error)) { libhal_free_string_array (val); printf ("FAILED105: %s\n", error.message); goto fail; } printf ("SUCCESS105\n"); if (libhal_string_array_length (val) != 2) { libhal_free_string_array (val); printf ("FAILED106\n"); goto fail; } printf ("SUCCESS106\n"); if (strcmp (val[0], "foostrlist2") != 0 || strcmp (val[1], "foostrlist3") != 0) { libhal_free_string_array (val); printf ("FAILED107\n"); goto fail; } printf ("SUCCESS107\n"); libhal_free_string_array (val); } if (libhal_device_get_property_int ( ctx, "/org/freedesktop/Hal/devices/testobj1", "test.int", &error) != 42 || dbus_error_is_set (&error)) { printf ("FAILED108\n"); goto fail; } printf ("SUCCESS108\n"); /* tests for libhal_psi */ { int type; char *key; LibHalPropertySet *pset; LibHalPropertySetIterator it; unsigned int psi_num_passed; unsigned int psi_num_elems; if ((pset = libhal_device_get_all_properties (ctx, "/org/freedesktop/Hal/devices/testobj1", &error)) == NULL) return FALSE; printf ("SUCCESS110\n"); psi_num_passed = 0; psi_num_elems = libhal_property_set_get_num_elems (pset); for (libhal_psi_init (&it, pset); libhal_psi_has_more (&it); libhal_psi_next (&it)) { type = libhal_psi_get_type (&it); key = libhal_psi_get_key (&it); switch (type) { case LIBHAL_PROPERTY_TYPE_STRING: if (strcmp (key, "info.udi") == 0) { if (strcmp (libhal_psi_get_string (&it), "/org/freedesktop/Hal/devices/testobj1") == 0) { psi_num_passed++; } else { printf ("fail on %s\n", key); } } else if (strcmp (key, "test.string") == 0) { if (strcmp (libhal_psi_get_string (&it), "fooooobar22") == 0) { psi_num_passed++; } else { printf ("fail on %s\n", key); } } else if (strcmp (key, "test.string2") == 0) { if (strcmp (libhal_psi_get_string (&it), "fooøةמ") == 0) { psi_num_passed++; } else { printf ("fail on %s\n", key); } } break; case LIBHAL_PROPERTY_TYPE_INT32: if (strcmp (key, "test.int") == 0) { if (libhal_psi_get_int (&it) == 42) psi_num_passed++; else printf ("fail on %s\n", key); } break; case LIBHAL_PROPERTY_TYPE_UINT64: if (strcmp (key, "test.uint64") == 0) { if (libhal_psi_get_uint64 (&it) == ((((dbus_uint64_t)1)<<35) + 5)) psi_num_passed++; else printf ("fail on %s\n", key); } break; case LIBHAL_PROPERTY_TYPE_BOOLEAN: if (strcmp (key, "test.bool") == 0) { if (libhal_psi_get_bool (&it) == TRUE) psi_num_passed++; else printf ("fail on %s\n", key); } break; case LIBHAL_PROPERTY_TYPE_DOUBLE: if (strcmp (key, "test.double") == 0) { double val = 0.53434343; double val2; val2 = libhal_psi_get_double (&it); if (memcmp (&val, &val2, sizeof (double)) == 0) psi_num_passed++; else printf ("fail on %s\n", key); } break; case LIBHAL_PROPERTY_TYPE_STRLIST: if (strcmp (key, "test.strlist") == 0) { char **val; val = libhal_psi_get_strlist (&it); if (libhal_string_array_length (val) == 2 && strcmp (val[0], "foostrlist2") == 0 && strcmp (val[1], "foostrlist3") == 0 && val[2] == NULL) psi_num_passed++; else printf ("fail on %s\n", key); } break; default: printf (" *** unknown type for key %s\n", key); break; } } libhal_free_property_set (pset); if (psi_num_passed != psi_num_elems) { printf ("FAILED111\n"); goto fail; } printf ("SUCCESS111\n"); } /* end libhal_test_psi */ printf ("Passed all libhal tests\n"); passed = TRUE; fail: if (dbus_error_is_set (&error)) dbus_error_free (&error); send_tests_done (conn, passed); exit (1); } else { printf ("child pid=%d\n", child_pid); } return TRUE; }
static void device_added(LibHalContext *hal_ctx, const char *udi) { char **props; /* Cleverly, these are currently all leaked. */ char *path = NULL, *driver = NULL, *name = NULL, *xkb_rules = NULL; char *xkb_model = NULL, *xkb_layout = NULL, *xkb_variant = NULL; char **xkb_options = NULL; DBusError error; struct xserver_option *options = NULL; int type = TYPE_NONE; int i; DeviceIntPtr dev = NULL; dbus_error_init(&error); props = libhal_device_get_property_strlist(hal_ctx, udi, "info.capabilities", &error); if (!props) { DebugF("[config/hal] couldn't get capabilities for %s: %s (%s)\n", udi, error.name, error.message); goto out_error; } for (i = 0; props[i]; i++) { /* input.keys is the new, of which input.keyboard is a subset, but * input.keyboard is the old 'we have keys', so we have to keep it * around. */ if (strcmp(props[i], "input.keys") == 0 || strcmp(props[i], "input.keyboard") == 0) type |= TYPE_KEYS; if (strcmp(props[i], "input.mouse") == 0) type |= TYPE_POINTER; } libhal_free_string_array(props); if (!type) goto out_error; driver = get_prop_string(hal_ctx, udi, "input.x11_driver"); path = get_prop_string(hal_ctx, udi, "input.device"); if (!driver || !path) { DebugF("[config/hal] no driver or path specified for %s\n", udi); goto unwind; } name = get_prop_string(hal_ctx, udi, "info.product"); if (!name) name = xstrdup("(unnamed)"); if (type & TYPE_KEYS) { xkb_rules = get_prop_string(hal_ctx, udi, "input.xkb.rules"); xkb_model = get_prop_string(hal_ctx, udi, "input.xkb.model"); xkb_layout = get_prop_string(hal_ctx, udi, "input.xkb.layout"); xkb_variant = get_prop_string(hal_ctx, udi, "input.xkb.variant"); xkb_options = get_prop_string_array(hal_ctx, udi, "input.xkb.options"); } options = xcalloc(sizeof(*options), 1); options->key = xstrdup("_source"); options->value = xstrdup("server/hal"); if (!options->key || !options->value) { ErrorF("[config] couldn't allocate first key/value pair\n"); goto unwind; } add_option(&options, "path", path); add_option(&options, "driver", driver); add_option(&options, "name", name); add_option(&options, "hal_udi", udi); if (xkb_model) add_option(&options, "xkb_model", xkb_model); if (xkb_layout) add_option(&options, "xkb_layout", xkb_layout); if (xkb_variant) add_option(&options, "xkb_variant", xkb_variant); #if 0 if (xkb_options) add_option(&options, "xkb_options", xkb_options); #endif /* Maemo-specific hack. Ugh. */ if (type & TYPE_KEYS) add_option(&options, "type", "keyboard"); else add_option(&options, "type", "pointer"); if (NewInputDeviceRequest(options, &dev) != Success) { DebugF("[config/hal] NewInputDeviceRequest failed\n"); goto unwind; } dbus_error_free(&error); return; unwind: if (path) xfree(path); if (driver) xfree(driver); if (name) xfree(name); if (xkb_rules) xfree(xkb_rules); if (xkb_model) xfree(xkb_model); if (xkb_layout) xfree(xkb_layout); if (xkb_options) { for (i = 0; xkb_options[i]; i++) xfree(xkb_options[i]); xfree(xkb_options); } out_error: dbus_error_free(&error); return; }
gboolean rb_generic_player_is_mount_player (GMount *mount) { gboolean result = FALSE; #ifdef HAVE_HAL LibHalContext *ctx; ctx = get_hal_context (); if (ctx != NULL) { char *udi = get_hal_udi_for_player (ctx, mount); if (udi != NULL) { DBusError error; char **proplist; char *prop; rb_debug ("Checking udi %s", udi); /* check that it can be accessed as mass-storage */ dbus_error_init (&error); proplist = libhal_device_get_property_strlist (ctx, udi, "portable_audio_player.access_method.protocols", &error); if (proplist != NULL && !dbus_error_is_set (&error)) { int i; for (i = 0; proplist[i] != NULL; i++) { rb_debug ("device access method: %s", proplist[i]); if (strcmp (proplist[i], "storage") == 0) { result = TRUE; break; } } libhal_free_string_array (proplist); } free_dbus_error ("checking device access method", &error); if (result == FALSE) { dbus_error_init (&error); prop = libhal_device_get_property_string (ctx, udi, "portable_audio_player.access_method", &error); if (prop != NULL && strcmp (prop, "storage") == 0 && !dbus_error_is_set (&error)) { /* the device has passed all tests, so it should be a usable player */ result = TRUE; } libhal_free_string (prop); free_dbus_error ("checking device access method", &error); } if (result == FALSE) { rb_debug ("device cannot be accessed via storage"); } } else { rb_debug ("device is not an audio player"); } g_free (udi); } cleanup_hal_context (ctx); #endif /* HAVE_HAL */ /* treat as audio player if ".is_audio_player" exists in the root of the volume */ if (!result) { GFile *is_audio_player; is_audio_player = get_is_audio_player_file (mount); if (is_audio_player != NULL) { result = TRUE; g_object_unref (is_audio_player); } } return result; }
static void get_device_info (RBGenericPlayerSource *source) { RBGenericPlayerSourcePrivate *priv = GENERIC_PLAYER_SOURCE_GET_PRIVATE (source); GMount *mount; GFile *is_audio_player; GError *error = NULL; #ifdef HAVE_HAL LibHalContext *ctx; #endif g_object_get (source, "mount", &mount, NULL); #ifdef HAVE_HAL ctx = get_hal_context (); if (ctx != NULL) { char *udi; udi = get_hal_udi_for_player (ctx, mount); if (udi != NULL) { DBusError error; char *prop; char **proplist; int value; /* get audio folders */ dbus_error_init (&error); proplist = libhal_device_get_property_strlist (ctx, udi, "portable_audio_player.audio_folders", &error); if (proplist) { if (!dbus_error_is_set (&error)) { priv->audio_folders = g_strdupv (proplist); } libhal_free_string_array (proplist); } free_dbus_error ("getting audio folder list", &error); /* get supported mime-types */ dbus_error_init (&error); proplist = libhal_device_get_property_strlist (ctx, udi, "portable_audio_player.output_formats", &error); if (proplist) { if (!dbus_error_is_set (&error)) { priv->output_mime_types = g_strdupv (proplist); } libhal_free_string_array (proplist); } free_dbus_error ("getting supported mime-type list", &error); /* get playlist format */ dbus_error_init (&error); proplist = libhal_device_get_property_strlist (ctx, udi, "portable_audio_player.playlist_format", &error); if (proplist) { if (!dbus_error_is_set (&error)) { set_playlist_formats (source, proplist); } libhal_free_string_array (proplist); } free_dbus_error ("getting playlist format", &error); /* get playlist path - in current hal-info packages, this is sometimes a string * and sometimes a strlist, so try both. * http://bugs.freedesktop.org/show_bug.cgi?id=19961 */ dbus_error_init (&error); proplist = libhal_device_get_property_strlist (ctx, udi, "portable_audio_player.playlist_path", &error); if (proplist && !dbus_error_is_set (&error)) { set_playlist_path (source, proplist[0]); libhal_free_string_array (proplist); } free_dbus_error ("getting playlist path (strlist)", &error); dbus_error_init (&error); prop = libhal_device_get_property_string (ctx, udi, "portable_audio_player.playlist_path", &error); if (prop && !dbus_error_is_set (&error)) { set_playlist_path (source, prop); libhal_free_string (prop); } free_dbus_error ("getting playlist path (string)", &error); /* get max folder depth */ dbus_error_init (&error); value = libhal_device_get_property_int (ctx, udi, "portable_audio_player.folder_depth", &error); if (!dbus_error_is_set (&error)) { priv->folder_depth = value; } free_dbus_error ("getting max folder depth", &error); debug_device_info (source, mount, "HAL"); } else { rb_debug ("no player info available (HAL doesn't recognise it as a player"); } g_free (udi); } cleanup_hal_context (ctx); #endif /* allow HAL info to be overridden with .is_audio_player file */ is_audio_player = get_is_audio_player_file (mount); if (is_audio_player != NULL) { char *data = NULL; gsize data_size = 0; rb_debug ("reading .is_audio_player file"); g_file_load_contents (is_audio_player, NULL, &data, &data_size, NULL, &error); if (error != NULL) { /* can we sensibly report this anywhere? */ rb_debug ("error reading .is_audio_player file: %s", error->message); g_clear_error (&error); } else { GKeyFile *keyfile; GError *error = NULL; char *munged; gsize munged_size; const char *fake_group = "[x-rb-data]\n"; char *group; /* prepend a group name to the file contents */ munged_size = data_size + strlen (fake_group); munged = g_malloc0 (munged_size + 1); strcpy (munged, fake_group); memcpy (munged + strlen (fake_group), data, data_size); keyfile = g_key_file_new (); g_key_file_set_list_separator (keyfile, ','); if (g_key_file_load_from_data (keyfile, munged, munged_size, G_KEY_FILE_NONE, &error) == FALSE) { /* and this */ rb_debug ("error loading .is_audio_player file: %s", error->message); g_error_free (error); } else { char *value; char **list; group = g_key_file_get_start_group (keyfile); list = g_key_file_get_string_list (keyfile, group, "audio_folders", NULL, NULL); if (list != NULL) { g_strfreev (priv->audio_folders); priv->audio_folders = list; } list = g_key_file_get_string_list (keyfile, group, "output_formats", NULL, NULL); if (list != NULL) { g_strfreev (priv->output_mime_types); priv->output_mime_types = list; } list = g_key_file_get_string_list (keyfile, group, "playlist_format", NULL, NULL); if (list != NULL) { set_playlist_formats (source, list); g_strfreev (list); } value = g_key_file_get_string (keyfile, group, "playlist_path", NULL); if (value != NULL) { set_playlist_path (source, value); g_free (value); } if (g_key_file_has_key (keyfile, group, "folder_depth", NULL)) { priv->folder_depth = g_key_file_get_integer (keyfile, group, "folder_depth", NULL); } g_free (group); } g_key_file_free (keyfile); g_free (munged); debug_device_info (source, mount, ".is_audio_player file"); } g_free (data); g_object_unref (is_audio_player); } else { rb_debug ("no .is_audio_player file found on this device"); } g_object_unref (mount); }