mirror of https://code.videolan.org/videolan/vlc
udisks: discover localdrives via udisks2
This commit is contained in:
parent
5acf302a46
commit
475d13b2a8
48
configure.ac
48
configure.ac
|
@ -1081,6 +1081,53 @@ PKG_CHECK_MODULES([SYSTEMD], [libsystemd], [
|
|||
])
|
||||
AM_CONDITIONAL([HAVE_SYSTEMD], [test "${have_systemd}" = "yes"])
|
||||
|
||||
dnl Check for sdbus
|
||||
|
||||
have_sdbus="no"
|
||||
AS_IF([test "${have_systemd}" = "yes"], [
|
||||
SDBUS_CFLAGS="${SYSTEMD_CFLAGS} -DSDBUS_HEADER='<systemd/sd-bus.h>'"
|
||||
SDBUS_LIBS="${SYSTEMD_LIBS}"
|
||||
have_sdbus="yes"
|
||||
])
|
||||
|
||||
dnl Check for elogind
|
||||
AC_ARG_ENABLE([elogind],
|
||||
AS_HELP_STRING([--disable-elogind], [ignore elogind as a sd-bus provider]), [], [enable_elogind="yes"])
|
||||
|
||||
AS_IF([test "${have_sdbus}" != "yes" && test "${enable_elogind}" != "no"], [
|
||||
PKG_CHECK_MODULES([ELOGIND], [libelogind], [
|
||||
have_elogind="yes"
|
||||
SDBUS_CFLAGS="${ELOGIND_CFLAGS} -DSDBUS_HEADER='<elogind/sd-bus.h>'"
|
||||
SDBUS_LIBS="${ELOGIND_LIBS}"
|
||||
have_sdbus="yes"
|
||||
], [
|
||||
AC_MSG_WARN([${ELOGIND_PKG_ERRORS}.])
|
||||
])
|
||||
])
|
||||
|
||||
dnl Check for basu
|
||||
AC_ARG_ENABLE([basu],
|
||||
AS_HELP_STRING([--disable-basu], [ignore basu as a sd-bus provider]), [], [enable_basu="yes"])
|
||||
|
||||
AS_IF([test "${have_sdbus}" != "yes" && test "${enable_basu}" != "no"], [
|
||||
PKG_CHECK_MODULES([BASU], [basu], [
|
||||
have_basu="yes"
|
||||
SDBUS_CFLAGS="${BASU_CFLAGS} -DSDBUS_HEADER='<basu/sd-bus.h>'"
|
||||
SDBUS_LIBS="${BASU_LIBS}"
|
||||
have_sdbus="yes"
|
||||
], [
|
||||
AC_MSG_WARN([${BASU_PKG_ERRORS}.])
|
||||
])
|
||||
])
|
||||
|
||||
AS_IF([test "$have_sdbus" = "yes" ], [
|
||||
AC_SUBST([SDBUS_CFLAGS])
|
||||
AC_SUBST([SDBUS_LIBS])
|
||||
], [
|
||||
AC_MSG_WARN([no sd-bus provider found.])
|
||||
])
|
||||
|
||||
AM_CONDITIONAL([HAVE_SDBUS], [test "$have_sdbus" = "yes"])
|
||||
|
||||
EXTEND_HELP_STRING([Optimization options:])
|
||||
dnl
|
||||
|
@ -4148,7 +4195,6 @@ dnl mDNS using libmicrodns
|
|||
dnl
|
||||
PKG_ENABLE_MODULES_VLC([MICRODNS], [], [microdns >= 0.1.2], [mDNS services discovery], [auto])
|
||||
|
||||
|
||||
EXTEND_HELP_STRING([Misc options:])
|
||||
|
||||
dnl
|
||||
|
|
|
@ -89,3 +89,10 @@ libbonjour_plugin_la_LDFLAGS = $(AM_LDFLAGS) -rpath '$(sddir)' -Wl,-framework,Fo
|
|||
if HAVE_DARWIN
|
||||
sd_LTLIBRARIES += libbonjour_plugin.la
|
||||
endif
|
||||
|
||||
libudisks_plugin_la_SOURCES = services_discovery/udisks.c
|
||||
libudisks_plugin_la_CFLAGS = $(AM_CFLAGS) $(SDBUS_CFLAGS)
|
||||
libudisks_plugin_la_LIBADD = $(SDBUS_LIBS)
|
||||
if HAVE_SDBUS
|
||||
sd_LTLIBRARIES += libudisks_plugin.la
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,550 @@
|
|||
/*****************************************************************************
|
||||
* udisks.c: file system services discovery module
|
||||
*****************************************************************************
|
||||
* Copyright © 2022 VLC authors, VideoLAN and VideoLabs
|
||||
*
|
||||
* Authors: Juliane de Sartiges <jill@videolabs.io>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation; either version 2.1 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this program; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif
|
||||
|
||||
#include <vlc_common.h>
|
||||
#include <vlc_plugin.h>
|
||||
#include <vlc_modules.h>
|
||||
#include <vlc_configuration.h>
|
||||
#include <vlc_services_discovery.h>
|
||||
#include <vlc_url.h>
|
||||
|
||||
#include <poll.h>
|
||||
|
||||
#include SDBUS_HEADER
|
||||
|
||||
#define DBUS_INTERFACE_UDISKS2 "org.freedesktop.UDisks2"
|
||||
#define DBUS_INTERFACE_UDISKS2_BLOCKS DBUS_INTERFACE_UDISKS2".Block"
|
||||
#define DBUS_INTERFACE_UDISKS2_DRIVE DBUS_INTERFACE_UDISKS2".Drive"
|
||||
#define DBUS_INTERFACE_UDISKS2_FILESYSTEM DBUS_INTERFACE_UDISKS2".Filesystem"
|
||||
#define DBUS_INTERFACE_UDISKS2_MANAGER DBUS_INTERFACE_UDISKS2".Manager"
|
||||
#define DBUS_INTERFACE_UDISKS2_PARTITION DBUS_INTERFACE_UDISKS2".Partition"
|
||||
#define DBUS_INTERFACE_UDISKS2_LOOP DBUS_INTERFACE_UDISKS2".Loop"
|
||||
|
||||
#define DBUS_PATH_UDISKS2 "/org/freedesktop/UDisks2"
|
||||
#define DBUS_PATH_UDISKS2_DRIVES DBUS_PATH_UDISKS2"/drives"
|
||||
#define DBUS_PATH_UDISKS2_BLOCK_DEV DBUS_PATH_UDISKS2"/block_devices"
|
||||
#define DBUS_PATH_UDISKS2_MANAGER DBUS_PATH_UDISKS2"/Manager"
|
||||
|
||||
struct fs_properties_changed_param
|
||||
{
|
||||
services_discovery_t *sd;
|
||||
char *object_path;
|
||||
};
|
||||
|
||||
struct device_info
|
||||
{
|
||||
sd_bus_slot *slot;
|
||||
input_item_t *item;
|
||||
char *label;
|
||||
uint64_t size;
|
||||
bool removable;
|
||||
struct fs_properties_changed_param *param;
|
||||
};
|
||||
|
||||
struct discovery_sys
|
||||
{
|
||||
sd_bus *bus;
|
||||
sd_bus_slot *interface_added_slot;
|
||||
sd_bus_slot *interface_removed_slot;
|
||||
vlc_thread_t thread;
|
||||
vlc_dictionary_t entries;
|
||||
};
|
||||
|
||||
static const char * const binary_prefixes[] = { N_("B"), N_("KiB"), N_("MiB"), N_("GiB"), N_("TiB") };
|
||||
|
||||
static void release_device_info(services_discovery_t *sd, struct device_info* info)
|
||||
{
|
||||
if(info->param)
|
||||
{
|
||||
free(info->param->object_path);
|
||||
free(info->param);
|
||||
}
|
||||
if(info->slot)
|
||||
sd_bus_slot_unref(info->slot);
|
||||
free(info->label);
|
||||
if(info->item)
|
||||
{
|
||||
services_discovery_RemoveItem(sd, info->item);
|
||||
input_item_Release(info->item);
|
||||
}
|
||||
free(info);
|
||||
}
|
||||
|
||||
static int human(uint64_t *i)
|
||||
{
|
||||
if (i == 0)
|
||||
return 0;
|
||||
unsigned exp = (63 - clz(*i)) / 10;
|
||||
exp = (exp < ARRAY_SIZE(binary_prefixes)) ? exp : ARRAY_SIZE(binary_prefixes);
|
||||
*i >>= (10 * exp);
|
||||
return exp;
|
||||
}
|
||||
|
||||
static const char *print_label(const char *drive_label, bool removable)
|
||||
{
|
||||
if(drive_label != NULL && drive_label[0] != '\0')
|
||||
return drive_label;
|
||||
if(removable)
|
||||
return _("Removable Drive");
|
||||
return _("Internal Drive");
|
||||
}
|
||||
|
||||
static input_item_t *input_item_NewDrive(const char *drive_label, const char *path, uint64_t size, bool removable)
|
||||
{
|
||||
int r = 0;
|
||||
input_item_t *ret = NULL;
|
||||
char *uri = NULL;
|
||||
char *label = NULL;
|
||||
|
||||
uri = vlc_path2uri(path, "file");
|
||||
if(!uri)
|
||||
return NULL;
|
||||
|
||||
int prefix = human(&size);
|
||||
r = asprintf(&label, "%s (%ld %s)", print_label(drive_label, removable), size, vlc_gettext(binary_prefixes[prefix]));
|
||||
if(r == -1)
|
||||
{
|
||||
free(uri);
|
||||
return NULL;
|
||||
}
|
||||
ret = input_item_NewDirectory(uri, label, ITEM_LOCAL);
|
||||
free(uri);
|
||||
free(label);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int fs_properties_changed(sd_bus_message *m, void *userdata, sd_bus_error *err)
|
||||
{
|
||||
VLC_UNUSED(err);
|
||||
int r;
|
||||
struct fs_properties_changed_param *param = userdata;
|
||||
services_discovery_t *sd = param->sd;
|
||||
struct discovery_sys *p_sys = sd->p_sys;
|
||||
|
||||
const char *interface_name;
|
||||
r = sd_bus_message_read(m, "s", &interface_name);
|
||||
if(r < 0)
|
||||
return r;
|
||||
if(strcmp(interface_name, DBUS_INTERFACE_UDISKS2_FILESYSTEM) != 0)
|
||||
return 0;
|
||||
|
||||
size_t mount_path_len;
|
||||
const char *mount_path = NULL;
|
||||
|
||||
char *property_name = NULL;
|
||||
|
||||
r = sd_bus_message_enter_container(m, 'a', "{sv}");
|
||||
if(r < 0)
|
||||
return r;
|
||||
for(;;)
|
||||
{
|
||||
r = sd_bus_message_enter_container(m, 'e', "sv");
|
||||
if (r < 0)
|
||||
return r;
|
||||
r = sd_bus_message_read(m, "s", &property_name);
|
||||
if(r < 0)
|
||||
return r;
|
||||
if (r == 0)
|
||||
return 0;
|
||||
if(strcmp(property_name, "MountPoints") == 0)
|
||||
break;
|
||||
}
|
||||
r = sd_bus_message_enter_container(m, 'v', "aay");
|
||||
if(r < 0)
|
||||
return r;
|
||||
r = sd_bus_message_enter_container(m, 'a', "ay");
|
||||
if(r < 0)
|
||||
return r;
|
||||
const void *path;
|
||||
r = sd_bus_message_read_array(m, 'y', &path, &mount_path_len);
|
||||
mount_path = path;
|
||||
if(r < 0)
|
||||
return r;
|
||||
struct device_info *info = vlc_dictionary_value_for_key(&p_sys->entries, param->object_path);
|
||||
if(!info)
|
||||
return -1;
|
||||
if(mount_path_len)
|
||||
{
|
||||
info->item = input_item_NewDrive(info->label, mount_path, info->size, info->removable);
|
||||
services_discovery_AddItem(sd, info->item);
|
||||
}
|
||||
else
|
||||
services_discovery_RemoveItem(sd, info->item);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int get_info_from_block_device(services_discovery_t *sd, const char *block_path, struct device_info **info_ret)
|
||||
{
|
||||
struct discovery_sys *p_sys = sd->p_sys;
|
||||
sd_bus *bus = p_sys->bus;
|
||||
sd_bus_error err = SD_BUS_ERROR_NULL;
|
||||
int r = 0;
|
||||
|
||||
struct device_info *info = NULL;
|
||||
size_t mount_path_len;
|
||||
const char *drive_path = NULL;
|
||||
const char *mount_path = NULL;
|
||||
|
||||
sd_bus_message *drive_reply = NULL;
|
||||
sd_bus_message *mounts_reply = NULL;
|
||||
|
||||
int autoclear;
|
||||
r = sd_bus_get_property_trivial(bus, DBUS_INTERFACE_UDISKS2,
|
||||
block_path, DBUS_INTERFACE_UDISKS2_LOOP,
|
||||
"Autoclear", &err, 'b', &autoclear);
|
||||
if(r == 0)
|
||||
{
|
||||
msg_Dbg(sd, "Ignoring loop device: %s\n", block_path);
|
||||
goto error;
|
||||
}
|
||||
if(r < 0 && r != -EINVAL)
|
||||
{
|
||||
msg_Err(sd, "%s: %s\n", err.name, err.message);
|
||||
goto error;
|
||||
}
|
||||
sd_bus_error_free( &err );
|
||||
err = SD_BUS_ERROR_NULL;
|
||||
|
||||
r = sd_bus_get_property(bus, DBUS_INTERFACE_UDISKS2,
|
||||
block_path, DBUS_INTERFACE_UDISKS2_FILESYSTEM,
|
||||
"MountPoints", &err, &mounts_reply, "aay");
|
||||
if(r == -EINVAL)
|
||||
{
|
||||
r = 0;
|
||||
msg_Dbg(sd, "%s block device does not contain any file system", block_path);
|
||||
goto error;
|
||||
}
|
||||
if(r < 0)
|
||||
{
|
||||
msg_Err(sd, "%s: %s\n", err.name, err.message);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = sd_bus_message_enter_container(mounts_reply, 'a', "ay");
|
||||
if(r < 0)
|
||||
goto error;
|
||||
|
||||
const void *path;
|
||||
r = sd_bus_message_read_array(mounts_reply, 'y', &path, &mount_path_len);
|
||||
mount_path = path;
|
||||
if(r < 0)
|
||||
goto error;
|
||||
|
||||
info = calloc(1, sizeof(struct device_info));
|
||||
if(!info)
|
||||
goto generic_error;
|
||||
|
||||
info->param = malloc(sizeof(struct fs_properties_changed_param));
|
||||
if(!info->param)
|
||||
goto generic_error;
|
||||
|
||||
info->param->sd = sd;
|
||||
info->param->object_path = strdup(block_path);
|
||||
|
||||
if(!info->param->object_path)
|
||||
goto generic_error;
|
||||
|
||||
r = sd_bus_match_signal(bus, &info->slot,
|
||||
NULL, block_path,
|
||||
"org.freedesktop.DBus.Properties", "PropertiesChanged",
|
||||
fs_properties_changed, info->param);
|
||||
if(r < 0)
|
||||
goto error;
|
||||
|
||||
r = sd_bus_get_property_trivial(bus, DBUS_INTERFACE_UDISKS2,
|
||||
block_path,
|
||||
DBUS_INTERFACE_UDISKS2_BLOCKS, "Size",
|
||||
&err, 't', &info->size);
|
||||
if(r < 0)
|
||||
{
|
||||
msg_Err(sd, "%s: %s\n", err.name, err.message);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = sd_bus_get_property(bus, DBUS_INTERFACE_UDISKS2,
|
||||
block_path, DBUS_INTERFACE_UDISKS2_BLOCKS,
|
||||
"Drive", &err, &drive_reply, "o");
|
||||
if(r < 0)
|
||||
{
|
||||
msg_Err(sd, "%s: %s\n", err.name, err.message);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = sd_bus_message_read(drive_reply, "o", &drive_path);
|
||||
if(r < 0)
|
||||
goto error;
|
||||
|
||||
if(strcmp(drive_path, "/") != 0)
|
||||
{
|
||||
r = sd_bus_get_property_trivial(bus, DBUS_INTERFACE_UDISKS2,
|
||||
drive_path,
|
||||
DBUS_INTERFACE_UDISKS2_DRIVE, "Removable",
|
||||
&err, 'b', &info->removable);
|
||||
if(r < 0)
|
||||
{
|
||||
msg_Err(sd, "%s: %s\n", err.name, err.message);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
r = sd_bus_get_property_string(bus, DBUS_INTERFACE_UDISKS2,
|
||||
block_path,
|
||||
DBUS_INTERFACE_UDISKS2_BLOCKS, "IdLabel",
|
||||
&err, &info->label);
|
||||
if(r < 0)
|
||||
{
|
||||
msg_Err(sd, "%s: %s\n", err.name, err.message);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if(mount_path)
|
||||
{
|
||||
info->item = input_item_NewDrive(info->label, mount_path, info->size, info->removable);
|
||||
if(!info->item)
|
||||
goto generic_error;
|
||||
}
|
||||
sd_bus_message_unref(drive_reply);
|
||||
sd_bus_error_free(&err);
|
||||
*info_ret = info;
|
||||
return 1;
|
||||
generic_error:
|
||||
r = -1;
|
||||
error:
|
||||
sd_bus_error_free(&err);
|
||||
if(drive_reply)
|
||||
sd_bus_message_unref(drive_reply);
|
||||
if(mounts_reply)
|
||||
sd_bus_message_unref(mounts_reply);
|
||||
if(info)
|
||||
release_device_info(sd, info);
|
||||
return r;
|
||||
}
|
||||
|
||||
static void FreeEntries(void *p_value, void *p_obj)
|
||||
{
|
||||
services_discovery_t *sd = p_obj;
|
||||
struct device_info *info = p_value;
|
||||
if(info)
|
||||
release_device_info(sd, info);
|
||||
}
|
||||
|
||||
static int interfaces_added_cb(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
|
||||
{
|
||||
VLC_UNUSED(ret_error);
|
||||
int r;
|
||||
services_discovery_t *sd = userdata;
|
||||
struct discovery_sys *p_sys = sd->p_sys;
|
||||
struct device_info *info = NULL;
|
||||
const char *path = NULL;
|
||||
r = sd_bus_message_read(m, "o", &path);
|
||||
if(r < 0)
|
||||
return r;
|
||||
if(strncmp(path, DBUS_PATH_UDISKS2_BLOCK_DEV, strlen(DBUS_PATH_UDISKS2_BLOCK_DEV)) != 0)
|
||||
return 0;
|
||||
r = get_info_from_block_device(sd, path, &info);
|
||||
if(r < 0)
|
||||
{
|
||||
if(info)
|
||||
release_device_info(sd, info);
|
||||
return r;
|
||||
}
|
||||
if(!info)
|
||||
return 0;
|
||||
vlc_dictionary_insert(&p_sys->entries, path, info);
|
||||
if(info->item)
|
||||
services_discovery_AddItem(sd, info->item);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int interfaces_removed_cb(sd_bus_message *m, void *userdata, sd_bus_error *ret_error)
|
||||
{
|
||||
VLC_UNUSED(ret_error);
|
||||
int r;
|
||||
services_discovery_t *sd = userdata;
|
||||
struct discovery_sys *p_sys = sd->p_sys;
|
||||
const char *path;
|
||||
r = sd_bus_message_read(m, "o", &path);
|
||||
if(r < 0)
|
||||
return r;
|
||||
if(strncmp(path, DBUS_PATH_UDISKS2_BLOCK_DEV, strlen(DBUS_PATH_UDISKS2_BLOCK_DEV)) != 0)
|
||||
return 0;
|
||||
struct device_info *info = vlc_dictionary_value_for_key(&p_sys->entries, path);
|
||||
if(!info)
|
||||
return 0;
|
||||
vlc_dictionary_remove_value_for_key(&p_sys->entries, path, FreeEntries, sd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void *Run(void *p_obj)
|
||||
{
|
||||
int r;
|
||||
int canc = vlc_savecancel();
|
||||
services_discovery_t *sd = p_obj;
|
||||
struct discovery_sys *p_sys = sd->p_sys;
|
||||
sd_bus *bus = p_sys->bus;
|
||||
|
||||
r = sd_bus_match_signal(bus, &p_sys->interface_added_slot,
|
||||
DBUS_INTERFACE_UDISKS2, DBUS_PATH_UDISKS2,
|
||||
"org.freedesktop.DBus.ObjectManager", "InterfacesAdded",
|
||||
interfaces_added_cb, sd);
|
||||
if(r < 0)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
r = sd_bus_match_signal(bus, &p_sys->interface_removed_slot,
|
||||
DBUS_INTERFACE_UDISKS2, DBUS_PATH_UDISKS2,
|
||||
"org.freedesktop.DBus.ObjectManager", "InterfacesRemoved",
|
||||
interfaces_removed_cb, sd);
|
||||
if(r < 0)
|
||||
{
|
||||
sd_bus_slot_unref(p_sys->interface_added_slot);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct pollfd ufd[1];
|
||||
ufd[0].fd = sd_bus_get_fd(bus);
|
||||
ufd[0].events = sd_bus_get_events(bus);
|
||||
|
||||
for(;;)
|
||||
{
|
||||
vlc_restorecancel(canc);
|
||||
|
||||
while(poll(ufd, 1, -1) < 0);
|
||||
|
||||
canc = vlc_savecancel();
|
||||
|
||||
sd_bus_message *msg = NULL;
|
||||
r = sd_bus_process(bus, &msg);
|
||||
if(r < 0)
|
||||
{
|
||||
msg_Err(sd, "Couldn't process new d-bus event : %d", -r);
|
||||
break;
|
||||
}
|
||||
sd_bus_message_unref(msg);
|
||||
}
|
||||
sd_bus_slot_unref(p_sys->interface_added_slot);
|
||||
sd_bus_slot_unref(p_sys->interface_removed_slot);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int Open(vlc_object_t *p_obj)
|
||||
{
|
||||
services_discovery_t *sd = (services_discovery_t *)p_obj;
|
||||
struct discovery_sys *p_sys = vlc_alloc(1, sizeof(struct discovery_sys));
|
||||
struct device_info *info = NULL;
|
||||
if (!p_sys)
|
||||
return VLC_ENOMEM;
|
||||
sd->p_sys = p_sys;
|
||||
|
||||
sd->description = _("Local drives discovery");
|
||||
vlc_dictionary_init(&p_sys->entries, 0);
|
||||
|
||||
int r;
|
||||
|
||||
/* connect to the session bus */
|
||||
r = sd_bus_open_system(&p_sys->bus);
|
||||
if(r < 0)
|
||||
goto error;
|
||||
sd_bus *bus = p_sys->bus;
|
||||
sd_bus_message *reply = NULL;
|
||||
sd_bus_error err = SD_BUS_ERROR_NULL;
|
||||
r = sd_bus_call_method(bus, DBUS_INTERFACE_UDISKS2, DBUS_PATH_UDISKS2_MANAGER,
|
||||
DBUS_INTERFACE_UDISKS2_MANAGER, "GetBlockDevices",
|
||||
&err, &reply, "a{sv}", NULL);
|
||||
if (r < 0)
|
||||
{
|
||||
msg_Err(sd, "%s: %s\n", err.name, err.message);
|
||||
goto error;
|
||||
}
|
||||
|
||||
r = sd_bus_message_enter_container(reply, 'a', "o");
|
||||
if (r < 0)
|
||||
goto error;
|
||||
|
||||
char *block_path = NULL;
|
||||
while ((r = sd_bus_message_read(reply, "o", &block_path)) != 0)
|
||||
{
|
||||
info = NULL;
|
||||
if(r < 0)
|
||||
goto error;
|
||||
r = get_info_from_block_device(sd, block_path, &info);
|
||||
if(r < 0)
|
||||
goto error;
|
||||
if(!info)
|
||||
continue;
|
||||
vlc_dictionary_insert(&p_sys->entries, block_path, info);
|
||||
if(info->item)
|
||||
services_discovery_AddItem(sd, info->item);
|
||||
}
|
||||
sd_bus_message_unref(reply);
|
||||
|
||||
if (vlc_clone(&p_sys->thread, Run, sd))
|
||||
goto error;
|
||||
sd_bus_error_free(&err);
|
||||
return VLC_SUCCESS;
|
||||
error:
|
||||
if(info)
|
||||
release_device_info(sd, info);
|
||||
vlc_dictionary_clear(&p_sys->entries, FreeEntries, sd);
|
||||
if(p_sys->bus)
|
||||
{
|
||||
sd_bus_flush(p_sys->bus);
|
||||
sd_bus_close(p_sys->bus);
|
||||
}
|
||||
sd_bus_error_free(&err);
|
||||
free(p_sys);
|
||||
return VLC_EGENERIC;
|
||||
}
|
||||
|
||||
static void Close(vlc_object_t *p_obj)
|
||||
{
|
||||
services_discovery_t *sd = (services_discovery_t *)p_obj;
|
||||
struct discovery_sys *p_sys = sd->p_sys;
|
||||
if(p_sys->interface_added_slot)
|
||||
sd_bus_slot_unref(p_sys->interface_added_slot);
|
||||
sd_bus_flush(p_sys->bus);
|
||||
sd_bus_close(p_sys->bus);
|
||||
vlc_cancel(p_sys->thread);
|
||||
vlc_join(p_sys->thread, NULL);
|
||||
vlc_dictionary_clear(&p_sys->entries, FreeEntries, sd);
|
||||
free(p_sys);
|
||||
}
|
||||
|
||||
VLC_SD_PROBE_HELPER("udisks", N_("UDisks2"), SD_CAT_DEVICES)
|
||||
|
||||
/*
|
||||
* Module descriptor
|
||||
*/
|
||||
vlc_module_begin()
|
||||
set_shortname( "UDisks" )
|
||||
set_description( N_( "Local Drives (UDisks)" ) )
|
||||
set_subcategory( SUBCAT_PLAYLIST_SD )
|
||||
set_capability( "services_discovery", 0 )
|
||||
set_callbacks( Open, Close )
|
||||
add_shortcut( "udisks" )
|
||||
VLC_SD_PROBE_SUBMODULE
|
||||
vlc_module_end ()
|
|
@ -1227,6 +1227,7 @@ modules/services_discovery/podcast.c
|
|||
modules/services_discovery/pulse.c
|
||||
modules/services_discovery/sap.c
|
||||
modules/services_discovery/udev.c
|
||||
modules/services_discovery/udisks.c
|
||||
modules/services_discovery/upnp.cpp
|
||||
modules/services_discovery/windrive.c
|
||||
modules/services_discovery/xcb_apps.c
|
||||
|
|
Loading…
Reference in New Issue