| | 727 | static pa_bool_t connect_and_register(DBusConnection *connection, void *data) |
| | 728 | { |
| | 729 | DBusError error; |
| | 730 | struct userdata *u = (struct userdata *)data; |
| | 731 | |
| | 732 | if (u->context) |
| | 733 | return TRUE; |
| | 734 | |
| | 735 | if (!(u->context = hal_context_new(pa_dbus_connection_get(u->connection)))) |
| | 736 | return FALSE; |
| | 737 | |
| | 738 | dbus_error_init(&error); |
| | 739 | |
| | 740 | hal_device_add_all(u); |
| | 741 | |
| | 742 | libhal_ctx_set_user_data(u->context, u); |
| | 743 | libhal_ctx_set_device_added(u->context, device_added_cb); |
| | 744 | libhal_ctx_set_device_removed(u->context, device_removed_cb); |
| | 745 | libhal_ctx_set_device_new_capability(u->context, new_capability_cb); |
| | 746 | libhal_ctx_set_device_lost_capability(u->context, lost_capability_cb); |
| | 747 | |
| | 748 | if (!libhal_device_property_watch_all(u->context, &error)) { |
| | 749 | pa_log_error("Error monitoring device list: %s: %s", error.name, error.message); |
| | 750 | goto fail; |
| | 751 | } |
| | 752 | |
| | 753 | if (!dbus_connection_add_filter(pa_dbus_connection_get (u->connection), filter_cb, u, NULL)) { |
| | 754 | pa_log_error("Failed to add filter function"); |
| | 755 | goto fail; |
| | 756 | } |
| | 757 | |
| | 758 | if (pa_dbus_add_matches( |
| | 759 | pa_dbus_connection_get (u->connection), &error, |
| | 760 | "type='signal',sender='org.freedesktop.Hal',interface='org.freedesktop.Hal.Device.AccessControl',member='ACLAdded'", |
| | 761 | "type='signal',sender='org.freedesktop.Hal',interface='org.freedesktop.Hal.Device.AccessControl',member='ACLRemoved'", |
| | 762 | "type='signal',interface='org.pulseaudio.Server',member='DirtyGiveUpMessage'", NULL) < 0) { |
| | 763 | pa_log_error("Unable to subscribe to HAL ACL signals: %s: %s", error.name, error.message); |
| | 764 | goto fail; |
| | 765 | } |
| | 766 | |
| | 767 | return TRUE; |
| | 768 | |
| | 769 | fail: |
| | 770 | dbus_error_free(&error); |
| | 771 | return FALSE; |
| | 772 | } |
| | 773 | |
| | 774 | static DBusHandlerResult ownerchanged_handler(DBusConnection *connection, DBusMessage *message, void *data) |
| | 775 | { |
| | 776 | int ret = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; |
| | 777 | |
| | 778 | if (dbus_message_is_signal(message, "org.freedesktop.DBus", "NameOwnerChanged")) { |
| | 779 | DBusError error; |
| | 780 | char *name, *old_owner, *new_owner; |
| | 781 | |
| | 782 | dbus_error_init(&error); |
| | 783 | dbus_message_get_args(message, &error, DBUS_TYPE_STRING, &name, DBUS_TYPE_STRING, &old_owner, DBUS_TYPE_STRING, &new_owner, DBUS_TYPE_INVALID); |
| | 784 | |
| | 785 | if (dbus_error_is_set(&error)) { |
| | 786 | pa_log_error("failed to get NameOwnerChanged args: %s (%s)", error.name, error.message); |
| | 787 | } else if (name && strcmp (name, "org.freedesktop.Hal") == 0) { |
| | 788 | if (!old_owner || !strlen (old_owner)) { |
| | 789 | pa_log_warn ("HAL startup detected."); |
| | 790 | if (connect_and_register (connection, data)) |
| | 791 | dbus_connection_unregister_object_path (connection, "/org/freedesktop/DBus"); |
| | 792 | else |
| | 793 | pa_log_error ("Failed to connect to HAL bus."); |
| | 794 | } |
| | 795 | |
| | 796 | ret = DBUS_HANDLER_RESULT_HANDLED; |
| | 797 | } |
| | 798 | dbus_error_free(&error); |
| | 799 | } |
| | 800 | |
| | 801 | return ret; |
| | 802 | } |
| | 803 | |
| | 804 | static pa_bool_t listen_for_startup(DBusConnection *connection, void *data) |
| | 805 | { |
| | 806 | DBusObjectPathVTable vtable = { .message_function = ownerchanged_handler, }; |
| | 807 | DBusError error; |
| | 808 | const char MATCH_RULE[] = "sender='org.freedesktop.DBus'," |
| | 809 | "interface='org.freedesktop.DBus'," |
| | 810 | "type='signal'," |
| | 811 | "path='/org/freedesktop/DBus'," |
| | 812 | "member='NameOwnerChanged'"; |
| | 813 | pa_bool_t rc = FALSE; |
| | 814 | |
| | 815 | dbus_error_init(&error); |
| | 816 | dbus_bus_add_match(connection, MATCH_RULE, &error); |
| | 817 | if (!dbus_error_is_set(&error)) { |
| | 818 | if (dbus_connection_register_object_path (connection, "/org/freedesktop/DBus", &vtable, data)) |
| | 819 | rc = TRUE; |
| | 820 | else |
| | 821 | pa_log_error("cannot register object path.\n"); |
| | 822 | } else { |
| | 823 | pa_log_error("Couldn't add match rule: %s (%s)\n", error.name, error.message); |
| | 824 | pa_log_error("Cannot detect a HAL startup."); |
| | 825 | } |
| | 826 | |
| | 827 | dbus_error_free(&error); |
| | 828 | |
| | 829 | return rc; |
| | 830 | } |
| | 831 | |
| 791 | | n = hal_device_add_all(u); |
| 792 | | |
| 793 | | libhal_ctx_set_user_data(u->context, u); |
| 794 | | libhal_ctx_set_device_added(u->context, device_added_cb); |
| 795 | | libhal_ctx_set_device_removed(u->context, device_removed_cb); |
| 796 | | libhal_ctx_set_device_new_capability(u->context, new_capability_cb); |
| 797 | | libhal_ctx_set_device_lost_capability(u->context, lost_capability_cb); |
| 798 | | |
| 799 | | if (!libhal_device_property_watch_all(u->context, &error)) { |
| 800 | | pa_log_error("Error monitoring device list: %s: %s", error.name, error.message); |
| 801 | | goto fail; |
| 802 | | } |
| 803 | | |
| 804 | | if (!dbus_connection_add_filter(pa_dbus_connection_get(u->connection), filter_cb, u, NULL)) { |
| 805 | | pa_log_error("Failed to add filter function"); |
| 806 | | goto fail; |
| 807 | | } |
| 808 | | |
| 809 | | if (pa_dbus_add_matches( |
| 810 | | pa_dbus_connection_get(u->connection), &error, |
| 811 | | "type='signal',sender='org.freedesktop.Hal',interface='org.freedesktop.Hal.Device.AccessControl',member='ACLAdded'", |
| 812 | | "type='signal',sender='org.freedesktop.Hal',interface='org.freedesktop.Hal.Device.AccessControl',member='ACLRemoved'", |
| 813 | | "type='signal',interface='org.pulseaudio.Server',member='DirtyGiveUpMessage'", NULL) < 0) { |
| 814 | | pa_log_error("Unable to subscribe to HAL ACL signals: %s: %s", error.name, error.message); |
| 815 | | goto fail; |
| 816 | | } |
| 817 | | |
| 818 | | pa_log_info("Loaded %i modules.", n); |
| 819 | | |