aboutsummaryrefslogtreecommitdiffstats
path: root/multimedia
diff options
context:
space:
mode:
authorcpm <cpm@FreeBSD.org>2017-04-04 06:40:47 +0800
committercpm <cpm@FreeBSD.org>2017-04-04 06:40:47 +0800
commit4c007dd29f0c2c809f033d31097a7d72cd331b56 (patch)
tree3f87965a2f7d8c69d4bc6149e40ca7b10769c9b9 /multimedia
parent90e830703b7f855ee6470a60d49284ba846949e5 (diff)
downloadfreebsd-ports-gnome-4c007dd29f0c2c809f033d31097a7d72cd331b56.tar.gz
freebsd-ports-gnome-4c007dd29f0c2c809f033d31097a7d72cd331b56.tar.zst
freebsd-ports-gnome-4c007dd29f0c2c809f033d31097a7d72cd331b56.zip
- Add missing extra-armv6_hal patch
Diffstat (limited to 'multimedia')
-rw-r--r--multimedia/kodi/files/extra-armv6_hal1463
1 files changed, 1463 insertions, 0 deletions
diff --git a/multimedia/kodi/files/extra-armv6_hal b/multimedia/kodi/files/extra-armv6_hal
new file mode 100644
index 000000000000..b65dbf109129
--- /dev/null
+++ b/multimedia/kodi/files/extra-armv6_hal
@@ -0,0 +1,1463 @@
+--- addons/resource.language.en_gb/resources/strings.po.orig 2016-11-12 UTC
++++ addons/resource.language.en_gb/resources/strings.po
+@@ -5652,17 +5652,17 @@ msgctxt "#13020"
+ msgid "Is another session active, perhaps over ssh?"
+ msgstr ""
+
+-#: xbmc/storage/MediaManager.cpp
++#: xbmc/linux/HALManager.cpp
+ msgctxt "#13021"
+ msgid "Mounted removable storage device"
+ msgstr ""
+
+-#: xbmc/storage/MediaManager.cpp
++#: xbmc/linux/HALManager.cpp
+ msgctxt "#13022"
+ msgid "Unsafe storage device removal"
+ msgstr ""
+
+-#: xbmc/storage/MediaManager.cpp
++#: xbmc/linux/HALManager.cpp
+ msgctxt "#13023"
+ msgid "Successfully removed storage device"
+ msgstr ""
+--- configure.ac.orig 2016-04-24 UTC
++++ configure.ac
+@@ -175,6 +175,9 @@ dbus_disabled="== DBUS support disabled.
+ x11_enabled="== X11 enabled. =="
+ x11_disabled="== X11 disabled. =="
+ pulse_not_found="== Could not find libpulse. PulseAudio support disabled. =="
++hal_not_found="== Could not find hal. HAL support disabled. =="
++halstorage_not_found="== Could not find hal-storage. HAL support disabled. =="
++hal_disabled="== HAL support disabled. =="
+ pulse_disabled="== PulseAudio support disabled. =="
+ avahi_not_found="== Could not find libavahi-common or libavahi-client. Avahi support disabled. =="
+ avahi_disabled="== Avahi support disabled. =="
+@@ -358,6 +361,12 @@ AC_ARG_ENABLE([mid],
+ [use_mid=$enableval],
+ [use_mid=no])
+
++AC_ARG_ENABLE([hal],
++ [AS_HELP_STRING([--disable-hal],
++ [disable HAL support (default is enabled if hal and hal-storage is found)])],
++ [use_hal=$enableval],
++ [use_hal=yes])
++
+ AC_ARG_ENABLE([avahi],
+ [AS_HELP_STRING([--disable-avahi],
+ [disable Avahi support (default is enabled if libavahi-common and libavahi-client is found)])],
+@@ -1249,6 +1258,26 @@ else
+ USE_PULSE=0
+ fi
+
++# HAL
++if test "$host_vendor" = "apple" ; then
++ use_hal="no"
++ AC_MSG_RESULT($hal_disabled)
++else
++ if test "$use_hal" = "yes"; then
++ PKG_CHECK_MODULES([HAL], [hal],
++ [INCLUDES="$INCLUDES $HAL_CFLAGS"; LIBS="$LIBS $HAL_LIBS"],
++ use_hal=no;AC_MSG_RESULT($hal_not_found))
++ PKG_CHECK_MODULES([HAL_STORAGE], [hal-storage],
++ [INCLUDES="$INCLUDES $HAL_STORAGE_CFLAGS"; LIBS="$LIBS $HAL_STORAGE_LIBS"],
++ use_hal=no;AC_MSG_RESULT($halstorage_not_found))
++ else
++ AC_MSG_RESULT($hal_disabled)
++ fi
++ if test "$use_hal" = "yes"; then
++ AC_DEFINE([HAS_HAL], [1], [Define to 1 if you have HAL installed])
++ fi
++fi
++
+ # avahi
+ if test "$use_avahi" = "yes"; then
+ AC_CHECK_LIB([avahi-common], [main],,
+@@ -1984,6 +2013,12 @@ else
+ final_message="$final_message\n PulseAudio:\tNo"
+ fi
+
++if test "$use_hal" = "yes"; then
++ final_message="$final_message\n HAL Support:\tYes"
++else
++ final_message="$final_message\n HAL Support:\tNo"
++fi
++
+ # Google Test Framework
+ if test "$configure_gtest" = "yes"; then
+ AC_MSG_NOTICE($gtest_enabled)
+--- xbmc/Application.cpp.orig 2016-09-03 UTC
++++ xbmc/Application.cpp
+@@ -194,6 +194,10 @@
+ #include <cdio/logging.h>
+ #endif
+
++#ifdef HAS_HAL
++#include "linux/HALManager.h"
++#endif
++
+ #include "storage/MediaManager.h"
+ #include "utils/JobManager.h"
+ #include "utils/SaveFileStateJob.h"
+--- xbmc/linux/HALManager.cpp.orig 2016-09-06 UTC
++++ xbmc/linux/HALManager.cpp
+@@ -0,0 +1,759 @@
++/*
++ * Copyright (C) 2005-2013 Team XBMC
++ * http://xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, 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 General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ */
++
++#include "system.h"
++#ifdef HAS_HAL
++#include "HALManager.h"
++#include "interfaces/builtins/Builtins.h"
++#include <libhal-storage.h>
++#include "threads/SingleLock.h"
++#include "utils/URIUtils.h"
++#include "guilib/LocalizeStrings.h"
++#include "powermanagement/PowerManager.h"
++#include "settings/AdvancedSettings.h"
++#include "dialogs/GUIDialogKaiToast.h"
++
++#ifdef HAS_SDL_JOYSTICK
++#include <SDL/SDL.h>
++#include <SDL/SDL_version.h>
++#include "input/SDLJoystick.h"
++#endif
++
++bool CHALManager::NewMessage;
++DBusError CHALManager::m_Error;
++CCriticalSection CHALManager::m_lock;
++
++/* A Removed device, It isn't possible to make a LibHalVolume from a removed device therefor
++ we catch the UUID from the udi on the removal */
++void CHALManager::DeviceRemoved(LibHalContext *ctx, const char *udi)
++{
++ NewMessage = true;
++ CLog::Log(LOGDEBUG, "HAL: Device (%s) Removed", udi);
++ g_HalManager.RemoveDevice(udi);
++}
++
++void CHALManager::DeviceNewCapability(LibHalContext *ctx, const char *udi, const char *capability)
++{
++ NewMessage = true;
++ CLog::Log(LOGDEBUG, "HAL: Device (%s) gained capability %s", udi, capability);
++ g_HalManager.UpdateDevice(udi);
++}
++
++void CHALManager::DeviceLostCapability(LibHalContext *ctx, const char *udi, const char *capability)
++{
++ NewMessage = true;
++ CLog::Log(LOGDEBUG, "HAL: Device (%s) lost capability %s", udi, capability);
++ g_HalManager.UpdateDevice(udi);
++}
++
++/* HAL Property modified callback. If a device is mounted. This is called. */
++void CHALManager::DevicePropertyModified(LibHalContext *ctx, const char *udi, const char *key, dbus_bool_t is_removed, dbus_bool_t is_added)
++{
++ NewMessage = true;
++ CLog::Log(LOGDEBUG, "HAL: Device (%s) Property %s modified", udi, key);
++ g_HalManager.UpdateDevice(udi);
++}
++
++void CHALManager::DeviceCondition(LibHalContext *ctx, const char *udi, const char *condition_name, const char *condition_details)
++{
++ NewMessage = true;
++ CLog::Log(LOGDEBUG, "HAL: Device (%s) Condition %s | %s", udi, condition_name, condition_details);
++ if (!strcmp(condition_name, "ButtonPressed") && !strcmp(condition_details, "power"))
++ CBuiltins::GetInstance().Execute("XBMC.ShutDown()");
++ else
++ g_HalManager.UpdateDevice(udi);
++}
++
++/* HAL Device added. This is before mount. And here is the place to mount the volume in the future */
++void CHALManager::DeviceAdded(LibHalContext *ctx, const char *udi)
++{
++ NewMessage = true;
++ CLog::Log(LOGDEBUG, "HAL: Device (%s) Added", udi);
++ g_HalManager.AddDevice(udi);
++}
++
++CHALManager g_HalManager;
++
++/* Iterate through all devices currently on the computer. Needed mostly at startup */
++void CHALManager::GenerateGDL()
++{
++ if (m_Context == NULL)
++ return;
++
++ char **GDL;
++ int i = 0;
++ CLog::Log(LOGDEBUG, "HAL: Clearing old global device list, if any");
++ m_Volumes.clear();
++
++ CLog::Log(LOGNOTICE, "HAL: Generating global device list");
++ GDL = libhal_get_all_devices(g_HalManager.m_Context, &i, &m_Error);
++
++ for (i = 0; GDL[i]; i++)
++ {
++ AddDevice(GDL[i]);
++ }
++ CLog::Log(LOGINFO, "HAL: Generated global device list, found %i", i);
++
++ libhal_free_string_array(GDL);
++}
++
++// Return all volumes that currently are available (Mostly needed at startup, the rest of the volumes comes as events.)
++std::vector<CStorageDevice> CHALManager::GetVolumeDevices()
++{
++ CSingleLock lock(m_lock);
++ return m_Volumes;
++}
++
++CHALManager::CHALManager()
++{
++ m_Notifications = false;
++ m_Context = NULL;
++ m_DBusSystemConnection = NULL;
++#if defined(HAS_SDL_JOYSTICK)
++ const SDL_version *sdl_version = SDL_Linked_Version();
++ m_bMultipleJoysticksSupport = (sdl_version->major >= 1 && sdl_version->minor >= 3)?true:false;
++#endif
++}
++
++void CHALManager::Stop()
++{
++ if (g_advancedSettings.m_handleMounting)
++ { // Unmount all media XBMC have mounted
++ for (unsigned int i = 0; i < m_Volumes.size(); i++)
++ {
++ if (m_Volumes[i].MountedByXBMC && m_Volumes[i].Mounted)
++ {
++ CLog::Log(LOGNOTICE, "HAL: Unmounts %s", m_Volumes[i].FriendlyName.c_str());
++ UnMount(m_Volumes[i]);
++ }
++ }
++ }
++
++ m_Volumes.clear();
++
++ if (m_Context != NULL)
++ libhal_ctx_shutdown(m_Context, NULL);
++ if (m_Context != NULL)
++ libhal_ctx_free(m_Context);
++
++ if (m_DBusSystemConnection != NULL)
++ {
++ dbus_connection_unref(m_DBusSystemConnection);
++ m_DBusSystemConnection = NULL;
++ }
++ dbus_error_free(&m_Error); // Needed?
++}
++
++// Initialize
++void CHALManager::Initialize()
++{
++ m_Notifications = false;
++ CLog::Log(LOGINFO, "HAL: Starting initializing");
++ g_HalManager.m_Context = g_HalManager.InitializeHal();
++ if (g_HalManager.m_Context == NULL)
++ {
++ CLog::Log(LOGERROR, "HAL: no Hal context");
++ return;
++ }
++
++ GenerateGDL();
++
++ CLog::Log(LOGINFO, "HAL: Successfully initialized");
++ m_Notifications = true;
++}
++
++// Initialize basic DBus connection
++bool CHALManager::InitializeDBus()
++{
++ if (m_DBusSystemConnection != NULL)
++ return true;
++
++ dbus_error_init (&m_Error);
++ if (m_DBusSystemConnection == NULL && !(m_DBusSystemConnection = dbus_bus_get (DBUS_BUS_SYSTEM, &m_Error)))
++ {
++ CLog::Log(LOGERROR, "DBus: Could not get system bus: %s", m_Error.message);
++ dbus_error_free (&m_Error);
++ }
++
++ if (m_DBusSystemConnection != NULL)
++ return true;
++ else
++ return false;
++}
++
++// Initialize basic HAL connection
++LibHalContext *CHALManager::InitializeHal()
++{
++ LibHalContext *ctx;
++ char **devices;
++ int nr;
++
++ if (!InitializeDBus())
++ return NULL;
++
++ if (!(ctx = libhal_ctx_new()))
++ {
++ CLog::Log(LOGERROR, "HAL: failed to create a HAL context!");
++ return NULL;
++ }
++
++ if (!libhal_ctx_set_dbus_connection(ctx, m_DBusSystemConnection))
++ CLog::Log(LOGERROR, "HAL: Failed to connect with dbus");
++
++ libhal_ctx_set_device_added(ctx, DeviceAdded);
++ libhal_ctx_set_device_removed(ctx, DeviceRemoved);
++ libhal_ctx_set_device_new_capability(ctx, DeviceNewCapability);
++ libhal_ctx_set_device_lost_capability(ctx, DeviceLostCapability);
++ libhal_ctx_set_device_property_modified(ctx, DevicePropertyModified);
++ libhal_ctx_set_device_condition(ctx, DeviceCondition);
++
++ if (!libhal_device_property_watch_all(ctx, &m_Error))
++ {
++ CLog::Log(LOGERROR, "HAL: Failed to set property watch %s", m_Error.message);
++ dbus_error_free(&m_Error);
++ libhal_ctx_free(ctx);
++ return NULL;
++ }
++
++ if (!libhal_ctx_init(ctx, &m_Error))
++ {
++ CLog::Log(LOGERROR, "HAL: Failed to initialize hal context: %s", m_Error.message);
++ dbus_error_free(&m_Error);
++ libhal_ctx_free(ctx);
++ return NULL;
++ }
++
++ /*
++ * Do something to ping the HAL daemon - the above functions will
++ * succeed even if hald is not running, so long as DBUS is. But we
++ * want to exit silently if hald is not running, to behave on
++ * pre-2.6 systems.
++ */
++ if (!(devices = libhal_get_all_devices(ctx, &nr, &m_Error)))
++ {
++ CLog::Log(LOGERROR, "HAL: seems that Hal daemon is not running: %s", m_Error.message);
++ dbus_error_free(&m_Error);
++
++ libhal_ctx_shutdown(ctx, NULL);
++ libhal_ctx_free(ctx);
++ return NULL;
++ }
++
++ libhal_free_string_array(devices);
++
++ return ctx;
++}
++
++// Helper function. creates a CStorageDevice from a HAL udi
++bool CHALManager::DeviceFromVolumeUdi(const char *udi, CStorageDevice *device)
++{
++ if (g_HalManager.m_Context == NULL)
++ return false;
++
++ LibHalVolume *tempVolume;
++ LibHalDrive *tempDrive;
++ bool Created = false;
++
++ tempVolume = libhal_volume_from_udi(g_HalManager.m_Context, udi);
++ if (tempVolume)
++ {
++ const char *DriveUdi = libhal_volume_get_storage_device_udi(tempVolume);
++ tempDrive = libhal_drive_from_udi(g_HalManager.m_Context, DriveUdi);
++
++ if (tempDrive)
++ {
++ char * FriendlyName = libhal_device_get_property_string(g_HalManager.m_Context, udi, "info.product", NULL);
++ device->FriendlyName = FriendlyName;
++ libhal_free_string(FriendlyName);
++ char *block = libhal_device_get_property_string(g_HalManager.m_Context, udi, "block.device", NULL);
++ device->DevID = block;
++ libhal_free_string(block);
++
++ device->HotPlugged = (bool)libhal_drive_is_hotpluggable(tempDrive);
++ device->Type = libhal_drive_get_type(tempDrive);
++ device->Mounted = (bool)libhal_volume_is_mounted(tempVolume);
++ if (libhal_volume_get_mount_point(tempVolume) != NULL)
++ device->MountPoint = libhal_volume_get_mount_point(tempVolume);
++ if (device->Mounted)
++ URIUtils::AddSlashAtEnd(device->MountPoint);
++ if (libhal_volume_get_label(tempVolume) != NULL)
++ device->Label = libhal_volume_get_label(tempVolume);
++ if (libhal_volume_get_uuid(tempVolume) != NULL)
++ device->UUID = libhal_volume_get_uuid(tempVolume);
++ if (libhal_volume_get_fstype(tempVolume) != NULL)
++ device->FileSystem = libhal_volume_get_fstype(tempVolume);
++ device->HalIgnore = libhal_device_get_property_bool(g_HalManager.m_Context, udi, "volume.ignore", NULL);
++ ApproveDevice(device);
++
++ libhal_drive_free(tempDrive);
++ Created = true;
++ }
++ else
++ CLog::Log(LOGERROR, "HAL: Couldn't create a Drive even if we had a volume - %s", udi);
++
++ libhal_volume_free(tempVolume);
++ }
++
++ return Created;
++}
++
++// Called from ProcessSlow to trigger the callbacks from DBus
++bool CHALManager::Update()
++{
++ CSingleLock lock(m_lock);
++ if (m_Context == NULL)
++ return false;
++
++ if (!dbus_connection_read_write_dispatch(m_DBusSystemConnection, 0)) // We choose 0 that means we won't wait for a message
++ {
++ CLog::Log(LOGERROR, "DBus: System - read/write dispatch");
++ return false;
++ }
++ if (NewMessage)
++ {
++ NewMessage = false;
++ return true;
++ }
++ else
++ return false;
++}
++
++/* libhal-storage type to readable form */
++const char *CHALManager::StorageTypeToString(int DeviceType)
++{
++ switch (DeviceType)
++ {
++ case 0: return "removable disk";
++ case 1: return "disk";
++ case 2: return "cdrom";
++ case 3: return "floppy";
++ case 4: return "tape";
++ case 5: return "compact flash";
++ case 6: return "memory stick";
++ case 7: return "smart media";
++ case 8: return "sd mmc";
++ case 9: return "camera";
++ case 10: return "audio player";
++ case 11: return "zip";
++ case 12: return "jaz";
++ case 13: return "flashkey";
++ case 14: return "magneto-optical";
++ default: return NULL;
++ }
++}
++
++/* Readable libhal-storage type to int type */
++int CHALManager::StorageTypeFromString(const char *DeviceString)
++{
++ if (strcmp(DeviceString, "removable disk") == 0) return 0;
++ else if (strcmp(DeviceString, "disk") == 0) return 1;
++ else if (strcmp(DeviceString, "cdrom") == 0) return 2;
++ else if (strcmp(DeviceString, "floppy") == 0) return 3;
++ else if (strcmp(DeviceString, "tape") == 0) return 4;
++ else if (strcmp(DeviceString, "compact flash") == 0) return 5;
++ else if (strcmp(DeviceString, "memory stick") == 0) return 6;
++ else if (strcmp(DeviceString, "smart media") == 0) return 7;
++ else if (strcmp(DeviceString, "sd mmc") == 0) return 8;
++ else if (strcmp(DeviceString, "camera") == 0) return 9;
++ else if (strcmp(DeviceString, "audio player") == 0) return 10;
++ else if (strcmp(DeviceString, "zip") == 0) return 11;
++ else if (strcmp(DeviceString, "jaz") == 0) return 12;
++ else if (strcmp(DeviceString, "flashkey") == 0) return 13;
++ else if (strcmp(DeviceString, "magneto-optical") == 0) return 14;
++ return -1;
++}
++
++void CHALManager::UpdateDevice(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))
++ return;
++ for (unsigned int i = 0; i < m_Volumes.size(); i++)
++ {
++ if (strcmp(m_Volumes[i].UDI.c_str(), udi) == 0)
++ {
++ CLog::Log(LOGDEBUG, "HAL: Update - %s | %s", CHALManager::StorageTypeToString(dev.Type), dev.toString().c_str());
++ if (g_advancedSettings.m_handleMounting) // If the device was mounted by XBMC before it's still mounted by XBMC.
++ dev.MountedByXBMC = m_Volumes[i].MountedByXBMC;
++ if (!dev.Mounted && m_Volumes[i].Mounted)
++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(13023), dev.FriendlyName.c_str(), TOAST_DISPLAY_TIME, false);
++ m_Volumes[i] = dev;
++
++ break;
++ }
++ }
++ }
++
++ libhal_free_string(category);
++}
++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], "block") == 0 && strcmp(capability[1], "volume") == 0)) // HDD
++ Mountable = true;
++
++ if (Mountable)
++ {
++ CLog::Log(LOGNOTICE, "HAL: Trying to mount %s", dev->FriendlyName.c_str());
++ std::string MountPoint;
++ std::string TestPath;
++ if (dev->Label.size() > 0)
++ {
++ MountPoint = dev->Label.c_str();
++ TestPath = StringUtils::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 = StringUtils::Format("/media/%s", MountPoint.c_str());
++ }
++ }
++ else
++ {
++ MountPoint = StorageTypeToString(dev->Type);
++ TestPath = StringUtils::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 = StringUtils::Format("%s%i", StorageTypeToString(dev->Type), Nbr);
++ TestPath = StringUtils::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);
++}
++
++/* Here we should iterate through our remembered devices if any of them are removed */
++bool CHALManager::RemoveDevice(const char *udi)
++{
++ CSingleLock lock(m_lock);
++ for (unsigned int i = 0; i < m_Volumes.size(); i++)
++ {
++ if (strcmp(m_Volumes[i].UDI.c_str(), udi) == 0)
++ {
++ CLog::Log(LOGNOTICE, "HAL: Removed - %s | %s", CHALManager::StorageTypeToString(m_Volumes[i].Type), m_Volumes[i].toString().c_str());
++
++ if (m_Volumes[i].Mounted)
++ {
++ if (g_advancedSettings.m_handleMounting)
++ UnMount(m_Volumes[i]);
++ if (m_Notifications)
++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(13022), m_Volumes[i].FriendlyName.c_str());
++ CLog::Log(LOGNOTICE, "HAL: Unsafe drive removal");
++ }
++ m_Volumes.erase(m_Volumes.begin() + i);
++ return true;
++ }
++ }
++#if defined(HAS_SDL_JOYSTICK)
++ for(uint i = 0; i < m_Joysticks.size(); i++)
++ {
++ if (strcmp(m_Joysticks[i].UDI.c_str(), udi) == 0)
++ {
++ if(m_Joysticks.size() < 3 || m_bMultipleJoysticksSupport)
++ {
++ // Restart SDL joystick subsystem
++ if (!g_Joystick.Reinitialize())
++ return false;
++
++ if (m_Notifications)
++ CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, g_localizeStrings.Get(13025), m_Joysticks[i].FriendlyName.c_str(), TOAST_DISPLAY_TIME, false);
++ }
++ m_Joysticks.erase(m_Joysticks.begin() + i);
++ return true;
++ }
++ }
++#endif
++ return false;
++}
++
++bool CHALManager::ApproveDevice(CStorageDevice *device)
++{
++ bool approve = true;
++ //This is only because it's easier to read...
++ const char *fs = device->FileSystem.c_str();
++
++ if ( strcmp(fs, "vfat") == 0 || strcmp(fs, "ext2") == 0
++ || strcmp(fs, "ext3") == 0 || strcmp(fs, "reiserfs") == 0
++ || strcmp(fs, "ntfs") == 0 || strcmp(fs, "ntfs-3g") == 0
++ || strcmp(fs, "udf") == 0 || strcmp(fs, "iso9660") == 0
++ || strcmp(fs, "xfs") == 0 || strcmp(fs, "hfsplus") == 0
++ || strcmp(fs, "ext4") == 0 || strcmp(fs, "ufs") == 0)
++ approve = true;
++ else
++ approve = false;
++
++ // Ignore some mountpoints, unless a weird setup these should never contain anything usefull for an enduser.
++ if (strcmp(device->MountPoint.c_str(), "/") == 0 || strcmp(device->MountPoint.c_str(), "/boot/") == 0 || strcmp(device->MountPoint.c_str(), "/mnt/") == 0 || strcmp(device->MountPoint.c_str(), "/home/") == 0)
++ approve = false;
++
++ if (device->HalIgnore)
++ approve = false;
++
++ device->Approved = approve;
++ return approve;
++}
++
++bool CHALManager::Eject(const std::string& path)
++{
++ for (unsigned int i = 0; i < m_Volumes.size(); i++)
++ {
++ if (m_Volumes[i].MountPoint == path)
++ return m_Volumes[i].HotPlugged ? UnMount(m_Volumes[i]) : false;
++ }
++
++ return false;
++}
++
++bool CHALManager::UnMount(CStorageDevice volume)
++{
++ CLog::Log(LOGNOTICE, "HAL: UnMounting %s (%s)", volume.UDI.c_str(), volume.toString().c_str());
++ DBusMessage* msg;
++ DBusMessageIter args;
++ DBusError error;
++ dbus_error_init (&error);
++ DBusConnection *connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
++ if (connection)
++ {
++ msg = dbus_message_new_method_call("org.freedesktop.Hal", volume.UDI.c_str(), "org.freedesktop.Hal.Device.Volume", "Unmount");
++ dbus_message_iter_init_append(msg, &args);
++ DBusMessageIter sub;
++ dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &sub);
++ const char *s = "lazy";
++ dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
++ dbus_message_iter_close_container(&args, &sub);
++
++ if (msg == NULL)
++ CLog::Log(LOGERROR, "DBus: Create UnMount Message failed");
++ else
++ {
++ DBusMessage *reply;
++ reply = dbus_connection_send_with_reply_and_block(connection, msg, -1, &error); //The reply timout might be bad to have as -1
++ if (dbus_error_is_set(&error))
++ {
++ CLog::Log(LOGERROR, "DBus: %s - %s", error.name, error.message);
++ dbus_error_free(&error);
++ return false;
++ }
++ // Need to create a reader for the Message
++ dbus_message_unref (reply);
++ dbus_message_unref(msg);
++ msg = NULL;
++ }
++
++ volume.MountPoint = "";
++ volume.Mounted = false;
++ dbus_connection_unref(connection);
++ connection = NULL;
++ return true;
++ }
++ else
++ {
++ CLog::Log(LOGERROR, "DBus: Failed to connect to Systembus");
++ dbus_error_free(&error);
++ return false;
++ }
++}
++
++bool CHALManager::Mount(CStorageDevice *volume, const std::string &mountpath)
++{
++ 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));
++ DBusMessage* msg;
++ DBusMessageIter args;
++ DBusError error;
++ dbus_error_init (&error);
++ DBusConnection *connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
++ const char *s;
++ if (connection)
++ {
++ msg = dbus_message_new_method_call("org.freedesktop.Hal", volume->UDI.c_str(), "org.freedesktop.Hal.Device.Volume", "Mount");
++ dbus_message_iter_init_append(msg, &args);
++ s = mountpath.c_str();
++ if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &s))
++ CLog::Log(LOGERROR, "DBus: Failed to append arguments");
++ s = ""; //FileSystem
++ if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &s))
++ CLog::Log(LOGERROR, "DBus: Failed to append arguments");
++ DBusMessageIter sub;
++ dbus_message_iter_open_container(&args, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &sub);
++
++ std::string temporaryString;
++
++#if defined(__linux__)
++ if (volume->FileSystem == "vfat")
++ {
++ int mask = umask (0);
++ temporaryString = StringUtils::Format("umask=%#o", mask);
++ s = temporaryString.c_str();
++ dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
++ temporaryString = StringUtils::Format("uid=%u", getuid());
++ s = temporaryString.c_str();
++ dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
++ s = "shortname=mixed";
++ dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
++ s = "utf8";
++ dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
++ // 'sync' option will slow down transfer speed significantly for FAT filesystems. We prefer 'flush' instead.
++ s = "flush";
++ dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
++ }
++ else
++ {
++ s = "sync";
++ dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &s);
++ }
++#endif
++
++ dbus_message_iter_close_container(&args, &sub);
++
++ if (msg == NULL)
++ CLog::Log(LOGERROR, "DBus: Create Mount Message failed");
++ else
++ {
++ DBusMessage *reply;
++ reply = dbus_connection_send_with_reply_and_block(connection, msg, -1, &error); //The reply timout might be bad to have as -1
++ if (dbus_error_is_set(&error))
++ {
++ CLog::Log(LOGERROR, "DBus: %s - %s", error.name, error.message);
++ dbus_error_free(&error);
++ return false;
++ }
++ // Need to create a reader for the Message
++ dbus_message_unref (reply);
++ dbus_message_unref(msg);
++ msg = NULL;
++ }
++
++ volume->Mounted = true;
++ volume->MountedByXBMC = true;
++ volume->MountPoint = mountpath;
++ dbus_connection_unref(connection);
++ connection = NULL;
++ return true;
++ }
++ else
++ {
++ CLog::Log(LOGERROR, "DBus: Failed to connect to Systembus");
++ dbus_error_free(&error);
++ return false;
++ }
++}
++#endif // HAS_HAL
+--- xbmc/linux/HALManager.h.orig 2016-09-03 UTC
++++ xbmc/linux/HALManager.h
+@@ -0,0 +1,166 @@
++#ifdef HAS_HAL
++#ifndef HALMANAGER_H
++#define HALMANAGER_H
++
++/*
++ * Copyright (C) 2005-2013 Team XBMC
++ * http://xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, 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 General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ */
++
++#include "system.h"
++#include <string.h>
++#include <stdio.h>
++#include <dbus/dbus.h>
++#include <libhal.h>
++#include <vector>
++
++#define BYTE char
++#include "utils/log.h"
++#include "threads/CriticalSection.h"
++#include "utils/StringUtils.h"
++#include "utils/URIUtils.h"
++#include "MediaSource.h"
++
++class CHALDevice
++{
++public:
++ std::string UDI;
++ std::string FriendlyName;
++ CHALDevice(const char *udi) { UDI = udi; }
++};
++
++class CStorageDevice : public CHALDevice
++{
++public:
++ CStorageDevice(const char *udi) : CHALDevice(udi) { HotPlugged = false; Mounted = false; Approved = false; MountedByXBMC = false; }
++ bool MountedByXBMC;
++ bool Mounted;
++ bool Approved;
++ bool HotPlugged;
++ bool HalIgnore;
++ std::string MountPoint;
++ std::string Label;
++ std::string UUID;
++ std::string DevID;
++ int Type;
++ std::string FileSystem;
++
++ std::string toString()
++ { // Not the prettiest but it's better than having to reproduce it elsewere in the code...
++ std::string rtn, tmp1, tmp2, tmp3, tmp4;
++ if (UUID.size() > 0)
++ tmp1 = StringUtils::Format("UUID %s | ", UUID.c_str());
++ if (FileSystem.size() > 0)
++ tmp2 = StringUtils::Format("FileSystem %s | ", FileSystem.c_str());
++ if (MountPoint.size() > 0)
++ tmp3 = StringUtils::Format("Mounted on %s | ", MountPoint.c_str());
++ if (HotPlugged)
++ tmp4 = StringUtils::Format("HotPlugged YES | ");
++ else
++ tmp4 = StringUtils::Format("HotPlugged NO | ");
++
++ if (Approved)
++ rtn = StringUtils::Format("%s%s%s%sType %i |Approved YES ", tmp1.c_str(), tmp2.c_str(), tmp3.c_str(), tmp4.c_str(), Type);
++ else
++ rtn = StringUtils::Format("%s%s%s%sType %i |Approved NO ", tmp1.c_str(), tmp2.c_str(), tmp3.c_str(), tmp4.c_str(), Type);
++
++ return rtn;
++ }
++ void toMediaSource(CMediaSource *share)
++ {
++ share->strPath = MountPoint;
++ if (Label.size() > 0)
++ share->strName = Label;
++ else
++ {
++ share->strName = MountPoint;
++ URIUtils::RemoveSlashAtEnd(share->strName);
++ share->strName = URIUtils::GetFileName(share->strName);
++ }
++
++ share->m_ignore = true;
++ if (HotPlugged)
++ share->m_iDriveType = CMediaSource::SOURCE_TYPE_REMOVABLE;
++ else if(strcmp(FileSystem.c_str(), "iso9660") == 0 || strcmp(FileSystem.c_str(), "udf") == 0)
++ share->m_iDriveType = CMediaSource::SOURCE_TYPE_DVD;
++ else
++ share->m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
++ }
++
++};
++
++
++class CHALManager
++{
++public:
++ static const char *StorageTypeToString(int DeviceType);
++ static int StorageTypeFromString(const char *DeviceString);
++ bool Update();
++
++ void Initialize();
++ CHALManager();
++ void Stop();
++ std::vector<CStorageDevice> GetVolumeDevices();
++ bool Eject(const std::string &path);
++protected:
++ DBusConnection *m_DBusSystemConnection;
++ LibHalContext *m_Context;
++ static DBusError m_Error;
++ static bool NewMessage;
++
++
++ void UpdateDevice(const char *udi);
++ void AddDevice(const char *udi);
++ bool RemoveDevice(const char *udi);
++
++private:
++ bool m_Notifications;
++ LibHalContext *InitializeHal();
++ bool InitializeDBus();
++ void GenerateGDL();
++
++ bool UnMount(CStorageDevice volume);
++ bool Mount(CStorageDevice *volume, const std::string& mountpath);
++ void HandleNewVolume(CStorageDevice *dev);
++ static bool ApproveDevice(CStorageDevice *device);
++
++ static bool DeviceFromVolumeUdi(const char *udi, CStorageDevice *device);
++ static CCriticalSection m_lock;
++
++#if defined(HAS_SDL_JOYSTICK)
++ bool m_bMultipleJoysticksSupport;
++#endif
++
++ //Callbacks HAL
++ static void DeviceRemoved(LibHalContext *ctx, const char *udi);
++ static void DeviceNewCapability(LibHalContext *ctx, const char *udi, const char *capability);
++ static void DeviceLostCapability(LibHalContext *ctx, const char *udi, const char *capability);
++ static void DevicePropertyModified(LibHalContext *ctx, const char *udi, const char *key, dbus_bool_t is_removed, dbus_bool_t is_added);
++ static void DeviceCondition(LibHalContext *ctx, const char *udi, const char *condition_name, const char *condition_details);
++ static void DeviceAdded(LibHalContext *ctx, const char *udi);
++
++ //Remembered Devices
++ std::vector<CStorageDevice> m_Volumes;
++#if defined(HAS_SDL_JOYSTICK)
++ std::vector<CHALDevice> m_Joysticks;
++#endif
++};
++
++extern CHALManager g_HalManager;
++#endif
++#endif // HAS_HAL
+--- xbmc/linux/Makefile.in.orig 2016-09-03 UTC
++++ xbmc/linux/Makefile.in
+@@ -4,6 +4,7 @@ SRCS = ConvUtils.cpp
+ SRCS += DBusUtil.cpp
+ SRCS += DBusMessage.cpp
+ SRCS += DBusReserve.cpp
++SRCS += HALManager.cpp
+ SRCS += FDEventMonitor.cpp
+ SRCS += LinuxResourceCounter.cpp
+ SRCS += LinuxTimezone.cpp
+--- xbmc/powermanagement/linux/HALPowerSyscall.cpp.orig 2016-09-03 UTC
++++ xbmc/powermanagement/linux/HALPowerSyscall.cpp
+@@ -0,0 +1,159 @@
++/*
++ * Copyright (C) 2005-2013 Team XBMC
++ * http://xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, 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 General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ */
++
++#include "system.h"
++#include "HALPowerSyscall.h"
++#include "utils/log.h"
++
++#ifdef HAS_HAL
++#include <dbus/dbus.h>
++#include <stdlib.h>
++
++CHALPowerSyscall::CHALPowerSyscall()
++{
++ m_CanPowerdown = true;
++ m_CanSuspend = QueryCapability("power_management.can_suspend");
++ m_CanHibernate = QueryCapability("power_management.can_hibernate");
++ m_CanReboot = true;
++}
++
++bool CHALPowerSyscall::Powerdown()
++{
++ return doPowerCall("Shutdown");
++}
++bool CHALPowerSyscall::Suspend()
++{
++ CPowerSyscallWithoutEvents::Suspend();
++ return doPowerCall("Suspend");
++}
++bool CHALPowerSyscall::Hibernate()
++{
++ CPowerSyscallWithoutEvents::Hibernate();
++ return doPowerCall("Hibernate");
++}
++bool CHALPowerSyscall::Reboot()
++{
++ return doPowerCall("Reboot");
++}
++
++bool CHALPowerSyscall::CanPowerdown()
++{
++ return m_CanPowerdown;
++}
++bool CHALPowerSyscall::CanSuspend()
++{
++ return m_CanSuspend;
++}
++bool CHALPowerSyscall::CanHibernate()
++{
++ return m_CanHibernate;
++}
++bool CHALPowerSyscall::CanReboot()
++{
++ return m_CanReboot;
++}
++
++int CHALPowerSyscall::BatteryLevel()
++{
++ return 0;
++}
++
++bool CHALPowerSyscall::doPowerCall(const char *powerstate)
++{
++ DBusMessage* msg;
++ DBusMessageIter args;
++ DBusError error;
++ dbus_error_init (&error);
++ DBusConnection *connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
++ dbus_int32_t int32 = 0;
++ if (connection)
++ {
++ bool result = false;
++ msg = dbus_message_new_method_call("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer", "org.freedesktop.Hal.Device.SystemPowerManagement", powerstate);
++
++ if (msg && strcmp(powerstate, "Suspend") == 0)
++ {
++ dbus_message_iter_init_append(msg, &args);
++ if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_INT32, &int32))
++ CLog::Log(LOGERROR, "DBus: Failed to append arguments");
++ }
++ if (msg == NULL)
++ CLog::Log(LOGERROR, "DBus: Create PowerManagement Message failed");
++ else
++ {
++ result = dbus_connection_send(connection, msg, NULL);
++ // Need to create a reader for the Message
++ dbus_message_unref(msg);
++ msg = NULL;
++ }
++
++ dbus_connection_unref(connection);
++ connection = NULL;
++ return result;
++ }
++ return false;
++}
++
++bool CHALPowerSyscall::QueryCapability(const char *capability)
++{
++ DBusMessage* msg;
++ DBusMessageIter args;
++ DBusError error;
++ dbus_error_init (&error);
++ DBusConnection *connection = dbus_bus_get (DBUS_BUS_SYSTEM, &error);
++ if (connection)
++ {
++ msg = dbus_message_new_method_call("org.freedesktop.Hal", "/org/freedesktop/Hal/devices/computer", "org.freedesktop.Hal.Device", "GetProperty");
++
++ dbus_message_iter_init_append(msg, &args);
++ if (!dbus_message_iter_append_basic(&args, DBUS_TYPE_STRING, &capability))
++ return false;
++
++ if (msg == NULL)
++ return false;
++
++ DBusMessage *reply;
++ reply = dbus_connection_send_with_reply_and_block(connection, msg, -1, &error);
++ if (reply == NULL)
++ {
++ if (dbus_error_is_set(&error))
++ dbus_error_free(&error);
++
++ dbus_message_unref(msg);
++ return false;
++ }
++
++ dbus_bool_t b = false;
++ dbus_message_get_args(reply, &error, DBUS_TYPE_BOOLEAN, &b);
++
++ if (dbus_error_is_set(&error))
++ dbus_error_free(&error);
++
++ dbus_message_unref(reply);
++ dbus_message_unref(msg);
++ msg = NULL;
++ return b;
++ }
++
++ if (dbus_error_is_set(&error))
++ dbus_error_free(&error);
++ return false;
++}
++#endif
+--- xbmc/powermanagement/linux/HALPowerSyscall.h.orig 2016-09-03 UTC
++++ xbmc/powermanagement/linux/HALPowerSyscall.h
+@@ -0,0 +1,50 @@
++/*
++ * Copyright (C) 2005-2013 Team XBMC
++ * http://xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, 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 General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ */
++#pragma once
++#include "powermanagement/IPowerSyscall.h"
++#include "system.h"
++#ifdef HAS_HAL
++
++class CHALPowerSyscall : public CPowerSyscallWithoutEvents
++{
++public:
++ CHALPowerSyscall();
++
++ virtual bool Powerdown();
++ virtual bool Suspend();
++ virtual bool Hibernate();
++ virtual bool Reboot();
++
++ virtual bool CanPowerdown();
++ virtual bool CanSuspend();
++ virtual bool CanHibernate();
++ virtual bool CanReboot();
++ virtual int BatteryLevel();
++
++private:
++ bool QueryCapability(const char *capability);
++ bool doPowerCall(const char *powerstate);
++
++ bool m_CanPowerdown;
++ bool m_CanSuspend;
++ bool m_CanHibernate;
++ bool m_CanReboot;
++};
++#endif
+--- xbmc/powermanagement/linux/Makefile.orig 2016-09-03 UTC
++++ xbmc/powermanagement/linux/Makefile
+@@ -1,5 +1,6 @@
+ SRCS=ConsoleDeviceKitPowerSyscall.cpp \
+ ConsoleUPowerSyscall.cpp \
++ HALPowerSyscall.cpp \
+ UPowerSyscall.cpp \
+ LogindUPowerSyscall.cpp
+
+--- xbmc/powermanagement/PowerManager.cpp.orig 2016-04-24 UTC
++++ xbmc/powermanagement/PowerManager.cpp
+@@ -50,6 +50,9 @@
+ #include "linux/ConsoleDeviceKitPowerSyscall.h"
+ #include "linux/LogindUPowerSyscall.h"
+ #include "linux/UPowerSyscall.h"
++#if defined(HAS_HAL)
++#include "linux/HALPowerSyscall.h"
++#endif // HAS_HAL
+ #endif // HAS_DBUS
+ #elif defined(TARGET_WINDOWS)
+ #include "powermanagement/windows/Win32PowerSyscall.h"
+@@ -74,7 +77,9 @@ void CPowerManager::Initialize()
+ {
+ SAFE_DELETE(m_instance);
+
+-#if defined(TARGET_DARWIN)
++#if defined(TARGET_RASPBERRY_PI)
++ m_instance = new CHALPowerSyscall();
++#elif defined(TARGET_DARWIN)
+ m_instance = new CCocoaPowerSyscall();
+ #elif defined(TARGET_ANDROID)
+ m_instance = new CAndroidPowerSyscall();
+--- xbmc/storage/linux/HALProvider.cpp.orig 2016-09-03 UTC
++++ xbmc/storage/linux/HALProvider.cpp
+@@ -0,0 +1,94 @@
++/*
++ * Copyright (C) 2005-2013 Team XBMC
++ * http://xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, 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 General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ */
++#include "HALProvider.h"
++#ifdef HAS_HAL
++#include "HALManager.h"
++#include "utils/log.h"
++#include "PosixMountProvider.h"
++
++CHALProvider::CHALProvider()
++{
++ m_removableLength = 0;
++}
++
++void CHALProvider::Initialize()
++{
++ CLog::Log(LOGDEBUG, "Selected HAL as storage provider");
++ g_HalManager.Initialize();
++ PumpDriveChangeEvents(NULL);
++}
++
++void CHALProvider::Stop()
++{
++ g_HalManager.Stop();
++}
++
++void CHALProvider::GetLocalDrives(VECSOURCES &localDrives)
++{
++ std::vector<CStorageDevice> devices = g_HalManager.GetVolumeDevices();
++
++ for (size_t i = 0; i < devices.size(); i++)
++ {
++ if (devices[i].Mounted && devices[i].Approved && !devices[i].HotPlugged)
++ {
++ CMediaSource share;
++ devices[i].toMediaSource(&share);
++ localDrives.push_back(share);
++ }
++ }
++}
++
++void CHALProvider::GetRemovableDrives(VECSOURCES &removableDrives)
++{
++ std::vector<CStorageDevice> devices = g_HalManager.GetVolumeDevices();
++
++ for (size_t i = 0; i < devices.size(); i++)
++ {
++ if (devices[i].Mounted && devices[i].Approved && devices[i].HotPlugged)
++ {
++ CMediaSource share;
++ devices[i].toMediaSource(&share);
++ removableDrives.push_back(share);
++ }
++ }
++}
++
++bool CHALProvider::Eject(const std::string& mountpath)
++{
++ return g_HalManager.Eject(mountpath);
++}
++
++std::vector<std::string> CHALProvider::GetDiskUsage()
++{
++ CPosixMountProvider legacy;
++ return legacy.GetDiskUsage();
++}
++
++// TODO Use HALs events for this instead.
++bool CHALProvider::PumpDriveChangeEvents(IStorageEventsCallback *callback)
++{
++//Pump HalManager dry of events
++ bool changed = false;
++ while (g_HalManager.Update())
++ changed = true;
++
++ return changed;
++}
++#endif
+--- xbmc/storage/linux/HALProvider.h.orig 2016-09-03 UTC
++++ xbmc/storage/linux/HALProvider.h
+@@ -0,0 +1,44 @@
++#pragma once
++/*
++ * Copyright (C) 2005-2013 Team XBMC
++ * http://xbmc.org
++ *
++ * This Program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2, 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 General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with XBMC; see the file COPYING. If not, see
++ * <http://www.gnu.org/licenses/>.
++ *
++ */
++#include "storage/IStorageProvider.h"
++#ifdef HAS_HAL
++
++class CHALProvider : public IStorageProvider
++{
++public:
++ CHALProvider();
++ virtual ~CHALProvider() { }
++
++ virtual void Initialize();
++ virtual void Stop();
++
++ virtual void GetLocalDrives(VECSOURCES &localDrives);
++ virtual void GetRemovableDrives(VECSOURCES &removableDrives);
++
++ virtual bool Eject(const std::string& mountpath);
++
++ virtual std::vector<std::string> GetDiskUsage();
++
++ virtual bool PumpDriveChangeEvents(IStorageEventsCallback *callback);
++private:
++ unsigned int m_removableLength;
++};
++#endif
+--- xbmc/storage/linux/LinuxStorageProvider.h.orig 2016-04-24 UTC
++++ xbmc/storage/linux/LinuxStorageProvider.h
+@@ -19,6 +19,7 @@
+ *
+ */
+ #include "storage/IStorageProvider.h"
++#include "HALProvider.h"
+ #include "DeviceKitDisksProvider.h"
+ #include "UDevProvider.h"
+ #include "UDisksProvider.h"
+@@ -37,6 +38,10 @@ public:
+ else if (CDeviceKitDisksProvider::HasDeviceKitDisks())
+ m_instance = new CDeviceKitDisksProvider();
+ #endif
++#ifdef HAS_HAL
++ if (m_instance == NULL)
++ m_instance = new CHALProvider();
++#endif
+ #ifdef HAVE_LIBUDEV
+ if (m_instance == NULL)
+ m_instance = new CUDevProvider();
+--- xbmc/storage/linux/Makefile.orig 2016-09-03 UTC
++++ xbmc/storage/linux/Makefile
+@@ -1,5 +1,6 @@
+ SRCS = DeviceKitDisksProvider.cpp
+ SRCS += UDisksProvider.cpp
++SRCS += HALProvider.cpp
+ SRCS += UDevProvider.cpp
+
+ LIB = storage_linux.a