From: Linus W. <lin...@gm...> - 2008-02-12 23:30:00
|
2008/2/12, Sciamano <sci...@iw...>: > Got it. I wonder how Amarok2, Rhythmbox and Gnomad2 have solved this issue. > Don't they depend on libmtp too? Yeah, we put in other dependencies to auto-detect device plugin. Rhythmbox and Gnomad2 do something like this: We include D-Bus and HAL libraries, define some useful global variables: #include <dbus/dbus-glib.h> #include <dbus/dbus.h> #include <dbus/dbus-glib-lowlevel.h> #include <hal/libhal.h> DBusConnection *dbus_system_conn; DBusError dbus_error; LibHalContext *hal_context; char *global_udistr = NULL; In some main() function we connect to the D-Bus system bus, then we connect the HAL handlers (callbacks) to that system bus: // Connect to the SYSTEM bus to detect devices and stuff. dbus_error_init(&dbus_error); dbus_system_conn = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error); if (dbus_system_conn == NULL) { g_printerr ("Failed to open connection to D-BUS SYSTEM bus\n"); } else { dbus_connection_setup_with_g_main(dbus_system_conn, NULL); // dbus_system_proxy = dbus_g_proxy_new_for_name (dbus_system_conn, // "org.freedesktop.Hal", // "/", // "org.freedesktop.Hal.Device"); // g_object_unref (dbus_system_proxy); hal_context = libhal_ctx_new (); if (hal_context == NULL) { g_print("Couldn't create HAL context!\n"); } else { //libhal_ctx_set_user_data (hal_context, (void *) NULL); libhal_ctx_set_dbus_connection (hal_context, dbus_system_conn); libhal_ctx_set_device_added (hal_context, hal_device_added); libhal_ctx_set_device_removed (hal_context, hal_device_removed); libhal_device_property_watch_all (hal_context, &dbus_error); if (!libhal_ctx_init (hal_context, &dbus_error)) { g_print("error: libhal_ctx_init: %s: %s\n", dbus_error.name, dbus_error.message); } } } dbus_error_free(&dbus_error); Then we have to have the functions that HAL shall call whenever a device is added/removed. In gnomad2 they look like this, and use the MTP libmtp.fdi HAL definitions to identify MTP devices. static void hal_device_added (LibHalContext *context, const char *udi) { int vendor_id; int product_id; char *protocol; vendor_id = libhal_device_get_property_int (context, udi, "usb.vendor_id", NULL); product_id = libhal_device_get_property_int (context, udi, "usb.product_id", NULL); protocol = libhal_device_get_property_string (context, udi, "portable_audio_player.type", NULL); if (protocol != NULL) { g_print("Detected connected device VID=0x%04x/PID=0x%04x, protocol: %s\n", vendor_id, product_id, protocol); g_print("UDI: %s\n", udi); if (!strcmp(protocol, "mtp")) { // LIBMTP_Get_First_Device(void) ETC. } } libhal_free_string(protocol); } static void hal_device_removed (LibHalContext *context, const char *udi) { int vendor_id; int product_id; vendor_id = libhal_device_get_property_int (context, udi, "usb.vendor_id", NULL); product_id = libhal_device_get_property_int (context, udi, "usb.product_id", NULL); if (global_udistr != NULL && !strcmp(udi, global_udistr)) { g_print("Device VID=0x%04x/PID=0x%04x detached.\n", vendor_id, product_id); g_print("UDI: %s\n", udi); // LIBMTP_Release_Device() ETC. free(global_udistr); global_udistr = NULL; } } The result is that libmtp is called to identify a device whenever a device listed in out HAL .fdi file is plugged in. Cute eh? This is all from glib C code, there are other (similar) constructs in other languages, not that I know how these work tho. Linus |