2 * Copyright (C) 2005-2013 Team XBMC
5 * This Program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2, or (at your option)
10 * This Program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with XBMC; see the file COPYING. If not, see
17 * <http://www.gnu.org/licenses/>.
23 #include "HALManager.h"
24 #include "interfaces/Builtins.h"
25 #include <libhal-storage.h>
26 #include "threads/SingleLock.h"
27 #include "utils/URIUtils.h"
28 #include "guilib/LocalizeStrings.h"
29 #include "powermanagement/PowerManager.h"
30 #include "settings/AdvancedSettings.h"
31 #include "dialogs/GUIDialogKaiToast.h"
33 #ifdef HAS_SDL_JOYSTICK
35 #include <SDL/SDL_version.h>
36 #include "input/SDLJoystick.h"
39 bool CHALManager::NewMessage;
40 DBusError CHALManager::m_Error;
41 CCriticalSection CHALManager::m_lock;
43 /* A Removed device, It isn't possible to make a LibHalVolume from a removed device therefor
44 we catch the UUID from the udi on the removal */
45 void CHALManager::DeviceRemoved(LibHalContext *ctx, const char *udi)
48 CLog::Log(LOGDEBUG, "HAL: Device (%s) Removed", udi);
49 g_HalManager.RemoveDevice(udi);
52 void CHALManager::DeviceNewCapability(LibHalContext *ctx, const char *udi, const char *capability)
55 CLog::Log(LOGDEBUG, "HAL: Device (%s) gained capability %s", udi, capability);
56 g_HalManager.UpdateDevice(udi);
59 void CHALManager::DeviceLostCapability(LibHalContext *ctx, const char *udi, const char *capability)
62 CLog::Log(LOGDEBUG, "HAL: Device (%s) lost capability %s", udi, capability);
63 g_HalManager.UpdateDevice(udi);
66 /* HAL Property modified callback. If a device is mounted. This is called. */
67 void CHALManager::DevicePropertyModified(LibHalContext *ctx, const char *udi, const char *key, dbus_bool_t is_removed, dbus_bool_t is_added)
70 CLog::Log(LOGDEBUG, "HAL: Device (%s) Property %s modified", udi, key);
71 g_HalManager.UpdateDevice(udi);
74 void CHALManager::DeviceCondition(LibHalContext *ctx, const char *udi, const char *condition_name, const char *condition_details)
77 CLog::Log(LOGDEBUG, "HAL: Device (%s) Condition %s | %s", udi, condition_name, condition_details);
78 if (!strcmp(condition_name, "ButtonPressed") && !strcmp(condition_details, "power"))
79 CBuiltins::Execute("XBMC.ShutDown()");
81 g_HalManager.UpdateDevice(udi);
84 /* HAL Device added. This is before mount. And here is the place to mount the volume in the future */
85 void CHALManager::DeviceAdded(LibHalContext *ctx, const char *udi)
88 CLog::Log(LOGDEBUG, "HAL: Device (%s) Added", udi);
89 g_HalManager.AddDevice(udi);
92 CHALManager g_HalManager;
94 /* Iterate through all devices currently on the computer. Needed mostly at startup */
95 void CHALManager::GenerateGDL()
97 if (m_Context == NULL)
102 CLog::Log(LOGDEBUG, "HAL: Clearing old global device list, if any");
105 CLog::Log(LOGNOTICE, "HAL: Generating global device list");
106 GDL = libhal_get_all_devices(g_HalManager.m_Context, &i, &m_Error);
108 for (i = 0; GDL[i]; i++)
112 CLog::Log(LOGINFO, "HAL: Generated global device list, found %i", i);
114 libhal_free_string_array(GDL);
117 // Return all volumes that currently are available (Mostly needed at startup, the rest of the volumes comes as events.)
118 std::vector<CStorageDevice> CHALManager::GetVolumeDevices()
120 CSingleLock lock(m_lock);
124 CHALManager::CHALManager()
126 m_Notifications = false;
128 m_DBusSystemConnection = NULL;
129 #if defined(HAS_SDL_JOYSTICK)
130 const SDL_version *sdl_version = SDL_Linked_Version();
131 m_bMultipleJoysticksSupport = (sdl_version->major >= 1 && sdl_version->minor >= 3)?true:false;
135 void CHALManager::Stop()
137 if (g_advancedSettings.m_handleMounting)
138 { // Unmount all media XBMC have mounted
139 for (unsigned int i = 0; i < m_Volumes.size(); i++)
141 if (m_Volumes[i].MountedByXBMC && m_Volumes[i].Mounted)
143 CLog::Log(LOGNOTICE, "HAL: Unmounts %s", m_Volumes[i].FriendlyName.c_str());
144 UnMount(m_Volumes[i]);
151 if (m_Context != NULL)
152 libhal_ctx_shutdown(m_Context, NULL);
153 if (m_Context != NULL)
154 libhal_ctx_free(m_Context);
156 if (m_DBusSystemConnection != NULL)
158 dbus_connection_unref(m_DBusSystemConnection);
159 m_DBusSystemConnection = NULL;
161 dbus_error_free(&m_Error); // Needed?
165 void CHALManager::Initialize()
167 m_Notifications = false;
168 CLog::Log(LOGINFO, "HAL: Starting initializing");
169 g_HalManager.m_Context = g_HalManager.InitializeHal();
170 if (g_HalManager.m_Context == NULL)
172 CLog::Log(LOGERROR, "HAL: no Hal context");
178 CLog::Log(LOGINFO, "HAL: Successfully initialized");
179 m_Notifications = true;
182 // Initialize basic DBus connection
183 bool CHALManager::InitializeDBus()
185 if (m_DBusSystemConnection != NULL)
188 dbus_error_init (&m_Error);
189 if (m_DBusSystemConnection == NULL && !(m_DBusSystemConnection = dbus_bus_get (DBUS_BUS_SYSTEM, &m_Error)))
191 CLog::Log(LOGERROR, "DBus: Could not get system bus: %s", m_Error.message);
192 dbus_error_free (&m_Error);
195 if (m_DBusSystemConnection != NULL)
201 // Initialize basic HAL connection
202 LibHalContext *CHALManager::InitializeHal()
208 if (!InitializeDBus())
211 if (!(ctx = libhal_ctx_new()))
213 CLog::Log(LOGERROR, "HAL: failed to create a HAL context!");
217 if (!libhal_ctx_set_dbus_connection(ctx, m_DBusSystemConnection))
218 CLog::Log(LOGERROR, "HAL: Failed to connect with dbus");
220 libhal_ctx_set_device_added(ctx, DeviceAdded);
221 libhal_ctx_set_device_removed(ctx, DeviceRemoved);
222 libhal_ctx_set_device_new_capability(ctx, DeviceNewCapability);
223 libhal_ctx_set_device_lost_capability(ctx, DeviceLostCapability);
224 libhal_ctx_set_device_property_modified(ctx, DevicePropertyModified);
225 libhal_ctx_set_device_condition(ctx, DeviceCondition);
227 if (!libhal_device_property_watch_all(ctx, &m_Error))
229 CLog::Log(LOGERROR, "HAL: Failed to set property watch %s", m_Error.message);
230 dbus_error_free(&m_Error);
231 libhal_ctx_free(ctx);
235 if (!libhal_ctx_init(ctx, &m_Error))
237 CLog::Log(LOGERROR, "HAL: Failed to initialize hal context: %s", m_Error.message);
238 dbus_error_free(&m_Error);
239 libhal_ctx_free(ctx);
244 * Do something to ping the HAL daemon - the above functions will
245 * succeed even if hald is not running, so long as DBUS is. But we
246 * want to exit silently if hald is not running, to behave on
249 if (!(devices = libhal_get_all_devices(ctx, &nr, &m_Error)))
251 CLog::Log(LOGERROR, "HAL: seems that Hal daemon is not running: %s", m_Error.message);
252 dbus_error_free(&m_Error);
254 libhal_ctx_shutdown(ctx, NULL);
255 libhal_ctx_free(ctx);
259 libhal_free_string_array(devices);
264 // Helper function. creates a CStorageDevice from a HAL udi
265 bool CHALManager::DeviceFromVolumeUdi(const char *udi, CStorageDevice *device)
267 if (g_HalManager.m_Context == NULL)
270 LibHalVolume *tempVolume;
271 LibHalDrive *tempDrive;
272 bool Created = false;
274 tempVolume = libhal_volume_from_udi(g_HalManager.m_Context, udi);
277 const char *DriveUdi = libhal_volume_get_storage_device_udi(tempVolume);
278 tempDrive = libhal_drive_from_udi(g_HalManager.m_Context, DriveUdi);
282 char * FriendlyName = libhal_device_get_property_string(g_HalManager.m_Context, udi, "info.product", NULL);
283 device->FriendlyName = FriendlyName;
284 libhal_free_string(FriendlyName);
285 char *block = libhal_device_get_property_string(g_HalManager.m_Context, udi, "block.device", NULL);
286 device->DevID = block;
287 libhal_free_string(block);
289 device->HotPlugged = (bool)libhal_drive_is_hotpluggable(tempDrive);
290 device->Type = libhal_drive_get_type(tempDrive);
291 device->Mounted = (bool)libhal_volume_is_mounted(tempVolume);
292 device->MountPoint = libhal_volume_get_mount_point(tempVolume);
294 URIUtils::AddSlashAtEnd(device->MountPoint);
295 device->Label = libhal_volume_get_label(tempVolume);
296 device->UUID = libhal_volume_get_uuid(tempVolume);
297 device->FileSystem = libhal_volume_get_fstype(tempVolume);
298 device->HalIgnore = libhal_device_get_property_bool(g_HalManager.m_Context, udi, "volume.ignore", NULL);
299 ApproveDevice(device);
301 libhal_drive_free(tempDrive);
305 CLog::Log(LOGERROR, "HAL: Couldn't create a Drive even if we had a volume - %s", udi);
307 libhal_volume_free(tempVolume);
313 // Called from ProcessSlow to trigger the callbacks from DBus
314 bool CHALManager::Update()
316 CSingleLock lock(m_lock);
317 if (m_Context == NULL)
320 if (!dbus_connection_read_write_dispatch(m_DBusSystemConnection, 0)) // We choose 0 that means we won't wait for a message
322 CLog::Log(LOGERROR, "DBus: System - read/write dispatch");
334 /* libhal-storage type to readable form */
335 const char *CHALManager::StorageTypeToString(int DeviceType)
339 case 0: return "removable disk";
340 case 1: return "disk";
341 case 2: return "cdrom";
342 case 3: return "floppy";
343 case 4: return "tape";
344 case 5: return "compact flash";
345 case 6: return "memory stick";
346 case 7: return "smart media";
347 case 8: return "sd mmc";
348 case 9: return "camera";
349 case 10: return "audio player";
350 case 11: return "zip";
351 case 12: return "jaz";
352 case 13: return "flashkey";
353 case 14: return "magneto-optical";
354 default: return NULL;
358 /* Readable libhal-storage type to int type */
359 int CHALManager::StorageTypeFromString(const char *DeviceString)
361 if (strcmp(DeviceString, "removable disk") == 0) return 0;
362 else if (strcmp(DeviceString, "disk") == 0) return 1;
363 else if (strcmp(DeviceString, "cdrom") == 0) return 2;
364 else if (strcmp(DeviceString, "floppy") == 0) return 3;
365 else if (strcmp(DeviceString, "tape") == 0) return 4;
366 else if (strcmp(DeviceString, "compact flash") == 0) return 5;
367 else if (strcmp(DeviceString, "memory stick") == 0) return 6;
368 else if (strcmp(DeviceString, "smart media") == 0) return 7;
369 else if (strcmp(DeviceString, "sd mmc") == 0) return 8;
370 else if (strcmp(DeviceString, "camera") == 0) return 9;
371 else if (strcmp(DeviceString, "audio player") == 0) return 10;
372 else if (strcmp(DeviceString, "zip") == 0) return 11;
373 else if (strcmp(DeviceString, "jaz") == 0) return 12;
374 else if (strcmp(DeviceString, "flashkey") == 0) return 13;
375 else if (strcmp(DeviceString, "magneto-optical") == 0) return 14;
379 void CHALManager::UpdateDevice(const char *udi)
381 CSingleLock lock(m_lock);
383 category = libhal_device_get_property_string(m_Context, udi, "info.category", NULL);
384 if (category == NULL)
387 if (strcmp(category, "volume") == 0)
389 CStorageDevice dev(udi);
390 if (!DeviceFromVolumeUdi(udi, &dev))
392 for (unsigned int i = 0; i < m_Volumes.size(); i++)
394 if (strcmp(m_Volumes[i].UDI.c_str(), udi) == 0)
396 CLog::Log(LOGDEBUG, "HAL: Update - %s | %s", CHALManager::StorageTypeToString(dev.Type), dev.toString().c_str());
397 if (g_advancedSettings.m_handleMounting) // If the device was mounted by XBMC before it's still mounted by XBMC.
398 dev.MountedByXBMC = m_Volumes[i].MountedByXBMC;
399 if (!dev.Mounted && m_Volumes[i].Mounted)
400 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(13023), dev.FriendlyName.c_str(), TOAST_DISPLAY_TIME, false);
408 libhal_free_string(category);
410 void CHALManager::HandleNewVolume(CStorageDevice *dev)
412 if (g_advancedSettings.m_handleMounting)
414 /* Here it can be checked if the device isn't mounted and then mount */
415 //TODO Have mountpoints be other than in /media/*
416 if (!dev->Mounted && (dev->HotPlugged || dev->Type == 2) && dev->Approved)
419 capability =libhal_device_get_property_strlist (m_Context, dev->UDI.c_str(), "info.capabilities", NULL);
421 bool Mountable = false;
422 if (dev->Type == 2 && (strcmp(capability[0], "volume.disc") == 0 && strcmp(capability[1], "volume") == 0)) // CD/DVD
424 else if ((strcmp(capability[0], "volume") == 0 && strcmp(capability[1], "block") == 0)) // HDD
429 CLog::Log(LOGNOTICE, "HAL: Trying to mount %s", dev->FriendlyName.c_str());
430 CStdString MountPoint;
432 if (dev->Label.size() > 0)
434 MountPoint = dev->Label.c_str();
435 TestPath = StringUtils::Format("/media/%s", MountPoint.c_str());
437 if (stat("/media", &St) != 0)
438 return; //If /media doesn't exist something is wrong.
439 while(stat (TestPath.c_str(), &St) == 0 && S_ISDIR (St.st_mode))
441 CLog::Log(LOGDEBUG, "HAL: Proposed Mountpoint already existed");
442 MountPoint.append("_");
443 TestPath = StringUtils::Format("/media/%s", MountPoint.c_str());
448 MountPoint = StorageTypeToString(dev->Type);
449 TestPath = StringUtils::Format("/media/%s", MountPoint.c_str());
452 if (stat("/media", &St) != 0)
453 return; //If /media doesn't exist something is wrong.
454 while(stat (TestPath.c_str(), &St) == 0 && S_ISDIR (St.st_mode))
456 CLog::Log(LOGDEBUG, "HAL: Proposed Mountpoint already existed");
458 MountPoint = StringUtils::Format("%s%i", StorageTypeToString(dev->Type), Nbr);
459 TestPath = StringUtils::Format("/media/%s", MountPoint.c_str());
462 if (Mount(dev, MountPoint))
464 CLog::Log(LOGINFO, "HAL: mounted %s on %s", dev->FriendlyName.c_str(), dev->MountPoint.c_str());
466 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(13021), dev->FriendlyName.c_str(), TOAST_DISPLAY_TIME, false);
469 libhal_free_string_array(capability);
474 /* Parse newly found device and add it to our remembered devices */
475 void CHALManager::AddDevice(const char *udi)
477 CSingleLock lock(m_lock);
479 category = libhal_device_get_property_string(m_Context, udi, "info.category", NULL);
480 if (category == NULL)
483 if (strcmp(category, "volume") == 0)
485 CStorageDevice dev(udi);
486 if (DeviceFromVolumeUdi(udi, &dev))
488 CLog::Log(LOGDEBUG, "HAL: Added - %s | %s", CHALManager::StorageTypeToString(dev.Type), dev.toString().c_str());
489 HandleNewVolume(&dev);
490 m_Volumes.push_back(dev);
493 #if defined(HAS_SDL_JOYSTICK)
494 // Scan input devices
495 else if (strcmp(category, "input") == 0)
498 dbus_error_init(&dbusError);
501 capability =libhal_device_get_property_strlist (m_Context, udi, "info.capabilities", &dbusError);
502 for(char **ptr = capability; *ptr != NULL;ptr++)
505 if(strcmp(*ptr, "input.joystick") == 0)
507 CLog::Log(LOGINFO, "HAL: Joystick plugged in");
508 CHALDevice dev = CHALDevice(udi);
509 dev.FriendlyName = libhal_device_get_property_string(m_Context, udi, "info.product", &m_Error);
510 m_Joysticks.push_back(dev);
512 if(m_Joysticks.size() < 2 || m_bMultipleJoysticksSupport)
514 // Restart SDL joystick subsystem
515 if (!g_Joystick.Reinitialize())
519 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(13024), dev.FriendlyName.c_str(), TOAST_DISPLAY_TIME, false);
523 libhal_free_string_array(capability);
527 else if (strcmp(category, "camera") == 0)
529 else if (strcmp(category, "bluetooth_hci") == 0)
530 { // Bluetooth-Devices }
531 else if (strcmp(category, "portable audio player") == 0)
533 else if (strcmp(category, "alsa") == 0)
537 libhal_free_string(category);
540 /* Here we should iterate through our remembered devices if any of them are removed */
541 bool CHALManager::RemoveDevice(const char *udi)
543 CSingleLock lock(m_lock);
544 for (unsigned int i = 0; i < m_Volumes.size(); i++)
546 if (strcmp(m_Volumes[i].UDI.c_str(), udi) == 0)
548 CLog::Log(LOGNOTICE, "HAL: Removed - %s | %s", CHALManager::StorageTypeToString(m_Volumes[i].Type), m_Volumes[i].toString().c_str());
550 if (m_Volumes[i].Mounted)
552 if (g_advancedSettings.m_handleMounting)
553 UnMount(m_Volumes[i]);
555 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(13022), m_Volumes[i].FriendlyName.c_str());
556 CLog::Log(LOGNOTICE, "HAL: Unsafe drive removal");
558 m_Volumes.erase(m_Volumes.begin() + i);
562 #if defined(HAS_SDL_JOYSTICK)
563 for(uint i = 0; i < m_Joysticks.size(); i++)
565 if (strcmp(m_Joysticks[i].UDI.c_str(), udi) == 0)
567 if(m_Joysticks.size() < 3 || m_bMultipleJoysticksSupport)
569 // Restart SDL joystick subsystem
570 if (!g_Joystick.Reinitialize())
574 CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(13025), m_Joysticks[i].FriendlyName.c_str(), TOAST_DISPLAY_TIME, false);
576 m_Joysticks.erase(m_Joysticks.begin() + i);
584 bool CHALManager::ApproveDevice(CStorageDevice *device)
587 //This is only because it's easier to read...
588 const char *fs = device->FileSystem.c_str();
590 if ( strcmp(fs, "vfat") == 0 || strcmp(fs, "ext2") == 0
591 || strcmp(fs, "ext3") == 0 || strcmp(fs, "reiserfs") == 0
592 || strcmp(fs, "ntfs") == 0 || strcmp(fs, "ntfs-3g") == 0
593 || strcmp(fs, "udf") == 0 || strcmp(fs, "iso9660") == 0
594 || strcmp(fs, "xfs") == 0 || strcmp(fs, "hfsplus") == 0
595 || strcmp(fs, "ext4") == 0)
600 // Ignore some mountpoints, unless a weird setup these should never contain anything usefull for an enduser.
601 if (strcmp(device->MountPoint, "/") == 0 || strcmp(device->MountPoint, "/boot/") == 0 || strcmp(device->MountPoint, "/mnt/") == 0 || strcmp(device->MountPoint, "/home/") == 0)
604 if (device->HalIgnore)
607 device->Approved = approve;
611 bool CHALManager::Eject(CStdString path)
613 for (unsigned int i = 0; i < m_Volumes.size(); i++)
615 if (m_Volumes[i].MountPoint.Equals(path))
616 return m_Volumes[i].HotPlugged ? UnMount(m_Volumes[i]) : false;
622 bool CHALManager::UnMount(CStorageDevice volume)
624 CLog::Log(LOGNOTICE, "HAL: UnMounting %s (%s)", volume.UDI.c_str(), volume.toString().c_str());
626 DBusMessageIter args;
628 dbus_error_init (&error);
629 DBusConnection *connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
632 msg = dbus_message_new_method_call("org.freedesktop.Hal", volume.UDI.c_str(), "org.freedesktop.Hal.Device.Volume", "Unmount");
633 dbus_message_iter_init_append(msg, &args);
635 dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &sub);
636 const char *s = "lazy";
637 dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
638 dbus_message_iter_close_container(&args, &sub);
641 CLog::Log(LOGERROR, "DBus: Create UnMount Message failed");
645 reply = dbus_connection_send_with_reply_and_block(connection, msg, -1, &error); //The reply timout might be bad to have as -1
646 if (dbus_error_is_set(&error))
648 CLog::Log(LOGERROR, "DBus: %s - %s", error.name, error.message);
649 dbus_error_free(&error);
652 // Need to create a reader for the Message
653 dbus_message_unref (reply);
654 dbus_message_unref(msg);
658 volume.MountPoint = "";
659 volume.Mounted = false;
660 dbus_connection_unref(connection);
666 CLog::Log(LOGERROR, "DBus: Failed to connect to Systembus");
667 dbus_error_free(&error);
672 bool CHALManager::Mount(CStorageDevice *volume, CStdString mountpath)
674 CLog::Log(LOGNOTICE, "HAL: Mounting %s (%s) at %s with umask=%u", volume->UDI.c_str(), volume->toString().c_str(), mountpath.c_str(), umask (0));
676 DBusMessageIter args;
678 dbus_error_init (&error);
679 DBusConnection *connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
683 msg = dbus_message_new_method_call("org.freedesktop.Hal", volume->UDI.c_str(), "org.freedesktop.Hal.Device.Volume", "Mount");
684 dbus_message_iter_init_append(msg, &args);
685 s = mountpath.c_str();
686 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &s))
687 CLog::Log(LOGERROR, "DBus: Failed to append arguments");
689 if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &s))
690 CLog::Log(LOGERROR, "DBus: Failed to append arguments");
692 dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &sub);
694 CStdString temporaryString;
696 if (volume->FileSystem.Equals("vfat"))
698 int mask = umask (0);
699 temporaryString = StringUtils::Format("umask=%#o", mask);
700 s = temporaryString.c_str();
701 dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
702 temporaryString = StringUtils::Format("uid=%u", getuid());
703 s = temporaryString.c_str();
704 dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
705 s = "shortname=mixed";
706 dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
708 dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
709 // 'sync' option will slow down transfer speed significantly for FAT filesystems. We prefer 'flush' instead.
711 dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
716 dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
719 dbus_message_iter_close_container(&args, &sub);
722 CLog::Log(LOGERROR, "DBus: Create Mount Message failed");
726 reply = dbus_connection_send_with_reply_and_block(connection, msg, -1, &error); //The reply timout might be bad to have as -1
727 if (dbus_error_is_set(&error))
729 CLog::Log(LOGERROR, "DBus: %s - %s", error.name, error.message);
730 dbus_error_free(&error);
733 // Need to create a reader for the Message
734 dbus_message_unref (reply);
735 dbus_message_unref(msg);
739 volume->Mounted = true;
740 volume->MountedByXBMC = true;
741 volume->MountPoint = mountpath;
742 dbus_connection_unref(connection);
748 CLog::Log(LOGERROR, "DBus: Failed to connect to Systembus");
749 dbus_error_free(&error);