From 034236bf690119b2a82be1133ff328bccbdc4411 Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Mon, 29 Aug 2011 15:04:49 +0200 Subject: [PATCH 1/2] Squashed original peripherals PR #383 This is a PR for a new "peripherals manager", /xbmc/peripherals, that detects devices and automatically configures them for use with XBMC. The device mappings and configurations can be defined in system/peripherals.xml. Users can modify settings via system->system->input->peripherals. It works as follows: - CPeripherals contains one or more CPeripheralBus instances. - CPeripheralBus contains the device scanning implementations for the different platforms we support. - The implementations for the devices can be found in peripheral/devices and all devices inherit from CPeripheral. - The devices that are detected are looked up in peripherals.xml, starting at the top of the file and going down. If no mapping was found for the device, an instance of one of the default classes will be created: CPeripheralHID, CPeripheralDisk or CPeripheralNIC. - in peripherals.xml, devices can be matched by vendor id (vendor="xxxx"), product id (product="xxxx"), bus type (bus="xxxx"), device class (class="xxxx") or a combination of these values. The class that will be instantiated for that device is defined in mapTo="xxxx" - the configuration for the device can be defined in peripherals.xml as well. Have a look at system/peripherals.xml, where you can find the possible settings in the demo entry at the bottom. When a device is inserted and there are any settings with configurable="true" present for that device, these settings will be added to the settings dialog, under system->system->input->peripherals. - an example of how these settings can be used can be found in CPeripheralHID, which checks for a "keymap" setting and will automatically switch the keymap XBMC uses to the one that is defined in the setting. TODO: - keep separate configs when the same device is found more than once - general review of this code. --- .gitignore | 3 + Makefile.in | 20 +- README.linux | 2 +- README.ubuntu | 2 +- XBMC.xcodeproj/project.pbxproj | 154 +++++- .../720p/DialogPeripheralManager.xml | 381 ++++++++++++++ .../720p/DialogPeripheralSettings.xml | 183 +++++++ configure.in | 53 +- language/English/strings.xml | 24 + project/VS2010Express/XBMC.vcxproj | 31 +- project/VS2010Express/XBMC.vcxproj.filters | 107 +++- system/deviceidmappings.xml | 3 - system/peripherals.xml | 30 ++ xbmc/Application.cpp | 16 +- xbmc/GUIUserMessages.h | 3 + xbmc/guilib/Key.h | 2 + xbmc/input/KeyboardStat.cpp | 34 +- xbmc/input/KeyboardStat.h | 2 + xbmc/input/KeymapLoader.cpp | 96 ---- xbmc/input/Makefile | 1 - xbmc/interfaces/Builtins.cpp | 6 + xbmc/peripherals/Makefile | 6 + xbmc/peripherals/PeripheralTypes.h | 170 +++++++ xbmc/peripherals/Peripherals.cpp | 476 ++++++++++++++++++ xbmc/peripherals/Peripherals.h | 161 ++++++ xbmc/peripherals/bus/Makefile.in | 14 + xbmc/peripherals/bus/PeripheralBus.cpp | 336 +++++++++++++ xbmc/peripherals/bus/PeripheralBus.h | 191 +++++++ .../bus/linux/PeripheralBusUSB.cpp | 170 +++++++ xbmc/peripherals/bus/linux/PeripheralBusUSB.h | 65 +++ xbmc/peripherals/bus/osx/PeripheralBusUSB.cpp | 278 ++++++++++ xbmc/peripherals/bus/osx/PeripheralBusUSB.h | 58 +++ .../bus/win32/PeripheralBusUSB.cpp | 138 +++++ xbmc/peripherals/bus/win32/PeripheralBusUSB.h | 45 ++ xbmc/peripherals/devices/Makefile | 13 + xbmc/peripherals/devices/Peripheral.cpp | 474 +++++++++++++++++ xbmc/peripherals/devices/Peripheral.h | 169 +++++++ .../devices/PeripheralBluetooth.cpp | 31 ++ .../devices/PeripheralBluetooth.h} | 19 +- .../devices/PeripheralCecAdapter.cpp | 59 +++ .../devices/PeripheralCecAdapter.h | 40 ++ xbmc/peripherals/devices/PeripheralDisk.cpp | 31 ++ xbmc/peripherals/devices/PeripheralDisk.h | 33 ++ xbmc/peripherals/devices/PeripheralHID.cpp | 90 ++++ xbmc/peripherals/devices/PeripheralHID.h | 41 ++ xbmc/peripherals/devices/PeripheralNIC.cpp | 33 ++ xbmc/peripherals/devices/PeripheralNIC.h | 33 ++ .../devices/PeripheralNyxboard.cpp | 70 +++ xbmc/peripherals/devices/PeripheralNyxboard.h | 34 ++ xbmc/peripherals/devices/PeripheralTuner.cpp | 31 ++ xbmc/peripherals/devices/PeripheralTuner.h | 33 ++ .../dialogs/GUIDialogPeripheralManager.cpp | 206 ++++++++ .../dialogs/GUIDialogPeripheralManager.h | 59 +++ .../dialogs/GUIDialogPeripheralSettings.cpp | 222 ++++++++ .../dialogs/GUIDialogPeripheralSettings.h | 50 ++ xbmc/peripherals/dialogs/Makefile | 7 + xbmc/settings/GUIDialogSettings.cpp | 39 ++ xbmc/settings/GUIDialogSettings.h | 3 +- xbmc/settings/GUISettings.cpp | 13 +- xbmc/settings/GUISettings.h | 43 +- xbmc/settings/GUIWindowSettingsCategory.cpp | 10 + xbmc/video/windows/GUIWindowVideoBase.cpp | 5 +- xbmc/win32/WIN32USBScan.cpp | 74 --- xbmc/win32/WIN32USBScan.h | 5 - xbmc/windowing/osx/WinEventsOSX.h | 3 - xbmc/windowing/osx/WinEventsOSX.mm | 180 ------- xbmc/windowing/windows/WinEventsWin32.cpp | 14 +- 67 files changed, 4979 insertions(+), 449 deletions(-) create mode 100644 addons/skin.confluence/720p/DialogPeripheralManager.xml create mode 100644 addons/skin.confluence/720p/DialogPeripheralSettings.xml delete mode 100644 system/deviceidmappings.xml create mode 100644 system/peripherals.xml delete mode 100644 xbmc/input/KeymapLoader.cpp create mode 100644 xbmc/peripherals/Makefile create mode 100644 xbmc/peripherals/PeripheralTypes.h create mode 100644 xbmc/peripherals/Peripherals.cpp create mode 100644 xbmc/peripherals/Peripherals.h create mode 100644 xbmc/peripherals/bus/Makefile.in create mode 100644 xbmc/peripherals/bus/PeripheralBus.cpp create mode 100644 xbmc/peripherals/bus/PeripheralBus.h create mode 100644 xbmc/peripherals/bus/linux/PeripheralBusUSB.cpp create mode 100644 xbmc/peripherals/bus/linux/PeripheralBusUSB.h create mode 100644 xbmc/peripherals/bus/osx/PeripheralBusUSB.cpp create mode 100644 xbmc/peripherals/bus/osx/PeripheralBusUSB.h create mode 100644 xbmc/peripherals/bus/win32/PeripheralBusUSB.cpp create mode 100644 xbmc/peripherals/bus/win32/PeripheralBusUSB.h create mode 100644 xbmc/peripherals/devices/Makefile create mode 100644 xbmc/peripherals/devices/Peripheral.cpp create mode 100644 xbmc/peripherals/devices/Peripheral.h create mode 100644 xbmc/peripherals/devices/PeripheralBluetooth.cpp rename xbmc/{input/KeymapLoader.h => peripherals/devices/PeripheralBluetooth.h} (66%) create mode 100644 xbmc/peripherals/devices/PeripheralCecAdapter.cpp create mode 100644 xbmc/peripherals/devices/PeripheralCecAdapter.h create mode 100644 xbmc/peripherals/devices/PeripheralDisk.cpp create mode 100644 xbmc/peripherals/devices/PeripheralDisk.h create mode 100644 xbmc/peripherals/devices/PeripheralHID.cpp create mode 100644 xbmc/peripherals/devices/PeripheralHID.h create mode 100644 xbmc/peripherals/devices/PeripheralNIC.cpp create mode 100644 xbmc/peripherals/devices/PeripheralNIC.h create mode 100644 xbmc/peripherals/devices/PeripheralNyxboard.cpp create mode 100644 xbmc/peripherals/devices/PeripheralNyxboard.h create mode 100644 xbmc/peripherals/devices/PeripheralTuner.cpp create mode 100644 xbmc/peripherals/devices/PeripheralTuner.h create mode 100644 xbmc/peripherals/dialogs/GUIDialogPeripheralManager.cpp create mode 100644 xbmc/peripherals/dialogs/GUIDialogPeripheralManager.h create mode 100644 xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp create mode 100644 xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h create mode 100644 xbmc/peripherals/dialogs/Makefile delete mode 100644 xbmc/win32/WIN32USBScan.cpp delete mode 100644 xbmc/win32/WIN32USBScan.h diff --git a/.gitignore b/.gitignore index 04c277989ae5a..2969b015f6b99 100644 --- a/.gitignore +++ b/.gitignore @@ -125,6 +125,9 @@ config.log /xbmc/guilib/Profile /xbmc/guilib/Profile_FastCap +# /xbmc/peripherals/ +/xbmc/peripherals/bus/Makefile + # /lib/ /lib/Makefile diff --git a/Makefile.in b/Makefile.in index 1aecd71889ebf..aa956c6e1fca9 100644 --- a/Makefile.in +++ b/Makefile.in @@ -73,7 +73,11 @@ BIN_DIRS= \ xbmc/input/linux \ xbmc/osx \ xbmc/threads \ - xbmc/windowing + xbmc/windowing \ + xbmc/peripherals \ + xbmc/peripherals/bus \ + xbmc/peripherals/devices \ + xbmc/peripherals/dialogs ifeq (@USE_OPENGL@,1) BIN_DIRS += xbmc/rendering/gl @@ -348,6 +352,14 @@ xbmc/utils/utils.a: force $(MAKE) -C xbmc/utils xbmc/osx/osx.a: force $(MAKE) -C xbmc/osx +xbmc/peripherals/peripherals.a: force + $(MAKE) -C xbmc/peripherals +xbmc/peripherals/bus/peripheral-bus.a: force + $(MAKE) -C xbmc/peripherals/bus +xbmc/peripherals/devices/peripheral-devices.a: force + $(MAKE) -C xbmc/peripherals/devices +xbmc/peripherals/dialogs/peripheral-dialogs.a: force + $(MAKE) -C xbmc/peripherals/dialogs lib/libapetag/.libs/libapetag.a: force $(MAKE) -C lib/libapetag lib/cpluff/libcpluff/.libs/libcpluff.a: force @@ -482,7 +494,11 @@ OBJSXBMC= \ lib/libhts/libhts.a \ lib/xbmc-dll-symbols/dll-symbols.a \ xbmc/rendering/rendering.a \ - xbmc/windowing/windowing.a + xbmc/windowing/windowing.a \ + xbmc/peripherals/peripherals.a \ + xbmc/peripherals/bus/peripheral-bus.a \ + xbmc/peripherals/devices/peripheral-devices.a \ + xbmc/peripherals/dialogs/peripheral-dialogs.a ifeq (@USE_OPENGL@,1) OBJSXBMC += xbmc/rendering/gl/rendering_gl.a diff --git a/README.linux b/README.linux index 8d4c6ca1d109a..b361da6d85ab5 100644 --- a/README.linux +++ b/README.linux @@ -55,7 +55,7 @@ Build-Depends: debhelper (>= 7.0.50~), python-support, cmake, libbluetooth-dev, zlib1g-dev, libsmbclient-dev, libboost-thread-dev libiso9660-dev, libssl-dev, lsb-release, libvdpau-dev, libmicrohttpd-dev, libmodplug-dev, librtmp-dev, libcrystalhd-dev, curl, python-dev, libyajl-dev, - libplist-dev + libplist-dev, libusb-dev, libudev-dev *** For developers and anyone else who compiles frequently it is recommended to use ccache diff --git a/README.ubuntu b/README.ubuntu index 92af2e7dcb5d0..3d239a80562e4 100644 --- a/README.ubuntu +++ b/README.ubuntu @@ -44,7 +44,7 @@ Two methods exist to install the required Ubuntu packages: For Ubuntu (all versions >= 7.04): - # sudo apt-get install git-core make g++ gcc gawk pmount libtool nasm yasm automake cmake gperf zip unzip bison libsdl-dev libsdl-image1.2-dev libsdl-gfx1.2-dev libsdl-mixer1.2-dev libfribidi-dev liblzo2-dev libfreetype6-dev libsqlite3-dev libogg-dev libasound-dev python-sqlite libglew-dev libcurl3 libcurl4-gnutls-dev libxrandr-dev libxrender-dev libmad0-dev libogg-dev libvorbisenc2 libsmbclient-dev libmysqlclient-dev libpcre3-dev libdbus-1-dev libhal-dev libhal-storage-dev libjasper-dev libfontconfig-dev libbz2-dev libboost-dev libenca-dev libxt-dev libxmu-dev libpng-dev libjpeg-dev libpulse-dev mesa-utils libcdio-dev libsamplerate-dev libmpeg3-dev libflac-dev libiso9660-dev libass-dev libssl-dev fp-compiler gdc libmpeg2-4-dev libmicrohttpd-dev libmodplug-dev libssh-dev gettext cvs python-dev libyajl-dev libboost-thread-dev libplist-dev + # sudo apt-get install git-core make g++ gcc gawk pmount libtool nasm yasm automake cmake gperf zip unzip bison libsdl-dev libsdl-image1.2-dev libsdl-gfx1.2-dev libsdl-mixer1.2-dev libfribidi-dev liblzo2-dev libfreetype6-dev libsqlite3-dev libogg-dev libasound-dev python-sqlite libglew-dev libcurl3 libcurl4-gnutls-dev libxrandr-dev libxrender-dev libmad0-dev libogg-dev libvorbisenc2 libsmbclient-dev libmysqlclient-dev libpcre3-dev libdbus-1-dev libhal-dev libhal-storage-dev libjasper-dev libfontconfig-dev libbz2-dev libboost-dev libenca-dev libxt-dev libxmu-dev libpng-dev libjpeg-dev libpulse-dev mesa-utils libcdio-dev libsamplerate-dev libmpeg3-dev libflac-dev libiso9660-dev libass-dev libssl-dev fp-compiler gdc libmpeg2-4-dev libmicrohttpd-dev libmodplug-dev libssh-dev gettext cvs python-dev libyajl-dev libboost-thread-dev libplist-dev libusb-dev libudev-dev For Ubuntu Maverick (10.10): # sudo apt-get install autopoint diff --git a/XBMC.xcodeproj/project.pbxproj b/XBMC.xcodeproj/project.pbxproj index a7d63bd32027c..1b70b4e1bf5dc 100644 --- a/XBMC.xcodeproj/project.pbxproj +++ b/XBMC.xcodeproj/project.pbxproj @@ -68,8 +68,6 @@ 18B4A00B1152BFA5001AF8A6 /* Scraper.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B49FFC1152BFA5001AF8A6 /* Scraper.cpp */; }; 18B4A00C1152BFA5001AF8A6 /* ScreenSaver.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B49FFE1152BFA5001AF8A6 /* ScreenSaver.cpp */; }; 18B4A00D1152BFA5001AF8A6 /* Visualisation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B4A0001152BFA5001AF8A6 /* Visualisation.cpp */; }; - 18B7006113A697270009C1AF /* KeymapLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7005F13A697270009C1AF /* KeymapLoader.cpp */; }; - 18B7006213A697270009C1AF /* KeymapLoader.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7005F13A697270009C1AF /* KeymapLoader.cpp */; }; 18B700E113A6A5750009C1AF /* AddonVersion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B700DF13A6A5750009C1AF /* AddonVersion.cpp */; }; 18B700E213A6A5750009C1AF /* AddonVersion.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B700DF13A6A5750009C1AF /* AddonVersion.cpp */; }; 18B7C3841294203F009E7A26 /* AddonDatabase.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 18B7C3821294203F009E7A26 /* AddonDatabase.cpp */; }; @@ -1851,6 +1849,32 @@ F5DC888B110A654000EE1B15 /* libapetag.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F5DC888A110A654000EE1B15 /* libapetag.a */; }; F5DC888C110A654000EE1B15 /* libapetag.a in Frameworks */ = {isa = PBXBuildFile; fileRef = F5DC888A110A654000EE1B15 /* libapetag.a */; }; F5E10D381428426B00175026 /* JpegIO.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 32C631261423A90F00F18420 /* JpegIO.cpp */; }; + F5E10537140AA38100175026 /* PeripheralBusUSB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10513140AA38000175026 /* PeripheralBusUSB.cpp */; }; + F5E10538140AA38100175026 /* PeripheralBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10515140AA38000175026 /* PeripheralBus.cpp */; }; + F5E1053B140AA38100175026 /* Peripheral.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1051C140AA38000175026 /* Peripheral.cpp */; }; + F5E1053C140AA38100175026 /* PeripheralBluetooth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1051E140AA38000175026 /* PeripheralBluetooth.cpp */; }; + F5E1053D140AA38100175026 /* PeripheralCecAdapter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10520140AA38000175026 /* PeripheralCecAdapter.cpp */; }; + F5E1053E140AA38100175026 /* PeripheralDisk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10522140AA38000175026 /* PeripheralDisk.cpp */; }; + F5E1053F140AA38100175026 /* PeripheralHID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10524140AA38000175026 /* PeripheralHID.cpp */; }; + F5E10540140AA38100175026 /* PeripheralNIC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10526140AA38000175026 /* PeripheralNIC.cpp */; }; + F5E10541140AA38100175026 /* PeripheralNyxboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10528140AA38000175026 /* PeripheralNyxboard.cpp */; }; + F5E10542140AA38100175026 /* PeripheralTuner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1052A140AA38000175026 /* PeripheralTuner.cpp */; }; + F5E10543140AA38100175026 /* GUIDialogPeripheralManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1052D140AA38000175026 /* GUIDialogPeripheralManager.cpp */; }; + F5E10544140AA38100175026 /* GUIDialogPeripheralSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1052F140AA38000175026 /* GUIDialogPeripheralSettings.cpp */; }; + F5E10547140AA38100175026 /* Peripherals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10533140AA38000175026 /* Peripherals.cpp */; }; + F5E10549140AA38100175026 /* PeripheralBusUSB.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10513140AA38000175026 /* PeripheralBusUSB.cpp */; }; + F5E1054A140AA38100175026 /* PeripheralBus.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10515140AA38000175026 /* PeripheralBus.cpp */; }; + F5E1054D140AA38100175026 /* Peripheral.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1051C140AA38000175026 /* Peripheral.cpp */; }; + F5E1054E140AA38100175026 /* PeripheralBluetooth.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1051E140AA38000175026 /* PeripheralBluetooth.cpp */; }; + F5E1054F140AA38100175026 /* PeripheralCecAdapter.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10520140AA38000175026 /* PeripheralCecAdapter.cpp */; }; + F5E10550140AA38100175026 /* PeripheralDisk.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10522140AA38000175026 /* PeripheralDisk.cpp */; }; + F5E10551140AA38100175026 /* PeripheralHID.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10524140AA38000175026 /* PeripheralHID.cpp */; }; + F5E10552140AA38100175026 /* PeripheralNIC.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10526140AA38000175026 /* PeripheralNIC.cpp */; }; + F5E10553140AA38100175026 /* PeripheralNyxboard.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10528140AA38000175026 /* PeripheralNyxboard.cpp */; }; + F5E10554140AA38100175026 /* PeripheralTuner.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1052A140AA38000175026 /* PeripheralTuner.cpp */; }; + F5E10555140AA38100175026 /* GUIDialogPeripheralManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1052D140AA38000175026 /* GUIDialogPeripheralManager.cpp */; }; + F5E10556140AA38100175026 /* GUIDialogPeripheralSettings.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E1052F140AA38000175026 /* GUIDialogPeripheralSettings.cpp */; }; + F5E10559140AA38100175026 /* Peripherals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E10533140AA38000175026 /* Peripherals.cpp */; }; F5E55B5D10741272006E788A /* DVDPlayerTeletext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E55B5B10741272006E788A /* DVDPlayerTeletext.cpp */; }; F5E55B5E10741272006E788A /* DVDPlayerTeletext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E55B5B10741272006E788A /* DVDPlayerTeletext.cpp */; }; F5E55B66107412DE006E788A /* GUIDialogTeletext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = F5E55B65107412DE006E788A /* GUIDialogTeletext.cpp */; }; @@ -1943,8 +1967,6 @@ 18B49FFF1152BFA5001AF8A6 /* ScreenSaver.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ScreenSaver.h; sourceTree = ""; }; 18B4A0001152BFA5001AF8A6 /* Visualisation.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Visualisation.cpp; sourceTree = ""; }; 18B4A0011152BFA5001AF8A6 /* Visualisation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Visualisation.h; sourceTree = ""; }; - 18B7005F13A697270009C1AF /* KeymapLoader.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = KeymapLoader.cpp; sourceTree = ""; }; - 18B7006013A697270009C1AF /* KeymapLoader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KeymapLoader.h; sourceTree = ""; }; 18B700DF13A6A5750009C1AF /* AddonVersion.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AddonVersion.cpp; sourceTree = ""; }; 18B700E013A6A5750009C1AF /* AddonVersion.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddonVersion.h; sourceTree = ""; }; 18B7C3821294203F009E7A26 /* AddonDatabase.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = AddonDatabase.cpp; sourceTree = ""; }; @@ -3840,6 +3862,33 @@ F5DC87FF110A46C700EE1B15 /* ModplugCodec.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ModplugCodec.h; sourceTree = ""; }; F5DC8800110A46C700EE1B15 /* ModplugCodec.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ModplugCodec.cpp; sourceTree = ""; }; F5DC888A110A654000EE1B15 /* libapetag.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libapetag.a; path = lib/libapetag/.libs/libapetag.a; sourceTree = ""; }; + F5E10513140AA38000175026 /* PeripheralBusUSB.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralBusUSB.cpp; sourceTree = ""; }; + F5E10514140AA38000175026 /* PeripheralBusUSB.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralBusUSB.h; sourceTree = ""; }; + F5E10515140AA38000175026 /* PeripheralBus.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralBus.cpp; sourceTree = ""; }; + F5E10516140AA38000175026 /* PeripheralBus.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralBus.h; sourceTree = ""; }; + F5E1051C140AA38000175026 /* Peripheral.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Peripheral.cpp; sourceTree = ""; }; + F5E1051D140AA38000175026 /* Peripheral.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Peripheral.h; sourceTree = ""; }; + F5E1051E140AA38000175026 /* PeripheralBluetooth.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralBluetooth.cpp; sourceTree = ""; }; + F5E1051F140AA38000175026 /* PeripheralBluetooth.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralBluetooth.h; sourceTree = ""; }; + F5E10520140AA38000175026 /* PeripheralCecAdapter.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralCecAdapter.cpp; sourceTree = ""; }; + F5E10521140AA38000175026 /* PeripheralCecAdapter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralCecAdapter.h; sourceTree = ""; }; + F5E10522140AA38000175026 /* PeripheralDisk.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralDisk.cpp; sourceTree = ""; }; + F5E10523140AA38000175026 /* PeripheralDisk.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralDisk.h; sourceTree = ""; }; + F5E10524140AA38000175026 /* PeripheralHID.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralHID.cpp; sourceTree = ""; }; + F5E10525140AA38000175026 /* PeripheralHID.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralHID.h; sourceTree = ""; }; + F5E10526140AA38000175026 /* PeripheralNIC.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralNIC.cpp; sourceTree = ""; }; + F5E10527140AA38000175026 /* PeripheralNIC.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralNIC.h; sourceTree = ""; }; + F5E10528140AA38000175026 /* PeripheralNyxboard.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralNyxboard.cpp; sourceTree = ""; }; + F5E10529140AA38000175026 /* PeripheralNyxboard.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralNyxboard.h; sourceTree = ""; }; + F5E1052A140AA38000175026 /* PeripheralTuner.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = PeripheralTuner.cpp; sourceTree = ""; }; + F5E1052B140AA38000175026 /* PeripheralTuner.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralTuner.h; sourceTree = ""; }; + F5E1052D140AA38000175026 /* GUIDialogPeripheralManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogPeripheralManager.cpp; sourceTree = ""; }; + F5E1052E140AA38000175026 /* GUIDialogPeripheralManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogPeripheralManager.h; sourceTree = ""; }; + F5E1052F140AA38000175026 /* GUIDialogPeripheralSettings.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = GUIDialogPeripheralSettings.cpp; sourceTree = ""; }; + F5E10530140AA38000175026 /* GUIDialogPeripheralSettings.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogPeripheralSettings.h; sourceTree = ""; }; + F5E10533140AA38000175026 /* Peripherals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = Peripherals.cpp; sourceTree = ""; }; + F5E10534140AA38000175026 /* Peripherals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Peripherals.h; sourceTree = ""; }; + F5E10535140AA38000175026 /* PeripheralTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PeripheralTypes.h; sourceTree = ""; }; F5E55B5B10741272006E788A /* DVDPlayerTeletext.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DVDPlayerTeletext.cpp; sourceTree = ""; }; F5E55B5C10741272006E788A /* DVDPlayerTeletext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DVDPlayerTeletext.h; sourceTree = ""; }; F5E55B64107412DE006E788A /* GUIDialogTeletext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GUIDialogTeletext.h; sourceTree = ""; }; @@ -4347,8 +4396,6 @@ 18B7C8CE12942546009E7A26 /* KeyboardLayoutConfiguration.h */, 18B7C8CF12942546009E7A26 /* KeyboardStat.cpp */, 18B7C8D012942546009E7A26 /* KeyboardStat.h */, - 18B7005F13A697270009C1AF /* KeymapLoader.cpp */, - 18B7006013A697270009C1AF /* KeymapLoader.h */, 18B7C8D112942546009E7A26 /* MouseStat.cpp */, 18B7C8D212942546009E7A26 /* MouseStat.h */, 18B7C8D312942546009E7A26 /* SDLJoystick.cpp */, @@ -5028,6 +5075,7 @@ 18B7C853129423A7009E7A26 /* music */, 431376F212D6449100680C15 /* network */, E37D5CB40D3023BB0081D327 /* osx */, + F5E1050C140AA38000175026 /* peripherals */, 4313767E12D63EC200680C15 /* pictures */, 18B7C91B129428CA009E7A26 /* playlists */, 430C880812D649B10098821A /* powermanagement */, @@ -6959,6 +7007,72 @@ path = "json-rpc"; sourceTree = ""; }; + F5E1050C140AA38000175026 /* peripherals */ = { + isa = PBXGroup; + children = ( + F5E1050D140AA38000175026 /* bus */, + F5E1051A140AA38000175026 /* devices */, + F5E1052C140AA38000175026 /* dialogs */, + F5E10533140AA38000175026 /* Peripherals.cpp */, + F5E10534140AA38000175026 /* Peripherals.h */, + F5E10535140AA38000175026 /* PeripheralTypes.h */, + ); + path = peripherals; + sourceTree = ""; + }; + F5E1050D140AA38000175026 /* bus */ = { + isa = PBXGroup; + children = ( + F5E10512140AA38000175026 /* osx */, + F5E10515140AA38000175026 /* PeripheralBus.cpp */, + F5E10516140AA38000175026 /* PeripheralBus.h */, + ); + path = bus; + sourceTree = ""; + }; + F5E10512140AA38000175026 /* osx */ = { + isa = PBXGroup; + children = ( + F5E10513140AA38000175026 /* PeripheralBusUSB.cpp */, + F5E10514140AA38000175026 /* PeripheralBusUSB.h */, + ); + path = osx; + sourceTree = ""; + }; + F5E1051A140AA38000175026 /* devices */ = { + isa = PBXGroup; + children = ( + F5E1051C140AA38000175026 /* Peripheral.cpp */, + F5E1051D140AA38000175026 /* Peripheral.h */, + F5E1051E140AA38000175026 /* PeripheralBluetooth.cpp */, + F5E1051F140AA38000175026 /* PeripheralBluetooth.h */, + F5E10520140AA38000175026 /* PeripheralCecAdapter.cpp */, + F5E10521140AA38000175026 /* PeripheralCecAdapter.h */, + F5E10522140AA38000175026 /* PeripheralDisk.cpp */, + F5E10523140AA38000175026 /* PeripheralDisk.h */, + F5E10524140AA38000175026 /* PeripheralHID.cpp */, + F5E10525140AA38000175026 /* PeripheralHID.h */, + F5E10526140AA38000175026 /* PeripheralNIC.cpp */, + F5E10527140AA38000175026 /* PeripheralNIC.h */, + F5E10528140AA38000175026 /* PeripheralNyxboard.cpp */, + F5E10529140AA38000175026 /* PeripheralNyxboard.h */, + F5E1052A140AA38000175026 /* PeripheralTuner.cpp */, + F5E1052B140AA38000175026 /* PeripheralTuner.h */, + ); + path = devices; + sourceTree = ""; + }; + F5E1052C140AA38000175026 /* dialogs */ = { + isa = PBXGroup; + children = ( + F5E1052D140AA38000175026 /* GUIDialogPeripheralManager.cpp */, + F5E1052E140AA38000175026 /* GUIDialogPeripheralManager.h */, + F5E1052F140AA38000175026 /* GUIDialogPeripheralSettings.cpp */, + F5E10530140AA38000175026 /* GUIDialogPeripheralSettings.h */, + ); + path = dialogs; + sourceTree = ""; + }; F5E55E601076B34F006E788A /* libsquish */ = { isa = PBXGroup; children = ( @@ -8114,7 +8228,6 @@ 1840B74D13993D8A007C848B /* JSONVariantParser.cpp in Sources */, 1840B75313993DA0007C848B /* JSONVariantWriter.cpp in Sources */, 7C0A7EC013A5DBCE00AFC2BD /* AppParamParser.cpp in Sources */, - 18B7006113A697270009C1AF /* KeymapLoader.cpp in Sources */, 18B700E113A6A5750009C1AF /* AddonVersion.cpp in Sources */, F558F25613ABCF7800631E12 /* WinEventsOSX.mm in Sources */, F558F27B13ABD56600631E12 /* DirtyRegionSolvers.cpp in Sources */, @@ -8143,6 +8256,19 @@ DF44845E140048C80069344B /* PipesManager.cpp in Sources */, DF4484EE140054530069344B /* BXAcodec.cpp in Sources */, DF98D98C1434F47D00A6EBE1 /* SkinVariable.cpp in Sources */, + F5E10537140AA38100175026 /* PeripheralBusUSB.cpp in Sources */, + F5E10538140AA38100175026 /* PeripheralBus.cpp in Sources */, + F5E1053B140AA38100175026 /* Peripheral.cpp in Sources */, + F5E1053C140AA38100175026 /* PeripheralBluetooth.cpp in Sources */, + F5E1053D140AA38100175026 /* PeripheralCecAdapter.cpp in Sources */, + F5E1053E140AA38100175026 /* PeripheralDisk.cpp in Sources */, + F5E1053F140AA38100175026 /* PeripheralHID.cpp in Sources */, + F5E10540140AA38100175026 /* PeripheralNIC.cpp in Sources */, + F5E10541140AA38100175026 /* PeripheralNyxboard.cpp in Sources */, + F5E10542140AA38100175026 /* PeripheralTuner.cpp in Sources */, + F5E10543140AA38100175026 /* GUIDialogPeripheralManager.cpp in Sources */, + F5E10544140AA38100175026 /* GUIDialogPeripheralSettings.cpp in Sources */, + F5E10547140AA38100175026 /* Peripherals.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -9018,7 +9144,6 @@ 1840B74E13993D8A007C848B /* JSONVariantParser.cpp in Sources */, 1840B75413993DA0007C848B /* JSONVariantWriter.cpp in Sources */, 7C0A7EC113A5DBCE00AFC2BD /* AppParamParser.cpp in Sources */, - 18B7006213A697270009C1AF /* KeymapLoader.cpp in Sources */, 18B700E213A6A5750009C1AF /* AddonVersion.cpp in Sources */, F558F25713ABCF7800631E12 /* WinEventsOSX.mm in Sources */, F558F27C13ABD56600631E12 /* DirtyRegionSolvers.cpp in Sources */, @@ -9047,6 +9172,19 @@ DF448460140048C80069344B /* PipesManager.cpp in Sources */, DF4484EF140054530069344B /* BXAcodec.cpp in Sources */, DF98D98D1434F47D00A6EBE1 /* SkinVariable.cpp in Sources */, + F5E10549140AA38100175026 /* PeripheralBusUSB.cpp in Sources */, + F5E1054A140AA38100175026 /* PeripheralBus.cpp in Sources */, + F5E1054D140AA38100175026 /* Peripheral.cpp in Sources */, + F5E1054E140AA38100175026 /* PeripheralBluetooth.cpp in Sources */, + F5E1054F140AA38100175026 /* PeripheralCecAdapter.cpp in Sources */, + F5E10550140AA38100175026 /* PeripheralDisk.cpp in Sources */, + F5E10551140AA38100175026 /* PeripheralHID.cpp in Sources */, + F5E10552140AA38100175026 /* PeripheralNIC.cpp in Sources */, + F5E10553140AA38100175026 /* PeripheralNyxboard.cpp in Sources */, + F5E10554140AA38100175026 /* PeripheralTuner.cpp in Sources */, + F5E10555140AA38100175026 /* GUIDialogPeripheralManager.cpp in Sources */, + F5E10556140AA38100175026 /* GUIDialogPeripheralSettings.cpp in Sources */, + F5E10559140AA38100175026 /* Peripherals.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/addons/skin.confluence/720p/DialogPeripheralManager.xml b/addons/skin.confluence/720p/DialogPeripheralManager.xml new file mode 100644 index 0000000000000..16195d97cad01 --- /dev/null +++ b/addons/skin.confluence/720p/DialogPeripheralManager.xml @@ -0,0 +1,381 @@ + + 20 + no + + 1 + 190 + 30 + + dialogeffect + + + + 0 + 0 + 900 + 660 + DialogBack.png + + + Dialog Header image + 40 + 16 + 820 + 40 + dialogheader.png + + + header label + 40 + 20 + 820 + 30 + font13_title + + center + center + selected + black + + + header label + 40 + 20 + 820 + 30 + font13_title + + center + center + selected + black + + + Close Window button + 810 + 15 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 10 + 10 + 10 + 10 + system.getbool(input.enablemouse) + + + + Peripheral list + 20 + 70 + + peripheral option header + 130 + 0 + 380 + 20 + font12_title + + left + center + blue + black + + + 0 + 40 + 25 + 445 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 9000 + 20 + false + vertical + + + 25 + 35 + 330 + 440 + button-nofocus.png + + + + 30 + 40 + 320 + 445 + 20 + 20 + 60 + 9000 + 60 + 200 + + + 0 + 0 + 320 + 40 + button-nofocus.png + + + 10 + 0 + 320 + 40 + font12 + left + center + grey2 + selected + ListItem.Label + + + + + 0 + 0 + 320 + 40 + button-nofocus.png + !Control.HasFocus(20) + + + 0 + 0 + 320 + 40 + button-focus2.png + Control.HasFocus(20) + + + 10 + 0 + 320 + 40 + font12 + left + center + white + selected + ListItem.Label + + + + + + Page Count Label + 80 + 480 + 420 + 20 + font12 + grey + false + center + center + + + + + + + 400 + 70 + + peripheral option header + 150 + 0 + 380 + 20 + font12_title + + left + center + blue + black + + + + name + 0 + 35 + 380 + 20 + + left + center + font12 + blue + black + + + name value + 150 + 35 + 330 + 20 + + left + center + font12 + true + black + + + + location + 0 + 60 + 380 + 20 + + left + center + font12 + blue + black + + + location value + 150 + 60 + 330 + 20 + + left + center + font12 + true + black + + + + class + 0 + 85 + 380 + 20 + + left + center + font12 + blue + black + + + class value + 150 + 85 + 330 + 20 + + left + center + font12 + true + black + + + + vendor + 0 + 110 + 380 + 20 + + left + center + font12 + blue + black + + + vendor value + 150 + 110 + 330 + 20 + + left + center + font12 + true + black + + + + product + 0 + 135 + 380 + 20 + + left + center + font12 + blue + black + + + product value + 150 + 135 + 330 + 20 + + left + center + font12 + true + black + + + + + + + 70 + 590 + + Close Button + 0 + 100 + 200 + 40 + center + center + font12_title + + 11 + 11 + 20 + 20 + + + Settings Button + 0 + 400 + 200 + 40 + center + center + font12_title + + 10 + 10 + 20 + 20 + + + + diff --git a/addons/skin.confluence/720p/DialogPeripheralSettings.xml b/addons/skin.confluence/720p/DialogPeripheralSettings.xml new file mode 100644 index 0000000000000..df089c1764706 --- /dev/null +++ b/addons/skin.confluence/720p/DialogPeripheralSettings.xml @@ -0,0 +1,183 @@ + + 5 + + 1 + 240 + 60 + + dialogeffect + + + Conditional + + background image + 0 + 0 + 800 + 600 + DialogBack2.png + + + Dialog Header image + 40 + 16 + 720 + 40 + dialogheader.png + + + Close Window button + 710 + 15 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 2 + 2 + 2 + 2 + system.getbool(input.enablemouse) + + + No Settings Label + 20 + 180 + 760 + center + + font13caps + + + control area + 40 + 65 + 720 + 490 + 5 + 60 + 9000 + 60 + 5 + 5 + + + 760 + 65 + 25 + 450 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 5 + 9000 + 61 + 61 + true + vertical + + + + Default Slider + 40 + button-nofocus.png + button-focus2.png + font13 + grey2 + white + + + Default Button + 0 + 0 + 40 + font13 + grey2 + white + button-focus2.png + + + Default RadioButton + 0 + 0 + 40 + font13 + grey2 + white + button-focus2.png + + + Default SpinControlex + 0 + 0 + 40 + font13 + grey2 + white + button-nofocus.png + button-focus2.png + center + yes + + + separator image + 2 + separator2.png + + + + 50 + 530 + + Cancel Button + 0 + 0 + 200 + 40 + center + center + font12_title + + 50 + 28 + 5 + 5 + + + OK Button + 0 + 250 + 200 + 40 + center + center + font12_title + + 29 + 50 + 5 + 5 + + + Defaults Button + 0 + 500 + 200 + 40 + center + center + font12_title + + 28 + 29 + 5 + 5 + + + + diff --git a/configure.in b/configure.in index 08ef959902f7d..5f6fc78f3f967 100755 --- a/configure.in +++ b/configure.in @@ -119,6 +119,10 @@ libplist_disabled="== AirPlay support disabled. ==" alsa_not_found="== Could not find ALSA. ALSA support disabled. ==" dbus_not_found="== Could not find DBUS. DBUS support disabled. ==" +udev_not_found="== Could not find libudev. Will use polling to check for device changes. ==" +udev_disabled="== udev support disabled. Will use polling to check for device changes. ==" +libusb_not_found="== Could not find libusb. Plug and play USB device support will not be available. ==" +libusb_disabled="== libusb disabled. Plug and play USB device support will not be available. ==" # External library message strings external_libraries_enabled="== Use of all supported external libraries enabled. ==" @@ -378,6 +382,18 @@ AC_ARG_WITH([lirc-device], [lirc_device=/dev/lircd]) AC_DEFINE_UNQUOTED([LIRC_DEVICE], ["$lirc_device"], [Default LIRC device]) +AC_ARG_ENABLE([udev], + [AS_HELP_STRING([--enable-udev], + [enable udev support (default is yes)])], + [use_udev=$enableval], + [use_udev=yes]) + +AC_ARG_ENABLE([libusb], + [AS_HELP_STRING([--enable-libusb], + [enable libusb support (default is yes)])], + [use_libusb=$enableval], + [use_libusb=yes]) + ### External libraries options AC_ARG_ENABLE([external-libraries], [AS_HELP_STRING([--enable-external-libraries], @@ -1050,6 +1066,39 @@ if test "x$use_airtunes" != "xno"; then fi fi +# udev +if test "$host_vendor" = "apple" ; then + use_udev="no" + AC_MSG_NOTICE($udev_disabled) +else + if test "$use_udev" = "yes" ; then + PKG_CHECK_MODULES([UDEV], [libudev], + [INCLUDES="$INCLUDES $UDEV_CFLAGS"; LIBS="$LIBS $UDEV_LIBS"]; \ + AC_DEFINE([HAVE_LIBUDEV],[1],["Define to 1 if libudev is installed"]), + use_udev="no";AC_MSG_ERROR($udev_not_found)) + else + AC_MSG_NOTICE($udev_disabled) + fi +fi + +# libusb +if test "$host_vendor" = "apple" ; then + use_libusb="no" + HAVE_LIBUSB=0 + AC_MSG_NOTICE($libusb_disabled) +else + if test "$use_libusb" = "yes" ; then + PKG_CHECK_MODULES([USB], [libusb], + [INCLUDES="$INCLUDES $USB_CFLAGS"; LIBS="$LIBS $USB_LIBS"; HAVE_LIBUSB=1]; \ + AC_DEFINE([HAVE_LIBUSB],[1],["Define to 1 if libusb is installed"]), + use_libusb="no"; HAVE_LIBUSB=0; AC_MSG_ERROR($libusb_not_found)) + else + use_libusb="no" + HAVE_LIBUSB=0 + AC_MSG_NOTICE($libusb_disabled) + fi +fi + ### External libraries checks # External FFmpeg if test "$use_external_ffmpeg" = "yes"; then @@ -1729,7 +1778,8 @@ OUTPUT_FILES="Makefile \ tools/Linux/xbmc.sh \ tools/Linux/xbmc-standalone.sh \ tools/TexturePacker/Makefile \ - tools/EventClients/Clients/OSXRemote/Makefile" + tools/EventClients/Clients/OSXRemote/Makefile \ + xbmc/peripherals/bus/Makefile" # Line below is used so we can use AM_INIT_AUTOMAKE. The corresponding # .dummy.am does nothing. @@ -1781,6 +1831,7 @@ AC_SUBST(USE_TEXTUREPACKER) AC_SUBST(USE_TEXTUREPACKER_NATIVE) AC_SUBST(USE_TEXTUREPACKER_NATIVE_ROOT) AC_SUBST(USE_AIRTUNES) +AC_SUBST(HAVE_LIBUSB) # pushd and popd are not available in other shells besides bash, so implement # our own pushd/popd functions diff --git a/language/English/strings.xml b/language/English/strings.xml index f3095f803de36..6bcb702ba0b4d 100644 --- a/language/English/strings.xml +++ b/language/English/strings.xml @@ -2351,4 +2351,28 @@ Can't find a next item to play Can't find a previous item to play + + Peripherals + + Generic HID device + Generic network adapter + Generic disk + There are no settings available for this peripheral. + New device configured + Device removed + Keymap to use for this device + Keymap enabled + + Location + Class + Name + Vendor + Product ID + + Pulse-Eight CEC adapter + Pulse-Eight Nyxboard + Switch to keyboard side command + Switch to remote side command + Press "user" button command + Enable switch side commands diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index 51afad2f84c8e..19b6aa2dcd0b0 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -451,7 +451,6 @@ - @@ -676,6 +675,19 @@ + + + + + + + + + + + + + @@ -837,7 +849,6 @@ - @@ -1371,7 +1382,6 @@ - @@ -1518,6 +1528,20 @@ + + + + + + + + + + + + + + @@ -1687,7 +1711,6 @@ - update_git_rev.bat diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters index 69354d64f4817..8b6e188acf0d2 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters @@ -238,6 +238,18 @@ {cea579fc-bdd7-499e-a6a6-07d681d1ab24} + + {43fa1d09-88f3-4c03-92f4-27ce109a0b1f} + + + {387fb53b-4497-4e2b-a37d-2efa9db0fce8} + + + {a3fe63d5-92eb-47e6-90f6-40b6e25d11d2} + + + {9571e2bc-891d-4496-bcba-2ec3eed45704} + @@ -1811,12 +1823,6 @@ settings - - win32 - - - input - storage @@ -2505,6 +2511,45 @@ interfaces\info + + peripherals + + + peripherals\bus + + + peripherals\devices + + + peripherals\devices + + + peripherals\devices + + + peripherals\devices + + + peripherals\devices + + + peripherals\devices + + + peripherals\bus + + + peripherals\devices + + + peripherals\devices + + + peripherals\dialogs + + + peripherals\dialogs + @@ -4315,12 +4360,6 @@ settings - - win32 - - - input - storage @@ -5033,6 +5072,48 @@ interfaces\info + + peripherals + + + peripherals\bus + + + peripherals\devices + + + peripherals\devices + + + peripherals\devices + + + peripherals\devices + + + peripherals\devices + + + peripherals\devices + + + peripherals\bus + + + peripherals + + + peripherals\devices + + + peripherals\devices + + + peripherals\dialogs + + + peripherals\dialogs + @@ -5044,4 +5125,4 @@ win32 - \ No newline at end of file + diff --git a/system/deviceidmappings.xml b/system/deviceidmappings.xml deleted file mode 100644 index 7114170a6d4e8..0000000000000 --- a/system/deviceidmappings.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/system/peripherals.xml b/system/peripherals.xml new file mode 100644 index 0000000000000..d410f433c7bc2 --- /dev/null +++ b/system/peripherals.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index d67875d68d70f..af7e60573136d 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -148,6 +148,9 @@ #include "cores/dvdplayer/DVDCodecs/Video/CrystalHD.h" #endif #include "interfaces/AnnouncementManager.h" +#include "peripherals/Peripherals.h" +#include "peripherals/dialogs/GUIDialogPeripheralManager.h" +#include "peripherals/dialogs/GUIDialogPeripheralSettings.h" // Windows includes #include "guilib/GUIWindowManager.h" @@ -252,7 +255,6 @@ #ifdef _WIN32 #include #include "win32util.h" -#include "win32/WIN32USBScan.h" #endif #ifdef HAS_XRANDR #include "windowing/X11/XRandR.h" @@ -309,6 +311,7 @@ using namespace DBUSSERVER; using namespace JSONRPC; #endif using namespace ANNOUNCEMENT; +using namespace PERIPHERALS; using namespace XbmcThreads; @@ -612,10 +615,6 @@ bool CApplication::Create() g_powerManager.Initialize(); -#ifdef _WIN32 - CWIN32USBScan(); -#endif - CLog::Log(LOGNOTICE, "load settings..."); g_guiSettings.Initialize(); // Initialize default Settings - don't move @@ -661,6 +660,8 @@ bool CApplication::Create() FatalErrorHandler(true, true, true); } + g_peripherals.Initialise(); + // Create the Mouse, Keyboard, Remote, and Joystick devices // Initialize after loading settings to get joystick deadzone setting g_Mouse.Initialize(); @@ -1121,6 +1122,9 @@ bool CApplication::Initialize() g_windowManager.Add(new CGUIDialogPlayEject); + g_windowManager.Add(new CGUIDialogPeripheralManager); + g_windowManager.Add(new CGUIDialogPeripheralSettings); + g_windowManager.Add(new CGUIWindowMusicPlayList); // window id = 500 g_windowManager.Add(new CGUIWindowMusicSongs); // window id = 501 g_windowManager.Add(new CGUIWindowMusicNav); // window id = 502 @@ -1579,6 +1583,8 @@ void CApplication::StopServices() CLog::Log(LOGNOTICE, "stop dvd detect media"); m_DetectDVDType.StopThread(); #endif + + g_peripherals.Clear(); } void CApplication::ReloadSkin() diff --git a/xbmc/GUIUserMessages.h b/xbmc/GUIUserMessages.h index e73ab0adbb06f..c5f100c9ad039 100644 --- a/xbmc/GUIUserMessages.h +++ b/xbmc/GUIUserMessages.h @@ -124,3 +124,6 @@ // Sent from filesystem if a path is known to have changed #define GUI_MSG_UPDATE_PATH GUI_MSG_USER + 33 + +// Sent to tell window to initiate a search dialog +#define GUI_MSG_SEARCH GUI_MSG_USER + 34 diff --git a/xbmc/guilib/Key.h b/xbmc/guilib/Key.h index b900577feda2c..aa0e7ae51b902 100644 --- a/xbmc/guilib/Key.h +++ b/xbmc/guilib/Key.h @@ -381,6 +381,8 @@ #define WINDOW_DIALOG_ADDON_INFO 10146 #define WINDOW_DIALOG_TEXT_VIEWER 10147 #define WINDOW_DIALOG_PLAY_EJECT 10148 +#define WINDOW_DIALOG_PERIPHERAL_MANAGER 10149 +#define WINDOW_DIALOG_PERIPHERAL_SETTINGS 10150 #define WINDOW_MUSIC_PLAYLIST 10500 #define WINDOW_MUSIC_FILES 10501 diff --git a/xbmc/input/KeyboardStat.cpp b/xbmc/input/KeyboardStat.cpp index 7afed1d6b3c5d..158dbb1d5da81 100644 --- a/xbmc/input/KeyboardStat.cpp +++ b/xbmc/input/KeyboardStat.cpp @@ -29,6 +29,16 @@ #include "windowing/XBMC_events.h" #include "utils/TimeUtils.h" #include "input/XBMC_keytable.h" +#include "peripherals/Peripherals.h" +#include "peripherals/devices/PeripheralHID.h" + +#if defined(_LINUX) && !defined(__APPLE__) +#include +#include +#endif + +using namespace std; +using namespace PERIPHERALS; CKeyboardStat g_Keyboard; @@ -46,6 +56,20 @@ void CKeyboardStat::Initialize() { } +bool CKeyboardStat::LookupSymAndUnicodePeripherals(XBMC_keysym &keysym, uint8_t *key, char *unicode) +{ + vector hidDevices; + g_peripherals.GetPeripheralsWithFeature(hidDevices, FEATURE_HID); + for (unsigned int iDevicePtr = 0; iDevicePtr < hidDevices.size(); iDevicePtr++) + { + CPeripheralHID *hidDevice = (CPeripheralHID *) hidDevices.at(iDevicePtr); + if (hidDevice && hidDevice->LookupSymAndUnicode(keysym, key, unicode)) + return true; + } + + return false; +} + const CKey CKeyboardStat::ProcessKeyDown(XBMC_keysym& keysym) { uint8_t vkey; wchar_t unicode; @@ -74,9 +98,15 @@ const CKey CKeyboardStat::ProcessKeyDown(XBMC_keysym& keysym) vkey = 0; held = 0; - // Start by trying to match both the sym and unicode. This will identify + // Start by check whether any of the HID peripherals wants to translate this keypress + if (LookupSymAndUnicodePeripherals(keysym, &vkey, &ascii)) + { + CLog::Log(LOGDEBUG, "%s - keypress translated by a HID peripheral", __FUNCTION__); + } + + // Continue by trying to match both the sym and unicode. This will identify // the majority of keypresses - if (KeyTableLookupSymAndUnicode(keysym.sym, keysym.unicode, &keytable)) + else if (KeyTableLookupSymAndUnicode(keysym.sym, keysym.unicode, &keytable)) { vkey = keytable.vkey; ascii = keytable.ascii; diff --git a/xbmc/input/KeyboardStat.h b/xbmc/input/KeyboardStat.h index 9d00809e8329a..d663fe8e868e5 100644 --- a/xbmc/input/KeyboardStat.h +++ b/xbmc/input/KeyboardStat.h @@ -55,6 +55,8 @@ class CKeyboardStat CStdString GetKeyName(int KeyID); private: + bool LookupSymAndUnicodePeripherals(XBMC_keysym &keysym, uint8_t *key, char *unicode); + XBMC_keysym m_lastKeysym; unsigned int m_lastKeyTime; }; diff --git a/xbmc/input/KeymapLoader.cpp b/xbmc/input/KeymapLoader.cpp deleted file mode 100644 index 031c9b3ea7d1b..0000000000000 --- a/xbmc/input/KeymapLoader.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (C) 2005-2011 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, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "KeymapLoader.h" -#include "filesystem/File.h" -#include "settings/Settings.h" -#include "utils/log.h" -#include "utils/XMLUtils.h" - -using namespace std; -using namespace XFILE; - -static std::map deviceMappings; -bool CKeymapLoader::parsedMappings = false; - -void CKeymapLoader::DeviceAdded(const CStdString& deviceId) -{ - ParseDeviceMappings(); - CStdString keymapName; - if (CKeymapLoader::FindMappedDevice(deviceId, keymapName)) - { - CLog::Log(LOGDEBUG, "Switching Active Keymapping to: %s", keymapName.c_str()); - g_settings.m_activeKeyboardMapping = keymapName; - } -} - -void CKeymapLoader::DeviceRemoved(const CStdString& deviceId) -{ - ParseDeviceMappings(); - CStdString keymapName; - if (FindMappedDevice(deviceId, keymapName)) - { - CLog::Log(LOGDEBUG, "Switching Active Keymapping to: default"); - g_settings.m_activeKeyboardMapping = "default"; - } -} - -void CKeymapLoader::ParseDeviceMappings() -{ - if (!parsedMappings) - { - parsedMappings = true; - CStdString file("special://xbmc/system/deviceidmappings.xml"); - TiXmlDocument deviceXML; - if (!CFile::Exists(file) || !deviceXML.LoadFile(file)) - return; - - TiXmlElement *pRootElement = deviceXML.RootElement(); - if (!pRootElement || strcmpi(pRootElement->Value(), "devicemappings") != 0) - return; - - TiXmlElement *pDevice = pRootElement->FirstChildElement("device"); - while (pDevice) - { - CStdString deviceId(pDevice->Attribute("id")); - CStdString keymap(pDevice->Attribute("keymap")); - if (!deviceId.empty() && !keymap.empty()) - deviceMappings.insert(pair(deviceId.ToUpper(), keymap)); - pDevice = pDevice->NextSiblingElement("device"); - } - } -} - -bool CKeymapLoader::FindMappedDevice(const CStdString& deviceId, CStdString& keymapName) -{ - CStdString deviceIdTemp = deviceId; - std::map::iterator deviceIdIt = deviceMappings.find(deviceIdTemp.ToUpper()); - if (deviceIdIt == deviceMappings.end()) - return false; - - keymapName = deviceIdIt->second; - return true; -} - -CStdString CKeymapLoader::ParseWin32HIDName(const CStdString& deviceLongName) -{ - return deviceLongName.Mid(deviceLongName.find_last_of('\\')+1, deviceLongName.find_last_of('#') - deviceLongName.find_last_of('\\')); -} \ No newline at end of file diff --git a/xbmc/input/Makefile b/xbmc/input/Makefile index 6221f4a133f31..f74c2b3c65977 100644 --- a/xbmc/input/Makefile +++ b/xbmc/input/Makefile @@ -2,7 +2,6 @@ SRCS=ButtonTranslator.cpp \ InertialScrollingHandler.cpp \ KeyboardLayoutConfiguration.cpp \ KeyboardStat.cpp \ - KeymapLoader.cpp \ MouseStat.cpp \ SDLJoystick.cpp \ XBMC_keytable.cpp \ diff --git a/xbmc/interfaces/Builtins.cpp b/xbmc/interfaces/Builtins.cpp index f191d21f71431..23641d55a5375 100644 --- a/xbmc/interfaces/Builtins.cpp +++ b/xbmc/interfaces/Builtins.cpp @@ -205,6 +205,7 @@ const BUILT_IN commands[] = { { "LCD.Suspend", false, "Suspends LCDproc" }, { "LCD.Resume", false, "Resumes LCDproc" }, #endif + { "VideoLibrary.Search", false, "Brings up a search dialog which will search the library" }, }; bool CBuiltins::HasCommand(const CStdString& execString) @@ -1539,6 +1540,11 @@ int CBuiltins::Execute(const CStdString& execString) CGUIMessage msg(GUI_MSG_MOVE_OFFSET, 0, 0, 0); g_windowManager.SendMessage(msg, WINDOW_WEATHER); } + else if (execute.Equals("videolibrary.search")) + { + CGUIMessage msg(GUI_MSG_SEARCH, 0, 0, 0); + g_windowManager.SendMessage(msg, WINDOW_VIDEO_NAV); + } else return -1; return 0; diff --git a/xbmc/peripherals/Makefile b/xbmc/peripherals/Makefile new file mode 100644 index 0000000000000..754a2c5de3434 --- /dev/null +++ b/xbmc/peripherals/Makefile @@ -0,0 +1,6 @@ +SRCS=Peripherals.cpp + +LIB=peripherals.a + +include ../../Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/peripherals/PeripheralTypes.h b/xbmc/peripherals/PeripheralTypes.h new file mode 100644 index 0000000000000..9323325cf2585 --- /dev/null +++ b/xbmc/peripherals/PeripheralTypes.h @@ -0,0 +1,170 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include +#ifdef _WIN32 +#include "PlatformDefs.h" +#endif +#include "utils/StdString.h" + +class CSetting; + +namespace PERIPHERALS +{ + enum PeripheralBusType + { + PERIPHERAL_BUS_UNKNOWN = 0, + PERIPHERAL_BUS_USB, + PERIPHERAL_BUS_PCI + }; + + enum PeripheralFeature + { + FEATURE_UNKNOWN = 0, + FEATURE_HID, + FEATURE_NIC, + FEATURE_DISK, + FEATURE_NYXBOARD, + FEATURE_CEC, + FEATURE_BLUETOOTH, + FEATURE_TUNER + }; + + enum PeripheralType + { + PERIPHERAL_UNKNOWN = 0, + PERIPHERAL_HID, + PERIPHERAL_NIC, + PERIPHERAL_DISK, + PERIPHERAL_NYXBOARD, + PERIPHERAL_CEC, + PERIPHERAL_BLUETOOTH, + PERIPHERAL_TUNER + }; + + struct PeripheralDeviceMapping + { + int m_iVendorId; + int m_iProductId; + PeripheralBusType m_busType; + PeripheralType m_class; + CStdString m_strDeviceName; + PeripheralType m_mappedTo; + std::map m_settings; + }; + + class PeripheralTypeTranslator + { + public: + static const char *TypeToString(const PeripheralType type) + { + switch (type) + { + case PERIPHERAL_BLUETOOTH: + return "bluetooth"; + case PERIPHERAL_CEC: + return "cec"; + case PERIPHERAL_DISK: + return "disk"; + case PERIPHERAL_HID: + return "hid"; + case PERIPHERAL_NIC: + return "nic"; + case PERIPHERAL_NYXBOARD: + return "nyxboard"; + case PERIPHERAL_TUNER: + return "tuner"; + default: + return "unknown"; + } + }; + + static PeripheralType GetTypeFromString(const CStdString &strType) + { + CStdString strTypeLowerCase(strType); + strTypeLowerCase.ToLower(); + + if (strTypeLowerCase.Equals("bluetooth")) + return PERIPHERAL_BLUETOOTH; + else if (strTypeLowerCase.Equals("cec")) + return PERIPHERAL_CEC; + else if (strTypeLowerCase.Equals("disk")) + return PERIPHERAL_DISK; + else if (strTypeLowerCase.Equals("hid")) + return PERIPHERAL_HID; + else if (strTypeLowerCase.Equals("nic")) + return PERIPHERAL_NIC; + else if (strTypeLowerCase.Equals("nyxboard")) + return PERIPHERAL_NYXBOARD; + else if (strTypeLowerCase.Equals("tuner")) + return PERIPHERAL_TUNER; + + return PERIPHERAL_UNKNOWN; + }; + + static const char *BusTypeToString(const PeripheralBusType type) + { + switch(type) + { + case PERIPHERAL_BUS_USB: + return "usb"; + case PERIPHERAL_BUS_PCI: + return "pci"; + default: + return "unknown"; + } + }; + + static PeripheralBusType GetBusTypeFromString(const CStdString &strType) + { + CStdString strTypeLowerCase(strType); + strTypeLowerCase.ToLower(); + + if (strTypeLowerCase.Equals("usb")) + return PERIPHERAL_BUS_USB; + else if (strTypeLowerCase.Equals("pci")) + return PERIPHERAL_BUS_PCI; + + return PERIPHERAL_BUS_UNKNOWN; + }; + + static int HexStringToInt(const char *strHex) + { + int iVal; + sscanf(strHex, "%x", &iVal); + return iVal; + }; + + static char *IntToHexString(int iVal) + { + if (iVal < 0) + iVal = 0; + if (iVal > 65536) + iVal = 65536; + + char *buf = new char[4]; + sprintf(buf, "%04X", iVal); + return buf; + }; + }; +} diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp new file mode 100644 index 0000000000000..eab975b69f3bb --- /dev/null +++ b/xbmc/peripherals/Peripherals.cpp @@ -0,0 +1,476 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Peripherals.h" +#include "bus/PeripheralBus.h" +#include "devices/PeripheralBluetooth.h" +#include "devices/PeripheralCecAdapter.h" +#include "devices/PeripheralDisk.h" +#include "devices/PeripheralHID.h" +#include "devices/PeripheralNIC.h" +#include "devices/PeripheralNyxboard.h" +#include "devices/PeripheralTuner.h" +#include "dialogs/GUIDialogPeripheralManager.h" + +#include "threads/SingleLock.h" +#include "utils/log.h" +#include "utils/XMLUtils.h" +#include "settings/GUISettings.h" +#include "tinyXML/tinyxml.h" +#include "filesystem/Directory.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/LocalizeStrings.h" +#include "dialogs/GUIDialogKaiToast.h" +#include "utils/StringUtils.h" + +#if defined(TARGET_WINDOWS) +#include "bus/win32/PeripheralBusUSB.h" +#elif defined(TARGET_LINUX) && defined(HAVE_LIBUSB) +#include "bus/linux/PeripheralBusUSB.h" +#elif defined(TARGET_DARWIN) +#include "bus/osx/PeripheralBusUSB.h" +#endif + +using namespace PERIPHERALS; +using namespace XFILE; +using namespace std; + +CPeripherals::CPeripherals(void) +{ + CDirectory::Create("special://profile/peripheral_data"); + + Clear(); +} + +CPeripherals::~CPeripherals(void) +{ + Clear(); +} + +CPeripherals &CPeripherals::Get(void) +{ + static CPeripherals peripheralsInstance; + return peripheralsInstance; +} + +void CPeripherals::Initialise(void) +{ + CSingleLock lock(m_critSection); + if (!m_bIsStarted) + { + m_bIsStarted = true; + + /* load mappings from peripherals.xml */ + LoadMappings(); + +#if defined(TARGET_WINDOWS) + /* add all busses for win32 */ + m_busses.push_back(new CPeripheralBusUSB(this)); +#elif defined(TARGET_LINUX) && defined(HAVE_LIBUSB) + /* add all busses for linux */ + m_busses.push_back(new CPeripheralBusUSB(this)); +#elif defined(TARGET_DARWIN) + /* add all busses for darwin */ + m_busses.push_back(new CPeripheralBusUSB(this)); +#endif + + /* initialise all known busses */ + for (int iBusPtr = (int)m_busses.size() - 1; iBusPtr >= 0; iBusPtr--) + { + if (!m_busses.at(iBusPtr)->Initialise()) + { + CLog::Log(LOGERROR, "%s - failed to initialise bus %s", __FUNCTION__, PeripheralTypeTranslator::BusTypeToString(m_busses.at(iBusPtr)->Type())); + delete m_busses.at(iBusPtr); + m_busses.erase(m_busses.begin() + iBusPtr); + } + } + + m_bInitialised = true; + } +} + +void CPeripherals::Clear(void) +{ + CSingleLock lock(m_critSection); + /* delete busses and devices */ + for (unsigned int iBusPtr = 0; iBusPtr < m_busses.size(); iBusPtr++) + delete m_busses.at(iBusPtr); + m_busses.clear(); + + /* delete mappings */ + for (unsigned int iMappingPtr = 0; iMappingPtr < m_mappings.size(); iMappingPtr++) + m_mappings.at(iMappingPtr).m_settings.clear(); + m_mappings.clear(); + + /* reset class state */ + m_bIsStarted = false; + m_bInitialised = false; +} + +void CPeripherals::TriggerDeviceScan(const PeripheralBusType type /* = PERIPHERAL_BUS_UNKNOWN */) +{ + CSingleLock lock(m_critSection); + for (unsigned int iBusPtr = 0; iBusPtr < m_busses.size(); iBusPtr++) + { + if (type == PERIPHERAL_BUS_UNKNOWN || m_busses.at(iBusPtr)->Type() == type) + { + m_busses.at(iBusPtr)->TriggerDeviceScan(); + if (type != PERIPHERAL_BUS_UNKNOWN) + break; + } + } +} + +CPeripheralBus *CPeripherals::GetBusByType(const PeripheralBusType type) const +{ + CPeripheralBus *bus(NULL); + + CSingleLock lock(m_critSection); + for (unsigned int iBusPtr = 0; iBusPtr < m_busses.size(); iBusPtr++) + { + if (m_busses.at(iBusPtr)->Type() == type) + { + bus = m_busses.at(iBusPtr); + break; + } + } + + return bus; +} + +CPeripheral *CPeripherals::GetPeripheralAtLocation(const CStdString &strLocation, PeripheralBusType busType /* = PERIPHERAL_BUS_UNKNOWN */) const +{ + CPeripheral *peripheral(NULL); + CSingleLock lock(m_critSection); + for (unsigned int iBusPtr = 0; iBusPtr < m_busses.size(); iBusPtr++) + { + /* check whether the bus matches if a bus type other than unknown was passed */ + if (busType != PERIPHERAL_BUS_UNKNOWN && m_busses.at(iBusPtr)->Type() != busType) + continue; + + /* return the first device that matches */ + if ((peripheral = m_busses.at(iBusPtr)->GetPeripheral(strLocation)) != NULL) + break; + } + + return peripheral; +} + +bool CPeripherals::HasPeripheralAtLocation(const CStdString &strLocation, PeripheralBusType busType /* = PERIPHERAL_BUS_UNKNOWN */) const +{ + return (GetPeripheralAtLocation(strLocation, busType) != NULL); +} + +CPeripheralBus *CPeripherals::GetBusWithDevice(const CStdString &strLocation) const +{ + CSingleLock lock(m_critSection); + for (unsigned int iBusPtr = 0; iBusPtr < m_busses.size(); iBusPtr++) + { + /* return the first bus that matches */ + if (m_busses.at(iBusPtr)->HasPeripheral(strLocation)) + return m_busses.at(iBusPtr); + } + + return NULL; +} + +int CPeripherals::GetPeripheralsWithFeature(vector &results, const PeripheralFeature feature, PeripheralBusType busType /* = PERIPHERAL_BUS_UNKNOWN */) const +{ + int iReturn(0); + CSingleLock lock(m_critSection); + for (unsigned int iBusPtr = 0; iBusPtr < m_busses.size(); iBusPtr++) + { + /* check whether the bus matches if a bus type other than unknown was passed */ + if (busType != PERIPHERAL_BUS_UNKNOWN && m_busses.at(iBusPtr)->Type() != busType) + continue; + + iReturn += m_busses.at(iBusPtr)->GetPeripheralsWithFeature(results, feature); + } + + return iReturn; +} + +bool CPeripherals::HasPeripheralWithFeature(const PeripheralFeature feature, PeripheralBusType busType /* = PERIPHERAL_BUS_UNKNOWN */) const +{ + vector dummy; + return (GetPeripheralsWithFeature(dummy, feature, busType) > 0); +} + +CPeripheral *CPeripherals::CreatePeripheral(CPeripheralBus &bus, const PeripheralType type, const CStdString &strLocation, int iVendorId /* = 0 */, int iProductId /* = 0 */) +{ + CPeripheral *peripheral = GetPeripheralAtLocation(strLocation, bus.Type()); + + /* only create a new device instances if there's no device at the given location */ + if (!peripheral) + { + /* check whether there's something mapped in peripherals.xml */ + PeripheralType mappedType = type; + CStdString strDeviceName; + int iMappingPtr = GetMappingForDevice(bus, type, iVendorId, iProductId); + bool bHasMapping(iMappingPtr >= 0); + if (bHasMapping) + { + mappedType = m_mappings[iMappingPtr].m_mappedTo; + strDeviceName = m_mappings[iMappingPtr].m_strDeviceName; + } + + switch(mappedType) + { + case PERIPHERAL_HID: + peripheral = new CPeripheralHID(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); + break; + + case PERIPHERAL_NIC: + peripheral = new CPeripheralNIC(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); + break; + + case PERIPHERAL_DISK: + peripheral = new CPeripheralDisk(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); + break; + + case PERIPHERAL_NYXBOARD: + peripheral = new CPeripheralNyxboard(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); + break; + + case PERIPHERAL_CEC: + peripheral = new CPeripheralCecAdapter(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); + break; + + case PERIPHERAL_TUNER: + peripheral = new CPeripheralTuner(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); + break; + + case PERIPHERAL_BLUETOOTH: + peripheral = new CPeripheralBluetooth(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); + break; + + default: + peripheral = new CPeripheral(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); + break; + } + + if (peripheral) + { + /* try to initialise the new peripheral + * Initialise() will make sure that each device is only initialised once */ + if (peripheral->Initialise()) + { + if (!bHasMapping) + peripheral->SetHidden(true); + bus.Register(peripheral); + } + else + { + CLog::Log(LOGDEBUG, "%s - failed to initialise peripheral on '%s'", __FUNCTION__, strLocation.c_str()); + delete peripheral; + peripheral = NULL; + } + } + } + + return peripheral; +} + +void CPeripherals::OnDeviceAdded(const CPeripheralBus &bus, const CStdString &strLocation) +{ + CGUIDialogPeripheralManager *dialog = (CGUIDialogPeripheralManager *)g_windowManager.GetWindow(WINDOW_DIALOG_PERIPHERAL_MANAGER); + if (dialog && dialog->IsActive()) + dialog->Update(); + + CPeripheral *peripheral = GetByPath(strLocation); + if (peripheral) + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(35005), peripheral->DeviceName()); +} + +void CPeripherals::OnDeviceDeleted(const CPeripheralBus &bus, const CStdString &strLocation) +{ + CGUIDialogPeripheralManager *dialog = (CGUIDialogPeripheralManager *)g_windowManager.GetWindow(WINDOW_DIALOG_PERIPHERAL_MANAGER); + if (dialog && dialog->IsActive()) + dialog->Update(); + + CPeripheral *peripheral = GetByPath(strLocation); + if (peripheral) + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, g_localizeStrings.Get(35006), peripheral->DeviceName()); +} + +int CPeripherals::GetMappingForDevice(const CPeripheralBus &bus, const PeripheralType classType, int iVendorId, int iProductId) const +{ + /* check all mappings in the order in which they are defined in peripherals.xml */ + for (unsigned int iMappingPtr = 0; iMappingPtr < m_mappings.size(); iMappingPtr++) + { + PeripheralDeviceMapping mapping = m_mappings.at(iMappingPtr); + bool bBusMatch = (mapping.m_busType == PERIPHERAL_BUS_UNKNOWN || mapping.m_busType == bus.Type()); + bool bVendorMatch = (mapping.m_iVendorId == 0 || mapping.m_iVendorId == iVendorId); + bool bProductMatch = (mapping.m_iProductId == 0 || mapping.m_iProductId == iProductId); + bool bClassMatch = (mapping.m_class == PERIPHERAL_UNKNOWN || mapping.m_class == classType); + + if (bBusMatch && bVendorMatch && bProductMatch && bClassMatch) + { + CLog::Log(LOGDEBUG, "%s - device (%s:%s) mapped to %s (type = %s)", __FUNCTION__, PeripheralTypeTranslator::IntToHexString(iVendorId), PeripheralTypeTranslator::IntToHexString(iProductId), mapping.m_strDeviceName.c_str(), PeripheralTypeTranslator::TypeToString(mapping.m_mappedTo)); + return iMappingPtr; + } + } + + return -1; +} + +void CPeripherals::GetSettingsFromMapping(CPeripheral &peripheral) const +{ + /* check all mappings in the order in which they are defined in peripherals.xml */ + for (unsigned int iMappingPtr = 0; iMappingPtr < m_mappings.size(); iMappingPtr++) + { + const PeripheralDeviceMapping *mapping = &m_mappings.at(iMappingPtr); + bool bBusMatch = (mapping->m_busType == PERIPHERAL_BUS_UNKNOWN || mapping->m_busType == peripheral.GetBusType()); + bool bVendorMatch = (mapping->m_iVendorId == 0 || mapping->m_iVendorId == peripheral.VendorId()); + bool bProductMatch = (mapping->m_iProductId == 0 || mapping->m_iProductId == peripheral.ProductId()); + bool bClassMatch = (mapping->m_class == PERIPHERAL_UNKNOWN || mapping->m_class == peripheral.Type()); + + if (bBusMatch && bVendorMatch && bProductMatch && bClassMatch) + { + for (map::const_iterator itr = mapping->m_settings.begin(); itr != mapping->m_settings.end(); itr++) + peripheral.AddSetting((*itr).first, (*itr).second); + } + } +} + +bool CPeripherals::LoadMappings(void) +{ + TiXmlDocument xmlDoc; + if (!xmlDoc.LoadFile("special://xbmc/system/peripherals.xml")) + { + CLog::Log(LOGWARNING, "%s - peripherals.xml does not exist", __FUNCTION__); + return true; + } + + TiXmlElement *pRootElement = xmlDoc.RootElement(); + if (strcmpi(pRootElement->Value(), "peripherals") != 0) + { + CLog::Log(LOGERROR, "%s - peripherals.xml does not contain ", __FUNCTION__); + return false; + } + + TiXmlElement *currentNode = pRootElement->FirstChildElement("peripheral"); + while (currentNode) + { + PeripheralDeviceMapping mapping; + + mapping.m_iVendorId = currentNode->Attribute("vendor") ? PeripheralTypeTranslator::HexStringToInt(currentNode->Attribute("vendor")) : 0; + mapping.m_iProductId = currentNode->Attribute("product") ? PeripheralTypeTranslator::HexStringToInt(currentNode->Attribute("product")) : 0; + mapping.m_busType = PeripheralTypeTranslator::GetBusTypeFromString(currentNode->Attribute("bus")); + mapping.m_class = PeripheralTypeTranslator::GetTypeFromString(currentNode->Attribute("class")); + mapping.m_strDeviceName = currentNode->Attribute("name") ? CStdString(currentNode->Attribute("name")) : StringUtils::EmptyString; + mapping.m_mappedTo = PeripheralTypeTranslator::GetTypeFromString(currentNode->Attribute("mapTo")); + GetSettingsFromMappingsFile(currentNode, mapping.m_settings); + + m_mappings.push_back(mapping); + currentNode = currentNode->NextSiblingElement("peripheral"); + } + + return true; +} + +void CPeripherals::GetSettingsFromMappingsFile(TiXmlElement *xmlNode, map &m_settings) +{ + TiXmlElement *currentNode = xmlNode->FirstChildElement("setting"); + while (currentNode) + { + CSetting *setting = NULL; + CStdString strKey(currentNode->Attribute("key")); + if (strKey.IsEmpty()) + continue; + + CStdString strSettingsType(currentNode->Attribute("type")); + int iLabelId = currentNode->Attribute("label") ? atoi(currentNode->Attribute("label")) : -1; + bool bConfigurable = (!currentNode->Attribute("configurable") || + strcmp(currentNode->Attribute("configurable"), "") == 0 || + (strcmp(currentNode->Attribute("configurable"), "no") != 0 && + strcmp(currentNode->Attribute("configurable"), "false") != 0 && + strcmp(currentNode->Attribute("configurable"), "0") != 0)); + if (strSettingsType.Equals("bool")) + { + bool bValue = (strcmp(currentNode->Attribute("value"), "no") != 0 && + strcmp(currentNode->Attribute("value"), "false") != 0 && + strcmp(currentNode->Attribute("value"), "0") != 0); + setting = new CSettingBool(0, strKey, iLabelId, bValue, CHECKMARK_CONTROL); + } + else if (strSettingsType.Equals("int")) + { + int iValue = currentNode->Attribute("value") ? atoi(currentNode->Attribute("value")) : 0; + int iMin = currentNode->Attribute("min") ? atoi(currentNode->Attribute("min")) : 0; + int iStep = currentNode->Attribute("step") ? atoi(currentNode->Attribute("step")) : 0; + int iMax = currentNode->Attribute("max") ? atoi(currentNode->Attribute("max")) : 0; + CStdString strFormat(currentNode->Attribute("format")); + setting = new CSettingInt(0, strKey, iLabelId, iValue, iMin, iStep, iMax, SPIN_CONTROL_INT, strFormat); + } + else if (strSettingsType.Equals("float")) + { + float fValue = currentNode->Attribute("value") ? atof(currentNode->Attribute("value")) : 0; + float fMin = currentNode->Attribute("min") ? atof(currentNode->Attribute("min")) : 0; + float fStep = currentNode->Attribute("step") ? atof(currentNode->Attribute("step")) : 0; + float fMax = currentNode->Attribute("max") ? atof(currentNode->Attribute("max")) : 0; + setting = new CSettingFloat(0, strKey, iLabelId, fValue, fMin, fStep, fMax, SPIN_CONTROL_FLOAT); + } + else + { + CStdString strValue(currentNode->Attribute("value")); + setting = new CSettingString(0, strKey, iLabelId, strValue, EDIT_CONTROL_INPUT, !bConfigurable, -1); + } + + //TODO add more types if needed + setting->SetVisible(bConfigurable); + m_settings[strKey] = setting; + currentNode = currentNode->NextSiblingElement("setting"); + } +} + +void CPeripherals::GetDirectory(const CStdString &strPath, CFileItemList &items) const +{ + if (!strPath.Left(14).Equals("peripherals://")) + return; + + CStdString strPathCut = strPath.Right(strPath.length() - 14); + CStdString strBus = strPathCut.Left(strPathCut.Find('/')); + + CSingleLock lock(m_critSection); + for (unsigned int iBusPtr = 0; iBusPtr < m_busses.size(); iBusPtr++) + { + if (strBus.Equals("all") || strBus.Equals(PeripheralTypeTranslator::BusTypeToString(m_busses.at(iBusPtr)->Type()))) + m_busses.at(iBusPtr)->GetDirectory(strPath, items); + } +} + +CPeripheral *CPeripherals::GetByPath(const CStdString &strPath) const +{ + if (!strPath.Left(14).Equals("peripherals://")) + return NULL; + + CStdString strPathCut = strPath.Right(strPath.length() - 14); + CStdString strBus = strPathCut.Left(strPathCut.Find('/')); + + CSingleLock lock(m_critSection); + for (unsigned int iBusPtr = 0; iBusPtr < m_busses.size(); iBusPtr++) + { + if (strBus.Equals(PeripheralTypeTranslator::BusTypeToString(m_busses.at(iBusPtr)->Type()))) + return m_busses.at(iBusPtr)->GetByPath(strPath); + } + + return NULL; +} diff --git a/xbmc/peripherals/Peripherals.h b/xbmc/peripherals/Peripherals.h new file mode 100644 index 0000000000000..96a3b1f07debc --- /dev/null +++ b/xbmc/peripherals/Peripherals.h @@ -0,0 +1,161 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "bus/PeripheralBus.h" +#include "devices/Peripheral.h" +#include "threads/CriticalSection.h" +#include "threads/Thread.h" + +class CFileItemList; +class CSetting; +class CSettingsCategory; +class TiXmlElement; + +namespace PERIPHERALS +{ + #define g_peripherals CPeripherals::Get() + + class CPeripherals + { + public: + static CPeripherals &Get(void); + virtual ~CPeripherals(void); + + /*! + * @brief Initialise the peripherals manager. + */ + virtual void Initialise(void); + + /*! + * @brief Clear all data known by the peripherals manager. + */ + virtual void Clear(void); + + /*! + * @brief Get the instance of the peripheral at the given location. + * @param strLocation The location. + * @param busType The bus to query. Default (PERIPHERAL_BUS_UNKNOWN) searches all busses. + * @return The peripheral or NULL if it wasn't found. + */ + virtual CPeripheral *GetPeripheralAtLocation(const CStdString &strLocation, PeripheralBusType busType = PERIPHERAL_BUS_UNKNOWN) const; + + /*! + * @brief Check whether a peripheral is present at the given location. + * @param strLocation The location. + * @param busType The bus to query. Default (PERIPHERAL_BUS_UNKNOWN) searches all busses. + * @return True when a peripheral was found, false otherwise. + */ + virtual bool HasPeripheralAtLocation(const CStdString &strLocation, PeripheralBusType busType = PERIPHERAL_BUS_UNKNOWN) const; + + /*! + * @brief Get the bus that holds the device with the given location. + * @param strLocation The location. + * @return The bus or NULL if no device was found. + */ + virtual CPeripheralBus *GetBusWithDevice(const CStdString &strLocation) const; + + /*! + * @brief Get all peripheral instances that have the given feature. + * @param results The list of results. + * @param feature The feature to search for. + * @param busType The bus to query. Default (PERIPHERAL_BUS_UNKNOWN) searches all busses. + * @return The number of devices that have been found. + */ + virtual int GetPeripheralsWithFeature(std::vector &results, const PeripheralFeature feature, PeripheralBusType busType = PERIPHERAL_BUS_UNKNOWN) const; + + /*! + * @brief Check whether there is at least one device present with the given feature. + * @param feature The feature to check for. + * @param busType The bus to query. Default (PERIPHERAL_BUS_UNKNOWN) searches all busses. + * @return True when at least one device was found with this feature, false otherwise. + */ + virtual bool HasPeripheralWithFeature(const PeripheralFeature feature, PeripheralBusType busType = PERIPHERAL_BUS_UNKNOWN) const; + + /*! + * @brief Called when a device has been added to a bus. + * @param bus The bus the device was added to. + * @param strLocation The path of the fileitem. + */ + virtual void OnDeviceAdded(const CPeripheralBus &bus, const CStdString &strLocation); + + /*! + * @brief Called when a device has been deleted from a bus. + * @param bus The bus from which the device removed. + * @param strLocation The path of the fileitem. + */ + virtual void OnDeviceDeleted(const CPeripheralBus &bus, const CStdString &strLocation); + + /*! + * @brief Creates a new instance of a peripheral. + * @param bus The bus on which this peripheral is present. + * @param type The type of the new peripheral. + * @param strLocation The location on the bus. + * @return The new peripheral or NULL if it could not be created. + */ + CPeripheral *CreatePeripheral(CPeripheralBus &bus, const PeripheralType type, const CStdString &strLocation, int iVendorId = 0, int iProductId = 0); + + /*! + * @brief Add the settings that are defined in the mappings file to the peripheral (if there is anything defined). + * @param peripheral The peripheral to get the settings for. + */ + void GetSettingsFromMapping(CPeripheral &peripheral) const; + + /*! + * @brief Trigger a device scan on all known busses + */ + virtual void TriggerDeviceScan(const PeripheralBusType type = PERIPHERAL_BUS_UNKNOWN); + + /*! + * @brief Get the instance of a bus given it's type. + * @param type The bus type. + * @return The bus or NULL if it wasn't found. + */ + virtual CPeripheralBus *GetBusByType(const PeripheralBusType type) const; + + /*! + * @brief Get all fileitems for a path. + * @param strPath The path to the directory to get the items from. + * @param items The item list. + */ + virtual void GetDirectory(const CStdString &strPath, CFileItemList &items) const; + + /*! + * @brief Get the instance of a peripheral given it's path. + * @param strPath The path to the peripheral. + * @return The peripheral or NULL if it wasn't found. + */ + virtual CPeripheral *GetByPath(const CStdString &strPath) const; + + private: + CPeripherals(void); + bool LoadMappings(void); + int GetMappingForDevice(const CPeripheralBus &bus, const PeripheralType classType, int iVendorId, int iProductId) const; + static void GetSettingsFromMappingsFile(TiXmlElement *xmlNode, std::map &m_settings); + + bool m_bInitialised; + bool m_bIsStarted; + std::vector m_busses; + std::vector m_mappings; + CSettingsCategory * m_settings; + CCriticalSection m_critSection; + }; +} diff --git a/xbmc/peripherals/bus/Makefile.in b/xbmc/peripherals/bus/Makefile.in new file mode 100644 index 0000000000000..0831e9d6657bf --- /dev/null +++ b/xbmc/peripherals/bus/Makefile.in @@ -0,0 +1,14 @@ +SRCS=PeripheralBus.cpp + +ifeq (@HAVE_LIBUSB@,1) +SRCS+=linux/PeripheralBusUSB.cpp +endif + +ifeq ($(findstring osx,@ARCH@),osx) +SRCS+=osx/PeripheralBusUSB.cpp +endif + +LIB=peripheral-bus.a + +include ../../../Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/peripherals/bus/PeripheralBus.cpp b/xbmc/peripherals/bus/PeripheralBus.cpp new file mode 100644 index 0000000000000..bea0517573377 --- /dev/null +++ b/xbmc/peripherals/bus/PeripheralBus.cpp @@ -0,0 +1,336 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralBus.h" +#include "peripherals/Peripherals.h" +#include "utils/log.h" +#include "FileItem.h" + +using namespace std; +using namespace PERIPHERALS; + +#define PERIPHERAL_DEFAULT_RESCAN_INTERVAL 1000 + +bool PeripheralScanResult::operator ==(const PeripheralScanResult &right) const +{ + return m_iVendorId == right.m_iVendorId && + m_iProductId == right.m_iProductId && + m_type == right.m_type && + m_strLocation.Equals(right.m_strLocation); +} + +bool PeripheralScanResult::operator !=(const PeripheralScanResult &right) const +{ + return !(*this == right); +} + +bool PeripheralScanResult::operator ==(const CPeripheral &right) const +{ + return m_iVendorId == right.VendorId() && + m_iProductId == right.ProductId() && + m_type == right.Type() && + m_strLocation.Equals(right.Location()); +} + +bool PeripheralScanResult::operator !=(const CPeripheral &right) const +{ + return !(*this == right); +} + +bool PeripheralScanResults::GetDeviceOnLocation(const CStdString &strLocation, PeripheralScanResult *result) const +{ + bool bReturn(false); + + for (unsigned int iDevicePtr = 0; iDevicePtr < m_results.size(); iDevicePtr++) + { + if (m_results.at(iDevicePtr).m_strLocation == strLocation) + { + *result = m_results.at(iDevicePtr); + bReturn = true; + break; + } + } + + return bReturn; +} + +bool PeripheralScanResults::ContainsResult(const PeripheralScanResult &result) const +{ + bool bReturn(false); + + for (unsigned int iDevicePtr = 0; iDevicePtr < m_results.size(); iDevicePtr++) + { + if (m_results.at(iDevicePtr) == result) + { + bReturn = true; + break; + } + } + + return bReturn; +} + +CPeripheralBus::CPeripheralBus(CPeripherals *manager, PeripheralBusType type) : + CThread("XBMC Peripherals"), + m_iRescanTime(PERIPHERAL_DEFAULT_RESCAN_INTERVAL), + m_bInitialised(false), + m_bIsStarted(false), + m_bNeedsPolling(true), + m_manager(manager), + m_type(type), + m_triggerEvent(true) +{ +} + +void CPeripheralBus::OnDeviceAdded(const CStdString &strLocation) +{ + ScanForDevices(); +} + +void CPeripheralBus::OnDeviceChanged(const CStdString &strLocation) +{ + ScanForDevices(); +} + +void CPeripheralBus::OnDeviceRemoved(const CStdString &strLocation) +{ + ScanForDevices(); +} + +void CPeripheralBus::Clear(void) +{ + if (m_bNeedsPolling) + { + m_bStop = true; + m_triggerEvent.Set(); + StopThread(true); + } + + CSingleLock lock(m_critSection); + for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < m_peripherals.size(); iPeripheralPtr++) + delete m_peripherals.at(iPeripheralPtr); + m_peripherals.clear(); +} + +void CPeripheralBus::UnregisterRemovedDevices(const PeripheralScanResults &results) +{ + CSingleLock lock(m_critSection); + for (int iDevicePtr = (int) m_peripherals.size() - 1; iDevicePtr >= 0; iDevicePtr--) + { + CPeripheral *peripheral = m_peripherals.at(iDevicePtr); + PeripheralScanResult updatedDevice; + if (!results.GetDeviceOnLocation(peripheral->Location(), &updatedDevice) || + updatedDevice != *peripheral) + { + /* device removed */ + if (peripheral->Type() != PERIPHERAL_UNKNOWN) + CLog::Log(LOGNOTICE, "%s - device removed from %s/%s: %s (%s:%s)", __FUNCTION__, PeripheralTypeTranslator::TypeToString(peripheral->Type()), peripheral->Location().c_str(), peripheral->DeviceName().c_str(), peripheral->VendorIdAsString(), peripheral->ProductIdAsString()); + m_manager->OnDeviceDeleted(*this, peripheral->FileLocation()); + delete peripheral; + m_peripherals.erase(m_peripherals.begin() + iDevicePtr); + } + } +} + +void CPeripheralBus::RegisterNewDevices(const PeripheralScanResults &results) +{ + CSingleLock lock(m_critSection); + for (unsigned int iResultPtr = 0; iResultPtr < results.m_results.size(); iResultPtr++) + { + PeripheralScanResult result = results.m_results.at(iResultPtr); + if (!HasPeripheral(result.m_strLocation) && result.m_type != PERIPHERAL_UNKNOWN) + g_peripherals.CreatePeripheral(*this, result.m_type, result.m_strLocation, result.m_iVendorId, result.m_iProductId); + } +} + +bool CPeripheralBus::ScanForDevices(void) +{ + bool bReturn(false); + + PeripheralScanResults results; + if (PerformDeviceScan(results)) + { + UnregisterRemovedDevices(results); + RegisterNewDevices(results); + + bReturn = true; + } + + m_bInitialised = true; + return bReturn; +} + +bool CPeripheralBus::HasFeature(const PeripheralFeature feature) const +{ + bool bReturn(false); + CSingleLock lock(m_critSection); + for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < m_peripherals.size(); iPeripheralPtr++) + { + if (m_peripherals.at(iPeripheralPtr)->HasFeature(feature)) + { + bReturn = true; + break; + } + } + return bReturn; +} + +void CPeripheralBus::GetFeatures(std::vector &features) const +{ + CSingleLock lock(m_critSection); + for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < m_peripherals.size(); iPeripheralPtr++) + m_peripherals.at(iPeripheralPtr)->GetFeatures(features); +} + +CPeripheral *CPeripheralBus::GetPeripheral(const CStdString &strLocation) const +{ + CPeripheral *peripheral(NULL); + CSingleLock lock(m_critSection); + for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < m_peripherals.size(); iPeripheralPtr++) + { + if (m_peripherals.at(iPeripheralPtr)->Location() == strLocation) + { + peripheral = m_peripherals.at(iPeripheralPtr); + break; + } + } + return peripheral; +} + +int CPeripheralBus::GetPeripheralsWithFeature(vector &results, const PeripheralFeature feature) const +{ + int iReturn(0); + CSingleLock lock(m_critSection); + for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < m_peripherals.size(); iPeripheralPtr++) + { + if (m_peripherals.at(iPeripheralPtr)->HasFeature(feature)) + { + results.push_back(m_peripherals.at(iPeripheralPtr)); + ++iReturn; + } + } + + return iReturn; +} + +void CPeripheralBus::Process(void) +{ + while (!m_bStop) + { + m_triggerEvent.Reset(); + + if (!ScanForDevices()) + break; + + if (!m_bStop) + m_triggerEvent.WaitMSec(m_iRescanTime); + } + + m_bIsStarted = false; +} + +bool CPeripheralBus::Initialise(void) +{ + CSingleLock lock(m_critSection); + if (!m_bIsStarted) + { + /* do an initial scan of the bus */ + m_bIsStarted = ScanForDevices(); + + if (m_bIsStarted && m_bNeedsPolling) + { + lock.Leave(); + m_triggerEvent.Reset(); + Create(); + SetPriority(-1); + } + } + + return m_bIsStarted; +} + +void CPeripheralBus::Register(CPeripheral *peripheral) +{ + if (!peripheral) + return; + + CSingleLock lock(m_critSection); + if (!HasPeripheral(peripheral->Location())) + { + m_peripherals.push_back(peripheral); + m_manager->OnDeviceAdded(*this, peripheral->FileLocation()); + CLog::Log(LOGNOTICE, "%s - new %s device registered on %s->%s: %s (%s:%s)", __FUNCTION__, PeripheralTypeTranslator::TypeToString(peripheral->Type()), PeripheralTypeTranslator::BusTypeToString(m_type), peripheral->Location().c_str(), peripheral->DeviceName().c_str(), peripheral->VendorIdAsString(), peripheral->ProductIdAsString()); + } +} + +void CPeripheralBus::TriggerDeviceScan(void) +{ + CSingleLock lock(m_critSection); + if (m_bNeedsPolling) + { + lock.Leave(); + m_triggerEvent.Set(); + } + else + { + lock.Leave(); + ScanForDevices(); + } +} + +bool CPeripheralBus::HasPeripheral(const CStdString &strLocation) const +{ + return (GetPeripheral(strLocation) != NULL); +} + +void CPeripheralBus::GetDirectory(const CStdString &strPath, CFileItemList &items) const +{ + CStdString strDevPath; + CSingleLock lock(m_critSection); + for (unsigned int iDevicePtr = 0; iDevicePtr < m_peripherals.size(); iDevicePtr++) + { + const CPeripheral *peripheral = m_peripherals.at(iDevicePtr); + if (peripheral->IsHidden()) + continue; + + CFileItemPtr peripheralFile(new CFileItem(peripheral->DeviceName())); + peripheralFile->SetPath(peripheral->FileLocation()); + peripheralFile->SetProperty("vendor", peripheral->VendorIdAsString()); + peripheralFile->SetProperty("product", peripheral->ProductIdAsString()); + peripheralFile->SetProperty("bus", PeripheralTypeTranslator::BusTypeToString(peripheral->GetBusType())); + peripheralFile->SetProperty("location", peripheral->Location()); + peripheralFile->SetProperty("class", PeripheralTypeTranslator::TypeToString(peripheral->Type())); + items.Add(peripheralFile); + } +} + +CPeripheral *CPeripheralBus::GetByPath(const CStdString &strPath) const +{ + CStdString strDevPath; + CSingleLock lock(m_critSection); + for (unsigned int iDevicePtr = 0; iDevicePtr < m_peripherals.size(); iDevicePtr++) + { + if (strPath.Equals(m_peripherals.at(iDevicePtr)->FileLocation())) + return m_peripherals.at(iDevicePtr); + } + + return NULL; +} diff --git a/xbmc/peripherals/bus/PeripheralBus.h b/xbmc/peripherals/bus/PeripheralBus.h new file mode 100644 index 0000000000000..28ddfe318cab6 --- /dev/null +++ b/xbmc/peripherals/bus/PeripheralBus.h @@ -0,0 +1,191 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include "utils/StdString.h" +#include "threads/Thread.h" +#include "peripherals/PeripheralTypes.h" +#include "peripherals/devices/Peripheral.h" + +class CFileItemList; + +namespace PERIPHERALS +{ + class CPeripherals; + + struct PeripheralScanResult + { + bool operator ==(const PeripheralScanResult &right) const; + bool operator !=(const PeripheralScanResult &right) const; + + bool operator ==(const CPeripheral &right) const; + bool operator !=(const CPeripheral &right) const; + + PeripheralType m_type; + CStdString m_strLocation; + int m_iVendorId; + int m_iProductId; + }; + + struct PeripheralScanResults + { + bool GetDeviceOnLocation(const CStdString &strLocation, PeripheralScanResult *result) const; + bool ContainsResult(const PeripheralScanResult &result) const; + + std::vector m_results; + }; + + /*! + * @class CPeripheralBus + * This represents a bus on the system. By default, this bus instance will scan for changes every second. + * If this bus only has to be updated after a notification sent by the system, set m_bNeedsPolling to false + * in the constructor, and implement the OnDeviceAdded(), OnDeviceChanged() and OnDeviceRemoved() methods. + * + * The PerformDeviceScan() method has to be implemented by each specific bus implementation. + */ + class CPeripheralBus : protected CThread + { + public: + CPeripheralBus(CPeripherals *manager, PeripheralBusType type); + virtual ~CPeripheralBus(void) { Clear(); } + + /*! + * @return The bus type + */ + const PeripheralBusType Type(void) const { return m_type; } + + /*! + * @return True if this bus needs to be polled for changes, false if this bus performs updates via callbacks + */ + bool NeedsPolling(void) const { return m_bNeedsPolling; } + + /*! + * @brief Get the instance of the peripheral at the given location. + * @param strLocation The location. + * @return The peripheral or NULL if it wasn't found. + */ + virtual CPeripheral *GetPeripheral(const CStdString &strLocation) const; + + /*! + * @brief Check whether a peripheral is present at the given location. + * @param strLocation The location. + * @return True when a peripheral was found, false otherwise. + */ + virtual bool HasPeripheral(const CStdString &strLocation) const; + + /*! + * @brief Get the first instance of a peripheral that has the given feature. + * @param feature The feature to search for. + * @return The peripheral or NULL if it wasn't found. + */ + virtual int GetPeripheralsWithFeature(std::vector &results, const PeripheralFeature feature) const; + + /*! + * @brief Get all features that are supported by devices on this bus. + * @param features All features. + */ + virtual void GetFeatures(std::vector &features) const; + + /*! + * @brief Check whether there is at least one device present with the given feature. + * @param feature The feature to check for. + * @return True when at least one device was found with this feature, false otherwise. + */ + virtual bool HasFeature(const PeripheralFeature feature) const; + + /*! + * @brief Callback method for when a device has been added. Will perform a device scan. + * @param strLocation The location of the device that has been added. + */ + virtual void OnDeviceAdded(const CStdString &strLocation); + + /*! + * @brief Callback method for when a device has been changed. Will perform a device scan. + * @param strLocation The location of the device that has been changed. + */ + virtual void OnDeviceChanged(const CStdString &strLocation); + + /*! + * @brief Callback method for when a device has been removed. Will perform a device scan. + * @param strLocation The location of the device that has been removed. + */ + virtual void OnDeviceRemoved(const CStdString &strLocation); + + /*! + * @brief Initialise this bus and start a polling thread if this bus needs polling. + */ + virtual bool Initialise(void); + + /*! + * @brief Stop the polling thread and clear all known devices on this bus. + */ + virtual void Clear(void); + + /*! + * @brief Scan for devices. + */ + virtual void TriggerDeviceScan(void); + + /*! + * @brief Get all fileitems for a path. + * @param strPath The path to the directory to get the items from. + * @param items The item list. + */ + virtual void GetDirectory(const CStdString &strPath, CFileItemList &items) const; + + /*! + * @brief Get the instance of a peripheral given it's path. + * @param strPath The path to the peripheral. + * @return The peripheral or NULL if it wasn't found. + */ + virtual CPeripheral *GetByPath(const CStdString &strPath) const; + + /*! + * @brief Register a new peripheral on this bus. + * @param peripheral The peripheral to register. + */ + virtual void Register(CPeripheral *peripheral); + + protected: + virtual void Process(void); + virtual bool ScanForDevices(void); + virtual void UnregisterRemovedDevices(const PeripheralScanResults &results); + virtual void RegisterNewDevices(const PeripheralScanResults &results); + + /*! + * @brief Scan for devices on this bus and add them to the results list. This will have to be implemented for each bus. + * @param results The result list. + * @return True when the scan was successful, false otherwise. + */ + virtual bool PerformDeviceScan(PeripheralScanResults &results) = 0; + + std::vector m_peripherals; + int m_iRescanTime; + bool m_bInitialised; + bool m_bIsStarted; + bool m_bNeedsPolling; /*!< true when this bus needs to be polled for new devices, false when it uses callbacks to notify this bus of changed */ + CPeripherals * m_manager; + PeripheralBusType m_type; + CCriticalSection m_critSection; + CEvent m_triggerEvent; + }; +} diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSB.cpp b/xbmc/peripherals/bus/linux/PeripheralBusUSB.cpp new file mode 100644 index 0000000000000..4a5faf7d486b6 --- /dev/null +++ b/xbmc/peripherals/bus/linux/PeripheralBusUSB.cpp @@ -0,0 +1,170 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralBusUSB.h" +#include "peripherals/Peripherals.h" +#include +#if defined(HAVE_LIBUDEV) +#include +#include +#include "utils/log.h" +#endif + +using namespace PERIPHERALS; + +CPeripheralBusUSB::CPeripheralBusUSB(CPeripherals *manager) : + CPeripheralBus(manager, PERIPHERAL_BUS_USB) +{ + usb_init(); + usb_find_busses(); + m_busses = usb_get_busses(); + +#if defined(HAVE_LIBUDEV) + InitialiseUdev(); +#endif +} + +bool CPeripheralBusUSB::PerformDeviceScan(PeripheralScanResults &results) +{ + struct usb_bus *bus; + usb_find_devices(); + for (bus = m_busses; bus; bus = bus->next) + { + struct usb_device *dev; + for (dev = bus->devices; dev; dev = dev->next) + { + PeripheralScanResult result; + result.m_iVendorId = dev->descriptor.idVendor; + result.m_iProductId = dev->descriptor.idProduct; + result.m_type = (dev->descriptor.bDeviceClass == USB_CLASS_PER_INTERFACE && dev->descriptor.bNumConfigurations > 0 && + dev->config[0].bNumInterfaces > 0 && dev->config[0].interface[0].num_altsetting > 0) ? + GetType(dev->config[0].interface[0].altsetting[0].bInterfaceClass) : + GetType(dev->descriptor.bDeviceClass); + result.m_strLocation.Format("/bus%s/dev%s", bus->dirname, dev->filename); + + if (!results.ContainsResult(result)) + results.m_results.push_back(result); + } + } + + return true; +} + +const PeripheralType CPeripheralBusUSB::GetType(int iDeviceClass) +{ + switch (iDeviceClass) + { + case USB_CLASS_HID: + return PERIPHERAL_HID; + case USB_CLASS_COMM: + return PERIPHERAL_NIC; + case USB_CLASS_MASS_STORAGE: + return PERIPHERAL_DISK; + case USB_CLASS_PER_INTERFACE: + case USB_CLASS_AUDIO: + case USB_CLASS_PRINTER: + case USB_CLASS_PTP: + case USB_CLASS_HUB: + case USB_CLASS_DATA: + case USB_CLASS_VENDOR_SPEC: + default: + return PERIPHERAL_UNKNOWN; + } +} + +#if defined(HAVE_LIBUDEV) +void CPeripheralBusUSB::Process(void) +{ + bool bUpdated(false); + ScanForDevices(); + while (!m_bStop) + { + bUpdated = WaitForUpdate(); + if (bUpdated && !m_bStop) + ScanForDevices(); + } + + m_bIsStarted = false; +} + +void CPeripheralBusUSB::Clear(void) +{ + StopThread(false); + if (m_udevFd != -1) + close(m_udevFd); + + udev_unref(m_udev); + + CPeripheralBus::Clear(); +} + +void CPeripheralBusUSB::InitialiseUdev(void) +{ + m_udev = NULL; + m_udevMon = NULL; + m_udevFd = -1; + + if (!(m_udev = udev_new())) + { + CLog::Log(LOGERROR, "%s - failed to allocate udev context", __FUNCTION__); + return; + } + + /* set up a devices monitor that listen for any device change */ + m_udevMon = udev_monitor_new_from_netlink(m_udev, "udev"); + udev_monitor_enable_receiving(m_udevMon); + m_udevFd = udev_monitor_get_fd(m_udevMon); + + CLog::Log(LOGDEBUG, "%s - initialised udev monitor: %d", __FUNCTION__, m_udevFd); +} + +bool CPeripheralBusUSB::WaitForUpdate() +{ + if (!m_udevFd) + return false; + + /* poll for udev changes */ + struct pollfd pollFd; + pollFd.fd = m_udevFd; + pollFd.events = POLLIN; + int iPollResult; + while (!m_bStop && ((iPollResult = poll(&pollFd, 1, 100)) <= 0)) + if (errno != EINTR && iPollResult != 0) + break; + + /* the thread is being stopped, so just return false */ + if (m_bStop) + return false; + + /* we have to read the message from the queue, even though we're not actually using it */ + struct udev_device *dev = udev_monitor_receive_device(m_udevMon); + if (dev) + udev_device_unref(dev); + else + { + CLog::Log(LOGERROR, "%s - failed to get device from udev_monitor_receive_device()", __FUNCTION__); + Clear(); + return false; + } + + return true; +} +#endif diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSB.h b/xbmc/peripherals/bus/linux/PeripheralBusUSB.h new file mode 100644 index 0000000000000..28b617502114b --- /dev/null +++ b/xbmc/peripherals/bus/linux/PeripheralBusUSB.h @@ -0,0 +1,65 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "peripherals/bus/PeripheralBus.h" +#include "peripherals/devices/Peripheral.h" + +struct usb_bus; + +#if defined(HAVE_LIBUDEV) +struct udev; +struct udev_monitor; +#endif + +namespace PERIPHERALS +{ + class CPeripherals; + + class CPeripheralBusUSB : public CPeripheralBus + { + public: + CPeripheralBusUSB(CPeripherals *manager); + +#if defined(HAVE_LIBUDEV) + virtual void Clear(void); +#endif + + /*! + * @see PeripheralBus::PerformDeviceScan() + */ + bool PerformDeviceScan(PeripheralScanResults &results); + + protected: + static const PeripheralType GetType(int iDeviceClass); + struct usb_bus *m_busses; + +#if defined(HAVE_LIBUDEV) + virtual void Process(void); + void InitialiseUdev(void); + bool WaitForUpdate(void); + + struct udev * m_udev; + struct udev_monitor *m_udevMon; + int m_udevFd; +#endif + }; +} diff --git a/xbmc/peripherals/bus/osx/PeripheralBusUSB.cpp b/xbmc/peripherals/bus/osx/PeripheralBusUSB.cpp new file mode 100644 index 0000000000000..f2333ea474918 --- /dev/null +++ b/xbmc/peripherals/bus/osx/PeripheralBusUSB.cpp @@ -0,0 +1,278 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralBusUSB.h" +#include "peripherals/Peripherals.h" +#include "utils/log.h" + +#ifdef TARGET_DARWIN_OSX +#include +#include +#include +#include + +typedef struct USBDevicePrivateData { + CPeripheralBusUSB *refCon; + CStdString deviceName; + io_object_t notification; + PeripheralScanResult result; +} USBDevicePrivateData; +#endif + +using namespace PERIPHERALS; + +CPeripheralBusUSB::CPeripheralBusUSB(CPeripherals *manager) : + CPeripheralBus(manager, PERIPHERAL_BUS_USB) +{ + m_bNeedsPolling = false; + +#ifdef TARGET_DARWIN_OSX + //set up the matching criteria for the devices we're interested in + //interested in instances of class IOUSBDevice and its subclasses + // match any usb device by not creating matching values in the dict + CFMutableDictionaryRef matching_dict = IOServiceMatching(kIOUSBDeviceClassName); + + m_notify_port = IONotificationPortCreate(kIOMasterPortDefault); + CFRunLoopSourceRef run_loop_source = IONotificationPortGetRunLoopSource(m_notify_port); + CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source, kCFRunLoopCommonModes); + + //add a notification callback for attach event + IOReturn result = IOServiceAddMatchingNotification(m_notify_port, + kIOFirstMatchNotification, matching_dict, + (IOServiceMatchingCallback)DeviceAttachCallback, this, &m_attach_iterator); + if (result == kIOReturnSuccess) + { + //call the callback to 'arm' the notification + DeviceAttachCallback(this, m_attach_iterator); + } +#endif +} + +CPeripheralBusUSB::~CPeripheralBusUSB() +{ +#ifdef TARGET_DARWIN_OSX + if (m_notify_port) + { + // remove the sleep notification port from the application runloop + CFRunLoopRemoveSource( CFRunLoopGetCurrent(), + IONotificationPortGetRunLoopSource(m_notify_port), kCFRunLoopDefaultMode ); + IONotificationPortDestroy(m_notify_port); + m_notify_port = 0; + } + if (m_attach_iterator) + { + IOObjectRelease(m_attach_iterator); + m_attach_iterator = 0; + } +#endif +} + +bool CPeripheralBusUSB::PerformDeviceScan(PeripheralScanResults &results) +{ + results = m_scan_results; + return true; +} + +#ifdef TARGET_DARWIN_OSX +const PeripheralType CPeripheralBusUSB::GetType(int iDeviceClass) +{ + switch (iDeviceClass) + { + case kUSBHIDClass: + return PERIPHERAL_HID; + case kUSBCommClass: + return PERIPHERAL_NIC; + case kUSBMassStorageClass: + return PERIPHERAL_DISK; + //case USB_CLASS_PER_INTERFACE: + case kUSBAudioClass: + case kUSBPrintingClass: + //case USB_CLASS_PTP: + case kUSBHubClass: + case kUSBDataClass: + case kUSBVendorSpecificClass: + default: + return PERIPHERAL_UNKNOWN; + } +} + +void CPeripheralBusUSB::DeviceDetachCallback(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) +{ + if (messageType == kIOMessageServiceIsTerminated) + { + IOReturn result; + + USBDevicePrivateData *privateDataRef = (USBDevicePrivateData*)refCon; + + std::vector::iterator it = privateDataRef->refCon->m_scan_results.m_results.begin(); + while(it != privateDataRef->refCon->m_scan_results.m_results.end()) + { + if (privateDataRef->result.m_strLocation == it->m_strLocation) + privateDataRef->refCon->m_scan_results.m_results.erase(it); + else + it++; + } + privateDataRef->refCon->ScanForDevices(); + + CLog::Log(LOGDEBUG, "HID Device Detach:%s, %s\n", + privateDataRef->deviceName.c_str(), privateDataRef->result.m_strLocation.c_str()); + result = IOObjectRelease(privateDataRef->notification); + delete privateDataRef; + //release the service + result = IOObjectRelease(service); + } +} + +void CPeripheralBusUSB::DeviceAttachCallback(CPeripheralBusUSB* refCon, io_iterator_t iterator) +{ + io_service_t usbDevice; + while ((usbDevice = IOIteratorNext(iterator))) + { + IOReturn result; + + io_name_t deviceName; + result = IORegistryEntryGetName(usbDevice, deviceName); + if (result != KERN_SUCCESS) + deviceName[0] = '\0'; + + SInt32 deviceScore; + IOCFPlugInInterface **devicePlugin; + result = IOCreatePlugInInterfaceForService(usbDevice, + kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &devicePlugin, &deviceScore); + if (result != kIOReturnSuccess) + { + IOObjectRelease(usbDevice); + continue; + } + + IOUSBDeviceInterface **deviceInterface; + // Use the plugin interface to retrieve the device interface. + result = (*devicePlugin)->QueryInterface(devicePlugin, + CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*)&deviceInterface); + if (result != kIOReturnSuccess) + { + IODestroyPlugInInterface(devicePlugin); + IOObjectRelease(usbDevice); + continue; + } + + // get vendor/product ids + UInt16 vendorId; + UInt16 productId; + UInt32 locationId; + UInt8 bDeviceClass; + + result = (*deviceInterface)->GetDeviceVendor( deviceInterface, &vendorId); + result = (*deviceInterface)->GetDeviceProduct(deviceInterface, &productId); + result = (*deviceInterface)->GetLocationID( deviceInterface, &locationId); + result = (*deviceInterface)->GetDeviceClass( deviceInterface, &bDeviceClass); + + // we only care about usb devices with an HID interface class + io_service_t usbInterface; + io_iterator_t interface_iterator; + IOUSBFindInterfaceRequest request; + request.bInterfaceClass = kUSBHIDInterfaceClass; + request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; + request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; + request.bAlternateSetting = kIOUSBFindInterfaceDontCare; + result = (*deviceInterface)->CreateInterfaceIterator(deviceInterface, &request, &interface_iterator); + while ((usbInterface = IOIteratorNext(interface_iterator))) + { + SInt32 interfaceScore; + IOCFPlugInInterface **interfacePlugin; + //create intermediate plugin for interface access + result = IOCreatePlugInInterfaceForService(usbInterface, + kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &interfacePlugin, &interfaceScore); + if (result != kIOReturnSuccess) + { + IOObjectRelease(usbInterface); + continue; + } + IOUSBInterfaceInterface** interfaceInterface; + result = (*interfacePlugin)->QueryInterface(interfacePlugin, + CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (void**)&interfaceInterface); + if (result != kIOReturnSuccess) + { + IODestroyPlugInInterface(interfacePlugin); + IOObjectRelease(usbInterface); + continue; + } + + // finally we can get to bInterfaceClass/bInterfaceProtocol + // we should also check for kHIDKeyboardInterfaceProtocol but + // some IR remotes that emulate an HID keyboard do not report this. + UInt8 bInterfaceClass; + result = (*interfaceInterface)->GetInterfaceClass(interfaceInterface, &bInterfaceClass); + if (bInterfaceClass == kUSBHIDInterfaceClass) + { + USBDevicePrivateData *privateDataRef; + privateDataRef = new USBDevicePrivateData; + // save the device info to our private data. + privateDataRef->refCon = refCon; + privateDataRef->deviceName = deviceName; + privateDataRef->result.m_iVendorId = vendorId; + privateDataRef->result.m_iProductId = productId; + privateDataRef->result.m_strLocation.Format("%d", locationId); + + if (bDeviceClass == kUSBCompositeClass) + privateDataRef->result.m_type = refCon->GetType(bInterfaceClass); + else + privateDataRef->result.m_type = refCon->GetType(bDeviceClass); + + if (!refCon->m_scan_results.ContainsResult(privateDataRef->result)) + { + // register this usb device for an interest notification callback. + result = IOServiceAddInterestNotification(refCon->m_notify_port, + usbDevice, // service + kIOGeneralInterest, // interestType + (IOServiceInterestCallback)DeviceDetachCallback, // callback + privateDataRef, // refCon + &privateDataRef->notification); // notification + + if (result == kIOReturnSuccess) + { + refCon->m_scan_results.m_results.push_back(privateDataRef->result); + CLog::Log(LOGDEBUG, "HID Device Attach:%s, %s\n", + deviceName, privateDataRef->result.m_strLocation.c_str()); + } + else + { + delete privateDataRef; + } + } + else + { + delete privateDataRef; + } + // done with this device, only need one notification per device. + IODestroyPlugInInterface(interfacePlugin); + IOObjectRelease(usbInterface); + break; + } + IODestroyPlugInInterface(interfacePlugin); + IOObjectRelease(usbInterface); + } + IODestroyPlugInInterface(devicePlugin); + IOObjectRelease(usbDevice); + } + refCon->ScanForDevices(); +} +#endif diff --git a/xbmc/peripherals/bus/osx/PeripheralBusUSB.h b/xbmc/peripherals/bus/osx/PeripheralBusUSB.h new file mode 100644 index 0000000000000..2c08a902da71b --- /dev/null +++ b/xbmc/peripherals/bus/osx/PeripheralBusUSB.h @@ -0,0 +1,58 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "peripherals/bus/PeripheralBus.h" +#include "peripherals/devices/Peripheral.h" + +#ifdef TARGET_DARWIN_OSX +#include +#include +#endif + +namespace PERIPHERALS +{ + class CPeripherals; + + class CPeripheralBusUSB : public CPeripheralBus + { + public: + CPeripheralBusUSB(CPeripherals *manager); + virtual ~CPeripheralBusUSB(); + + /*! + * @see PeripheralBus::PerformDeviceScan() + */ + bool PerformDeviceScan(PeripheralScanResults &results); + + protected: + PeripheralScanResults m_scan_results; + #ifdef TARGET_DARWIN_OSX + static const PeripheralType GetType(int iDeviceClass); + static void DeviceDetachCallback(void *refCon, io_service_t service, natural_t messageType, void *messageArgument); + static void DeviceAttachCallback(CPeripheralBusUSB* refCon, io_iterator_t iterator); + + IONotificationPortRef m_notify_port; + io_iterator_t m_attach_iterator; + #endif + }; + +} diff --git a/xbmc/peripherals/bus/win32/PeripheralBusUSB.cpp b/xbmc/peripherals/bus/win32/PeripheralBusUSB.cpp new file mode 100644 index 0000000000000..f537296b7a164 --- /dev/null +++ b/xbmc/peripherals/bus/win32/PeripheralBusUSB.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralBusUSB.h" +#include "peripherals/Peripherals.h" +#include "utils/log.h" +#include "utils/StringUtils.h" + +static GUID USB_RAW_GUID = { 0xA5DCBF10, 0x6530, 0x11D2, { 0x90, 0x1F, 0x00, 0xC0, 0x4F, 0xB9, 0x51, 0xED } }; +static GUID USB_HID_GUID = { 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } }; +static GUID USB_DISK_GUID = { 0x53F56307, 0xB6BF, 0x11D0, { 0x94, 0xF2, 0x00, 0xA0, 0xC9, 0x1E, 0xFB, 0x8B } }; +static GUID USB_NIC_GUID = { 0xAD498944, 0x762F, 0x11D0, { 0x8D, 0xCB, 0x00, 0xC0, 0x4F, 0xC3, 0x35, 0x8C } }; + +using namespace PERIPHERALS; + +CPeripheralBusUSB::CPeripheralBusUSB(CPeripherals *manager) : + CPeripheralBus(manager, PERIPHERAL_BUS_USB) +{ + /* device removals aren't always triggering OnDeviceRemoved events, so poll for changes every 5 seconds to be sure we don't miss anything */ + m_iRescanTime = 5000; +} + +bool CPeripheralBusUSB::PerformDeviceScan(PeripheralScanResults &results) +{ + bool bReturn(true); + + /* add device scans for non-generic devices here */ + + bReturn |= PerformDeviceScan(&USB_HID_GUID, PERIPHERAL_HID, results); + bReturn |= PerformDeviceScan(&USB_DISK_GUID, PERIPHERAL_DISK, results); + + return bReturn; +} + +bool CPeripheralBusUSB::PerformDeviceScan(const GUID *guid, const PeripheralType type, PeripheralScanResults &results) +{ + bool bReturn(false); + HDEVINFO hDevHandle; + DWORD required = 0, iMemberIndex = 0; + int nBufferSize = 0; + + SP_DEVICE_INTERFACE_DATA deviceInterfaceData; + deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); + + SP_DEVINFO_DATA devInfoData; + devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); + + if ((hDevHandle = SetupDiGetClassDevs(guid, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE)) == INVALID_HANDLE_VALUE) + { + CLog::Log(LOGWARNING, "%s - cannot query USB devices: invalid handle", __FUNCTION__); + return bReturn; + } + + bReturn = true; + BOOL bResult = true; + TCHAR *buffer = NULL; + PSP_DEVICE_INTERFACE_DETAIL_DATA devicedetailData; + while(bResult) + { + bResult = SetupDiEnumDeviceInfo(hDevHandle, iMemberIndex, &devInfoData); + + if (bResult) + bResult = SetupDiEnumDeviceInterfaces(hDevHandle, 0, guid, iMemberIndex, &deviceInterfaceData); + + if(!bResult) + { + SetupDiDestroyDeviceInfoList(hDevHandle); + delete []buffer; + buffer = NULL; + return bReturn; + } + + iMemberIndex++; + BOOL bDetailResult = false; + { + // As per MSDN, Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail with a + // NULL DeviceInterfaceDetailData pointer, a DeviceInterfaceDetailDataSize of zero, + // and a valid RequiredSize variable. In response to such a call, this function returns + // the required buffer size at RequiredSize and fails with GetLastError returning + // ERROR_INSUFFICIENT_BUFFER. + // Allocate an appropriately sized buffer and call the function again to get the interface details. + + SetupDiGetDeviceInterfaceDetail(hDevHandle, &deviceInterfaceData, NULL, 0, &required, NULL); + + buffer = new TCHAR[required]; + devicedetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) buffer; + devicedetailData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); + nBufferSize = required; + } + + bDetailResult = SetupDiGetDeviceInterfaceDetail(hDevHandle, &deviceInterfaceData, devicedetailData, nBufferSize , &required, NULL); + if(!bDetailResult) + continue; + + CStdString strVendorId(StringUtils::EmptyString); + CStdString strProductId(StringUtils::EmptyString); + if (type == PERIPHERAL_HID) + { + CStdString strTmp(devicedetailData->DevicePath); + strVendorId = strTmp.substr(strTmp.Find("vid_") + 4, 4); + strProductId = strTmp.substr(strTmp.Find("pid_") + 4, 4); + if (strTmp.Find("&mi_") >= 0 && strTmp.Find("&mi_00") < 0) + continue; + } + + PeripheralScanResult prevDevice; + if (!results.GetDeviceOnLocation(devicedetailData->DevicePath, &prevDevice)) + { + PeripheralScanResult result; + result.m_strLocation = devicedetailData->DevicePath; + result.m_type = type; + result.m_iVendorId = PeripheralTypeTranslator::HexStringToInt(strVendorId.c_str()); + result.m_iProductId = PeripheralTypeTranslator::HexStringToInt(strProductId.c_str()); + + results.m_results.push_back(result); + } + } + + return bReturn; +} diff --git a/xbmc/peripherals/bus/win32/PeripheralBusUSB.h b/xbmc/peripherals/bus/win32/PeripheralBusUSB.h new file mode 100644 index 0000000000000..4491120fc2bc8 --- /dev/null +++ b/xbmc/peripherals/bus/win32/PeripheralBusUSB.h @@ -0,0 +1,45 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "peripherals/bus/PeripheralBus.h" +#include "peripherals/devices/Peripheral.h" +#include //needed for GUID + +namespace PERIPHERALS +{ + class CPeripherals; + + class CPeripheralBusUSB : public CPeripheralBus + { + public: + CPeripheralBusUSB(CPeripherals *manager); + + /*! + * @see PeripheralBus::PerformDeviceScan() + */ + bool PerformDeviceScan(PeripheralScanResults &results); + + private: + bool PerformDeviceScan(const GUID *guid, const PeripheralType type, PeripheralScanResults &results); + bool GetProductAndVendorId(const PeripheralType type, const CStdString &strDeviceLocation, int *iVendorId, int *iProductId); + }; +} diff --git a/xbmc/peripherals/devices/Makefile b/xbmc/peripherals/devices/Makefile new file mode 100644 index 0000000000000..85246df537789 --- /dev/null +++ b/xbmc/peripherals/devices/Makefile @@ -0,0 +1,13 @@ +SRCS=Peripheral.cpp \ + PeripheralBluetooth.cpp \ + PeripheralCecAdapter.cpp \ + PeripheralDisk.cpp \ + PeripheralHID.cpp \ + PeripheralNIC.cpp \ + PeripheralNyxboard.cpp \ + PeripheralTuner.cpp + +LIB=peripheral-devices.a + +include ../../../Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/peripherals/devices/Peripheral.cpp b/xbmc/peripherals/devices/Peripheral.cpp new file mode 100644 index 0000000000000..fba7735061c8e --- /dev/null +++ b/xbmc/peripherals/devices/Peripheral.cpp @@ -0,0 +1,474 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Peripheral.h" +#include "peripherals/Peripherals.h" +#include "utils/log.h" +#include "utils/StringUtils.h" +#include "settings/GUISettings.h" +#include "lib/tinyXML/tinyxml.h" +#include "utils/URIUtils.h" + +using namespace PERIPHERALS; +using namespace std; + +CPeripheral::CPeripheral(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId) : + m_type(type), + m_busType(busType), + m_strLocation(strLocation), + m_strDeviceName(strDeviceName), + m_strFileLocation(StringUtils::EmptyString), + m_iVendorId(iVendorId), + m_strVendorId(PeripheralTypeTranslator::IntToHexString(iVendorId)), + m_iProductId(iProductId), + m_strProductId(PeripheralTypeTranslator::IntToHexString(iProductId)), + m_bInitialised(false), + m_bHidden(false) +{ + m_strFileLocation.Format("peripherals://%s/%s.dev", PeripheralTypeTranslator::BusTypeToString(busType), strLocation.c_str()); +} + +CPeripheral::CPeripheral(void) : + m_type(PERIPHERAL_UNKNOWN), + m_busType(PERIPHERAL_BUS_UNKNOWN), + m_strLocation(StringUtils::EmptyString), + m_strDeviceName(StringUtils::EmptyString), + m_strFileLocation(StringUtils::EmptyString), + m_iVendorId(0), + m_strVendorId(PeripheralTypeTranslator::IntToHexString(0)), + m_iProductId(0), + m_strProductId(PeripheralTypeTranslator::IntToHexString(0)), + m_bInitialised(false), + m_bHidden(false) +{ +} + +CPeripheral::~CPeripheral(void) +{ + PersistSettings(); + + for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++) + delete m_subDevices.at(iSubdevicePtr); + m_subDevices.clear(); + + ClearSettings(); +} + +bool CPeripheral::operator ==(const CPeripheral &right) const +{ + return m_type == right.m_type && + m_strLocation == right.m_strLocation && + m_iVendorId == right.m_iVendorId && + m_iProductId == right.m_iProductId; +} + +bool CPeripheral::operator !=(const CPeripheral &right) const +{ + return !(*this == right); +} + +bool CPeripheral::HasFeature(const PeripheralFeature feature) const +{ + bool bReturn(false); + + for (unsigned int iFeaturePtr = 0; iFeaturePtr < m_features.size(); iFeaturePtr++) + { + if (m_features.at(iFeaturePtr) == feature) + { + bReturn = true; + break; + } + } + + if (!bReturn) + { + for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++) + { + if (m_subDevices.at(iSubdevicePtr)->HasFeature(feature)) + { + bReturn = true; + break; + } + } + } + + return bReturn; +} + +void CPeripheral::GetFeatures(std::vector &features) const +{ + for (unsigned int iFeaturePtr = 0; iFeaturePtr < m_features.size(); iFeaturePtr++) + features.push_back(m_features.at(iFeaturePtr)); + + for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++) + m_subDevices.at(iSubdevicePtr)->GetFeatures(features); +} + +bool CPeripheral::Initialise(void) +{ + bool bReturn(true); + if (m_bInitialised) + return bReturn; + + g_peripherals.GetSettingsFromMapping(*this); + m_strSettingsFile.Format("special://profile/peripheral_data/%s_%s_%s.xml", PeripheralTypeTranslator::BusTypeToString(m_busType), m_strVendorId, m_strProductId); + LoadPersistedSettings(); + + for (unsigned int iFeaturePtr = 0; iFeaturePtr < m_features.size(); iFeaturePtr++) + { + PeripheralFeature feature = m_features.at(iFeaturePtr); + bReturn &= InitialiseFeature(feature); + } + + for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++) + bReturn &= m_subDevices.at(iSubdevicePtr)->Initialise(); + + if (bReturn) + { + CLog::Log(LOGDEBUG, "%s - initialised peripheral on '%s' with %d features and %d sub devices", __FUNCTION__, m_strLocation.c_str(), m_features.size(), m_subDevices.size()); + m_bInitialised = true; + } + + return bReturn; +} + +void CPeripheral::GetSubdevices(vector &subDevices) const +{ + for (unsigned int iSubdevicePtr = 0; iSubdevicePtr < m_subDevices.size(); iSubdevicePtr++) + subDevices.push_back(m_subDevices.at(iSubdevicePtr)); +} + +bool CPeripheral::IsMultiFunctional(void) const +{ + return m_subDevices.size() > 0; +} + +void CPeripheral::AddSetting(const CStdString &strKey, const CSetting *setting) +{ + if (!setting) + { + CLog::Log(LOGERROR, "%s - invalid setting", __FUNCTION__); + return; + } + + if (!HasSetting(strKey)) + { + switch(setting->GetType()) + { + case SETTINGS_TYPE_BOOL: + { + const CSettingBool *mappedSetting = (const CSettingBool *) setting; + CSettingBool *boolSetting = new CSettingBool(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->GetControlType()); + if (boolSetting) + { + boolSetting->SetVisible(mappedSetting->IsVisible()); + m_settings.insert(make_pair(strKey, boolSetting)); + } + } + break; + case SETTINGS_TYPE_INT: + { + const CSettingInt *mappedSetting = (const CSettingInt *) setting; + CSettingInt *intSetting = new CSettingInt(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_iMin, mappedSetting->m_iStep, mappedSetting->m_iMax, mappedSetting->GetControlType(), mappedSetting->m_strFormat); + if (intSetting) + { + intSetting->SetVisible(mappedSetting->IsVisible()); + m_settings.insert(make_pair(strKey, intSetting)); + } + } + break; + case SETTINGS_TYPE_FLOAT: + { + const CSettingFloat *mappedSetting = (const CSettingFloat *) setting; + CSettingFloat *floatSetting = new CSettingFloat(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData(), mappedSetting->m_fMin, mappedSetting->m_fStep, mappedSetting->m_fMax, mappedSetting->GetControlType()); + if (floatSetting) + { + floatSetting->SetVisible(mappedSetting->IsVisible()); + m_settings.insert(make_pair(strKey, floatSetting)); + } + } + break; + case SETTINGS_TYPE_STRING: + { + const CSettingString *mappedSetting = (const CSettingString *) setting; + CSettingString *stringSetting = new CSettingString(0, strKey.c_str(), mappedSetting->GetLabel(), mappedSetting->GetData().c_str(), mappedSetting->GetControlType(), mappedSetting->m_bAllowEmpty, mappedSetting->m_iHeadingString); + if (stringSetting) + { + stringSetting->SetVisible(mappedSetting->IsVisible()); + m_settings.insert(make_pair(strKey, stringSetting)); + } + } + break; + default: + //TODO add more types if needed + break; + } + } +} + +bool CPeripheral::HasSetting(const CStdString &strKey) const +{ + map:: const_iterator it = m_settings.find(strKey); + return it != m_settings.end(); +} + +bool CPeripheral::HasSettings(void) const +{ + return m_settings.size() > 0; +} + +bool CPeripheral::HasConfigurableSettings(void) const +{ + bool bReturn(false); + map::const_iterator it = m_settings.begin(); + while (it != m_settings.end() && !bReturn) + { + if ((*it).second->IsVisible()) + { + bReturn = true; + break; + } + + ++it; + } + + return bReturn; +} + +bool CPeripheral::GetSettingBool(const CStdString &strKey) const +{ + map::const_iterator it = m_settings.find(strKey); + if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_BOOL) + { + CSettingBool *boolSetting = (CSettingBool *) (*it).second; + if (boolSetting) + return boolSetting->GetData(); + } + + return false; +} + +int CPeripheral::GetSettingInt(const CStdString &strKey) const +{ + map::const_iterator it = m_settings.find(strKey); + if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_INT) + { + CSettingInt *intSetting = (CSettingInt *) (*it).second; + if (intSetting) + return intSetting->GetData(); + } + + return 0; +} + +float CPeripheral::GetSettingFloat(const CStdString &strKey) const +{ + map::const_iterator it = m_settings.find(strKey); + if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_FLOAT) + { + CSettingFloat *floatSetting = (CSettingFloat *) (*it).second; + if (floatSetting) + return floatSetting->GetData(); + } + + return 0; +} + +const CStdString CPeripheral::GetSettingString(const CStdString &strKey) const +{ + map::const_iterator it = m_settings.find(strKey); + if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_STRING) + { + CSettingString *stringSetting = (CSettingString *) (*it).second; + if (stringSetting) + return stringSetting->GetData(); + } + + return StringUtils::EmptyString; +} + +void CPeripheral::SetSetting(const CStdString &strKey, bool bValue) +{ + map::iterator it = m_settings.find(strKey); + if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_BOOL) + { + CSettingBool *boolSetting = (CSettingBool *) (*it).second; + if (boolSetting) + { + bool bChanged(boolSetting->GetData() != bValue); + boolSetting->SetData(bValue); + if (bChanged) + OnSettingChanged(strKey); + } + } +} + +void CPeripheral::SetSetting(const CStdString &strKey, int iValue) +{ + map::iterator it = m_settings.find(strKey); + if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_INT) + { + CSettingInt *intSetting = (CSettingInt *) (*it).second; + if (intSetting) + { + bool bChanged(intSetting->GetData() != iValue); + intSetting->SetData(iValue); + if (bChanged) + OnSettingChanged(strKey); + } + } +} + +void CPeripheral::SetSetting(const CStdString &strKey, float fValue) +{ + map::iterator it = m_settings.find(strKey); + if (it != m_settings.end() && (*it).second->GetType() == SETTINGS_TYPE_FLOAT) + { + CSettingFloat *floatSetting = (CSettingFloat *) (*it).second; + if (floatSetting) + { + bool bChanged(floatSetting->GetData() != fValue); + floatSetting->SetData(fValue); + if (bChanged) + OnSettingChanged(strKey); + } + } +} + +void CPeripheral::SetSetting(const CStdString &strKey, const CStdString &strValue) +{ + map::iterator it = m_settings.find(strKey); + if (it != m_settings.end()) + { + if ((*it).second->GetType() == SETTINGS_TYPE_STRING) + { + CSettingString *stringSetting = (CSettingString *) (*it).second; + if (stringSetting) + { + bool bChanged(!stringSetting->GetData().Equals(strValue)); + stringSetting->SetData(strValue); + if (bChanged) + OnSettingChanged(strKey); + } + } + else if ((*it).second->GetType() == SETTINGS_TYPE_INT) + SetSetting(strKey, (int) (strValue.IsEmpty() ? 0 : atoi(strValue.c_str()))); + else if ((*it).second->GetType() == SETTINGS_TYPE_FLOAT) + SetSetting(strKey, (float) (strValue.IsEmpty() ? 0 : atof(strValue.c_str()))); + else if ((*it).second->GetType() == SETTINGS_TYPE_BOOL) + SetSetting(strKey, strValue.Equals("1")); + } +} + +void CPeripheral::PersistSettings(void) const +{ + TiXmlDocument doc; + TiXmlElement node("settings"); + doc.InsertEndChild(node); + for (map::const_iterator itr = m_settings.begin(); itr != m_settings.end(); itr++) + { + TiXmlElement nodeSetting("setting"); + nodeSetting.SetAttribute("id", itr->first.c_str()); + CStdString strValue; + switch ((*itr).second->GetType()) + { + case SETTINGS_TYPE_STRING: + { + CSettingString *stringSetting = (CSettingString *) (*itr).second; + if (stringSetting) + strValue = stringSetting->GetData(); + } + break; + case SETTINGS_TYPE_INT: + { + CSettingInt *intSetting = (CSettingInt *) (*itr).second; + if (intSetting) + strValue.Format("%d", intSetting->GetData()); + } + break; + case SETTINGS_TYPE_FLOAT: + { + CSettingFloat *floatSetting = (CSettingFloat *) (*itr).second; + if (floatSetting) + strValue.Format("%.2f", floatSetting->GetData()); + } + break; + case SETTINGS_TYPE_BOOL: + { + CSettingBool *boolSetting = (CSettingBool *) (*itr).second; + if (boolSetting) + strValue.Format("%d", boolSetting->GetData() ? 1:0); + } + break; + default: + break; + } + nodeSetting.SetAttribute("value", strValue.c_str()); + doc.RootElement()->InsertEndChild(nodeSetting); + } + + doc.SaveFile(m_strSettingsFile); +} + +void CPeripheral::LoadPersistedSettings(void) +{ + TiXmlDocument doc; + if (doc.LoadFile(m_strSettingsFile)) + { + const TiXmlElement *setting = doc.RootElement()->FirstChildElement("setting"); + while (setting) + { + CStdString strId(setting->Attribute("id")); + CStdString strValue(setting->Attribute("value")); + SetSetting(strId, strValue); + + setting = setting->NextSiblingElement("setting"); + } + } +} + +void CPeripheral::ResetDefaultSettings(void) +{ + ClearSettings(); + g_peripherals.GetSettingsFromMapping(*this); + OnSettingsChanged(); +} + +void CPeripheral::ClearSettings(void) +{ + map::iterator it = m_settings.begin(); + while (it != m_settings.end()) + { + delete (*it).second; + ++it; + } + m_settings.clear(); +} + +void CPeripheral::OnSettingsChanged(void) +{ + map::iterator it = m_settings.begin(); + while (it != m_settings.end()) + { + OnSettingChanged((*it).first); + ++it; + } +} diff --git a/xbmc/peripherals/devices/Peripheral.h b/xbmc/peripherals/devices/Peripheral.h new file mode 100644 index 0000000000000..f0881c1f98a2b --- /dev/null +++ b/xbmc/peripherals/devices/Peripheral.h @@ -0,0 +1,169 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include +#include "utils/StdString.h" +#include "peripherals/PeripheralTypes.h" + +class TiXmlDocument; + +namespace PERIPHERALS +{ + class CGUIDialogPeripheralSettings; + + class CPeripheral + { + friend class CGUIDialogPeripheralSettings;; + + public: + CPeripheral(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); + CPeripheral(void); + virtual ~CPeripheral(void); + + bool operator ==(const CPeripheral &right) const; + bool operator !=(const CPeripheral &right) const; + + const CStdString &FileLocation(void) const { return m_strFileLocation; } + const CStdString &Location(void) const { return m_strLocation; } + int VendorId(void) const { return m_iVendorId; } + const char *VendorIdAsString(void) const { return m_strVendorId; } + int ProductId(void) const { return m_iProductId; } + const char *ProductIdAsString(void) const { return m_strProductId; } + const PeripheralType Type(void) const { return m_type; } + const PeripheralBusType GetBusType(void) const { return m_busType; }; + const CStdString &DeviceName(void) const { return m_strDeviceName; } + bool IsHidden(void) const { return m_bHidden; } + void SetHidden(bool bSetTo = true) { m_bHidden = bSetTo; } + + /*! + * @brief Check whether this device has the given feature. + * @param feature The feature to check for. + * @return True when the device has the feature, false otherwise. + */ + bool HasFeature(const PeripheralFeature feature) const; + + /*! + * @brief Get all features that are supported by this device. + * @param features The features. + */ + void GetFeatures(std::vector &features) const; + + /*! + * @brief Initialises the peripheral. + * @return True when the peripheral has been initialised succesfully, false otherwise. + */ + bool Initialise(void); + + /*! + * @brief Initialise one of the features of this peripheral. + * @param feature The feature to initialise. + * @return True when the feature has been initialised succesfully, false otherwise. + */ + virtual bool InitialiseFeature(const PeripheralFeature feature) { return true; } + + /*! + * @brief Called when a setting changed. + * @param strChangedSetting The changed setting. + */ + virtual void OnSettingChanged(const CStdString &strChangedSetting) {}; + + /*! + * @brief Called when one or more settings changed. Calls OnSettingChanged for every setting. + */ + virtual void OnSettingsChanged(void); + + /*! + * @brief Get all subdevices if this device is multifunctional. + * @param subDevices The subdevices. + */ + virtual void GetSubdevices(std::vector &subDevices) const; + + /*! + * @return True when this device is multifunctional, false otherwise. + */ + virtual bool IsMultiFunctional(void) const; + + /*! + * @brief Add a setting to this peripheral. This will overwrite a previous setting with the same key. + * @param strKey The key of the setting. + * @param setting The setting. + */ + virtual void AddSetting(const CStdString &strKey, const CSetting *setting); + + /*! + * @brief Check whether a setting is known with the given key. + * @param strKey The key to search. + * @return True when found, false otherwise. + */ + virtual bool HasSetting(const CStdString &strKey) const; + + /*! + * @return True when this device has any settings, false otherwise. + */ + virtual bool HasSettings(void) const; + + /*! + * @return True when this device has any configurable settings, false otherwise. + */ + virtual bool HasConfigurableSettings(void) const; + + /*! + * @brief Get the value of a setting. + * @param strKey The key to search. + * @return The value or an empty string if it wasn't found. + */ + virtual const CStdString GetSettingString(const CStdString &strKey) const; + virtual void SetSetting(const CStdString &strKey, const CStdString &strValue); + + virtual int GetSettingInt(const CStdString &strKey) const; + virtual void SetSetting(const CStdString &strKey, int iValue); + + virtual bool GetSettingBool(const CStdString &strKey) const; + virtual void SetSetting(const CStdString &strKey, bool bValue); + + virtual float GetSettingFloat(const CStdString &strKey) const; + virtual void SetSetting(const CStdString &strKey, float fValue); + + virtual void PersistSettings(void) const; + virtual void LoadPersistedSettings(void); + virtual void ResetDefaultSettings(void); + + protected: + virtual void ClearSettings(void); + + PeripheralType m_type; + PeripheralBusType m_busType; + CStdString m_strLocation; + CStdString m_strDeviceName; + CStdString m_strSettingsFile; + CStdString m_strFileLocation; + int m_iVendorId; + char * m_strVendorId; + int m_iProductId; + char * m_strProductId; + bool m_bInitialised; + bool m_bHidden; + std::vector m_features; + std::vector m_subDevices; + std::map m_settings; + }; +} diff --git a/xbmc/peripherals/devices/PeripheralBluetooth.cpp b/xbmc/peripherals/devices/PeripheralBluetooth.cpp new file mode 100644 index 0000000000000..745bba6c87fe6 --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralBluetooth.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralBluetooth.h" +#include "utils/log.h" + +using namespace PERIPHERALS; + +CPeripheralBluetooth::CPeripheralBluetooth(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId) : + CPeripheral(type, busType, strLocation, strDeviceName, iVendorId, iProductId) +{ + m_features.push_back(FEATURE_BLUETOOTH); +} diff --git a/xbmc/input/KeymapLoader.h b/xbmc/peripherals/devices/PeripheralBluetooth.h similarity index 66% rename from xbmc/input/KeymapLoader.h rename to xbmc/peripherals/devices/PeripheralBluetooth.h index 4c57ef5e9181e..7a11cd4adc642 100644 --- a/xbmc/input/KeymapLoader.h +++ b/xbmc/peripherals/devices/PeripheralBluetooth.h @@ -20,17 +20,14 @@ * */ -#include -#include "utils/StdString.h" +#include "Peripheral.h" -class CKeymapLoader +namespace PERIPHERALS { + class CPeripheralBluetooth : public CPeripheral + { public: - static void DeviceRemoved(const CStdString& deviceID); - static void DeviceAdded(const CStdString& deviceID); - static CStdString ParseWin32HIDName(const CStdString& deviceLongName); - private: - static void ParseDeviceMappings(); - static bool FindMappedDevice(const CStdString& deviceId, CStdString& keymapName); - static bool parsedMappings; -}; \ No newline at end of file + CPeripheralBluetooth(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); + virtual ~CPeripheralBluetooth(void) {}; + }; +} diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp new file mode 100644 index 0000000000000..a78e24dc6e920 --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralCecAdapter.h" +#include "utils/log.h" + +using namespace PERIPHERALS; +using namespace ANNOUNCEMENT; + +CPeripheralCecAdapter::CPeripheralCecAdapter(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId) : + CPeripheral(type, busType, strLocation, strDeviceName, iVendorId, iProductId) +{ + m_features.push_back(FEATURE_CEC); +} + +CPeripheralCecAdapter::~CPeripheralCecAdapter(void) +{ + CAnnouncementManager::RemoveAnnouncer(this); +} + +void CPeripheralCecAdapter::Announce(EAnnouncementFlag flag, const char *sender, const char *message, const CVariant &data) +{ + if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "ApplicationStop")) + { + ScreenSetPower(false); + } +} + +bool CPeripheralCecAdapter::ScreenSetPower(bool bSetTo) +{ + // TODO + return false; +} + +bool CPeripheralCecAdapter::InitialiseFeature(const PeripheralFeature feature) +{ + if (feature == FEATURE_CEC) + CAnnouncementManager::AddAnnouncer(this); + + return CPeripheral::InitialiseFeature(feature); +} diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h new file mode 100644 index 0000000000000..8b8c6c8d8c43f --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Peripheral.h" +#include "interfaces/AnnouncementManager.h" + +namespace PERIPHERALS +{ + class CPeripheralCecAdapter : public CPeripheral, public ANNOUNCEMENT::IAnnouncer + { + public: + CPeripheralCecAdapter(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); + virtual ~CPeripheralCecAdapter(void); + + virtual void Announce(ANNOUNCEMENT::EAnnouncementFlag flag, const char *sender, const char *message, const CVariant &data); + bool ScreenSetPower(bool bSetTo); + + protected: + virtual bool InitialiseFeature(const PeripheralFeature feature); + }; +} diff --git a/xbmc/peripherals/devices/PeripheralDisk.cpp b/xbmc/peripherals/devices/PeripheralDisk.cpp new file mode 100644 index 0000000000000..f15ab16e2e102 --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralDisk.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralDisk.h" +#include "guilib/LocalizeStrings.h" + +using namespace PERIPHERALS; + +CPeripheralDisk::CPeripheralDisk(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId) : + CPeripheral(type, busType, strLocation, strDeviceName.IsEmpty() ? g_localizeStrings.Get(35003) : strDeviceName, iVendorId, iProductId) +{ + m_features.push_back(FEATURE_DISK); +} diff --git a/xbmc/peripherals/devices/PeripheralDisk.h b/xbmc/peripherals/devices/PeripheralDisk.h new file mode 100644 index 0000000000000..196b9cab830dd --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralDisk.h @@ -0,0 +1,33 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Peripheral.h" + +namespace PERIPHERALS +{ + class CPeripheralDisk : public CPeripheral + { + public: + CPeripheralDisk(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); + virtual ~CPeripheralDisk(void) {}; + }; +} diff --git a/xbmc/peripherals/devices/PeripheralHID.cpp b/xbmc/peripherals/devices/PeripheralHID.cpp new file mode 100644 index 0000000000000..da590d54ff23a --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralHID.cpp @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralHID.h" +#include "utils/log.h" +#include "settings/Settings.h" +#include "guilib/LocalizeStrings.h" + +using namespace PERIPHERALS; +using namespace std; + +CPeripheralHID::CPeripheralHID(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId) : + CPeripheral(type, busType, strLocation, strDeviceName.IsEmpty() ? g_localizeStrings.Get(35001) : strDeviceName, iVendorId, iProductId), + m_bInitialised(false) +{ + m_features.push_back(FEATURE_HID); +} + +CPeripheralHID::~CPeripheralHID(void) +{ + if (!m_strKeymap.IsEmpty() && GetSettingBool("keymap_enabled") && g_settings.m_activeKeyboardMapping.Equals(m_strKeymap)) + { + CLog::Log(LOGDEBUG, "%s - switching active keymapping to: default", __FUNCTION__); + g_settings.m_activeKeyboardMapping = "default"; + } +} + +bool CPeripheralHID::InitialiseFeature(const PeripheralFeature feature) +{ + if (feature == FEATURE_HID && !m_bInitialised) + { + m_bInitialised = true; + + if (HasSetting("keymap")) + m_strKeymap = GetSettingString("keymap"); + + if (m_strKeymap.IsEmpty()) + { + m_strKeymap.Format("v%sp%s", VendorIdAsString(), ProductIdAsString()); + SetSetting("keymap", m_strKeymap); + } + + if (!m_strKeymap.IsEmpty()) + { + bool bKeymapEnabled(GetSettingBool("keymap_enabled")); + if (bKeymapEnabled) + { + CLog::Log(LOGDEBUG, "%s - switching active keymapping to: %s", __FUNCTION__, m_strKeymap.c_str()); + g_settings.m_activeKeyboardMapping = m_strKeymap; + } + else if (!bKeymapEnabled && g_settings.m_activeKeyboardMapping.Equals(m_strKeymap)) + { + CLog::Log(LOGDEBUG, "%s - switching active keymapping to: default", __FUNCTION__); + g_settings.m_activeKeyboardMapping = "default"; + } + } + + CLog::Log(LOGDEBUG, "%s - initialised HID device (%s:%s)", __FUNCTION__, m_strVendorId, m_strProductId); + } + + return CPeripheral::InitialiseFeature(feature); +} + +void CPeripheralHID::OnSettingChanged(const CStdString &strChangedSetting) +{ + if (m_bInitialised && ((strChangedSetting.Equals("keymap") && GetSettingBool("keymap_enabled")) || strChangedSetting.Equals("keymap_enabled"))) + { + m_bInitialised = false; + InitialiseFeature(FEATURE_HID); + } +} + diff --git a/xbmc/peripherals/devices/PeripheralHID.h b/xbmc/peripherals/devices/PeripheralHID.h new file mode 100644 index 0000000000000..93515c88ff069 --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralHID.h @@ -0,0 +1,41 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Peripheral.h" +#include "input/XBMC_keyboard.h" + +namespace PERIPHERALS +{ + class CPeripheralHID : public CPeripheral + { + public: + CPeripheralHID(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); + virtual ~CPeripheralHID(void); + virtual bool InitialiseFeature(const PeripheralFeature feature); + virtual bool LookupSymAndUnicode(XBMC_keysym &keysym, uint8_t *key, char *unicode) { return false; } + virtual void OnSettingChanged(const CStdString &strChangedSetting); + + protected: + bool m_bInitialised; + CStdString m_strKeymap; + }; +} diff --git a/xbmc/peripherals/devices/PeripheralNIC.cpp b/xbmc/peripherals/devices/PeripheralNIC.cpp new file mode 100644 index 0000000000000..02210c8fab883 --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralNIC.cpp @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralNIC.h" +#include "utils/log.h" +#include "guilib/LocalizeStrings.h" + +using namespace PERIPHERALS; +using namespace std; + +CPeripheralNIC::CPeripheralNIC(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId) : + CPeripheral(type, busType, strLocation, strDeviceName.IsEmpty() ? g_localizeStrings.Get(35002) : strDeviceName, iVendorId, iProductId) +{ + m_features.push_back(FEATURE_NIC); +} diff --git a/xbmc/peripherals/devices/PeripheralNIC.h b/xbmc/peripherals/devices/PeripheralNIC.h new file mode 100644 index 0000000000000..f645a729f1211 --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralNIC.h @@ -0,0 +1,33 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Peripheral.h" + +namespace PERIPHERALS +{ + class CPeripheralNIC : public CPeripheral + { + public: + CPeripheralNIC(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); + virtual ~CPeripheralNIC(void) {}; + }; +} diff --git a/xbmc/peripherals/devices/PeripheralNyxboard.cpp b/xbmc/peripherals/devices/PeripheralNyxboard.cpp new file mode 100644 index 0000000000000..4ba895b1a486d --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralNyxboard.cpp @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralNyxboard.h" +#include "PeripheralHID.h" +#include "guilib/Key.h" +#include "utils/log.h" +#include "interfaces/Builtins.h" + +using namespace PERIPHERALS; +using namespace std; + +CPeripheralNyxboard::CPeripheralNyxboard(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId) : + CPeripheralHID(type, busType, strLocation, strDeviceName, iVendorId, iProductId) +{ + m_features.push_back(FEATURE_NYXBOARD); +} + +bool CPeripheralNyxboard::LookupSymAndUnicode(XBMC_keysym &keysym, uint8_t *key, char *unicode) +{ + CStdString strCommand; + if (keysym.sym == XBMCK_F7 && keysym.mod == XBMCKMOD_NONE && GetSettingBool("enable_flip_commands")) + { + /* switched to keyboard side */ + CLog::Log(LOGDEBUG, "%s - switched to keyboard side", __FUNCTION__); + strCommand = GetSettingString("flip_keyboard"); + } + else if (keysym.sym == XBMCK_F7 && keysym.mod == XBMCKMOD_LCTRL && GetSettingBool("enable_flip_commands")) + { + /* switched to remote side */ + CLog::Log(LOGDEBUG, "%s - switched to remote side", __FUNCTION__); + strCommand = GetSettingString("flip_remote"); + } + else if (keysym.sym == XBMCK_F4 && keysym.mod == XBMCKMOD_NONE) + { + /* 'user' key pressed */ + CLog::Log(LOGDEBUG, "%s - 'user' key pressed", __FUNCTION__); + strCommand = GetSettingString("key_user"); + } + + if (!strCommand.IsEmpty()) + { + CLog::Log(LOGDEBUG, "%s - executing command '%s'", __FUNCTION__, strCommand.c_str()); + CBuiltins::Execute(strCommand); + + *key = 0; + *unicode = (char) 0; + return true; + } + + return false; +} diff --git a/xbmc/peripherals/devices/PeripheralNyxboard.h b/xbmc/peripherals/devices/PeripheralNyxboard.h new file mode 100644 index 0000000000000..cec51e64ee36f --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralNyxboard.h @@ -0,0 +1,34 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralHID.h" + +namespace PERIPHERALS +{ + class CPeripheralNyxboard : public CPeripheralHID + { + public: + CPeripheralNyxboard(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); + virtual ~CPeripheralNyxboard(void) {}; + virtual bool LookupSymAndUnicode(XBMC_keysym &keysym, uint8_t *key, char *unicode); + }; +} diff --git a/xbmc/peripherals/devices/PeripheralTuner.cpp b/xbmc/peripherals/devices/PeripheralTuner.cpp new file mode 100644 index 0000000000000..3a147d5050ed3 --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralTuner.cpp @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralTuner.h" +#include "utils/log.h" + +using namespace PERIPHERALS; + +CPeripheralTuner::CPeripheralTuner(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId) : + CPeripheral(type, busType, strLocation, strDeviceName, iVendorId, iProductId) +{ + m_features.push_back(FEATURE_TUNER); +} diff --git a/xbmc/peripherals/devices/PeripheralTuner.h b/xbmc/peripherals/devices/PeripheralTuner.h new file mode 100644 index 0000000000000..08d8f74fe9429 --- /dev/null +++ b/xbmc/peripherals/devices/PeripheralTuner.h @@ -0,0 +1,33 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "Peripheral.h" + +namespace PERIPHERALS +{ + class CPeripheralTuner : public CPeripheral + { + public: + CPeripheralTuner(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); + virtual ~CPeripheralTuner(void) {}; + }; +} diff --git a/xbmc/peripherals/dialogs/GUIDialogPeripheralManager.cpp b/xbmc/peripherals/dialogs/GUIDialogPeripheralManager.cpp new file mode 100644 index 0000000000000..599bacbb168b5 --- /dev/null +++ b/xbmc/peripherals/dialogs/GUIDialogPeripheralManager.cpp @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GUIDialogPeripheralManager.h" +#include "GUIDialogPeripheralSettings.h" +#include "guilib/GUIWindowManager.h" +#include "peripherals/Peripherals.h" +#include "FileItem.h" +#include "guilib/Key.h" +#include "utils/log.h" + +#define BUTTON_CLOSE 10 +#define BUTTON_SETTINGS 11 +#define CONTROL_LIST 20 + +using namespace std; +using namespace PERIPHERALS; + +CGUIDialogPeripheralManager::CGUIDialogPeripheralManager(void) : + CGUIDialog(WINDOW_DIALOG_PERIPHERAL_MANAGER, "DialogPeripheralManager.xml"), + m_iSelected(0), + m_peripheralItems(new CFileItemList) +{ +} + +CGUIDialogPeripheralManager::~CGUIDialogPeripheralManager(void) +{ + delete m_peripheralItems; +} + +bool CGUIDialogPeripheralManager::OnAction(const CAction &action) +{ + int iActionId = action.GetID(); + if (iActionId == ACTION_PREVIOUS_MENU || iActionId == ACTION_PARENT_DIR) + { + Close(); + return true; + } + else if (GetFocusedControlID() == CONTROL_LIST && + (iActionId == ACTION_MOVE_DOWN || iActionId == ACTION_MOVE_UP || + iActionId == ACTION_PAGE_DOWN || iActionId == ACTION_PAGE_UP)) + { + CGUIDialog::OnAction(action); + int iSelected = m_viewControl.GetSelectedItem(); + if (iSelected != m_iSelected) + m_iSelected = iSelected; + UpdateButtons(); + return true; + } + + return CGUIDialog::OnAction(action); +} + +bool CGUIDialogPeripheralManager::OnMessageInit(CGUIMessage &message) +{ + CGUIWindow::OnMessage(message); + m_iSelected = 0; + Update(); + + return true; +} + +bool CGUIDialogPeripheralManager::OnClickList(CGUIMessage &message) +{ + if (CurrentItemHasSettings()) + return OpenSettingsDialog(); + + return true; +} + +bool CGUIDialogPeripheralManager::OnClickButtonClose(CGUIMessage &message) +{ + Close(); + return true; +} + +bool CGUIDialogPeripheralManager::OnClickButtonSettings(CGUIMessage &message) +{ + return OpenSettingsDialog(); +} + +bool CGUIDialogPeripheralManager::OpenSettingsDialog(void) +{ + CGUIDialogPeripheralSettings *dialog = (CGUIDialogPeripheralSettings *)g_windowManager.GetWindow(WINDOW_DIALOG_PERIPHERAL_SETTINGS); + if (dialog) + { + dialog->SetFileItem(GetCurrentListItem()); + dialog->DoModal(); + return true; + } + + return false; +} + +bool CGUIDialogPeripheralManager::OnMessageClick(CGUIMessage &message) +{ + int iControl = message.GetSenderId(); + switch(iControl) + { + case CONTROL_LIST: + return OnClickList(message); + case BUTTON_CLOSE: + return OnClickButtonClose(message); + case BUTTON_SETTINGS: + return OnClickButtonSettings(message); + default: + return false; + } +} + +bool CGUIDialogPeripheralManager::OnMessage(CGUIMessage& message) +{ + unsigned int iMessage = message.GetMessage(); + + switch (iMessage) + { + case GUI_MSG_WINDOW_DEINIT: + Clear(); + break; + case GUI_MSG_ITEM_SELECT: + return true; + case GUI_MSG_WINDOW_INIT: + return OnMessageInit(message); + case GUI_MSG_CLICKED: + return OnMessageClick(message); + } + + return CGUIDialog::OnMessage(message); +} + +void CGUIDialogPeripheralManager::OnWindowLoaded(void) +{ + CGUIDialog::OnWindowLoaded(); + + m_viewControl.Reset(); + m_viewControl.SetParentWindow(GetID()); + const CGUIControl *list = GetControl(CONTROL_LIST); + m_viewControl.AddView(list); +} + +void CGUIDialogPeripheralManager::OnWindowUnload(void) +{ + CGUIDialog::OnWindowUnload(); + m_viewControl.Reset(); +} + +CFileItemPtr CGUIDialogPeripheralManager::GetCurrentListItem(void) const +{ + return m_peripheralItems->Get(m_iSelected); +} + +void CGUIDialogPeripheralManager::Update() +{ + CSingleLock lock(g_graphicsContext); + + m_viewControl.SetCurrentView(CONTROL_LIST); + Clear(); + g_peripherals.GetDirectory("peripherals://all/", *m_peripheralItems); + m_viewControl.SetItems(*m_peripheralItems); + m_viewControl.SetSelectedItem(m_iSelected); + + UpdateButtons(); + CGUIControl *list = (CGUIControl *) GetControl(CONTROL_LIST); + if (list) + list->SetInvalid(); +} + +void CGUIDialogPeripheralManager::Clear(void) +{ + m_viewControl.Clear(); + m_peripheralItems->Clear(); +} + +bool CGUIDialogPeripheralManager::CurrentItemHasSettings(void) const +{ + CSingleLock lock(g_graphicsContext); + CFileItemPtr currentItem = GetCurrentListItem(); + if (!currentItem) + return false; + + CPeripheral *peripheral = g_peripherals.GetByPath(currentItem.get()->GetPath()); + return peripheral && peripheral->HasConfigurableSettings(); +} + +void CGUIDialogPeripheralManager::UpdateButtons(void) +{ + CONTROL_ENABLE_ON_CONDITION(BUTTON_SETTINGS, CurrentItemHasSettings()); +} diff --git a/xbmc/peripherals/dialogs/GUIDialogPeripheralManager.h b/xbmc/peripherals/dialogs/GUIDialogPeripheralManager.h new file mode 100644 index 0000000000000..d682f42a3e329 --- /dev/null +++ b/xbmc/peripherals/dialogs/GUIDialogPeripheralManager.h @@ -0,0 +1,59 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "guilib/GUIDialog.h" +#include "GUIViewControl.h" + +namespace PERIPHERALS +{ + class CGUIDialogPeripheralManager : public CGUIDialog + { + public: + CGUIDialogPeripheralManager(void); + virtual ~CGUIDialogPeripheralManager(void); + virtual bool OnMessage(CGUIMessage& message); + virtual bool OnAction(const CAction& action); + virtual void OnWindowLoaded(void); + virtual void OnWindowUnload(void); + virtual bool HasListItems() const { return true; }; + virtual CFileItemPtr GetCurrentListItem(void) const; + virtual void Update(void); + + protected: + virtual bool OnMessageInit(CGUIMessage &message); + virtual bool OnMessageClick(CGUIMessage &message); + + virtual bool OnClickList(CGUIMessage &message); + virtual bool OnClickButtonClose(CGUIMessage &message); + virtual bool OnClickButtonSettings(CGUIMessage &message); + virtual bool OpenSettingsDialog(void); + virtual bool CurrentItemHasSettings(void) const; + + private: + void Clear(void); + void UpdateButtons(void); + + int m_iSelected; + CFileItemList* m_peripheralItems; + CGUIViewControl m_viewControl; + }; +} diff --git a/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp new file mode 100644 index 0000000000000..8018d5450343e --- /dev/null +++ b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.cpp @@ -0,0 +1,222 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GUIDialogPeripheralSettings.h" +#include "addons/Skin.h" +#include "peripherals/Peripherals.h" +#include "settings/GUISettings.h" +#include "utils/log.h" +#include "video/dialogs/GUIDialogVideoSettings.h" + +using namespace std; +using namespace PERIPHERALS; + +#define BUTTON_DEFAULTS 50 + +CGUIDialogPeripheralSettings::CGUIDialogPeripheralSettings(void) : + CGUIDialogSettings(WINDOW_DIALOG_PERIPHERAL_SETTINGS, "DialogPeripheralSettings.xml"), + m_item(NULL), + m_bIsInitialising(true) +{ +} + +CGUIDialogPeripheralSettings::~CGUIDialogPeripheralSettings(void) +{ + if (m_item) + delete m_item; +} + +void CGUIDialogPeripheralSettings::SetFileItem(CFileItemPtr item) +{ + if (m_item) + { + delete m_item; + m_boolSettings.clear(); + m_intSettings.clear(); + m_floatSettings.clear(); + m_stringSettings.clear(); + m_settings.clear(); + } + + m_item = new CFileItem(*item.get()); +} + +void CGUIDialogPeripheralSettings::CreateSettings() +{ + m_bIsInitialising = true; + m_usePopupSliders = g_SkinInfo->HasSkinFile("DialogSlider.xml"); + + if (m_item) + { + int iIndex = 1; + CPeripheral *peripheral = g_peripherals.GetByPath(m_item->GetPath()); + if (peripheral) + { + map::iterator it = peripheral->m_settings.begin(); + while (it != peripheral->m_settings.end()) + { + CSetting *setting = (*it).second; + if (!setting->IsVisible()) + { + ++it; + CLog::Log(LOGDEBUG, "%s - invisible", __FUNCTION__); + continue; + } + + switch(setting->GetType()) + { + case SETTINGS_TYPE_BOOL: + { + CSettingBool *boolSetting = (CSettingBool *) setting; + if (boolSetting) + { + m_boolSettings.insert(make_pair(CStdString(boolSetting->GetSetting()), boolSetting->GetData())); + AddBool(iIndex++, boolSetting->GetLabel(), &m_boolSettings[boolSetting->GetSetting()], true); + } + } + break; + case SETTINGS_TYPE_INT: + { + CSettingInt *intSetting = (CSettingInt *) setting; + if (intSetting) + { + m_intSettings.insert(make_pair(CStdString(intSetting->GetSetting()), (float) intSetting->GetData())); + AddSlider(iIndex++, intSetting->GetLabel(), &m_intSettings[intSetting->GetSetting()], intSetting->m_iMin, intSetting->m_iStep, intSetting->m_iMax, CGUIDialogVideoSettings::FormatInteger, false); + } + } + break; + case SETTINGS_TYPE_FLOAT: + { + CSettingFloat *floatSetting = (CSettingFloat *) setting; + if (floatSetting) + { + m_floatSettings.insert(make_pair(CStdString(floatSetting->GetSetting()), floatSetting->GetData())); + AddSlider(iIndex++, floatSetting->GetLabel(), &m_floatSettings[floatSetting->GetSetting()], floatSetting->m_fMin, floatSetting->m_fStep, floatSetting->m_fMax, CGUIDialogVideoSettings::FormatFloat, false); + } + } + break; + case SETTINGS_TYPE_STRING: + { + CSettingString *stringSetting = (CSettingString *) setting; + if (stringSetting) + { + m_stringSettings.insert(make_pair(CStdString(stringSetting->GetSetting()), stringSetting->GetData())); + AddString(iIndex, stringSetting->GetLabel(), &m_stringSettings[stringSetting->GetSetting()]); + } + } + break; + default: + //TODO add more types if needed + CLog::Log(LOGDEBUG, "%s - unknown type", __FUNCTION__); + break; + } + ++it; + } + } + else + { + CLog::Log(LOGDEBUG, "%s - no peripheral", __FUNCTION__); + } + } + + m_bIsInitialising = false; +} + +void CGUIDialogPeripheralSettings::UpdatePeripheralSettings(void) +{ + if (!m_item || m_bIsInitialising) + return; + + CPeripheral *peripheral = g_peripherals.GetByPath(m_item->GetPath()); + if (!peripheral) + return; + + map::iterator boolItr = m_boolSettings.begin(); + while (boolItr != m_boolSettings.end()) + { + peripheral->SetSetting((*boolItr).first, (*boolItr).second); + ++boolItr; + } + + map::iterator intItr = m_intSettings.begin(); + while (intItr != m_intSettings.end()) + { + peripheral->SetSetting((*intItr).first, (int) (*intItr).second); + ++intItr; + } + + map::iterator floatItr = m_floatSettings.begin(); + while (floatItr != m_floatSettings.end()) + { + peripheral->SetSetting((*floatItr).first, (*floatItr).second); + ++floatItr; + } + + map::iterator stringItr = m_stringSettings.begin(); + while (stringItr != m_stringSettings.end()) + { + peripheral->SetSetting((*stringItr).first, (*stringItr).second); + ++stringItr; + } +} + +bool CGUIDialogPeripheralSettings::OnMessage(CGUIMessage &message) +{ + if (message.GetMessage() == GUI_MSG_CLICKED && + message.GetSenderId() == BUTTON_DEFAULTS) + { + ResetDefaultSettings(); + return true; + } + + return CGUIDialogSettings::OnMessage(message); +} + +void CGUIDialogPeripheralSettings::OnOkay(void) +{ + UpdatePeripheralSettings(); +} + +void CGUIDialogPeripheralSettings::ResetDefaultSettings(void) +{ + if (m_item) + { + CPeripheral *peripheral = g_peripherals.GetByPath(m_item->GetPath()); + if (!peripheral) + return; + + /* reset the settings in the peripheral */ + peripheral->ResetDefaultSettings(); + + CSingleLock lock(g_graphicsContext); + + /* clear the settings */ + m_boolSettings.clear(); + m_intSettings.clear(); + m_floatSettings.clear(); + m_stringSettings.clear(); + m_settings.clear(); + + /* reinit the window */ + CreateSettings(); + SetupPage(); // will clear the previous controls first + } +} diff --git a/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h new file mode 100644 index 0000000000000..9511e842ba49f --- /dev/null +++ b/xbmc/peripherals/dialogs/GUIDialogPeripheralSettings.h @@ -0,0 +1,50 @@ +#pragma once +/* + * Copyright (C) 2005-2011 Team XBMC + * http://www.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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "guilib/GUIDialog.h" +#include "settings/GUIDialogSettings.h" +#include "FileItem.h" + +namespace PERIPHERALS +{ + class CGUIDialogPeripheralSettings : public CGUIDialogSettings + { + public: + CGUIDialogPeripheralSettings(void); + virtual ~CGUIDialogPeripheralSettings(void); + + virtual void SetFileItem(CFileItemPtr item); + virtual bool OnMessage(CGUIMessage &message); + protected: + virtual void CreateSettings(); + virtual void OnOkay(void); + virtual void ResetDefaultSettings(void); + virtual void UpdatePeripheralSettings(void); + + CFileItem * m_item; + bool m_bIsInitialising; + std::map m_boolSettings; + std::map m_intSettings; + std::map m_floatSettings; + std::map m_stringSettings; + }; +} diff --git a/xbmc/peripherals/dialogs/Makefile b/xbmc/peripherals/dialogs/Makefile new file mode 100644 index 0000000000000..4aa6331efdd12 --- /dev/null +++ b/xbmc/peripherals/dialogs/Makefile @@ -0,0 +1,7 @@ +SRCS=GUIDialogPeripheralSettings.cpp \ + GUIDialogPeripheralManager.cpp + +LIB=peripheral-dialogs.a + +include ../../../Makefile.include +-include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/settings/GUIDialogSettings.cpp b/xbmc/settings/GUIDialogSettings.cpp index a1ac08d63f96c..609a2999040fc 100644 --- a/xbmc/settings/GUIDialogSettings.cpp +++ b/xbmc/settings/GUIDialogSettings.cpp @@ -28,6 +28,7 @@ #include "guilib/LocalizeStrings.h" #include "GUISettings.h" #include "utils/log.h" +#include "dialogs/GUIDialogKeyboard.h" #define CONTROL_GROUP_LIST 5 #define CONTROL_SETTINGS_LABEL 2 @@ -190,6 +191,14 @@ void CGUIDialogSettings::UpdateSetting(unsigned int id) if (m_usePopupSliders && setting.data && setting.formatFunction) SET_CONTROL_LABEL2(controlID,setting.formatFunction(*(float *)setting.data, setting.interval)); } + else if (setting.type == SettingInfo::STRING) + { + SET_CONTROL_LABEL(controlID, setting.name); + string strNewValue = string(*(CStdString *)setting.data); + if (strNewValue.empty()) + strNewValue = "-"; + SET_CONTROL_LABEL2(controlID, strNewValue); + } if (setting.enabled) { @@ -251,6 +260,14 @@ void CGUIDialogSettings::OnClick(int iID) if (setting.formatFunction) SET_CONTROL_LABEL2(iID, setting.formatFunction(*(float *)setting.data, setting.interval)); } + else if (setting.type == SettingInfo::STRING) + { + CGUIDialogKeyboard::ShowAndGetInput(*(CStdString *) setting.data, true); + string strNewValue = string(*(CStdString *)setting.data); + if (strNewValue.empty()) + strNewValue = "-"; + SET_CONTROL_LABEL2(iID, strNewValue); + } OnSettingChanged(setting); } @@ -317,6 +334,17 @@ void CGUIDialogSettings::AddSetting(SettingInfo &setting, float width, int iCont ((CGUISettingsSliderControl *)pControl)->SetFloatInterval(setting.interval); if (setting.data) ((CGUISettingsSliderControl *)pControl)->SetFloatValue(*(float *)setting.data); } + if (setting.type == SettingInfo::STRING && m_pOriginalSettingsButton) + { + pControl = new CGUIButtonControl(*m_pOriginalSettingsButton); + if (!pControl) return ; + ((CGUIButtonControl *)pControl)->SetLabel(setting.name); + string strValue = string(*(CStdString *)setting.data); + if (strValue.empty()) + strValue = "-"; + ((CGUIButtonControl *)pControl)->SetLabel2(strValue); + pControl->SetWidth(width); + } if (!pControl) return; pControl->SetID(iControlID); @@ -346,6 +374,17 @@ void CGUIDialogSettings::AddButton(unsigned int id, int label, float *current, f m_settings.push_back(setting); } +void CGUIDialogSettings::AddString(unsigned int id, int label, CStdString *current) +{ + SettingInfo setting; + setting.id = id; + setting.name = g_localizeStrings.Get(label); + setting.type = SettingInfo::STRING; + setting.data = current; + setting.enabled = true; + m_settings.push_back(setting); +} + void CGUIDialogSettings::AddBool(unsigned int id, int label, bool *on, bool enabled) { SettingInfo setting; diff --git a/xbmc/settings/GUIDialogSettings.h b/xbmc/settings/GUIDialogSettings.h index 628c90705b6b4..9768bf3a5b06f 100644 --- a/xbmc/settings/GUIDialogSettings.h +++ b/xbmc/settings/GUIDialogSettings.h @@ -35,7 +35,7 @@ typedef CStdString (*FORMATFUNCTION) (float value, float min); class SettingInfo { public: - enum SETTING_TYPE { NONE=0, BUTTON, CHECK, CHECK_UCHAR, SPIN, SLIDER, SEPARATOR }; + enum SETTING_TYPE { NONE=0, BUTTON, CHECK, CHECK_UCHAR, SPIN, SLIDER, SEPARATOR, STRING }; SettingInfo() { id = 0; @@ -85,6 +85,7 @@ class CGUIDialogSettings : void AddButton(unsigned int id, int label, float *current = NULL, float min = 0, float interval = 0, float max = 0, FORMATFUNCTION function = NULL); void AddBool(unsigned int id, int label, bool *on, bool enabled = true); + void AddString(unsigned int id, int label, CStdString *current); void AddSpin(unsigned int id, int label, int *current, unsigned int max, const int *entries); void AddSpin(unsigned int id, int label, int *current, unsigned int min, unsigned int max, const char* minLabel = NULL); void AddSpin(unsigned int id, int label, int *current, std::vector > &values); diff --git a/xbmc/settings/GUISettings.cpp b/xbmc/settings/GUISettings.cpp index c94e9d9626196..9acee6fb6d066 100644 --- a/xbmc/settings/GUISettings.cpp +++ b/xbmc/settings/GUISettings.cpp @@ -85,7 +85,7 @@ void CSettingBool::FromString(const CStdString &strValue) m_bData = (strValue == "true"); } -CStdString CSettingBool::ToString() +CStdString CSettingBool::ToString() const { return m_bData ? "true" : "false"; } @@ -109,7 +109,7 @@ void CSettingFloat::FromString(const CStdString &strValue) SetData((float)atof(strValue.c_str())); } -CStdString CSettingFloat::ToString() +CStdString CSettingFloat::ToString() const { CStdString strValue; strValue.Format("%f", m_fData); @@ -162,7 +162,7 @@ void CSettingInt::FromString(const CStdString &strValue) SetData(id); } -CStdString CSettingInt::ToString() +CStdString CSettingInt::ToString() const { CStdString strValue; strValue.Format("%i", m_iData); @@ -176,7 +176,7 @@ void CSettingHex::FromString(const CStdString &strValue) SetData(iHexValue); } -CStdString CSettingHex::ToString() +CStdString CSettingHex::ToString() const { CStdString strValue; strValue.Format("%x", m_iData); @@ -196,7 +196,7 @@ void CSettingString::FromString(const CStdString &strValue) m_strData = strValue; } -CStdString CSettingString::ToString() +CStdString CSettingString::ToString() const { return m_strData; } @@ -467,6 +467,7 @@ void CGUISettings::Initialize() #endif CSettingsCategory* in = AddCategory(4, "input", 14094); + AddString(in, "input.peripherals", 35000, "", BUTTON_CONTROL_STANDARD); #if defined(__APPLE__) map remotemode; remotemode.insert(make_pair(13610,APPLE_REMOTE_DISABLED)); @@ -1085,7 +1086,7 @@ void CGUISettings::AddDefaultAddon(CSettingsCategory* cat, const char *strSettin settingsMap.insert(pair(CStdString(strSetting).ToLower(), pSetting)); } -const CStdString &CGUISettings::GetString(const char *strSetting, bool bPrompt) const +const CStdString &CGUISettings::GetString(const char *strSetting, bool bPrompt /* = true */) const { ASSERT(settingsMap.size()); constMapIter it = settingsMap.find(CStdString(strSetting).ToLower()); diff --git a/xbmc/settings/GUISettings.h b/xbmc/settings/GUISettings.h index 6925bdc8496f6..869e3361fda27 100644 --- a/xbmc/settings/GUISettings.h +++ b/xbmc/settings/GUISettings.h @@ -221,19 +221,20 @@ class CSetting m_visible = true; }; virtual ~CSetting() {}; - virtual int GetType() { return 0; }; - int GetControlType() { return m_iControlType; }; + virtual int GetType() const { return 0; }; + int GetControlType() const { return m_iControlType; }; virtual void FromString(const CStdString &strValue) {}; - virtual CStdString ToString() { return ""; }; - const char *GetSetting() { return m_strSetting.c_str(); }; - int GetLabel() { return m_iLabel; }; + virtual CStdString ToString() const { return ""; }; + const char *GetSetting() const { return m_strSetting.c_str(); }; + int GetLabel() const { return m_iLabel; }; int GetOrder() const { return m_iOrder; }; + void SetOrder(int iOrder) { m_iOrder = iOrder; }; void SetAdvanced() { m_advanced = true; }; - bool IsAdvanced() { return m_advanced; }; + bool IsAdvanced() const { return m_advanced; }; // A setting might be invisible in the current session, yet carried over // in the config file. void SetVisible(bool visible) { m_visible = visible; } - bool IsVisible() { return m_visible; } + bool IsVisible() const { return m_visible; } private: int m_iControlType; int m_iLabel; @@ -249,9 +250,9 @@ class CSettingBool : public CSetting CSettingBool(int iOrder, const char *strSetting, int iLabel, bool bData, int iControlType): CSetting(iOrder, strSetting, iLabel, iControlType) { m_bData = bData; }; virtual ~CSettingBool() {}; - virtual int GetType() { return SETTINGS_TYPE_BOOL; }; + virtual int GetType() const { return SETTINGS_TYPE_BOOL; }; virtual void FromString(const CStdString &strValue); - virtual CStdString ToString(); + virtual CStdString ToString() const; void SetData(bool bData) { m_bData = bData; }; bool GetData() const { return m_bData; }; @@ -266,12 +267,12 @@ class CSettingFloat : public CSetting CSettingFloat(int iOrder, const char *strSetting, int iLabel, float fData, float fMin, float fStep, float fMax, int iControlType); virtual ~CSettingFloat() {}; - virtual int GetType() { return SETTINGS_TYPE_FLOAT; }; + virtual int GetType() const { return SETTINGS_TYPE_FLOAT; }; virtual void FromString(const CStdString &strValue); - virtual CStdString ToString(); + virtual CStdString ToString() const; void SetData(float fData) { m_fData = fData; if (m_fData < m_fMin) m_fData = m_fMin; if (m_fData > m_fMax) m_fData = m_fMax;}; -float GetData() const { return m_fData; }; + float GetData() const { return m_fData; }; float m_fMin; float m_fStep; @@ -289,9 +290,9 @@ class CSettingInt : public CSetting CSettingInt(int iOrder, const char *strSetting, int iLabel, int iData, const std::map& entries, int iControlType); virtual ~CSettingInt() {}; - virtual int GetType() { return SETTINGS_TYPE_INT; }; + virtual int GetType() const { return SETTINGS_TYPE_INT; }; virtual void FromString(const CStdString &strValue); - virtual CStdString ToString(); + virtual CStdString ToString() const; void SetData(int iData) { @@ -335,8 +336,8 @@ class CSettingHex : public CSettingInt : CSettingInt(iOrder, strSetting, iLabel, iData, iMin, iStep, iMax, iControlType, strFormat) {}; virtual ~CSettingHex() {}; virtual void FromString(const CStdString &strValue); - virtual CStdString ToString(); - virtual int GetType() { return SETTINGS_TYPE_HEX; }; + virtual CStdString ToString() const; + virtual int GetType() const { return SETTINGS_TYPE_HEX; }; }; class CSettingString : public CSetting @@ -345,9 +346,9 @@ class CSettingString : public CSetting CSettingString(int iOrder, const char *strSetting, int iLabel, const char *strData, int iControlType, bool bAllowEmpty, int iHeadingString); virtual ~CSettingString() {}; - virtual int GetType() { return SETTINGS_TYPE_STRING; }; + virtual int GetType() const { return SETTINGS_TYPE_STRING; }; virtual void FromString(const CStdString &strValue); - virtual CStdString ToString(); + virtual CStdString ToString() const; void SetData(const char *strData) { m_strData = strData; }; const CStdString &GetData() const { return m_strData; }; @@ -364,7 +365,7 @@ class CSettingPath : public CSettingString CSettingPath(int iOrder, const char *strSetting, int iLabel, const char *strData, int iControlType, bool bAllowEmpty, int iHeadingString); virtual ~CSettingPath() {}; - virtual int GetType() { return SETTINGS_TYPE_PATH; }; + virtual int GetType() const { return SETTINGS_TYPE_PATH; }; }; class CSettingAddon : public CSettingString @@ -372,7 +373,7 @@ class CSettingAddon : public CSettingString public: CSettingAddon(int iOrder, const char *strSetting, int iLabel, const char *strData, const ADDON::TYPE type); virtual ~CSettingAddon() {}; - virtual int GetType() { return SETTINGS_TYPE_ADDON; }; + virtual int GetType() const { return SETTINGS_TYPE_ADDON; }; const ADDON::TYPE m_type; }; @@ -383,7 +384,7 @@ class CSettingSeparator : public CSetting CSettingSeparator(int iOrder, const char *strSetting); virtual ~CSettingSeparator() {}; - virtual int GetType() { return SETTINGS_TYPE_SEPARATOR; }; + virtual int GetType() const { return SETTINGS_TYPE_SEPARATOR; }; }; class CSettingsCategory diff --git a/xbmc/settings/GUIWindowSettingsCategory.cpp b/xbmc/settings/GUIWindowSettingsCategory.cpp index ab69a9c1350d6..e977e0cd24eda 100644 --- a/xbmc/settings/GUIWindowSettingsCategory.cpp +++ b/xbmc/settings/GUIWindowSettingsCategory.cpp @@ -91,6 +91,8 @@ #include "filesystem/SpecialProtocol.h" #include "network/Zeroconf.h" +#include "peripherals/Peripherals.h" +#include "peripherals/dialogs/GUIDialogPeripheralManager.h" #ifdef _WIN32 #include "WIN32Util.h" @@ -117,6 +119,7 @@ using namespace std; using namespace XFILE; using namespace ADDON; +using namespace PERIPHERALS; #define CONTROL_GROUP_BUTTONS 0 #define CONTROL_GROUP_SETTINGS 1 @@ -1022,6 +1025,13 @@ void CGUIWindowSettingsCategory::OnClick(CBaseSettingControl *pSettingControl) else return; } + else if (strSetting.Equals("input.peripherals")) + { + CGUIDialogPeripheralManager *dialog = (CGUIDialogPeripheralManager *)g_windowManager.GetWindow(WINDOW_DIALOG_PERIPHERAL_MANAGER); + if (dialog) + dialog->DoModal(); + return; + } // if OnClick() returns false, the setting hasn't changed or doesn't // require immediate update diff --git a/xbmc/video/windows/GUIWindowVideoBase.cpp b/xbmc/video/windows/GUIWindowVideoBase.cpp index 9ce661af67624..f1559e7484f6c 100644 --- a/xbmc/video/windows/GUIWindowVideoBase.cpp +++ b/xbmc/video/windows/GUIWindowVideoBase.cpp @@ -62,7 +62,7 @@ #include "utils/log.h" #include "utils/FileUtils.h" #include "utils/URIUtils.h" - +#include "GUIUserMessages.h" #include "addons/Skin.h" using namespace std; @@ -217,6 +217,9 @@ bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message) } } break; + case GUI_MSG_SEARCH: + OnSearch(); + break; } return CGUIMediaWindow::OnMessage(message); } diff --git a/xbmc/win32/WIN32USBScan.cpp b/xbmc/win32/WIN32USBScan.cpp deleted file mode 100644 index b382c3161e903..0000000000000 --- a/xbmc/win32/WIN32USBScan.cpp +++ /dev/null @@ -1,74 +0,0 @@ -#include -#include "WIN32USBScan.h" -#include "input/KeymapLoader.h" - -static GUID USB_HID_GUID = { 0x4D1E55B2, 0xF16F, 0x11CF, { 0x88, 0xCB, 0x00, 0x11, 0x11, 0x00, 0x00, 0x30 } }; - -CWIN32USBScan::CWIN32USBScan() -{ - HDEVINFO hDevHandle; - SP_DEVICE_INTERFACE_DATA deviceInterfaceData; - DWORD required = 0; - deviceInterfaceData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); - - int nBufferSize = 0; - - SP_DEVINFO_DATA devInfoData; - devInfoData.cbSize = sizeof(SP_DEVINFO_DATA); - - DWORD MemberIndex = 0; - BOOL Result; - - hDevHandle = SetupDiGetClassDevs(&USB_HID_GUID, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE); - - if (hDevHandle == INVALID_HANDLE_VALUE) - return; - - bool bStart = false; - TCHAR *buffer = NULL; - PSP_DEVICE_INTERFACE_DETAIL_DATA devicedetailData; - do - { - Result = SetupDiEnumDeviceInfo(hDevHandle, MemberIndex, &devInfoData); - - if (Result) - Result = SetupDiEnumDeviceInterfaces(hDevHandle, 0, &USB_HID_GUID, MemberIndex, &deviceInterfaceData); - - if(!Result) - { - SetupDiDestroyDeviceInfoList(hDevHandle); - delete []buffer; - buffer = NULL; - return; - } - - MemberIndex++; - BOOL detailResult = false; - - if(!bStart) - { - // As per MSDN, Get the required buffer size. Call SetupDiGetDeviceInterfaceDetail with a - // NULL DeviceInterfaceDetailData pointer, a DeviceInterfaceDetailDataSize of zero, - // and a valid RequiredSize variable. In response to such a call, this function returns - // the required buffer size at RequiredSize and fails with GetLastError returning - // ERROR_INSUFFICIENT_BUFFER. - // Allocate an appropriately sized buffer and call the function again to get the interface details. - - SetupDiGetDeviceInterfaceDetail(hDevHandle, &deviceInterfaceData, NULL, 0, &required, NULL); - - buffer = new TCHAR[required]; - devicedetailData = (PSP_DEVICE_INTERFACE_DETAIL_DATA) buffer; - devicedetailData->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA); - nBufferSize = required; - bStart = true; - } - - detailResult = SetupDiGetDeviceInterfaceDetail(hDevHandle, &deviceInterfaceData, devicedetailData, nBufferSize , &required, NULL); - - CKeymapLoader::DeviceAdded(CKeymapLoader::ParseWin32HIDName(devicedetailData->DevicePath)); - - if(!detailResult) - continue; - - } while(Result); -} \ No newline at end of file diff --git a/xbmc/win32/WIN32USBScan.h b/xbmc/win32/WIN32USBScan.h deleted file mode 100644 index f580911b55910..0000000000000 --- a/xbmc/win32/WIN32USBScan.h +++ /dev/null @@ -1,5 +0,0 @@ -class CWIN32USBScan -{ - public: - CWIN32USBScan(); -}; \ No newline at end of file diff --git a/xbmc/windowing/osx/WinEventsOSX.h b/xbmc/windowing/osx/WinEventsOSX.h index e390f3bbe6a5c..886fcf5f2eae5 100644 --- a/xbmc/windowing/osx/WinEventsOSX.h +++ b/xbmc/windowing/osx/WinEventsOSX.h @@ -30,7 +30,4 @@ class CWinEventsOSX : public CWinEventsBase ~CWinEventsOSX(); static bool MessagePump(); -private: - void Initialize(void); - }; diff --git a/xbmc/windowing/osx/WinEventsOSX.mm b/xbmc/windowing/osx/WinEventsOSX.mm index efb7bcc50baa0..3a1ebbdc218f6 100644 --- a/xbmc/windowing/osx/WinEventsOSX.mm +++ b/xbmc/windowing/osx/WinEventsOSX.mm @@ -22,7 +22,6 @@ #define BOOL XBMC_BOOL #include "system.h" #include "utils/log.h" -#include "input/KeymapLoader.h" #include "windowing/WinEventsSDL.h" #include "windowing/osx/WinEventsOSX.h" #undef BOOL @@ -39,194 +38,15 @@ // place holder for future native osx event handler -typedef struct USBDevicePrivateData { - UInt16 vendorId; - UInt16 productId; - CStdString deviceName; - CStdString keymapDeviceId; - io_object_t notification; -} USBDevicePrivateData; - -static IONotificationPortRef g_notify_port = 0; -static io_iterator_t g_attach_iterator = 0; - CWinEventsOSX::CWinEventsOSX() { - Initialize(); } CWinEventsOSX::~CWinEventsOSX() { - if (g_notify_port) - { - // remove the sleep notification port from the application runloop - CFRunLoopRemoveSource( CFRunLoopGetCurrent(), - IONotificationPortGetRunLoopSource(g_notify_port), kCFRunLoopDefaultMode ); - IONotificationPortDestroy(g_notify_port); - g_notify_port = 0; - } - if (g_attach_iterator) - { - IOObjectRelease(g_attach_iterator); - g_attach_iterator = 0; - } } bool CWinEventsOSX::MessagePump() { return CWinEventsSDL::MessagePump(); } - -static void DeviceDetachCallback(void *refCon, io_service_t service, natural_t messageType, void *messageArgument) -{ - if (messageType == kIOMessageServiceIsTerminated) - { - IOReturn result; - - USBDevicePrivateData *privateDataRef = (USBDevicePrivateData*)refCon; - CKeymapLoader().DeviceRemoved(privateDataRef->keymapDeviceId); - CLog::Log(LOGDEBUG, "HID Device Detach:%s, %s\n", - privateDataRef->deviceName.c_str(), privateDataRef->keymapDeviceId.c_str()); - result = IOObjectRelease(privateDataRef->notification); - delete privateDataRef; - //release the service - result = IOObjectRelease(service); - } -} - -static void DeviceAttachCallback(void* refCon, io_iterator_t iterator) -{ - io_service_t usbDevice; - while ((usbDevice = IOIteratorNext(iterator))) - { - IOReturn result; - - io_name_t deviceName; - result = IORegistryEntryGetName(usbDevice, deviceName); - if (result != KERN_SUCCESS) - deviceName[0] = '\0'; - - SInt32 deviceScore; - IOCFPlugInInterface **devicePlugin; - result = IOCreatePlugInInterfaceForService(usbDevice, - kIOUSBDeviceUserClientTypeID, kIOCFPlugInInterfaceID, &devicePlugin, &deviceScore); - if (result != kIOReturnSuccess) - { - IOObjectRelease(usbDevice); - continue; - } - - IOUSBDeviceInterface **deviceInterface; - // Use the plugin interface to retrieve the device interface. - result = (*devicePlugin)->QueryInterface(devicePlugin, - CFUUIDGetUUIDBytes(kIOUSBDeviceInterfaceID), (LPVOID*)&deviceInterface); - if (result != kIOReturnSuccess) - { - IODestroyPlugInInterface(devicePlugin); - IOObjectRelease(usbDevice); - continue; - } - - // get vendor/product ids - UInt16 vendorId; - UInt16 productId; - result = (*deviceInterface)->GetDeviceVendor( deviceInterface, &vendorId); - result = (*deviceInterface)->GetDeviceProduct(deviceInterface, &productId); - - // we only care about usb devices with an HID interface class - io_service_t usbInterface; - io_iterator_t interface_iterator; - IOUSBFindInterfaceRequest request; - request.bInterfaceClass = kUSBHIDInterfaceClass; - request.bInterfaceSubClass = kIOUSBFindInterfaceDontCare; - request.bInterfaceProtocol = kIOUSBFindInterfaceDontCare; - request.bAlternateSetting = kIOUSBFindInterfaceDontCare; - result = (*deviceInterface)->CreateInterfaceIterator(deviceInterface, &request, &interface_iterator); - while ((usbInterface = IOIteratorNext(interface_iterator))) - { - SInt32 interfaceScore; - IOCFPlugInInterface **interfacePlugin; - //create intermediate plugin for interface access - result = IOCreatePlugInInterfaceForService(usbInterface, - kIOUSBInterfaceUserClientTypeID, kIOCFPlugInInterfaceID, &interfacePlugin, &interfaceScore); - if (result != kIOReturnSuccess) - { - IOObjectRelease(usbInterface); - continue; - } - IOUSBInterfaceInterface** interfaceInterface; - result = (*interfacePlugin)->QueryInterface(interfacePlugin, - CFUUIDGetUUIDBytes(kIOUSBInterfaceInterfaceID), (void**)&interfaceInterface); - if (result != kIOReturnSuccess) - { - IODestroyPlugInInterface(interfacePlugin); - IOObjectRelease(usbInterface); - continue; - } - - // finally we can get to bInterfaceClass/bInterfaceProtocol - // we should also check for kHIDKeyboardInterfaceProtocol but - // some IR remotes that emulate an HID keyboard do not report this. - UInt8 bInterfaceClass; - result = (*interfaceInterface)->GetInterfaceClass(interfaceInterface, &bInterfaceClass); - if (bInterfaceClass == kUSBHIDInterfaceClass) - { - USBDevicePrivateData *privateDataRef; - privateDataRef = new USBDevicePrivateData; - // save some device info to our private data. - privateDataRef->vendorId = vendorId; - privateDataRef->productId = productId; - privateDataRef->deviceName = deviceName; - privateDataRef->keymapDeviceId.Format("HID#VID_%04X&PID_%04X", vendorId, productId); - // register this usb device for an interest notification callback. - result = IOServiceAddInterestNotification(g_notify_port, - usbDevice, // service - kIOGeneralInterest, // interestType - DeviceDetachCallback, // callback - privateDataRef, // refCon - &privateDataRef->notification // notification - ); - if (result == kIOReturnSuccess) - { - CKeymapLoader().DeviceAdded(privateDataRef->keymapDeviceId); - CLog::Log(LOGDEBUG, "HID Device Attach:%s, %s\n", - deviceName, privateDataRef->keymapDeviceId.c_str()); - } - - // done with this device, only need one notification per device. - IODestroyPlugInInterface(interfacePlugin); - IOObjectRelease(usbInterface); - break; - } - IODestroyPlugInInterface(interfacePlugin); - IOObjectRelease(usbInterface); - } - IODestroyPlugInInterface(devicePlugin); - IOObjectRelease(usbDevice); - } -} - -void CWinEventsOSX::Initialize(void) -{ - IOReturn result; - - //set up the matching criteria for the devices we're interested in - //interested in instances of class IOUSBDevice and its subclasses - // match any usb device by not creating matching values in the dict - CFMutableDictionaryRef matching_dict = IOServiceMatching(kIOUSBDeviceClassName); - - g_notify_port = IONotificationPortCreate(kIOMasterPortDefault); - CFRunLoopSourceRef run_loop_source = IONotificationPortGetRunLoopSource(g_notify_port); - CFRunLoopAddSource(CFRunLoopGetCurrent(), run_loop_source, kCFRunLoopCommonModes); - - //add a notification callback for attach event - result = IOServiceAddMatchingNotification(g_notify_port, - kIOFirstMatchNotification, matching_dict, DeviceAttachCallback, NULL, &g_attach_iterator); - if (result == kIOReturnSuccess) - { - //call the callback to 'arm' the notification - DeviceAttachCallback(NULL, g_attach_iterator); - } -} - - diff --git a/xbmc/windowing/windows/WinEventsWin32.cpp b/xbmc/windowing/windows/WinEventsWin32.cpp index 08877d1df5c6d..4113ff189044d 100644 --- a/xbmc/windowing/windows/WinEventsWin32.cpp +++ b/xbmc/windowing/windows/WinEventsWin32.cpp @@ -27,12 +27,10 @@ #include "Application.h" #include "input/XBMC_vkeys.h" #include "input/MouseStat.h" -#include "input/KeymapLoader.h" #include "storage/MediaManager.h" #include "windowing/WindowingFactory.h" #include #include "guilib/LocalizeStrings.h" -#include "input/KeymapLoader.h" #include "input/KeyboardStat.h" #include "guilib/GUIWindowManager.h" #include "guilib/GUIControl.h" // for EVENT_RESULT @@ -40,9 +38,12 @@ #include "Shlobj.h" #include "settings/Settings.h" #include "settings/AdvancedSettings.h" +#include "peripherals/Peripherals.h" #ifdef _WIN32 +using namespace PERIPHERALS; + #define XBMC_arraysize(array) (sizeof(array)/sizeof(array[0])) /* Masks for processing the windows KEYDOWN and KEYUP messages */ @@ -658,19 +659,12 @@ LRESULT CALLBACK CWinEventsWin32::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, L case WM_DEVICECHANGE: { PDEV_BROADCAST_DEVICEINTERFACE b = (PDEV_BROADCAST_DEVICEINTERFACE) lParam; - CStdString dbcc_name(b->dbcc_name); - dbcc_name = CKeymapLoader::ParseWin32HIDName(b->dbcc_name); switch (wParam) { case DBT_DEVICEARRIVAL: - CKeymapLoader().DeviceAdded(dbcc_name); - break; case DBT_DEVICEREMOVECOMPLETE: - CKeymapLoader().DeviceRemoved(dbcc_name); - break; case DBT_DEVNODES_CHANGED: - //CLog::Log(LOGDEBUG, "HID Device Changed"); - //We generally don't care about Change notifications, only need to know if a device is removed or added to rescan the device list + g_peripherals.TriggerDeviceScan(PERIPHERAL_BUS_USB); break; } break; From 1ac45d82a5983538bcc8cde252ad5a9b1325a4da Mon Sep 17 00:00:00 2001 From: Lars Op den Kamp Date: Mon, 29 Aug 2011 15:22:26 +0200 Subject: [PATCH 2/2] cec: added support for the Pulse-Eight CEC Adaptor. split up linux/PeripheralBusUSB into PeripheralBusUSBLibUdev and PeripheralBusUSBLibUSB. fixed automake files --- .gitignore | 15 + Makefile.in | 4 +- configure.in | 97 +++- language/English/strings.xml | 9 + .../BuildDependencies/scripts/libcec_d.bat | 14 + .../BuildDependencies/scripts/libcec_d.txt | 2 + project/VS2010Express/XBMC.vcxproj | 2 +- system/peripherals.xml | 11 + xbmc/Application.cpp | 22 + xbmc/Application.h | 1 + xbmc/peripherals/Peripherals.cpp | 32 +- xbmc/peripherals/bus/Makefile.in | 6 +- xbmc/peripherals/bus/PeripheralBus.cpp | 9 +- xbmc/peripherals/bus/PeripheralBus.h | 2 + xbmc/peripherals/bus/PeripheralBusUSB.h | 35 ++ .../bus/linux/PeripheralBusUSBLibUSB.cpp | 84 +++ .../bus/linux/PeripheralBusUSBLibUSB.h | 46 ++ ...BusUSB.cpp => PeripheralBusUSBLibUdev.cpp} | 107 ++-- ...eralBusUSB.h => PeripheralBusUSBLibUdev.h} | 11 - .../devices/{Makefile => Makefile.in} | 9 +- xbmc/peripherals/devices/Peripheral.cpp | 18 +- xbmc/peripherals/devices/Peripheral.h | 3 + .../devices/PeripheralCecAdapter.cpp | 517 +++++++++++++++++- .../devices/PeripheralCecAdapter.h | 41 +- 24 files changed, 960 insertions(+), 137 deletions(-) create mode 100644 project/BuildDependencies/scripts/libcec_d.bat create mode 100644 project/BuildDependencies/scripts/libcec_d.txt create mode 100644 xbmc/peripherals/bus/PeripheralBusUSB.h create mode 100644 xbmc/peripherals/bus/linux/PeripheralBusUSBLibUSB.cpp create mode 100644 xbmc/peripherals/bus/linux/PeripheralBusUSBLibUSB.h rename xbmc/peripherals/bus/linux/{PeripheralBusUSB.cpp => PeripheralBusUSBLibUdev.cpp} (65%) rename xbmc/peripherals/bus/linux/{PeripheralBusUSB.h => PeripheralBusUSBLibUdev.h} (89%) rename xbmc/peripherals/devices/{Makefile => Makefile.in} (75%) diff --git a/.gitignore b/.gitignore index 2969b015f6b99..f58453c29610e 100644 --- a/.gitignore +++ b/.gitignore @@ -127,6 +127,7 @@ config.log # /xbmc/peripherals/ /xbmc/peripherals/bus/Makefile +/xbmc/peripherals/devices/Makefile # /lib/ /lib/Makefile @@ -229,6 +230,20 @@ lib/cmyth/Makefile /lib/libass/m4/ltversion.m4 /lib/libass/m4/lt~obsolete.m4 +# /lib/libcec +/lib/libcec/Makefile +/lib/libcec/Makefile.in +/lib/libcec/aclocal.m4 +/lib/libcec/config.guess +/lib/libcec/config.sub +/lib/libcec/configure +/lib/libcec/depcomp +/lib/libcec/install-sh +/lib/libcec/ltmain.sh +/lib/libcec/missing +/lib/libcec/src/lib/Makefile.in +/lib/libcec/src/testclient/Makefile.in + # /lib/libiconv /lib/libiconv/libiconv_win32/Debug /lib/libiconv/libiconv_win32/Release diff --git a/Makefile.in b/Makefile.in index aa956c6e1fca9..bff37e6b37c74 100644 --- a/Makefile.in +++ b/Makefile.in @@ -77,7 +77,7 @@ BIN_DIRS= \ xbmc/peripherals \ xbmc/peripherals/bus \ xbmc/peripherals/devices \ - xbmc/peripherals/dialogs + xbmc/peripherals/dialogs \ ifeq (@USE_OPENGL@,1) BIN_DIRS += xbmc/rendering/gl @@ -498,7 +498,7 @@ OBJSXBMC= \ xbmc/peripherals/peripherals.a \ xbmc/peripherals/bus/peripheral-bus.a \ xbmc/peripherals/devices/peripheral-devices.a \ - xbmc/peripherals/dialogs/peripheral-dialogs.a + xbmc/peripherals/dialogs/peripheral-dialogs.a ifeq (@USE_OPENGL@,1) OBJSXBMC += xbmc/rendering/gl/rendering_gl.a diff --git a/configure.in b/configure.in index 5f6fc78f3f967..5f43acbbf14ee 100755 --- a/configure.in +++ b/configure.in @@ -119,10 +119,12 @@ libplist_disabled="== AirPlay support disabled. ==" alsa_not_found="== Could not find ALSA. ALSA support disabled. ==" dbus_not_found="== Could not find DBUS. DBUS support disabled. ==" -udev_not_found="== Could not find libudev. Will use polling to check for device changes. ==" -udev_disabled="== udev support disabled. Will use polling to check for device changes. ==" +libudev_not_found="== Could not find libudev. Will use polling to check for device changes. ==" +libudev_disabled="== udev support disabled. Will use polling to check for device changes. ==" libusb_not_found="== Could not find libusb. Plug and play USB device support will not be available. ==" libusb_disabled="== libusb disabled. Plug and play USB device support will not be available. ==" +libcec_not_found="== Could not find libcec. CEC device support will not be available. ==" +libcec_disabled="== libcec disabled. CEC device support will not be available. ==" # External library message strings external_libraries_enabled="== Use of all supported external libraries enabled. ==" @@ -384,15 +386,21 @@ AC_DEFINE_UNQUOTED([LIRC_DEVICE], ["$lirc_device"], [Default LIRC device]) AC_ARG_ENABLE([udev], [AS_HELP_STRING([--enable-udev], - [enable udev support (default is yes)])], - [use_udev=$enableval], - [use_udev=yes]) + [enable udev support (default is auto)])], + [use_libudev=$enableval], + [use_libudev=auto]) AC_ARG_ENABLE([libusb], [AS_HELP_STRING([--enable-libusb], - [enable libusb support (default is yes)])], + [enable libusb support (default is auto)])], [use_libusb=$enableval], - [use_libusb=yes]) + [use_libusb=auto]) + +AC_ARG_ENABLE([libcec], + [AS_HELP_STRING([--enable-libcec], + [enable libcec support (default is auto)])], + [use_libcec=$enableval], + [use_libcec=auto]) ### External libraries options AC_ARG_ENABLE([external-libraries], @@ -1066,39 +1074,69 @@ if test "x$use_airtunes" != "xno"; then fi fi -# udev -if test "$host_vendor" = "apple" ; then - use_udev="no" - AC_MSG_NOTICE($udev_disabled) -else - if test "$use_udev" = "yes" ; then - PKG_CHECK_MODULES([UDEV], [libudev], - [INCLUDES="$INCLUDES $UDEV_CFLAGS"; LIBS="$LIBS $UDEV_LIBS"]; \ - AC_DEFINE([HAVE_LIBUDEV],[1],["Define to 1 if libudev is installed"]), - use_udev="no";AC_MSG_ERROR($udev_not_found)) - else - AC_MSG_NOTICE($udev_disabled) - fi -fi - # libusb if test "$host_vendor" = "apple" ; then use_libusb="no" - HAVE_LIBUSB=0 AC_MSG_NOTICE($libusb_disabled) else - if test "$use_libusb" = "yes" ; then + if test "$use_libusb" = "auto"; then PKG_CHECK_MODULES([USB], [libusb], - [INCLUDES="$INCLUDES $USB_CFLAGS"; LIBS="$LIBS $USB_LIBS"; HAVE_LIBUSB=1]; \ + use_libusb="yes"; HAVE_LIBUSB=1; [INCLUDES="$INCLUDES $USB_CFLAGS"; LIBS="$LIBS $USB_LIBS"; HAVE_LIBUSB=1]; \ AC_DEFINE([HAVE_LIBUSB],[1],["Define to 1 if libusb is installed"]), - use_libusb="no"; HAVE_LIBUSB=0; AC_MSG_ERROR($libusb_not_found)) + use_libusb="no"; AC_MSG_RESULT($libusb_not_found)) + elif test "$use_libusb" = "yes"; then + PKG_CHECK_MODULES([USB], [libusb], + use_libusb="yes"; HAVE_LIBUSB=1; [INCLUDES="$INCLUDES $USB_CFLAGS"; LIBS="$LIBS $USB_LIBS"; HAVE_LIBUSB=1]; \ + AC_DEFINE([HAVE_LIBUSB],[1],["Define to 1 if libusb is installed"]), + use_libusb="no"; AC_MSG_ERROR($libusb_not_found)) else use_libusb="no" - HAVE_LIBUSB=0 AC_MSG_NOTICE($libusb_disabled) fi fi +# udev +if test "$use_libusb" = "yes"; then + if test "$host_vendor" = "apple" ; then + use_libudev="no" + AC_MSG_NOTICE($libudev_disabled) + else + if test "$use_libudev" = "auto"; then + PKG_CHECK_MODULES([UDEV], [libudev], + use_libudev="yes"; use_libusb="no"; HAVE_LIBUDEV=1; [INCLUDES="$INCLUDES $UDEV_CFLAGS"; LIBS="$LIBS $UDEV_LIBS"]; \ + AC_DEFINE([HAVE_LIBUDEV],[1],["Define to 1 if libudev is installed"]), + AC_MSG_RESULT($libudev_not_found)) + elif test "$use_libudev" = "yes" ; then + PKG_CHECK_MODULES([UDEV], [libudev], + use_libudev="yes"; use_libusb="no"; HAVE_LIBUDEV=1; [INCLUDES="$INCLUDES $UDEV_CFLAGS"; LIBS="$LIBS $UDEV_LIBS"]; \ + AC_DEFINE([HAVE_LIBUDEV],[1],["Define to 1 if libudev is installed"]), + AC_MSG_ERROR($libudev_not_found)) + else + use_libudev="no" + AC_MSG_NOTICE($libudev_disabled) + fi + fi +else + use_libudev="no" + AC_MSG_NOTICE($libudev_disabled) +fi + +# libcec +if test "$use_libcec" = "auto"; then + PKG_CHECK_MODULES([CEC], [libcec], + use_libcec="yes"; HAVE_LIBCEC=1; [INCLUDES="$INCLUDES $CEC_CFLAGS"; LIBS="$LIBS $CEC_LIBS";] \ + AC_DEFINE([HAVE_LIBCEC],[1],["Define to 1 if libcec is installed"]), + use_libcec="no"; AC_MSG_RESULT($libcec_not_found)) +elif test "$use_libcec" = "yes"; then + PKG_CHECK_MODULES([CEC], [libcec], + use_libcec="yes"; HAVE_LIBCEC=1; [INCLUDES="$INCLUDES $CEC_CFLAGS"; LIBS="$LIBS $CEC_LIBS";] \ + AC_DEFINE([HAVE_LIBCEC],[1],["Define to 1 if libcec is installed"]), + use_libcec="no"; AC_MSG_ERROR($libcec_not_found)) +else + use_libcec="no" + AC_MSG_NOTICE($libcec_disabled) +fi + ### External libraries checks # External FFmpeg if test "$use_external_ffmpeg" = "yes"; then @@ -1779,7 +1817,8 @@ OUTPUT_FILES="Makefile \ tools/Linux/xbmc-standalone.sh \ tools/TexturePacker/Makefile \ tools/EventClients/Clients/OSXRemote/Makefile \ - xbmc/peripherals/bus/Makefile" + xbmc/peripherals/bus/Makefile \ + xbmc/peripherals/devices/Makefile" # Line below is used so we can use AM_INIT_AUTOMAKE. The corresponding # .dummy.am does nothing. @@ -1831,7 +1870,9 @@ AC_SUBST(USE_TEXTUREPACKER) AC_SUBST(USE_TEXTUREPACKER_NATIVE) AC_SUBST(USE_TEXTUREPACKER_NATIVE_ROOT) AC_SUBST(USE_AIRTUNES) +AC_SUBST(HAVE_LIBUDEV) AC_SUBST(HAVE_LIBUSB) +AC_SUBST(HAVE_LIBCEC) # pushd and popd are not available in other shells besides bash, so implement # our own pushd/popd functions diff --git a/language/English/strings.xml b/language/English/strings.xml index 6bcb702ba0b4d..4860cf199507e 100644 --- a/language/English/strings.xml +++ b/language/English/strings.xml @@ -2375,4 +2375,13 @@ Switch to remote side command Press "user" button command Enable switch side commands + Could not open the adapter + Power on devices when starting XBMC + Power off devices when stopping XBMC + Put devices in standby mode when activating screensaver + Set as inactive source when stopping XBMC + Could not detect the CEC port. Set it up manually. + Could not detect the CEC adapter. + Unsupported libcec interface version. %d is greater than the version XBMC supports (%d) + Put this PC in standby mode when the TV is switched off diff --git a/project/BuildDependencies/scripts/libcec_d.bat b/project/BuildDependencies/scripts/libcec_d.bat new file mode 100644 index 0000000000000..2a776bcb1190e --- /dev/null +++ b/project/BuildDependencies/scripts/libcec_d.bat @@ -0,0 +1,14 @@ +@ECHO OFF + +SET LOC_PATH=%CD% +SET FILES=%LOC_PATH%\libcec_d.txt + +CALL dlextract.bat libcec %FILES% + +cd %TMP_PATH% + +xcopy libcec\include\* "%CUR_PATH%\include\libcec" /E /Q /I /Y +xcopy libcec\*.dll "%CUR_PATH%\lib\." /Y +xcopy libcec\*.lib "%CUR_PATH%\lib\." /Y + +cd %LOC_PATH% \ No newline at end of file diff --git a/project/BuildDependencies/scripts/libcec_d.txt b/project/BuildDependencies/scripts/libcec_d.txt new file mode 100644 index 0000000000000..9019c8b9b4601 --- /dev/null +++ b/project/BuildDependencies/scripts/libcec_d.txt @@ -0,0 +1,2 @@ +; filename mirror source of the file +libcec2.zip http://xbmc.opdenkamp.eu/ http://packages.pulse-eight.net/ diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index 19b6aa2dcd0b0..0c705432cf489 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -239,7 +239,7 @@ Disabled ..\..\;..\..\xbmc\;..\..\xbmc\win32\;..\..\xbmc\cores\dvdplayer;..\..\lib;..\..\lib\ffmpeg;..\..\lib\ffmpeg\include-xbmc-win32;..\..\lib\liblame\include;..\..\lib\libUPnP\Platinum\Source\Devices\MediaRenderer;..\..\lib\libUPnP\Platinum\Source\Devices\MediaConnect;..\..\lib\libUPnP\Platinum\Source\Devices\MediaServer;..\..\lib\libUPnP\Platinum\Source\Platinum;..\..\lib\libUPnP\Platinum\Source\Core;..\..\lib\libUPnP\Neptune\Source\Core;..\..\lib\libUPnP\Neptune\Source\System\Win32;..\..\lib\win32\pcre;..\..\lib\win32 - TARGET_WINDOWS;_WINDOWS;_MSVC;WIN32;_DEBUG;_WIN32_WINNT=0x0501;NTDDI_VERSION=0x05010300;NOMINMAX;_USE_32BIT_TIME_T;HAS_GL;__STDC_CONSTANT_MACROS;%(PreprocessorDefinitions) + TARGET_WINDOWS;_WINDOWS;_MSVC;WIN32;_DEBUG;_WIN32_WINNT=0x0501;NTDDI_VERSION=0x05010300;NOMINMAX;_USE_32BIT_TIME_T;HAS_GL;__STDC_CONSTANT_MACROS;HAVE_LIBCEC;%(PreprocessorDefinitions) false Async Default diff --git a/system/peripherals.xml b/system/peripherals.xml index d410f433c7bc2..408b0bd05071b 100644 --- a/system/peripherals.xml +++ b/system/peripherals.xml @@ -16,6 +16,17 @@ + + + + + + + + + + + diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index af7e60573136d..64af600925f00 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -149,6 +149,7 @@ #endif #include "interfaces/AnnouncementManager.h" #include "peripherals/Peripherals.h" +#include "peripherals/devices/PeripheralCecAdapter.h" #include "peripherals/dialogs/GUIDialogPeripheralManager.h" #include "peripherals/dialogs/GUIDialogPeripheralSettings.h" @@ -2678,6 +2679,7 @@ void CApplication::FrameMove(bool processEvents) ProcessRemote(frameTime); ProcessGamepad(frameTime); ProcessEventServer(frameTime); + ProcessPeripherals(frameTime); m_pInertialScrollingHandler->ProcessInertialScroll(frameTime); } if (!m_bStop) @@ -2799,6 +2801,26 @@ bool CApplication::ProcessRemote(float frameTime) return false; } +bool CApplication::ProcessPeripherals(float frameTime) +{ + vector peripherals; + if (g_peripherals.GetPeripheralsWithFeature(peripherals, FEATURE_CEC)) + { + for (unsigned int iPeripheralPtr = 0; iPeripheralPtr < peripherals.size(); iPeripheralPtr++) + { + CPeripheralCecAdapter *cecDevice = (CPeripheralCecAdapter *) peripherals.at(iPeripheralPtr); + if (cecDevice && cecDevice->GetButton()) + { + CKey key(cecDevice->GetButton(), cecDevice->GetHoldTime()); + cecDevice->ResetButton(); + return OnKey(key); + } + } + } + + return false; +} + bool CApplication::ProcessMouse() { MEASURE_FUNCTION; diff --git a/xbmc/Application.h b/xbmc/Application.h index c83cc3393720d..3f4f9002bf49f 100644 --- a/xbmc/Application.h +++ b/xbmc/Application.h @@ -360,6 +360,7 @@ class CApplication : public CXBApplicationEx, public IPlayerCallback, public IMs bool ProcessRemote(float frameTime); bool ProcessGamepad(float frameTime); bool ProcessEventServer(float frameTime); + bool ProcessPeripherals(float frameTime); bool ProcessHTTPApiButtons(); bool ProcessJoystickEvent(const std::string& joystickName, int button, bool isAxis, float fAmount); diff --git a/xbmc/peripherals/Peripherals.cpp b/xbmc/peripherals/Peripherals.cpp index eab975b69f3bb..e1c73bafd7605 100644 --- a/xbmc/peripherals/Peripherals.cpp +++ b/xbmc/peripherals/Peripherals.cpp @@ -22,12 +22,15 @@ #include "Peripherals.h" #include "bus/PeripheralBus.h" #include "devices/PeripheralBluetooth.h" -#include "devices/PeripheralCecAdapter.h" #include "devices/PeripheralDisk.h" #include "devices/PeripheralHID.h" #include "devices/PeripheralNIC.h" #include "devices/PeripheralNyxboard.h" #include "devices/PeripheralTuner.h" +#ifdef HAVE_LIBCEC +#include "devices/PeripheralCecAdapter.h" +#endif +#include "bus/PeripheralBusUSB.h" #include "dialogs/GUIDialogPeripheralManager.h" #include "threads/SingleLock.h" @@ -41,14 +44,6 @@ #include "dialogs/GUIDialogKaiToast.h" #include "utils/StringUtils.h" -#if defined(TARGET_WINDOWS) -#include "bus/win32/PeripheralBusUSB.h" -#elif defined(TARGET_LINUX) && defined(HAVE_LIBUSB) -#include "bus/linux/PeripheralBusUSB.h" -#elif defined(TARGET_DARWIN) -#include "bus/osx/PeripheralBusUSB.h" -#endif - using namespace PERIPHERALS; using namespace XFILE; using namespace std; @@ -81,14 +76,7 @@ void CPeripherals::Initialise(void) /* load mappings from peripherals.xml */ LoadMappings(); -#if defined(TARGET_WINDOWS) - /* add all busses for win32 */ - m_busses.push_back(new CPeripheralBusUSB(this)); -#elif defined(TARGET_LINUX) && defined(HAVE_LIBUSB) - /* add all busses for linux */ - m_busses.push_back(new CPeripheralBusUSB(this)); -#elif defined(TARGET_DARWIN) - /* add all busses for darwin */ +#if defined(HAVE_PERIPHERAL_BUS_USB) m_busses.push_back(new CPeripheralBusUSB(this)); #endif @@ -250,10 +238,6 @@ CPeripheral *CPeripherals::CreatePeripheral(CPeripheralBus &bus, const Periphera peripheral = new CPeripheralNyxboard(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); break; - case PERIPHERAL_CEC: - peripheral = new CPeripheralCecAdapter(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); - break; - case PERIPHERAL_TUNER: peripheral = new CPeripheralTuner(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); break; @@ -262,6 +246,12 @@ CPeripheral *CPeripherals::CreatePeripheral(CPeripheralBus &bus, const Periphera peripheral = new CPeripheralBluetooth(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); break; +#ifdef HAVE_LIBCEC + case PERIPHERAL_CEC: + peripheral = new CPeripheralCecAdapter(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); + break; +#endif + default: peripheral = new CPeripheral(type, bus.Type(), strLocation, strDeviceName, iVendorId, iProductId); break; diff --git a/xbmc/peripherals/bus/Makefile.in b/xbmc/peripherals/bus/Makefile.in index 0831e9d6657bf..b1370068e17ff 100644 --- a/xbmc/peripherals/bus/Makefile.in +++ b/xbmc/peripherals/bus/Makefile.in @@ -1,7 +1,11 @@ SRCS=PeripheralBus.cpp ifeq (@HAVE_LIBUSB@,1) -SRCS+=linux/PeripheralBusUSB.cpp +ifeq (@HAVE_LIBUDEV@,1) +SRCS+=linux/PeripheralBusUSBLibUdev.cpp +else +SRCS+=linux/PeripheralBusUSBLibUSB.cpp +endif endif ifeq ($(findstring osx,@ARCH@),osx) diff --git a/xbmc/peripherals/bus/PeripheralBus.cpp b/xbmc/peripherals/bus/PeripheralBus.cpp index bea0517573377..4b680e5eaae2d 100644 --- a/xbmc/peripherals/bus/PeripheralBus.cpp +++ b/xbmc/peripherals/bus/PeripheralBus.cpp @@ -21,6 +21,7 @@ #include "PeripheralBus.h" #include "peripherals/Peripherals.h" +#include "utils/Variant.h" #include "utils/log.h" #include "FileItem.h" @@ -143,9 +144,11 @@ void CPeripheralBus::UnregisterRemovedDevices(const PeripheralScanResults &resul /* device removed */ if (peripheral->Type() != PERIPHERAL_UNKNOWN) CLog::Log(LOGNOTICE, "%s - device removed from %s/%s: %s (%s:%s)", __FUNCTION__, PeripheralTypeTranslator::TypeToString(peripheral->Type()), peripheral->Location().c_str(), peripheral->DeviceName().c_str(), peripheral->VendorIdAsString(), peripheral->ProductIdAsString()); + m_peripherals.erase(m_peripherals.begin() + iDevicePtr); + lock.Leave(); + m_manager->OnDeviceDeleted(*this, peripheral->FileLocation()); delete peripheral; - m_peripherals.erase(m_peripherals.begin() + iDevicePtr); } } } @@ -276,8 +279,10 @@ void CPeripheralBus::Register(CPeripheral *peripheral) if (!HasPeripheral(peripheral->Location())) { m_peripherals.push_back(peripheral); - m_manager->OnDeviceAdded(*this, peripheral->FileLocation()); CLog::Log(LOGNOTICE, "%s - new %s device registered on %s->%s: %s (%s:%s)", __FUNCTION__, PeripheralTypeTranslator::TypeToString(peripheral->Type()), PeripheralTypeTranslator::BusTypeToString(m_type), peripheral->Location().c_str(), peripheral->DeviceName().c_str(), peripheral->VendorIdAsString(), peripheral->ProductIdAsString()); + lock.Leave(); + + m_manager->OnDeviceAdded(*this, peripheral->FileLocation()); } } diff --git a/xbmc/peripherals/bus/PeripheralBus.h b/xbmc/peripherals/bus/PeripheralBus.h index 28ddfe318cab6..e1dd2be4dd204 100644 --- a/xbmc/peripherals/bus/PeripheralBus.h +++ b/xbmc/peripherals/bus/PeripheralBus.h @@ -165,6 +165,8 @@ namespace PERIPHERALS */ virtual void Register(CPeripheral *peripheral); + virtual bool FindComPort(CStdString &strLocation) { return false; } + protected: virtual void Process(void); virtual bool ScanForDevices(void); diff --git a/xbmc/peripherals/bus/PeripheralBusUSB.h b/xbmc/peripherals/bus/PeripheralBusUSB.h new file mode 100644 index 0000000000000..5aa7bb6df6b1f --- /dev/null +++ b/xbmc/peripherals/bus/PeripheralBusUSB.h @@ -0,0 +1,35 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#if defined(TARGET_WINDOWS) +#define HAVE_PERIPHERAL_BUS_USB 1 +#include "win32/PeripheralBusUSB.h" +#elif defined(TARGET_LINUX) && defined(HAVE_LIBUDEV) +#define HAVE_PERIPHERAL_BUS_USB 1 +#include "linux/PeripheralBusUSBLibUdev.h" +#elif defined(TARGET_LINUX) && defined(HAVE_LIBUSB) +#define HAVE_PERIPHERAL_BUS_USB 1 +#include "linux/PeripheralBusUSBLibUSB.h" +#elif defined(TARGET_DARWIN) +#define HAVE_PERIPHERAL_BUS_USB 1 +#include "osx/PeripheralBusUSB.h" +#endif diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUSB.cpp b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUSB.cpp new file mode 100644 index 0000000000000..196f26781e52d --- /dev/null +++ b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUSB.cpp @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "PeripheralBusUSBLibUSB.h" +#include "peripherals/Peripherals.h" +#include +#include "utils/log.h" + +using namespace PERIPHERALS; + +CPeripheralBusUSB::CPeripheralBusUSB(CPeripherals *manager) : + CPeripheralBus(manager, PERIPHERAL_BUS_USB) +{ + usb_init(); + usb_find_busses(); + m_busses = usb_get_busses(); + CLog::Log(LOGDEBUG, "%s - using libusb peripheral scanning", __FUNCTION__); +} + +bool CPeripheralBusUSB::PerformDeviceScan(PeripheralScanResults &results) +{ + struct usb_bus *bus; + usb_find_devices(); + for (bus = m_busses; bus; bus = bus->next) + { + struct usb_device *dev; + for (dev = bus->devices; dev; dev = dev->next) + { + PeripheralScanResult result; + result.m_iVendorId = dev->descriptor.idVendor; + result.m_iProductId = dev->descriptor.idProduct; + result.m_type = (dev->descriptor.bDeviceClass == USB_CLASS_PER_INTERFACE && dev->descriptor.bNumConfigurations > 0 && + dev->config[0].bNumInterfaces > 0 && dev->config[0].interface[0].num_altsetting > 0) ? + GetType(dev->config[0].interface[0].altsetting[0].bInterfaceClass) : + GetType(dev->descriptor.bDeviceClass); + result.m_strLocation.Format("/bus%s/dev%s", bus->dirname, dev->filename); + + if (!results.ContainsResult(result)) + results.m_results.push_back(result); + } + } + + return true; +} + +const PeripheralType CPeripheralBusUSB::GetType(int iDeviceClass) +{ + switch (iDeviceClass) + { + case USB_CLASS_HID: + return PERIPHERAL_HID; + case USB_CLASS_COMM: + return PERIPHERAL_NIC; + case USB_CLASS_MASS_STORAGE: + return PERIPHERAL_DISK; + case USB_CLASS_PER_INTERFACE: + case USB_CLASS_AUDIO: + case USB_CLASS_PRINTER: + case USB_CLASS_PTP: + case USB_CLASS_HUB: + case USB_CLASS_DATA: + case USB_CLASS_VENDOR_SPEC: + default: + return PERIPHERAL_UNKNOWN; + } +} diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUSB.h b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUSB.h new file mode 100644 index 0000000000000..e61c18e780e64 --- /dev/null +++ b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUSB.h @@ -0,0 +1,46 @@ +#pragma once +/* + * Copyright (C) 2005-2011 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, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "peripherals/bus/PeripheralBus.h" +#include "peripherals/devices/Peripheral.h" + +struct usb_bus; + +namespace PERIPHERALS +{ + class CPeripherals; + + class CPeripheralBusUSB : public CPeripheralBus + { + public: + CPeripheralBusUSB(CPeripherals *manager); + + /*! + * @see PeripheralBus::PerformDeviceScan() + */ + bool PerformDeviceScan(PeripheralScanResults &results); + + protected: + static const PeripheralType GetType(int iDeviceClass); + struct usb_bus *m_busses; + }; +} diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSB.cpp b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp similarity index 65% rename from xbmc/peripherals/bus/linux/PeripheralBusUSB.cpp rename to xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp index 4a5faf7d486b6..b0e87c8dc4370 100644 --- a/xbmc/peripherals/bus/linux/PeripheralBusUSB.cpp +++ b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.cpp @@ -19,51 +19,84 @@ * */ -#include "PeripheralBusUSB.h" +#include "PeripheralBusUSBLibUdev.h" #include "peripherals/Peripherals.h" -#include -#if defined(HAVE_LIBUDEV) #include +#include #include #include "utils/log.h" -#endif using namespace PERIPHERALS; CPeripheralBusUSB::CPeripheralBusUSB(CPeripherals *manager) : CPeripheralBus(manager, PERIPHERAL_BUS_USB) { - usb_init(); - usb_find_busses(); - m_busses = usb_get_busses(); + /* the Process() method in this class overrides the one in CPeripheralBus, so leave this set to true */ + m_bNeedsPolling = true; + + m_udev = NULL; + m_udevMon = NULL; + m_udevFd = -1; + + if (!(m_udev = udev_new())) + { + CLog::Log(LOGERROR, "%s - failed to allocate udev context", __FUNCTION__); + return; + } + + /* set up a devices monitor that listen for any device change */ + m_udevMon = udev_monitor_new_from_netlink(m_udev, "udev"); + udev_monitor_enable_receiving(m_udevMon); + m_udevFd = udev_monitor_get_fd(m_udevMon); -#if defined(HAVE_LIBUDEV) - InitialiseUdev(); -#endif + CLog::Log(LOGDEBUG, "%s - initialised udev monitor: %d", __FUNCTION__, m_udevFd); } bool CPeripheralBusUSB::PerformDeviceScan(PeripheralScanResults &results) { - struct usb_bus *bus; - usb_find_devices(); - for (bus = m_busses; bus; bus = bus->next) + struct udev_enumerate *enumerate; + struct udev_list_entry *devices, *dev_list_entry; + struct udev_device *dev; + enumerate = udev_enumerate_new(m_udev); + udev_enumerate_scan_devices(enumerate); + devices = udev_enumerate_get_list_entry(enumerate); + udev_list_entry_foreach(dev_list_entry, devices) { - struct usb_device *dev; - for (dev = bus->devices; dev; dev = dev->next) + const char *strPath; + strPath = udev_list_entry_get_name(dev_list_entry); + + dev = udev_device_new_from_syspath(m_udev, strPath); + if (!dev) + continue; + + dev = udev_device_get_parent(udev_device_get_parent(dev)); + if (!dev || !udev_device_get_sysattr_value(dev,"idVendor") || !udev_device_get_sysattr_value(dev, "idProduct")) + continue; + + const char *strClass = udev_device_get_sysattr_value(dev, "bDeviceClass"); + if (!strClass) + continue; + + int iClass = PeripheralTypeTranslator::HexStringToInt(strClass); + if (iClass == USB_CLASS_PER_INTERFACE) { - PeripheralScanResult result; - result.m_iVendorId = dev->descriptor.idVendor; - result.m_iProductId = dev->descriptor.idProduct; - result.m_type = (dev->descriptor.bDeviceClass == USB_CLASS_PER_INTERFACE && dev->descriptor.bNumConfigurations > 0 && - dev->config[0].bNumInterfaces > 0 && dev->config[0].interface[0].num_altsetting > 0) ? - GetType(dev->config[0].interface[0].altsetting[0].bInterfaceClass) : - GetType(dev->descriptor.bDeviceClass); - result.m_strLocation.Format("/bus%s/dev%s", bus->dirname, dev->filename); - - if (!results.ContainsResult(result)) - results.m_results.push_back(result); + //TODO + iClass = USB_CLASS_HID; } + + PeripheralScanResult result; + result.m_iVendorId = PeripheralTypeTranslator::HexStringToInt(udev_device_get_sysattr_value(dev, "idVendor")); + result.m_iProductId = PeripheralTypeTranslator::HexStringToInt(udev_device_get_sysattr_value(dev, "idProduct")); + result.m_type = GetType(iClass); + result.m_strLocation = udev_device_get_syspath(dev); + + if (!results.ContainsResult(result)) + results.m_results.push_back(result); + + udev_device_unref(dev); } + /* Free the enumerator object */ + udev_enumerate_unref(enumerate); return true; } @@ -90,7 +123,6 @@ const PeripheralType CPeripheralBusUSB::GetType(int iDeviceClass) } } -#if defined(HAVE_LIBUDEV) void CPeripheralBusUSB::Process(void) { bool bUpdated(false); @@ -116,26 +148,6 @@ void CPeripheralBusUSB::Clear(void) CPeripheralBus::Clear(); } -void CPeripheralBusUSB::InitialiseUdev(void) -{ - m_udev = NULL; - m_udevMon = NULL; - m_udevFd = -1; - - if (!(m_udev = udev_new())) - { - CLog::Log(LOGERROR, "%s - failed to allocate udev context", __FUNCTION__); - return; - } - - /* set up a devices monitor that listen for any device change */ - m_udevMon = udev_monitor_new_from_netlink(m_udev, "udev"); - udev_monitor_enable_receiving(m_udevMon); - m_udevFd = udev_monitor_get_fd(m_udevMon); - - CLog::Log(LOGDEBUG, "%s - initialised udev monitor: %d", __FUNCTION__, m_udevFd); -} - bool CPeripheralBusUSB::WaitForUpdate() { if (!m_udevFd) @@ -167,4 +179,3 @@ bool CPeripheralBusUSB::WaitForUpdate() return true; } -#endif diff --git a/xbmc/peripherals/bus/linux/PeripheralBusUSB.h b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h similarity index 89% rename from xbmc/peripherals/bus/linux/PeripheralBusUSB.h rename to xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h index 28b617502114b..5dbd7c972207d 100644 --- a/xbmc/peripherals/bus/linux/PeripheralBusUSB.h +++ b/xbmc/peripherals/bus/linux/PeripheralBusUSBLibUdev.h @@ -23,12 +23,8 @@ #include "peripherals/bus/PeripheralBus.h" #include "peripherals/devices/Peripheral.h" -struct usb_bus; - -#if defined(HAVE_LIBUDEV) struct udev; struct udev_monitor; -#endif namespace PERIPHERALS { @@ -38,10 +34,7 @@ namespace PERIPHERALS { public: CPeripheralBusUSB(CPeripherals *manager); - -#if defined(HAVE_LIBUDEV) virtual void Clear(void); -#endif /*! * @see PeripheralBus::PerformDeviceScan() @@ -50,16 +43,12 @@ namespace PERIPHERALS protected: static const PeripheralType GetType(int iDeviceClass); - struct usb_bus *m_busses; -#if defined(HAVE_LIBUDEV) virtual void Process(void); - void InitialiseUdev(void); bool WaitForUpdate(void); struct udev * m_udev; struct udev_monitor *m_udevMon; int m_udevFd; -#endif }; } diff --git a/xbmc/peripherals/devices/Makefile b/xbmc/peripherals/devices/Makefile.in similarity index 75% rename from xbmc/peripherals/devices/Makefile rename to xbmc/peripherals/devices/Makefile.in index 85246df537789..dd2daa91698a1 100644 --- a/xbmc/peripherals/devices/Makefile +++ b/xbmc/peripherals/devices/Makefile.in @@ -1,13 +1,16 @@ SRCS=Peripheral.cpp \ PeripheralBluetooth.cpp \ - PeripheralCecAdapter.cpp \ PeripheralDisk.cpp \ PeripheralHID.cpp \ PeripheralNIC.cpp \ PeripheralNyxboard.cpp \ PeripheralTuner.cpp - -LIB=peripheral-devices.a + +ifeq (@HAVE_LIBCEC@,1) +SRCS+=PeripheralCecAdapter.cpp +endif + +LIB = peripheral-devices.a include ../../../Makefile.include -include $(patsubst %.cpp,%.P,$(patsubst %.c,%.P,$(SRCS))) diff --git a/xbmc/peripherals/devices/Peripheral.cpp b/xbmc/peripherals/devices/Peripheral.cpp index fba7735061c8e..42c4102f7eb23 100644 --- a/xbmc/peripherals/devices/Peripheral.cpp +++ b/xbmc/peripherals/devices/Peripheral.cpp @@ -41,7 +41,8 @@ CPeripheral::CPeripheral(const PeripheralType type, const PeripheralBusType busT m_iProductId(iProductId), m_strProductId(PeripheralTypeTranslator::IntToHexString(iProductId)), m_bInitialised(false), - m_bHidden(false) + m_bHidden(false), + m_bError(false) { m_strFileLocation.Format("peripherals://%s/%s.dev", PeripheralTypeTranslator::BusTypeToString(busType), strLocation.c_str()); } @@ -124,7 +125,12 @@ void CPeripheral::GetFeatures(std::vector &features) const bool CPeripheral::Initialise(void) { - bool bReturn(true); + bool bReturn(false); + + if (m_bError) + return bReturn; + + bReturn = true; if (m_bInitialised) return bReturn; @@ -315,7 +321,7 @@ void CPeripheral::SetSetting(const CStdString &strKey, bool bValue) { bool bChanged(boolSetting->GetData() != bValue); boolSetting->SetData(bValue); - if (bChanged) + if (bChanged && m_bInitialised) OnSettingChanged(strKey); } } @@ -331,7 +337,7 @@ void CPeripheral::SetSetting(const CStdString &strKey, int iValue) { bool bChanged(intSetting->GetData() != iValue); intSetting->SetData(iValue); - if (bChanged) + if (bChanged && m_bInitialised) OnSettingChanged(strKey); } } @@ -347,7 +353,7 @@ void CPeripheral::SetSetting(const CStdString &strKey, float fValue) { bool bChanged(floatSetting->GetData() != fValue); floatSetting->SetData(fValue); - if (bChanged) + if (bChanged && m_bInitialised) OnSettingChanged(strKey); } } @@ -365,7 +371,7 @@ void CPeripheral::SetSetting(const CStdString &strKey, const CStdString &strValu { bool bChanged(!stringSetting->GetData().Equals(strValue)); stringSetting->SetData(strValue); - if (bChanged) + if (bChanged && m_bInitialised) OnSettingChanged(strKey); } } diff --git a/xbmc/peripherals/devices/Peripheral.h b/xbmc/peripherals/devices/Peripheral.h index f0881c1f98a2b..291f6794f64b5 100644 --- a/xbmc/peripherals/devices/Peripheral.h +++ b/xbmc/peripherals/devices/Peripheral.h @@ -147,6 +147,8 @@ namespace PERIPHERALS virtual void LoadPersistedSettings(void); virtual void ResetDefaultSettings(void); + virtual bool ErrorOccured(void) const { return m_bError; } + protected: virtual void ClearSettings(void); @@ -162,6 +164,7 @@ namespace PERIPHERALS char * m_strProductId; bool m_bInitialised; bool m_bHidden; + bool m_bError; std::vector m_features; std::vector m_subDevices; std::map m_settings; diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp index a78e24dc6e920..ddd9b3c17be05 100644 --- a/xbmc/peripherals/devices/PeripheralCecAdapter.cpp +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.cpp @@ -20,40 +20,535 @@ */ #include "PeripheralCecAdapter.h" +#include "dialogs/GUIDialogOK.h" +#include "input/XBIRRemote.h" +#include "Application.h" +#include "threads/SingleLock.h" +#include "dialogs/GUIDialogKaiToast.h" +#include "guilib/LocalizeStrings.h" +#include "peripherals/Peripherals.h" +#include "peripherals/bus/PeripheralBus.h" #include "utils/log.h" using namespace PERIPHERALS; using namespace ANNOUNCEMENT; +using namespace CEC; + +#define CEC_LIB_SUPPORTED_VERSION 2 CPeripheralCecAdapter::CPeripheralCecAdapter(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId) : - CPeripheral(type, busType, strLocation, strDeviceName, iVendorId, iProductId) + CPeripheralHID(type, busType, strLocation, strDeviceName, iVendorId, iProductId), + CThread("CEC parser"), + m_bStarted(false), + m_bHasButton(false), + m_bIsReady(false) { - m_features.push_back(FEATURE_CEC); + m_cecParser = LoadLibCec("XBMC", CECDEVICE_PLAYBACKDEVICE1); + if (!m_cecParser || m_cecParser->GetMinVersion() > CEC_LIB_SUPPORTED_VERSION) + { + /* unsupported libcec version */ + CLog::Log(LOGERROR, g_localizeStrings.Get(36013).c_str(), CEC_LIB_SUPPORTED_VERSION, m_cecParser ? m_cecParser->GetMinVersion() : -1); + + CStdString strMessage; + strMessage.Format(g_localizeStrings.Get(36013).c_str(), CEC_LIB_SUPPORTED_VERSION, m_cecParser ? m_cecParser->GetMinVersion() : -1); + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), strMessage); + m_bError = true; + UnloadLibCec(m_cecParser); + m_cecParser = NULL; + } + else + { + m_features.push_back(FEATURE_CEC); + } } CPeripheralCecAdapter::~CPeripheralCecAdapter(void) { CAnnouncementManager::RemoveAnnouncer(this); + if (m_cecParser) + { + FlushLog(); + m_cecParser->Close(1000); + UnloadLibCec(m_cecParser); + } + StopThread(true); } void CPeripheralCecAdapter::Announce(EAnnouncementFlag flag, const char *sender, const char *message, const CVariant &data) { - if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "ApplicationStop")) + if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "ApplicationStop") && m_bIsReady) { - ScreenSetPower(false); + if (GetSettingBool("cec_power_off_shutdown")) + m_cecParser->PowerOffDevices(); + else if (GetSettingBool("cec_mark_inactive_shutdown")) + m_cecParser->SetInactiveView(); } -} + else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverDeactivated") && GetSettingBool("cec_standby_screensaver") && m_bIsReady) + { + m_cecParser->PowerOnDevices(); + } + else if (flag == GUI && !strcmp(sender, "xbmc") && !strcmp(message, "OnScreensaverActivated") && GetSettingBool("cec_standby_screensaver")) + { + m_cecParser->StandbyDevices(); + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnSleep")) + { + if (GetSettingBool("cec_power_off_shutdown") && m_bIsReady) + m_cecParser->PowerOffDevices(); -bool CPeripheralCecAdapter::ScreenSetPower(bool bSetTo) -{ - // TODO - return false; + m_bStop = true; + m_cecParser->Close(500); + WaitForThreadExit(2000); + CLog::Log(LOGDEBUG, "%s - closing the connection to the CEC adapter while in standby mode", __FUNCTION__); + } + else if (flag == System && !strcmp(sender, "xbmc") && !strcmp(message, "OnWake")) + { + CLog::Log(LOGDEBUG, "%s - reconnecting to the CEC adapter after standby mode", __FUNCTION__); + m_bStop = false; + Create(); + } } bool CPeripheralCecAdapter::InitialiseFeature(const PeripheralFeature feature) { - if (feature == FEATURE_CEC) - CAnnouncementManager::AddAnnouncer(this); + if (feature == FEATURE_CEC && !m_bStarted) + { + m_bStarted = true; + Create(); + } return CPeripheral::InitialiseFeature(feature); } + +void CPeripheralCecAdapter::Process(void) +{ + if (!GetSettingBool("enabled")) + { + m_bStarted = false; + return; + } + + // the device needs a second to settle after it's plugged in + Sleep(CEC_SETTLE_DOWN_TIME); + + + CStdString strPort = GetSettingString("port"); + if (strPort.IsEmpty()) + { + std::vector deviceList; + strPort = m_strFileLocation; + TranslateComPort(strPort); + int iFound = m_cecParser->FindDevices(deviceList, strPort); + + if (iFound <= 0) + { + CLog::Log(LOGWARNING, "%s - no CEC adapters found on %s", __FUNCTION__, strPort.c_str()); + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), g_localizeStrings.Get(36011)); + m_bStarted = false; + return; + } + else if (iFound > 0) + { + cec_device dev = deviceList[0]; + if (iFound > 1) + CLog::Log(LOGDEBUG, "%s - multiple com ports found for device. taking the first one", __FUNCTION__); + else + CLog::Log(LOGDEBUG, "%s - autodetect com port '%s'", __FUNCTION__, dev.comm.c_str()); + if (!strPort.Equals(dev.comm.c_str())) + { + strPort = dev.comm.c_str(); + SetSetting("port", strPort); + } + } + } + + // open the CEC adapter + CLog::Log(LOGDEBUG, "%s - opening CEC adapter: %s", __FUNCTION__, strPort.c_str()); + + if (!m_cecParser->Open(strPort.c_str(), 10000)) + { + FlushLog(); + CGUIDialogOK::ShowAndGetInput(257, 0, 36006, 0); + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, g_localizeStrings.Get(36000), g_localizeStrings.Get(36012)); + m_bStarted = false; + return; + } + + CLog::Log(LOGDEBUG, "%s - CEC adapter opened", __FUNCTION__); + m_bIsReady = true; + CAnnouncementManager::AddAnnouncer(this); + + if (GetSettingBool("cec_power_on_startup")) + PowerOnCecDevices(); + m_cecParser->SetActiveView(); + FlushLog(); + + while (!m_bStop) + { + FlushLog(); + ProcessNextCommand(); + Sleep(50); + } + + m_bStarted = false; +} + +bool CPeripheralCecAdapter::PowerOffCecDevices(void) +{ + bool bReturn(false); + + if (m_cecParser && m_bIsReady) + { + CLog::Log(LOGDEBUG, "%s - powering off CEC capable devices", __FUNCTION__); + bReturn = m_cecParser->PowerOffDevices(); + } + + return bReturn; +} + +bool CPeripheralCecAdapter::PowerOnCecDevices(void) +{ + bool bReturn(false); + + if (m_cecParser && m_bIsReady) + { + CLog::Log(LOGDEBUG, "%s - powering on CEC capable devices", __FUNCTION__); + bReturn = m_cecParser->PowerOnDevices(); + } + + return bReturn; +} + +bool CPeripheralCecAdapter::StandbyCecDevices(void) +{ + bool bReturn(false); + + if (m_cecParser && m_bIsReady) + { + CLog::Log(LOGDEBUG, "%s - putting CEC capable devices in standby mode", __FUNCTION__); + bReturn = m_cecParser->StandbyDevices(); + } + + return bReturn; +} + +bool CPeripheralCecAdapter::SendPing(void) +{ + bool bReturn(false); + if (m_cecParser && m_bIsReady) + { + CLog::Log(LOGDEBUG, "%s - sending ping to the CEC adapter", __FUNCTION__); + bReturn = m_cecParser->Ping(); + } + + return bReturn; +} + +bool CPeripheralCecAdapter::StartBootloader(void) +{ + bool bReturn(false); + if (m_cecParser && m_bIsReady) + { + CLog::Log(LOGDEBUG, "%s - starting the bootloader", __FUNCTION__); + bReturn = m_cecParser->StartBootloader(); + } + + return bReturn; +} + +void CPeripheralCecAdapter::ProcessNextCommand(void) +{ + cec_command command; + if (m_cecParser && m_bIsReady && m_cecParser->GetNextCommand(&command)) + { + CLog::Log(LOGDEBUG, "%s - processing command: initiator=%d destination=%d opcode=%d", __FUNCTION__, command.source, command.destination, command.opcode); + + switch (command.opcode) + { + case CEC_OPCODE_STANDBY: + /* a device was put in standby mode */ + CLog::Log(LOGDEBUG, "%s - device %d was put in standby mode", __FUNCTION__, command.source); + if (command.source == CECDEVICE_TV && GetSettingBool("standby_pc_on_tv_standby")) + { + m_bStarted = false; + g_application.getApplicationMessenger().Suspend(); + } + break; + default: + break; + } + } +} + +bool CPeripheralCecAdapter::GetNextKey(void) +{ + CSingleLock lock(m_critSection); + if (m_bHasButton) + return false; + + cec_keypress key; + if (!m_bIsReady || !(m_bHasButton = m_cecParser->GetNextKeypress(&key))) + return false; + + CLog::Log(LOGDEBUG, "%s - received key %d", __FUNCTION__, key.keycode); + m_button.iButtonReleased = XbmcThreads::SystemClockMillis(); + m_button.iButton = 0; + m_button.iButtonPressed = m_button.iButtonReleased - key.duration; + + switch (key.keycode) + { + case CEC_USER_CONTROL_CODE_SELECT: + m_button.iButton = XINPUT_IR_REMOTE_SELECT; + break; + case CEC_USER_CONTROL_CODE_UP: + m_button.iButton = XINPUT_IR_REMOTE_UP; + break; + case CEC_USER_CONTROL_CODE_DOWN: + m_button.iButton = XINPUT_IR_REMOTE_DOWN; + break; + case CEC_USER_CONTROL_CODE_LEFT: + case CEC_USER_CONTROL_CODE_LEFT_UP: + case CEC_USER_CONTROL_CODE_LEFT_DOWN: + m_button.iButton = XINPUT_IR_REMOTE_LEFT; + break; + case CEC_USER_CONTROL_CODE_RIGHT: + case CEC_USER_CONTROL_CODE_RIGHT_UP: + case CEC_USER_CONTROL_CODE_RIGHT_DOWN: + m_button.iButton = XINPUT_IR_REMOTE_RIGHT; + break; + case CEC_USER_CONTROL_CODE_ROOT_MENU: + m_button.iButton = XINPUT_IR_REMOTE_MENU; + break; + case CEC_USER_CONTROL_CODE_EXIT: + m_button.iButton = XINPUT_IR_REMOTE_BACK; + break; + case CEC_USER_CONTROL_CODE_ENTER: + m_button.iButton = XINPUT_IR_REMOTE_ENTER; + break; + case CEC_USER_CONTROL_CODE_CHANNEL_DOWN: + m_button.iButton = XINPUT_IR_REMOTE_CHANNEL_MINUS; + break; + case CEC_USER_CONTROL_CODE_CHANNEL_UP: + m_button.iButton = XINPUT_IR_REMOTE_CHANNEL_PLUS; + break; + case CEC_USER_CONTROL_CODE_PREVIOUS_CHANNEL: + m_button.iButton = XINPUT_IR_REMOTE_BACK; + break; + case CEC_USER_CONTROL_CODE_SOUND_SELECT: + m_button.iButton = XINPUT_IR_REMOTE_LANGUAGE; + break; + case CEC_USER_CONTROL_CODE_POWER: + m_button.iButton = XINPUT_IR_REMOTE_POWER; + break; + case CEC_USER_CONTROL_CODE_VOLUME_UP: + m_button.iButton = XINPUT_IR_REMOTE_VOLUME_PLUS; + break; + case CEC_USER_CONTROL_CODE_VOLUME_DOWN: + m_button.iButton = XINPUT_IR_REMOTE_VOLUME_MINUS; + break; + case CEC_USER_CONTROL_CODE_MUTE: + m_button.iButton = XINPUT_IR_REMOTE_MUTE; + break; + case CEC_USER_CONTROL_CODE_PLAY: + m_button.iButton = XINPUT_IR_REMOTE_PLAY; + break; + case CEC_USER_CONTROL_CODE_STOP: + m_button.iButton = XINPUT_IR_REMOTE_STOP; + break; + case CEC_USER_CONTROL_CODE_PAUSE: + m_button.iButton = XINPUT_IR_REMOTE_STOP; + break; + case CEC_USER_CONTROL_CODE_REWIND: + m_button.iButton = XINPUT_IR_REMOTE_REVERSE; + break; + case CEC_USER_CONTROL_CODE_FAST_FORWARD: + m_button.iButton = XINPUT_IR_REMOTE_FORWARD; + break; + case CEC_USER_CONTROL_CODE_NUMBER0: + m_button.iButton = XINPUT_IR_REMOTE_0; + break; + case CEC_USER_CONTROL_CODE_NUMBER1: + m_button.iButton = XINPUT_IR_REMOTE_1; + break; + case CEC_USER_CONTROL_CODE_NUMBER2: + m_button.iButton = XINPUT_IR_REMOTE_2; + break; + case CEC_USER_CONTROL_CODE_NUMBER3: + m_button.iButton = XINPUT_IR_REMOTE_3; + break; + case CEC_USER_CONTROL_CODE_NUMBER4: + m_button.iButton = XINPUT_IR_REMOTE_4; + break; + case CEC_USER_CONTROL_CODE_NUMBER5: + m_button.iButton = XINPUT_IR_REMOTE_5; + break; + case CEC_USER_CONTROL_CODE_NUMBER6: + m_button.iButton = XINPUT_IR_REMOTE_6; + break; + case CEC_USER_CONTROL_CODE_NUMBER7: + m_button.iButton = XINPUT_IR_REMOTE_7; + break; + case CEC_USER_CONTROL_CODE_NUMBER8: + m_button.iButton = XINPUT_IR_REMOTE_8; + break; + case CEC_USER_CONTROL_CODE_NUMBER9: + m_button.iButton = XINPUT_IR_REMOTE_9; + break; + case CEC_USER_CONTROL_CODE_RECORD: + m_button.iButton = XINPUT_IR_REMOTE_RECORD; + break; + case CEC_USER_CONTROL_CODE_CLEAR: + m_button.iButton = XINPUT_IR_REMOTE_CLEAR; + break; + case CEC_USER_CONTROL_CODE_DISPLAY_INFORMATION: + m_button.iButton = XINPUT_IR_REMOTE_INFO; + break; + case CEC_USER_CONTROL_CODE_PAGE_UP: + m_button.iButton = XINPUT_IR_REMOTE_CHANNEL_PLUS; + break; + case CEC_USER_CONTROL_CODE_PAGE_DOWN: + m_button.iButton = XINPUT_IR_REMOTE_CHANNEL_MINUS; + break; + case CEC_USER_CONTROL_CODE_EJECT: + break; + case CEC_USER_CONTROL_CODE_FORWARD: + m_button.iButton = XINPUT_IR_REMOTE_SKIP_PLUS; + break; + case CEC_USER_CONTROL_CODE_BACKWARD: + m_button.iButton = XINPUT_IR_REMOTE_SKIP_MINUS; + break; + case CEC_USER_CONTROL_CODE_POWER_ON_FUNCTION: + break; + case CEC_USER_CONTROL_CODE_F1_BLUE: + m_button.iButton = XINPUT_IR_REMOTE_BLUE; + break; + case CEC_USER_CONTROL_CODE_F2_RED: + m_button.iButton = XINPUT_IR_REMOTE_RED; + break; + case CEC_USER_CONTROL_CODE_F3_GREEN: + m_button.iButton = XINPUT_IR_REMOTE_GREEN; + break; + case CEC_USER_CONTROL_CODE_F4_YELLOW: + m_button.iButton = XINPUT_IR_REMOTE_YELLOW; + break; + case CEC_USER_CONTROL_CODE_SETUP_MENU: + case CEC_USER_CONTROL_CODE_CONTENTS_MENU: + case CEC_USER_CONTROL_CODE_FAVORITE_MENU: + case CEC_USER_CONTROL_CODE_DOT: + case CEC_USER_CONTROL_CODE_NEXT_FAVORITE: + case CEC_USER_CONTROL_CODE_INPUT_SELECT: + case CEC_USER_CONTROL_CODE_INITIAL_CONFIGURATION: + case CEC_USER_CONTROL_CODE_HELP: + case CEC_USER_CONTROL_CODE_STOP_RECORD: + case CEC_USER_CONTROL_CODE_PAUSE_RECORD: + case CEC_USER_CONTROL_CODE_ANGLE: + case CEC_USER_CONTROL_CODE_SUB_PICTURE: + case CEC_USER_CONTROL_CODE_VIDEO_ON_DEMAND: + case CEC_USER_CONTROL_CODE_ELECTRONIC_PROGRAM_GUIDE: + case CEC_USER_CONTROL_CODE_TIMER_PROGRAMMING: + case CEC_USER_CONTROL_CODE_PLAY_FUNCTION: + case CEC_USER_CONTROL_CODE_PAUSE_PLAY_FUNCTION: + case CEC_USER_CONTROL_CODE_RECORD_FUNCTION: + case CEC_USER_CONTROL_CODE_PAUSE_RECORD_FUNCTION: + case CEC_USER_CONTROL_CODE_STOP_FUNCTION: + case CEC_USER_CONTROL_CODE_MUTE_FUNCTION: + case CEC_USER_CONTROL_CODE_RESTORE_VOLUME_FUNCTION: + case CEC_USER_CONTROL_CODE_TUNE_FUNCTION: + case CEC_USER_CONTROL_CODE_SELECT_MEDIA_FUNCTION: + case CEC_USER_CONTROL_CODE_SELECT_AV_INPUT_FUNCTION: + case CEC_USER_CONTROL_CODE_SELECT_AUDIO_INPUT_FUNCTION: + case CEC_USER_CONTROL_CODE_POWER_TOGGLE_FUNCTION: + case CEC_USER_CONTROL_CODE_POWER_OFF_FUNCTION: + case CEC_USER_CONTROL_CODE_F5: + case CEC_USER_CONTROL_CODE_DATA: + case CEC_USER_CONTROL_CODE_UNKNOWN: + m_bHasButton = false; + return false; + } + + return true; +} + +WORD CPeripheralCecAdapter::GetButton(void) +{ + CSingleLock lock(m_critSection); + if (!m_bHasButton) + GetNextKey(); + + return m_bHasButton ? m_button.iButton : 0; +} + +unsigned int CPeripheralCecAdapter::GetHoldTime(void) +{ + CSingleLock lock(m_critSection); + if (!m_bHasButton) + GetNextKey(); + + if (!m_bHasButton) + return 0; + + if (m_button.iButtonPressed && m_button.iButtonReleased) + return m_button.iButtonReleased - m_button.iButtonPressed; + else if (m_button.iButtonPressed) + return XbmcThreads::SystemClockMillis() - m_button.iButtonPressed; + + return 0; +} + +void CPeripheralCecAdapter::ResetButton(void) +{ + CSingleLock lock(m_critSection); + m_bHasButton = false; +} + +void CPeripheralCecAdapter::OnSettingChanged(const CStdString &strChangedSetting) +{ + if (strChangedSetting.Equals("enabled")) + { + bool bEnabled(GetSettingBool("enabled")); + if (!bEnabled && m_cecParser && m_bStarted) + StopThread(true); + else if (bEnabled && !m_cecParser && m_bStarted) + InitialiseFeature(FEATURE_CEC); + } +} + +void CPeripheralCecAdapter::FlushLog(void) +{ + cec_log_message message; + while (m_cecParser && m_cecParser->GetNextLogMessage(&message)) + { + int iLevel = -1; + switch (message.level) + { + case CEC_LOG_ERROR: + iLevel = LOGERROR; + break; + case CEC_LOG_WARNING: + iLevel = LOGWARNING; + break; + case CEC_LOG_NOTICE: + iLevel = LOGDEBUG; + break; + case CEC_LOG_DEBUG: + if (GetSettingBool("cec_debug_logging")) + iLevel = LOGDEBUG; + break; + } + + if (iLevel >= 0) + CLog::Log(iLevel, "%s - %s", __FUNCTION__, message.message.c_str()); + } +} + +bool CPeripheralCecAdapter::TranslateComPort(CStdString &strLocation) +{ + if (strLocation.Left(18).Equals("peripherals://usb/") && strLocation.Right(4).Equals(".dev")) + { + strLocation = strLocation.Right(strLocation.length() - 18); + strLocation = strLocation.Left(strLocation.length() - 4); + return true; + } + + return false; +} diff --git a/xbmc/peripherals/devices/PeripheralCecAdapter.h b/xbmc/peripherals/devices/PeripheralCecAdapter.h index 8b8c6c8d8c43f..fd27f2bd33c14 100644 --- a/xbmc/peripherals/devices/PeripheralCecAdapter.h +++ b/xbmc/peripherals/devices/PeripheralCecAdapter.h @@ -20,21 +20,56 @@ * */ -#include "Peripheral.h" +#include "PeripheralHID.h" #include "interfaces/AnnouncementManager.h" +#include "threads/Thread.h" +#include "threads/CriticalSection.h" +#include +#include namespace PERIPHERALS { - class CPeripheralCecAdapter : public CPeripheral, public ANNOUNCEMENT::IAnnouncer + typedef struct + { + WORD iButton; + unsigned int iButtonPressed; + unsigned int iButtonReleased; + } CecButtonPress; + + class CPeripheralCecAdapter : public CPeripheralHID, public ANNOUNCEMENT::IAnnouncer, private CThread { public: CPeripheralCecAdapter(const PeripheralType type, const PeripheralBusType busType, const CStdString &strLocation, const CStdString &strDeviceName, int iVendorId, int iProductId); virtual ~CPeripheralCecAdapter(void); virtual void Announce(ANNOUNCEMENT::EAnnouncementFlag flag, const char *sender, const char *message, const CVariant &data); - bool ScreenSetPower(bool bSetTo); + virtual bool PowerOffCecDevices(void); + virtual bool PowerOnCecDevices(void); + virtual bool StandbyCecDevices(void); + + virtual bool SendPing(void); + virtual bool StartBootloader(void); + + virtual void OnSettingChanged(const CStdString &strChangedSetting); + + virtual WORD GetButton(void); + virtual unsigned int GetHoldTime(void); + virtual void ResetButton(void); protected: + virtual void FlushLog(void); + virtual bool GetNextKey(void); virtual bool InitialiseFeature(const PeripheralFeature feature); + virtual void Process(void); + virtual void ProcessNextCommand(void); + static bool FindConfigLocation(CStdString &strString); + static bool TranslateComPort(CStdString &strPort); + + CEC::ICECDevice *m_cecParser; + bool m_bStarted; + bool m_bHasButton; + bool m_bIsReady; + CecButtonPress m_button; + CCriticalSection m_critSection; }; }