mirror of
				https://github.com/DigitalDevices/pvr.octonet.git
				synced 2025-03-01 10:53:09 +00:00 
			
		
		
		
	Compare commits
	
		
			43 Commits
		
	
	
		
			0.1
			...
			1.0.0-3-Ma
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 203f800eaa | ||
|  | 153dfeb3d5 | ||
|  | 1e44819300 | ||
|  | 54680a38bd | ||
|  | 689afbf4cd | ||
|  | c4af00a4fe | ||
|  | f1f8d44b78 | ||
|  | e9b4c05de5 | ||
|  | a77cf111bb | ||
|  | 020dd98e7b | ||
|  | d7bb865329 | ||
|  | 9bbd7cf3c4 | ||
|  | 7b9ec7d884 | ||
|  | 37abebb540 | ||
|  | 3494c4c470 | ||
|  | ff41fc9acc | ||
|  | 1ced6b3fa4 | ||
|  | cd774b6edc | ||
|  | 2a63777b6d | ||
|  | e9f0d6bf76 | ||
|  | 8549a31c8d | ||
|  | 0a7fb087ac | ||
|  | 5c0f000a91 | ||
|  | 2b020cec9c | ||
|  | 96a19310ca | ||
|  | 3a6f4eb7b5 | ||
|  | 2067aba378 | ||
|  | b52f50ef30 | ||
|  | d1f9af2225 | ||
|  | 880d313bef | ||
|  | 94eb166783 | ||
|  | ba7e50e79c | ||
|  | 5fc6fc2ebc | ||
|  | 8778ebe422 | ||
|  | 0adb1ade91 | ||
|  | 844a5c3cd4 | ||
|  | 838c0094b7 | ||
|  | c5b90f130b | ||
|  | 415d2c98ac | ||
|  | 2aa320ee2d | ||
|  | de0bf9c847 | ||
|  | 9abe9180b6 | ||
|  | 4665b282a2 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
								
							| @@ -1 +1,2 @@ | ||||
| /build | ||||
| pvr.octonet/addon.xml | ||||
|   | ||||
| @@ -37,9 +37,9 @@ before_install: | ||||
| before_script: | ||||
|   - cd $TRAVIS_BUILD_DIR/.. | ||||
|   - git clone --depth=1 https://github.com/xbmc/xbmc.git | ||||
|   - mkdir -p xbmc/project/cmake/addons/addons/pvr.octonet | ||||
|   - echo "pvr.octonet https://github.com/DigitalDevices/pvr.octonet master" > xbmc/project/cmake/addons/addons/pvr.octonet/pvr.octonet.txt | ||||
|   - mkdir -p xbmc/cmake/addons/addons/pvr.octonet | ||||
|   - echo "pvr.octonet https://github.com/DigitalDevices/pvr.octonet master" > xbmc/cmake/addons/addons/pvr.octonet/pvr.octonet.txt | ||||
|   - cd $TRAVIS_BUILD_DIR && mkdir build && cd build | ||||
|   - cmake -DADDONS_TO_BUILD=pvr.octonet -DADDON_SRC_PREFIX=$TRAVIS_BUILD_DIR/.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/../xbmc/addons -DPACKAGE_ZIP=1 $TRAVIS_BUILD_DIR/../xbmc/project/cmake/addons | ||||
|   - cmake -DADDONS_TO_BUILD=pvr.octonet -DADDON_SRC_PREFIX=$TRAVIS_BUILD_DIR/.. -DCMAKE_BUILD_TYPE=Debug -DCMAKE_INSTALL_PREFIX=$TRAVIS_BUILD_DIR/../xbmc/addons -DPACKAGE_ZIP=1 $TRAVIS_BUILD_DIR/../xbmc/cmake/addons | ||||
|  | ||||
| script: make | ||||
|   | ||||
| @@ -26,10 +26,19 @@ set(OCTONET_SOURCES | ||||
| 	src/Socket.cpp | ||||
| 	src/rtsp_client.cpp) | ||||
|  | ||||
| set(OCTONET_HEADERS | ||||
| 	src/client.h | ||||
| 	src/OctonetData.h | ||||
| 	src/Socket.h) | ||||
|  | ||||
| build_addon(pvr.octonet OCTONET DEPLIBS) | ||||
|  | ||||
| if(WIN32) | ||||
| 	target_link_libraries(pvr.octonet wsock32 ws2_32) | ||||
| 	if(NOT CMAKE_SYSTEM_NAME STREQUAL WindowsStore) | ||||
| 		target_link_libraries(pvr.octonet wsock32 ws2_32) | ||||
| 	else() | ||||
| 		target_link_libraries(pvr.octonet ws2_32) | ||||
| 	endif() | ||||
| endif() | ||||
|  | ||||
| include(CPack) | ||||
|   | ||||
							
								
								
									
										1
									
								
								Jenkinsfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								Jenkinsfile
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| buildPlugin() | ||||
							
								
								
									
										47
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										47
									
								
								README.md
									
									
									
									
									
								
							| @@ -1,27 +1,40 @@ | ||||
| # Octonet PVR | ||||
| DigitalDevices [Octonet] (http://www.digital-devices.eu/shop/de/netzwerk-tv/) PVR client addon for [Kodi] (http://kodi.tv) | ||||
| Digital Devices [Octonet](http://www.digital-devices.eu/shop/de/netzwerk-tv/) PVR client addon for [Kodi](http://kodi.tv) | ||||
|  | ||||
| | Platform | Status | | ||||
| |----------|--------| | ||||
| | Linux + OS X (Travis) | [](https://travis-ci.org/julianscheel/pvr.octonet) | | ||||
| | Windows (AppVeyor) | [](https://ci.appveyor.com/project/julianscheel/pvr-octonet) | | ||||
|  | ||||
| # Building | ||||
|  | ||||
| ## Windows | ||||
| 1. Create a file `project/cmake/addons/addons/kodi.pvr.octonet/kodi.pvr.octonet.txt` containing a | ||||
|    single line `kodi.pvr.octonet file://C:\some\path`. The path doesn't matter and doesn't need to | ||||
|    actually exist. | ||||
| These instructions work on all supported platforms for the most part. Obviously, paths need to be | ||||
| adjusted according to your OS (`/` vs `\`). We use Linux paths here as an example. | ||||
|  | ||||
| 2. Use a shell that has environment variables setup by Visual Studio for the native x86 toolchain. | ||||
|    Run the following in a new build directory and adjust paths accordingly: | ||||
| Clone the `pvr.octonet` repository: | ||||
|  | ||||
| ``` | ||||
| cmake -G "NMake Makefiles" ^ | ||||
|     -DCMAKE_BUILD_TYPE=Release ^ | ||||
|     -DADDONS_TO_BUILD="kodi.pvr.octonet" ^ | ||||
|     -DADDON_SRC_PREFIX="path_to_where_kodi.pvr.octonet_is" ^ | ||||
|     -DCMAKE_INSTALL_PREFIX="some_subdirectory" ^ | ||||
|     -DPACKAGE_ZIP=ON ^ | ||||
|     "path_to_kodi\project\cmake\addons" | ||||
| $ git clone https://github.com/DigitalDevices/pvr.octonet.git | ||||
| ``` | ||||
|  | ||||
| Make sure `ADDON_SRC_PREFIX` points to the parent directory of `kodi.pvr.octonet`. | ||||
| Clone the Kodi repository: | ||||
|  | ||||
| 4. Build the addon by running `nmake`. Run `nmake package-addons` to package a zip file of the | ||||
|    addon. | ||||
| ``` | ||||
| $ git clone https://github.com/xbmc/xbmc.git | ||||
| ``` | ||||
|  | ||||
| If you already have a local Kodi checkout, you can use that one. Just make sure it is recent enough | ||||
| (Kodi 17 Beta 5 or later should work). | ||||
|  | ||||
| ``` | ||||
| $ cd pvr.octonet | ||||
| $ mkdir build | ||||
| $ cd build | ||||
| $ cmake -DCMAKE_BUILD_TYPE=Release -DADDONS_TO_BUILD="pvr.octonet" -DADDON_SRC_PREFIX="path to parent of pvr.octonet" -DCMAKE_INSTALL_PREFIX="install" -DPACKAGE_ZIP=ON "path to kodi/cmake/addons" | ||||
| ``` | ||||
|  | ||||
| On Windows, you should add `-G "NMake Makefiles"` to the CMake invocation. Make sure that | ||||
| `ADDON_SRC_PREFIX` does _not_ point directly to `pvr.octonet` but instead to its parent directory. | ||||
|  | ||||
| Finally, build the plugin with `make` (or `nmake` on Windows). The plugin should be in an `install` | ||||
| subdirectory. | ||||
|   | ||||
							
								
								
									
										11
									
								
								appveyor.yml
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								appveyor.yml
									
									
									
									
									
								
							| @@ -21,15 +21,20 @@ environment: | ||||
|     - GENERATOR: "Visual Studio 14" | ||||
|       CONFIG: Release | ||||
|  | ||||
| artifacts: | ||||
|   - path: build/install/ | ||||
|     name: pvr.octonet | ||||
|     type: zip | ||||
|  | ||||
| build_script: | ||||
|   - cd .. | ||||
|   - set ROOT=%cd% | ||||
|   - git clone --depth=1 https://github.com/xbmc/xbmc.git | ||||
|   - mkdir xbmc\project\cmake\addons\addons\pvr.octonet | ||||
|   - echo pvr.octonet https://github.com/DigitalDevices/pvr.octonet master > xbmc\project\cmake\addons\addons\pvr.octonet\pvr.octonet.txt | ||||
|   - mkdir xbmc\cmake\addons\addons\pvr.octonet | ||||
|   - echo pvr.octonet https://github.com/DigitalDevices/pvr.octonet master > xbmc\cmake\addons\addons\pvr.octonet\pvr.octonet.txt | ||||
|   - cd %ADDON% | ||||
|   - mkdir build | ||||
|   - cd build | ||||
|   # Must use absolute path for cmake to build depends correctly | ||||
|   - cmake -G "%GENERATOR%" -DADDONS_TO_BUILD=%ADDON% -DCMAKE_BUILD_TYPE=%CONFIG% -DADDON_SRC_PREFIX=%ROOT% -DCMAKE_INSTALL_PREFIX=%ROOT%\xbmc\addons -DPACKAGE_ZIP=1 %ROOT%\xbmc\project\cmake\addons | ||||
|   - cmake -G "%GENERATOR%" -DADDONS_TO_BUILD=%ADDON% -DCMAKE_BUILD_TYPE=%CONFIG% -DADDON_SRC_PREFIX=%ROOT% -DCMAKE_INSTALL_PREFIX=install -DPACKAGE_ZIP=1 %ROOT%\xbmc\cmake\addons | ||||
|   - cmake --build . --config %CONFIG% | ||||
|   | ||||
							
								
								
									
										7
									
								
								debian/changelog.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								debian/changelog.in
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| kodi-pvr-octonet (#PACKAGEVERSION#-#TAGREV#~#DIST#) #DIST#; urgency=low | ||||
|  | ||||
|   [ kodi ] | ||||
|   * autogenerated dummy changelog | ||||
|  | ||||
|  -- Nobody <nobody@kodi.tv>  Sat, 01 Jun 2013 00:59:22 +0200 | ||||
|  | ||||
							
								
								
									
										1
									
								
								debian/compat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/compat
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| 9 | ||||
							
								
								
									
										22
									
								
								debian/control
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								debian/control
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| Source: kodi-pvr-octonet | ||||
| Priority: extra | ||||
| Maintainer: Julian Scheel <julian@jusst.de> | ||||
| Build-Depends: debhelper (>= 9.0.0), cmake, libjsoncpp-dev, | ||||
|                libkodiplatform-dev (>= 16.0.0), kodi-addon-dev | ||||
| Standards-Version: 3.9.4 | ||||
| Section: libs | ||||
| Homepage: https://github.com/DigitalDevices/pvr.octonet | ||||
|  | ||||
| Package: kodi-pvr-octonet | ||||
| Section: libs | ||||
| Architecture: any | ||||
| Depends: ${shlibs:Depends}, ${misc:Depends} | ||||
| Description: Digital Devices Octopus NET PVR for Kodi | ||||
|  Digital Devices Octopus NET PVR for Kodi | ||||
|  | ||||
| Package: kodi-pvr-octonet-dbg | ||||
| Section: libs | ||||
| Architecture: any | ||||
| Depends: ${shlibs:Depends}, ${misc:Depends} | ||||
| Description: debug symbols for Digital Devices Octopus NET PVR for Kodi | ||||
|  debug symbols for Digital Devices Octopus NET PVR for Kodi | ||||
							
								
								
									
										46
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								debian/copyright
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| Format: http://dep.debian.net/deps/dep5 | ||||
| Upstream-Name: pvr.octonet | ||||
| Source: https://github.com/DigitalDevices/pvr.octonet | ||||
|  | ||||
| Files: * | ||||
| Copyright: 2015-2016 Julian Scheel | ||||
|            2015-2016 jusst technologies GmbH | ||||
|            2005-2013 Team XBMC | ||||
| License: GPL-2+ | ||||
|  This package 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 of the License, or | ||||
|  (at your option) any later version. | ||||
|  . | ||||
|  This package 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 this program. If not, see <http://www.gnu.org/licenses/> | ||||
|  . | ||||
|  On Debian systems, the complete text of the GNU General | ||||
|  Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". | ||||
|  | ||||
| Files: debian/* | ||||
| Copyright: 2016 Julian Scheel <julian@jusst.de> | ||||
|            2015 Jean-Luc Barriere | ||||
|            2015 wsnipex <wsnipex@a1.net> | ||||
| License: GPL-2+ | ||||
|  This package 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 of the License, or | ||||
|  (at your option) any later version. | ||||
|  . | ||||
|  This package 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 this program. If not, see <http://www.gnu.org/licenses/> | ||||
|  . | ||||
|  On Debian systems, the complete text of the GNU General | ||||
|  Public License version 2 can be found in "/usr/share/common-licenses/GPL-2". | ||||
|  | ||||
							
								
								
									
										2
									
								
								debian/kodi-pvr-octonet.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2
									
								
								debian/kodi-pvr-octonet.install
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,2 @@ | ||||
| usr/lib/ | ||||
| usr/share/ | ||||
							
								
								
									
										24
									
								
								debian/rules
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						
									
										24
									
								
								debian/rules
									
									
									
									
										vendored
									
									
										Executable file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| #!/usr/bin/make -f | ||||
| # -*- makefile -*- | ||||
| # Sample debian/rules that uses debhelper. | ||||
| # This file was originally written by Joey Hess and Craig Small. | ||||
| # As a special exception, when this file is copied by dh-make into a | ||||
| # dh-make output file, you may use that output file without restriction. | ||||
| # This special exception was added by Craig Small in version 0.37 of dh-make. | ||||
|  | ||||
| # Uncomment this to turn on verbose mode. | ||||
| #export DH_VERBOSE=1 | ||||
|  | ||||
| %: | ||||
| 	dh $@  | ||||
|  | ||||
| override_dh_auto_configure: | ||||
| # USE_LTO breaks build | ||||
| 	dh_auto_configure -- -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 | ||||
|  | ||||
| override_dh_strip: | ||||
| 	dh_strip -pkodi-pvr-octonet --dbg-package=kodi-pvr-octonet-dbg | ||||
|  | ||||
| override_dh_installdocs: | ||||
| 	dh_installdocs --link-doc=kodi-pvr-octonet | ||||
|  | ||||
							
								
								
									
										1
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								debian/source/format
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| 3.0 (quilt) | ||||
| @@ -1,7 +1,10 @@ | ||||
| project(jsoncpp) | ||||
|  | ||||
| cmake_minimum_required(VERSION 2.6) | ||||
| cmake_minimum_required(VERSION 3.1) | ||||
| enable_language(CXX) | ||||
| SET(CMAKE_CXX_STANDARD 11) | ||||
| SET(CMAKE_CXX_STANDARD_REQUIRED ON) | ||||
| SET(CMAKE_CXX_EXTENSIONS OFF) | ||||
|  | ||||
| set(SOURCES src/lib_json/json_reader.cpp | ||||
|             src/lib_json/json_value.cpp | ||||
|   | ||||
| @@ -1 +1 @@ | ||||
| jsoncpp http://mirrors.kodi.tv/build-deps/sources/jsoncpp-src-0.5.0.tar.gz | ||||
| jsoncpp http://mirrors.kodi.tv/build-deps/sources/jsoncpp-1.8.3.tar.gz | ||||
|   | ||||
| @@ -1,23 +0,0 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <addon | ||||
| 	id="pvr.octonet" | ||||
| 	version="0.3" | ||||
| 	name="PVR DigitalDevices Octonet Client" | ||||
| 	provider-name="digitaldevices"> | ||||
| 	<requires> | ||||
| 		<c-pluff version="0.1" /> | ||||
| 		<import addon="xbmc.pvr" version="5.2.0" /> | ||||
| 	</requires> | ||||
| 	<extension | ||||
| 		point="xbmc.pvrclient" | ||||
| 		library_linux="pvr.octonet.so" | ||||
| 		library_osx="pvr.octonet.dylib" | ||||
| 		library_freebsd="pvr.octonet.so" | ||||
| 		library_windx="pvr.octonet.dll" | ||||
| 		library_android="libpvr.octonet.so" /> | ||||
| 	<extension point="xbmc.addon.metadata"> | ||||
| 		<summary lang="de_DE">Kodi PVR Addon für DigitalDevices Octonet Streams</summary> | ||||
| 		<summary lang="en_US">Kodi PVR Addon for DigitalDevices Octonet Streams</summary> | ||||
| 		<platform>all</platform> | ||||
| 	</extension> | ||||
| </addon> | ||||
							
								
								
									
										16
									
								
								pvr.octonet/addon.xml.in
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								pvr.octonet/addon.xml.in
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <addon | ||||
| 	id="pvr.octonet" | ||||
| 	version="0.7.0" | ||||
| 	name="Digital Devices Octopus NET Client" | ||||
| 	provider-name="digitaldevices"> | ||||
| 	<requires>@ADDON_DEPENDS@</requires> | ||||
| 	<extension | ||||
| 		point="xbmc.pvrclient" | ||||
| 		library_@PLATFORM@="@LIBRARY_FILENAME@"/> | ||||
| 	<extension point="xbmc.addon.metadata"> | ||||
| 		<summary lang="de_DE">Kodi PVR Addon für Digital Devices Octopus NET Streams</summary> | ||||
| 		<summary lang="en_US">Kodi PVR Addon for Digital Devices Octopus NET Streams</summary> | ||||
| 		<platform>@PLATFORM@</platform> | ||||
| 	</extension> | ||||
| </addon> | ||||
| @@ -19,3 +19,7 @@ msgstr "" | ||||
| msgctxt "#30000" | ||||
| msgid "Octonet Server Address" | ||||
| msgstr "" | ||||
|  | ||||
| msgctxt "#30001" | ||||
| msgid "Could not load chanellist" | ||||
| msgstr "" | ||||
|   | ||||
| @@ -19,3 +19,7 @@ msgstr "" | ||||
| msgctxt "#30000" | ||||
| msgid "Octonet Server Address" | ||||
| msgstr "" | ||||
|  | ||||
| msgctxt "#30001" | ||||
| msgid "Could not load chanellist" | ||||
| msgstr "" | ||||
|   | ||||
| @@ -41,8 +41,8 @@ OctonetData::OctonetData() | ||||
| 	groups.clear(); | ||||
| 	lastEpgLoad = 0; | ||||
|  | ||||
| 	if (loadChannelList()) | ||||
| 		kodi->QueueNotification(QUEUE_INFO, "%d channels loaded.", channels.size()); | ||||
| 	if (!loadChannelList()) | ||||
| 		libKodi->QueueNotification(QUEUE_ERROR, libKodi->GetLocalizedString(30001), channels.size()); | ||||
| } | ||||
|  | ||||
| OctonetData::~OctonetData(void) | ||||
| @@ -53,14 +53,8 @@ OctonetData::~OctonetData(void) | ||||
|  | ||||
| int64_t OctonetData::parseID(std::string id) | ||||
| { | ||||
| 	int64_t nativeId; | ||||
| 	size_t strip; | ||||
| 	/* Strip colons from id */ | ||||
| 	while ((strip = id.find(":")) != std::string::npos) | ||||
| 		id.erase(strip, 1); | ||||
|  | ||||
| 	std::stringstream ids(id); | ||||
| 	ids >> nativeId; | ||||
| 	std::hash<std::string> hash_fn; | ||||
| 	int64_t nativeId = hash_fn(id); | ||||
|  | ||||
| 	return nativeId; | ||||
| } | ||||
| @@ -68,15 +62,15 @@ int64_t OctonetData::parseID(std::string id) | ||||
| bool OctonetData::loadChannelList() | ||||
| { | ||||
| 	std::string jsonContent; | ||||
| 	void *f = kodi->OpenFile(("http://" + serverAddress + "/channellist.lua?select=json").c_str(), 0); | ||||
| 	void *f = libKodi->OpenFile(("http://" + serverAddress + "/channellist.lua?select=json").c_str(), 0); | ||||
| 	if (!f) | ||||
| 		return false; | ||||
|  | ||||
| 	char buf[1024]; | ||||
| 	while (int read = kodi->ReadFile(f, buf, 1024)) | ||||
| 	while (int read = libKodi->ReadFile(f, buf, 1024)) | ||||
| 		jsonContent.append(buf, read); | ||||
|  | ||||
| 	kodi->CloseFile(f); | ||||
| 	libKodi->CloseFile(f); | ||||
|  | ||||
| 	Json::Value root; | ||||
| 	Json::Reader reader; | ||||
| @@ -125,7 +119,6 @@ OctonetChannel* OctonetData::findChannel(int64_t nativeId) | ||||
| time_t OctonetData::parseDateTime(std::string date) | ||||
| { | ||||
| 	struct tm timeinfo; | ||||
| 	time_t time; | ||||
|  | ||||
| 	memset(&timeinfo, 0, sizeof(timeinfo)); | ||||
|  | ||||
| @@ -154,15 +147,15 @@ bool OctonetData::loadEPG(void) | ||||
| 		return false; | ||||
|  | ||||
| 	std::string jsonContent; | ||||
| 	void *f = kodi->OpenFile(("http://" + serverAddress + "/epg.lua?;#|encoding=gzip").c_str(), 0); | ||||
| 	void *f = libKodi->OpenFile(("http://" + serverAddress + "/epg.lua?;#|encoding=gzip").c_str(), 0); | ||||
| 	if (!f) | ||||
| 		return false; | ||||
|  | ||||
| 	char buf[1024]; | ||||
| 	while (int read = kodi->ReadFile(f, buf, 1024)) | ||||
| 	while (int read = libKodi->ReadFile(f, buf, 1024)) | ||||
| 		jsonContent.append(buf, read); | ||||
|  | ||||
| 	kodi->CloseFile(f); | ||||
| 	libKodi->CloseFile(f); | ||||
|  | ||||
| 	Json::Value root; | ||||
| 	Json::Reader reader; | ||||
| @@ -191,7 +184,7 @@ bool OctonetData::loadEPG(void) | ||||
| 			channel = findChannel(entry.channelId); | ||||
|  | ||||
| 		if (channel == NULL) { | ||||
| 			kodi->Log(LOG_ERROR, "EPG for unknown channel."); | ||||
| 			libKodi->Log(LOG_ERROR, "EPG for unknown channel."); | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| @@ -237,20 +230,23 @@ PVR_ERROR OctonetData::getChannels(ADDON_HANDLE handle, bool bRadio) | ||||
|  | ||||
| PVR_ERROR OctonetData::getEPG(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t start, time_t end) | ||||
| { | ||||
| 	bool needs_reload = false; | ||||
| 	for (unsigned int i = 0; i < channels.size(); i++) | ||||
| 	{ | ||||
| 		OctonetChannel &chan = channels.at(i); | ||||
| 		if (channel.iUniqueId != chan.id) | ||||
| 			continue; | ||||
|  | ||||
| 		if(chan.epg.empty()) { | ||||
| 			loadEPG(); | ||||
| 		} | ||||
|  | ||||
| 		// FIXME: Check if reload is needed!? | ||||
|  | ||||
| 		std::vector<OctonetEpgEntry>::iterator it; | ||||
| 		time_t last_end = 0; | ||||
| 		for (it = chan.epg.begin(); it < chan.epg.end(); ++it) { | ||||
| 			if (end > last_end) | ||||
| 				last_end = end; | ||||
| 		for (it = chan.epg.begin(); it != chan.epg.end(); ++it) { | ||||
| 			if (it->end > last_end) | ||||
| 				last_end = it->end; | ||||
|  | ||||
| 			if (it->end < start || it->start > end) { | ||||
| 				continue; | ||||
| @@ -259,7 +255,7 @@ PVR_ERROR OctonetData::getEPG(ADDON_HANDLE handle, const PVR_CHANNEL &channel, t | ||||
| 			EPG_TAG entry; | ||||
| 			memset(&entry, 0, sizeof(EPG_TAG)); | ||||
|  | ||||
| 			entry.iChannelNumber = i; | ||||
| 			entry.iUniqueChannelId = chan.id; | ||||
| 			entry.iUniqueBroadcastId = it->id; | ||||
| 			entry.strTitle = it->title.c_str(); | ||||
| 			entry.strPlotOutline = it->subtitle.c_str(); | ||||
| @@ -271,6 +267,24 @@ PVR_ERROR OctonetData::getEPG(ADDON_HANDLE handle, const PVR_CHANNEL &channel, t | ||||
|  | ||||
| 		if (last_end < end) | ||||
| 			loadEPG(); | ||||
|  | ||||
| 		for (it = chan.epg.begin(); it != chan.epg.end(); ++it) { | ||||
| 			if (it->end < start || it->start > end) { | ||||
| 				continue; | ||||
| 			} | ||||
|  | ||||
| 			EPG_TAG entry; | ||||
| 			memset(&entry, 0, sizeof(EPG_TAG)); | ||||
|  | ||||
| 			entry.iUniqueChannelId = chan.id; | ||||
| 			entry.iUniqueBroadcastId = it->id; | ||||
| 			entry.strTitle = it->title.c_str(); | ||||
| 			entry.strPlotOutline = it->subtitle.c_str(); | ||||
| 			entry.startTime = it->start; | ||||
| 			entry.endTime = it->end; | ||||
|  | ||||
| 			pvr->TransferEpgEntry(handle, &entry); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return PVR_ERROR_NO_ERROR; | ||||
| @@ -286,6 +300,16 @@ const std::string& OctonetData::getUrl(int id) const { | ||||
| 	return channels[0].url; | ||||
| } | ||||
|  | ||||
| const std::string& OctonetData::getName(int id) const { | ||||
| 	for(std::vector<OctonetChannel>::const_iterator iter = channels.begin(); iter != channels.end(); ++iter) { | ||||
| 		if(iter->id == id) { | ||||
| 			return iter->name; | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	return channels[0].name; | ||||
| } | ||||
|  | ||||
| int OctonetData::getGroupCount(void) | ||||
| { | ||||
| 	return groups.size(); | ||||
|   | ||||
| @@ -71,6 +71,7 @@ class OctonetData : public P8PLATFORM::CThread | ||||
|  | ||||
| 		virtual PVR_ERROR getEPG(ADDON_HANDLE handle, const PVR_CHANNEL &channel, time_t start, time_t end); | ||||
| 		const std::string& getUrl(int id) const; | ||||
| 		const std::string& getName(int id) const; | ||||
|  | ||||
| 	protected: | ||||
| 		virtual bool loadChannelList(void); | ||||
|   | ||||
| @@ -196,13 +196,13 @@ int Socket::send ( const char* data, const unsigned int len ) | ||||
|  | ||||
|   if (result < 0) | ||||
|   { | ||||
|     kodi->Log(LOG_ERROR, "Socket::send  - select failed"); | ||||
|     libKodi->Log(LOG_ERROR, "Socket::send  - select failed"); | ||||
|     close(); | ||||
|     return 0; | ||||
|   } | ||||
|   if (FD_ISSET(_sd, &set_w)) | ||||
|   { | ||||
|     kodi->Log(LOG_ERROR, "Socket::send  - failed to send data"); | ||||
|     libKodi->Log(LOG_ERROR, "Socket::send  - failed to send data"); | ||||
|     close(); | ||||
|     return 0; | ||||
|   } | ||||
| @@ -212,7 +212,7 @@ int Socket::send ( const char* data, const unsigned int len ) | ||||
|   if (status == -1) | ||||
|   { | ||||
|     errormessage( getLastError(), "Socket::send"); | ||||
|     kodi->Log(LOG_ERROR, "Socket::send  - failed to send data"); | ||||
|     libKodi->Log(LOG_ERROR, "Socket::send  - failed to send data"); | ||||
|     close(); | ||||
|     return 0; | ||||
|   } | ||||
| @@ -296,7 +296,7 @@ bool Socket::ReadLine (string& line) | ||||
|  | ||||
|     if (result < 0) | ||||
|     { | ||||
|       kodi->Log(LOG_DEBUG, "%s: select failed", __FUNCTION__); | ||||
|       libKodi->Log(LOG_DEBUG, "%s: select failed", __FUNCTION__); | ||||
|       errormessage(getLastError(), __FUNCTION__); | ||||
|       close(); | ||||
|       return false; | ||||
| @@ -306,11 +306,11 @@ bool Socket::ReadLine (string& line) | ||||
|     { | ||||
|       if (retries != 0) | ||||
|       { | ||||
|          kodi->Log(LOG_DEBUG, "%s: timeout waiting for response, retrying... (%i)", __FUNCTION__, retries); | ||||
|          libKodi->Log(LOG_DEBUG, "%s: timeout waiting for response, retrying... (%i)", __FUNCTION__, retries); | ||||
|          retries--; | ||||
|         continue; | ||||
|       } else { | ||||
|          kodi->Log(LOG_DEBUG, "%s: timeout waiting for response. Aborting after 10 retries.", __FUNCTION__); | ||||
|          libKodi->Log(LOG_DEBUG, "%s: timeout waiting for response. Aborting after 10 retries.", __FUNCTION__); | ||||
|          return false; | ||||
|       } | ||||
|     } | ||||
| @@ -318,7 +318,7 @@ bool Socket::ReadLine (string& line) | ||||
|     result = recv(_sd, buffer, sizeof(buffer) - 1, 0); | ||||
|     if (result < 0) | ||||
|     { | ||||
|       kodi->Log(LOG_DEBUG, "%s: recv failed", __FUNCTION__); | ||||
|       libKodi->Log(LOG_DEBUG, "%s: recv failed", __FUNCTION__); | ||||
|       errormessage(getLastError(), __FUNCTION__); | ||||
|       close(); | ||||
|       return false; | ||||
| @@ -389,7 +389,7 @@ bool Socket::connect ( const std::string& host, const unsigned short port ) | ||||
|  | ||||
|   if ( !setHostname( host ) ) | ||||
|   { | ||||
|     kodi->Log(LOG_ERROR, "Socket::setHostname(%s) failed.\n", host.c_str()); | ||||
|     libKodi->Log(LOG_ERROR, "Socket::setHostname(%s) failed.\n", host.c_str()); | ||||
|     return false; | ||||
|   } | ||||
|   _port = port; | ||||
| @@ -438,7 +438,7 @@ bool Socket::connect ( const std::string& host, const unsigned short port ) | ||||
|  | ||||
|   if (address == NULL) | ||||
|   { | ||||
|     kodi->Log(LOG_ERROR, "Socket::connect %s:%u\n", host.c_str(), port); | ||||
|     libKodi->Log(LOG_ERROR, "Socket::connect %s:%u\n", host.c_str(), port); | ||||
|     errormessage(getLastError(), "Socket::connect"); | ||||
|     close(); | ||||
|     return false; | ||||
| @@ -474,7 +474,7 @@ bool Socket::set_non_blocking ( const bool b ) | ||||
|  | ||||
|   if (ioctlsocket(_sd, FIONBIO, &iMode) == -1) | ||||
|   { | ||||
|     kodi->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket condition to: %i", iMode); | ||||
|     libKodi->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket condition to: %i", iMode); | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
| @@ -565,7 +565,7 @@ void Socket::errormessage( int errnum, const char* functionname) const | ||||
|   default: | ||||
|     errmsg = "WSA Error"; | ||||
|   } | ||||
|   kodi->Log(LOG_ERROR, "%s: (Winsock error=%i) %s\n", functionname, errnum, errmsg); | ||||
|   libKodi->Log(LOG_ERROR, "%s: (Winsock error=%i) %s\n", functionname, errnum, errmsg); | ||||
| } | ||||
|  | ||||
| int Socket::getLastError() const | ||||
| @@ -623,7 +623,7 @@ bool Socket::set_non_blocking ( const bool b ) | ||||
|  | ||||
|   if(fcntl (_sd , F_SETFL, opts) == -1) | ||||
|   { | ||||
|     kodi->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket flags to: %i", opts); | ||||
|     libKodi->Log(LOG_ERROR, "Socket::set_non_blocking - Can't set socket flags to: %i", opts); | ||||
|     return false; | ||||
|   } | ||||
|   return true; | ||||
| @@ -699,7 +699,7 @@ void Socket::errormessage( int errnum, const char* functionname) const | ||||
|       break; | ||||
|   } | ||||
|  | ||||
|   kodi->Log(LOG_ERROR, "%s: (errno=%i) %s\n", functionname, errnum, errmsg); | ||||
|   libKodi->Log(LOG_ERROR, "%s: (errno=%i) %s\n", functionname, errnum, errmsg); | ||||
| } | ||||
|  | ||||
| int Socket::getLastError() const | ||||
|   | ||||
							
								
								
									
										101
									
								
								src/client.cpp
									
									
									
									
									
								
							
							
						
						
									
										101
									
								
								src/client.cpp
									
									
									
									
									
								
							| @@ -36,7 +36,7 @@ std::string octonetAddress = ""; | ||||
|  | ||||
| /* internal state variables */ | ||||
| ADDON_STATUS addonStatus = ADDON_STATUS_UNKNOWN; | ||||
| CHelper_libXBMC_addon *kodi = NULL; | ||||
| CHelper_libXBMC_addon *libKodi = NULL; | ||||
| CHelper_libXBMC_pvr *pvr = NULL; | ||||
|  | ||||
| OctonetData *data = NULL; | ||||
| @@ -49,7 +49,7 @@ extern "C" { | ||||
| void ADDON_ReadSettings(void) | ||||
| { | ||||
| 	char buffer[2048]; | ||||
| 	if (kodi->GetSetting("octonetAddress", &buffer)) | ||||
| 	if (libKodi->GetSetting("octonetAddress", &buffer)) | ||||
| 		octonetAddress = buffer; | ||||
| } | ||||
|  | ||||
| @@ -59,22 +59,22 @@ ADDON_STATUS ADDON_Create(void *callbacks, void* props) | ||||
| 		return ADDON_STATUS_UNKNOWN; | ||||
|  | ||||
| 	PVR_PROPERTIES *pvrprops = (PVR_PROPERTIES*)props; | ||||
| 	kodi = new CHelper_libXBMC_addon; | ||||
| 	if (!kodi->RegisterMe(callbacks)) { | ||||
| 		kodi->Log(LOG_ERROR, "%s: Failed to register octonet addon", __func__); | ||||
| 		SAFE_DELETE(kodi); | ||||
| 	libKodi = new CHelper_libXBMC_addon; | ||||
| 	if (!libKodi->RegisterMe(callbacks)) { | ||||
| 		libKodi->Log(LOG_ERROR, "%s: Failed to register octonet addon", __func__); | ||||
| 		SAFE_DELETE(libKodi); | ||||
| 		return ADDON_STATUS_PERMANENT_FAILURE; | ||||
| 	} | ||||
|  | ||||
| 	pvr = new CHelper_libXBMC_pvr; | ||||
| 	if (!pvr->RegisterMe(callbacks)) { | ||||
| 		kodi->Log(LOG_ERROR, "%s: Failed to register octonet pvr addon", __func__); | ||||
| 		libKodi->Log(LOG_ERROR, "%s: Failed to register octonet pvr addon", __func__); | ||||
| 		SAFE_DELETE(pvr); | ||||
| 		SAFE_DELETE(kodi); | ||||
| 		SAFE_DELETE(libKodi); | ||||
| 		return ADDON_STATUS_PERMANENT_FAILURE; | ||||
| 	} | ||||
|  | ||||
| 	kodi->Log(LOG_DEBUG, "%s: Creating octonet pvr addon", __func__); | ||||
| 	libKodi->Log(LOG_DEBUG, "%s: Creating octonet pvr addon", __func__); | ||||
| 	ADDON_ReadSettings(); | ||||
|  | ||||
| 	data = new OctonetData; | ||||
| @@ -83,12 +83,10 @@ ADDON_STATUS ADDON_Create(void *callbacks, void* props) | ||||
| 	return addonStatus; | ||||
| } | ||||
|  | ||||
| void ADDON_Stop() {} /* no-op */ | ||||
|  | ||||
| void ADDON_Destroy() | ||||
| { | ||||
| 	delete pvr; | ||||
| 	delete kodi; | ||||
| 	delete libKodi; | ||||
| 	addonStatus = ADDON_STATUS_UNKNOWN; | ||||
| } | ||||
|  | ||||
| @@ -97,16 +95,6 @@ ADDON_STATUS ADDON_GetStatus() | ||||
| 	return addonStatus; | ||||
| } | ||||
|  | ||||
| bool ADDON_HasSettings() | ||||
| { | ||||
| 	return true; | ||||
| } | ||||
|  | ||||
| unsigned int ADDON_GetSettings(ADDON_StructSetting ***sSet) | ||||
| { | ||||
| 	return 0; | ||||
| } | ||||
|  | ||||
| ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) | ||||
| { | ||||
| 	/* For simplicity do a full addon restart whenever settings are | ||||
| @@ -114,9 +102,6 @@ ADDON_STATUS ADDON_SetSetting(const char *settingName, const void *settingValue) | ||||
| 	return ADDON_STATUS_NEED_RESTART; | ||||
| } | ||||
|  | ||||
| void ADDON_FreeSettings() {} /* no-op */ | ||||
| void ADDON_Announce(const char *flag, const char *sender, const char *message, const void *data) {} /* no-op */ | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| @@ -125,44 +110,28 @@ void ADDON_Announce(const char *flag, const char *sender, const char *message, c | ||||
| extern "C" | ||||
| { | ||||
|  | ||||
| const char* GetPVRAPIVersion(void) | ||||
| { | ||||
| 	return XBMC_PVR_API_VERSION; | ||||
| } | ||||
|  | ||||
| const char* GetMininumPVRAPIVersion(void) | ||||
| { | ||||
| 	return XBMC_PVR_MIN_API_VERSION; | ||||
| } | ||||
|  | ||||
| const char* GetGUIAPIVersion(void) | ||||
| { | ||||
| 	return KODI_GUILIB_API_VERSION; | ||||
| } | ||||
|  | ||||
| const char* GetMininumGUIAPIVersion(void) | ||||
| { | ||||
| 	return KODI_GUILIB_MIN_API_VERSION; | ||||
| } | ||||
|  | ||||
| PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES *pCapabilities) | ||||
| { | ||||
| 	pCapabilities->bSupportsTV = true; | ||||
| 	pCapabilities->bSupportsRadio = true; | ||||
| 	pCapabilities->bSupportsChannelGroups = true; | ||||
| 	pCapabilities->bSupportsEPG = true; | ||||
| 	pCapabilities->bSupportsRecordings = false; | ||||
| 	pCapabilities->bSupportsRecordingsRename = false; | ||||
| 	pCapabilities->bSupportsRecordingsLifetimeChange = false; | ||||
| 	pCapabilities->bSupportsDescrambleInfo = false; | ||||
|  | ||||
| 	return PVR_ERROR_NO_ERROR; | ||||
| } | ||||
|  | ||||
| const char* GetBackendName(void) | ||||
| { | ||||
| 	return "DigitalDevice Octonet PVR Addon"; | ||||
| 	return "Digital Devices Octopus NET Client"; | ||||
| } | ||||
|  | ||||
| const char* GetBackendVersion(void) | ||||
| { | ||||
| 	return XBMC_PVR_API_VERSION; | ||||
| 	return STR(OCTONET_VERSION); | ||||
| } | ||||
|  | ||||
| const char* GetConnectionString(void) | ||||
| @@ -174,12 +143,12 @@ PVR_ERROR GetDriveSpace(long long* iTotal, long long* iUsed) { return PVR_ERROR_ | ||||
| PVR_ERROR CallMenuHook(const PVR_MENUHOOK& menuhook, const PVR_MENUHOOK_DATA &item) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
|  | ||||
| void OnSystemSleep() { | ||||
| 	kodi->Log(LOG_INFO, "Received event: %s", __FUNCTION__); | ||||
| 	libKodi->Log(LOG_INFO, "Received event: %s", __FUNCTION__); | ||||
| 	// FIXME: Disconnect? | ||||
| } | ||||
|  | ||||
| void OnSystemWake() { | ||||
| 	kodi->Log(LOG_INFO, "Received event: %s", __FUNCTION__); | ||||
| 	libKodi->Log(LOG_INFO, "Received event: %s", __FUNCTION__); | ||||
| 	// FIXME:Reconnect? | ||||
| } | ||||
|  | ||||
| @@ -192,6 +161,9 @@ PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL& channel, time | ||||
| 	return data->getEPG(handle, channel, iStart, iEnd); | ||||
| } | ||||
|  | ||||
| PVR_ERROR IsEPGTagRecordable(const EPG_TAG*, bool*) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR IsEPGTagPlayable(const EPG_TAG*, bool*) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
|  | ||||
| /* Channel groups */ | ||||
| int GetChannelGroupsAmount(void) | ||||
| { | ||||
| @@ -223,7 +195,6 @@ PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio) | ||||
|  | ||||
| PVR_ERROR DeleteChannel(const PVR_CHANNEL& channel) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR RenameChannel(const PVR_CHANNEL& channel) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR MoveChannel(const PVR_CHANNEL& channel) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR OpenDialogChannelSettings(const PVR_CHANNEL& channel) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR OpenDialogChannelAdd(const PVR_CHANNEL& channel) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
|  | ||||
| @@ -234,6 +205,7 @@ PVR_ERROR DeleteRecording(const PVR_RECORDING& recording) { return PVR_ERROR_NOT | ||||
| PVR_ERROR UndeleteRecording(const PVR_RECORDING& recording) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR DeleteAllRecordingsFromTrash() { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR RenameRecording(const PVR_RECORDING& recording) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR SetRecordingLifetime(const PVR_RECORDING*) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR SetRecordingPlayCount(const PVR_RECORDING& recording, int count) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR SetRecordingLastPlayedPosition(const PVR_RECORDING& recording, int lastplayedposition) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| int GetRecordingLastPlayedPosition(const PVR_RECORDING& recording) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| @@ -245,11 +217,18 @@ PVR_ERROR AddTimer(const PVR_TIMER& timer) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR DeleteTimer(const PVR_TIMER& timer, bool bForceDelete) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR UpdateTimer(const PVR_TIMER& timer) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
|  | ||||
| /* PVR stream properties handling */ | ||||
| PVR_ERROR GetStreamReadChunkSize(int* chunksize) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR GetChannelStreamProperties(const PVR_CHANNEL*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR GetRecordingStreamProperties(const PVR_RECORDING*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR GetEPGTagStreamProperties(const EPG_TAG*, PVR_NAMED_VALUE*, unsigned int*) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR GetEPGTagEdl(const EPG_TAG* epgTag, PVR_EDL_ENTRY edl[], int *size) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
|  | ||||
| /* PVR stream handling */ | ||||
| /* entirely unused, as we use standard RTSP+TS mux, which can be handlded by | ||||
|  * Kodi core */ | ||||
| bool OpenLiveStream(const PVR_CHANNEL& channel) { | ||||
| 	return rtsp_open(data->getUrl(channel.iUniqueId)); | ||||
| 	return rtsp_open(data->getName(channel.iUniqueId), data->getUrl(channel.iUniqueId)); | ||||
| } | ||||
|  | ||||
| int ReadLiveStream(unsigned char* pBuffer, unsigned int iBufferSize) { | ||||
| @@ -261,25 +240,24 @@ void CloseLiveStream(void) { | ||||
| } | ||||
|  | ||||
| long long SeekLiveStream(long long iPosition, int iWhence) { return -1; } | ||||
| long long PositionLiveStream(void) { return -1; } | ||||
| long long LengthLiveStream(void) { return -1; } | ||||
| bool IsRealTimeStream(void) { return true; } | ||||
|  | ||||
| bool SwitchChannel(const PVR_CHANNEL& channel) { | ||||
| 	CloseLiveStream(); | ||||
| 	return OpenLiveStream(channel); | ||||
| PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS& signalStatus) { | ||||
| 	memset(&signalStatus, 0, sizeof(PVR_SIGNAL_STATUS)); | ||||
| 	rtsp_fill_signal_status(signalStatus); | ||||
| 	return PVR_ERROR_NO_ERROR; | ||||
| } | ||||
|  | ||||
| PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS& signalStatus) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| const char* GetLiveStreamURL(const PVR_CHANNEL& channel) { return NULL; } | ||||
| PVR_ERROR GetStreamTimes(PVR_STREAM_TIMES *times) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
| PVR_ERROR GetDescrambleInfo(PVR_DESCRAMBLE_INFO*) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
|  | ||||
| /* Recording stream handling */ | ||||
| bool OpenRecordedStream(const PVR_RECORDING& recording) { return false; } | ||||
| void CloseRecordedStream(void) {} | ||||
| int ReadRecordedStream(unsigned char* pBuffer, unsigned int iBufferSize) { return -1; } | ||||
| long long SeekRecordedStream(long long iPosition, int iWhence) { return -1; } | ||||
| long long PositionRecordedStream(void) { return -1; } | ||||
| long long LengthRecordedStream(void) { return -1; } | ||||
|  | ||||
| /* PVR demuxer */ | ||||
| @@ -290,21 +268,16 @@ void DemuxFlush(void) {} | ||||
| DemuxPacket* DemuxRead(void) { return NULL; } | ||||
|  | ||||
| /* Various helper functions */ | ||||
| unsigned int GetChannelSwitchDelay(void) { return 0; } | ||||
| bool IsTimeshifting(void) { return false; } | ||||
| bool CanPauseStream() { return false; } | ||||
| bool CanSeekStream() { return false; } | ||||
|  | ||||
| /* Callbacks */ | ||||
| void PauseStream(bool bPaused) {} | ||||
| bool SeekTime(int time, bool backwards, double *startpts) { return false; } | ||||
| bool SeekTime(double time, bool backwards, double *startpts) { return false; } | ||||
| void SetSpeed(int speed) {} | ||||
| PVR_ERROR SetEPGTimeFrame(int) { return PVR_ERROR_NOT_IMPLEMENTED; } | ||||
|  | ||||
| time_t GetPlayingTime() { return 0; } | ||||
| time_t GetBufferTimeStart() { return 0; } | ||||
| time_t GetBufferTimeEnd() { return 0; } | ||||
|  | ||||
| const char* GetBackendHostname() | ||||
| { | ||||
| 	return octonetAddress.c_str(); | ||||
|   | ||||
| @@ -28,7 +28,7 @@ | ||||
| #define __func__ __FUNCTION__ | ||||
| #endif | ||||
|  | ||||
| extern ADDON::CHelper_libXBMC_addon *kodi; | ||||
| extern ADDON::CHelper_libXBMC_addon *libKodi; | ||||
| extern CHelper_libXBMC_pvr *pvr; | ||||
|  | ||||
| /* IP or hostname of the octonet to be connected to */ | ||||
|   | ||||
| @@ -37,6 +37,7 @@ int asprintf(char **sptr, char *fmt, ...) { | ||||
| #define KEEPALIVE_INTERVAL 60 | ||||
| #define KEEPALIVE_MARGIN 5 | ||||
| #define UDP_ADDRESS_LEN 16 | ||||
| #define RTCP_BUFFER_SIZE 1024 | ||||
|  | ||||
| using namespace std; | ||||
| using namespace ADDON; | ||||
| @@ -66,12 +67,17 @@ struct rtsp_client { | ||||
|  | ||||
| 	Socket tcp_sock; | ||||
| 	Socket udp_sock; | ||||
| 	Socket rtcp_sock; | ||||
|  | ||||
| 	enum rtsp_state state; | ||||
| 	int cseq; | ||||
|  | ||||
| 	size_t fifo_size; | ||||
| 	uint16_t last_seq_nr; | ||||
|  | ||||
| 	string name; | ||||
| 	int level; | ||||
| 	int quality; | ||||
| }; | ||||
|  | ||||
| struct url { | ||||
| @@ -81,6 +87,16 @@ struct url { | ||||
| 	string path; | ||||
| }; | ||||
|  | ||||
| struct rtcp_app { | ||||
| 	uint8_t subtype; | ||||
| 	uint8_t pt; | ||||
| 	uint16_t len; | ||||
| 	uint32_t ssrc; | ||||
| 	char name[4]; | ||||
| 	uint16_t identifier; | ||||
| 	uint16_t string_len; | ||||
| }; | ||||
|  | ||||
| static rtsp_client *rtsp = NULL; | ||||
|  | ||||
| static url parse_url(const std::string& str) { | ||||
| @@ -109,6 +125,16 @@ static url parse_url(const std::string& str) { | ||||
| 	return result; | ||||
| } | ||||
|  | ||||
| void split_string(const string& s, char delim, vector<string>& elems) { | ||||
| 	stringstream ss; | ||||
| 	ss.str(s); | ||||
|  | ||||
| 	string item; | ||||
| 	while(getline(ss, item, delim)) { | ||||
| 		elems.push_back(item); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| static int tcp_sock_read_line(string &line) { | ||||
| 	static string buf; | ||||
|  | ||||
| @@ -266,7 +292,7 @@ static enum rtsp_result rtsp_handle() { | ||||
| 	return (enum rtsp_result)rtsp_result; | ||||
| } | ||||
|  | ||||
| bool rtsp_open(const string& url_str) | ||||
| bool rtsp_open(const string& name, const string& url_str) | ||||
| { | ||||
| 	string setup_url_str; | ||||
| 	const char *psz_setup_url; | ||||
| @@ -279,13 +305,17 @@ bool rtsp_open(const string& url_str) | ||||
| 	if (rtsp == NULL) | ||||
| 		return false; | ||||
|  | ||||
| 	kodi->Log(LOG_DEBUG, "try to open '%s'", url_str.c_str()); | ||||
| 	rtsp->name = name; | ||||
| 	rtsp->level = 0; | ||||
| 	rtsp->quality = 0; | ||||
|  | ||||
| 	libKodi->Log(LOG_DEBUG, "try to open '%s'", url_str.c_str()); | ||||
|  | ||||
| 	url dst = parse_url(url_str); | ||||
| 	kodi->Log(LOG_DEBUG, "connect to host '%s'", dst.host.c_str()); | ||||
| 	libKodi->Log(LOG_DEBUG, "connect to host '%s'", dst.host.c_str()); | ||||
|  | ||||
| 	if(!rtsp->tcp_sock.connect(dst.host, dst.port)) { | ||||
| 		kodi->Log(LOG_ERROR, "Failed to connect to RTSP server %s:%d", dst.host.c_str(), dst.port); | ||||
| 		libKodi->Log(LOG_ERROR, "Failed to connect to RTSP server %s:%d", dst.host.c_str(), dst.port); | ||||
| 		goto error; | ||||
| 	} | ||||
|  | ||||
| @@ -323,7 +353,7 @@ bool rtsp_open(const string& url_str) | ||||
| 	rtsp->tcp_sock.send(setup_ss.str()); | ||||
|  | ||||
| 	if (rtsp_handle() != RTSP_RESULT_OK) { | ||||
| 		kodi->Log(LOG_ERROR, "Failed to setup RTSP session"); | ||||
| 		libKodi->Log(LOG_ERROR, "Failed to setup RTSP session"); | ||||
| 		goto error; | ||||
| 	} | ||||
|  | ||||
| @@ -338,7 +368,15 @@ bool rtsp_open(const string& url_str) | ||||
| 	rtsp->tcp_sock.send(play_ss.str()); | ||||
|  | ||||
| 	if (rtsp_handle() != RTSP_RESULT_OK) { | ||||
| 		kodi->Log(LOG_ERROR, "Failed to play RTSP session"); | ||||
| 		libKodi->Log(LOG_ERROR, "Failed to play RTSP session"); | ||||
| 		goto error; | ||||
| 	} | ||||
|  | ||||
| 	rtsp->rtcp_sock = Socket(af_inet, pf_inet, sock_dgram, udp); | ||||
| 	if(!rtsp->rtcp_sock.bind(rtsp->udp_port + 1)) { | ||||
| 		goto error; | ||||
| 	} | ||||
| 	if(!rtsp->rtcp_sock.set_non_blocking(true)) { | ||||
| 		goto error; | ||||
| 	} | ||||
|  | ||||
| @@ -349,11 +387,49 @@ error: | ||||
| 	return false; | ||||
| } | ||||
|  | ||||
| static void parse_rtcp(const char *buf, int size) { | ||||
| 	int offset = 0; | ||||
| 	while(size > 4) { | ||||
| 		const rtcp_app *app = reinterpret_cast<const rtcp_app *>(buf + offset); | ||||
| 		uint16_t len = 4 * (ntohs(app->len) + 1); | ||||
|  | ||||
| 		if((app->pt != 204) || (memcmp(app->name, "SES1", 4) != 0)) { | ||||
| 			size -= len; | ||||
| 			offset += len; | ||||
| 			continue; | ||||
| 		} | ||||
|  | ||||
| 		uint16_t string_len = ntohs(app->string_len); | ||||
| 		string app_data(&buf[offset + sizeof(rtcp_app)], string_len); | ||||
|  | ||||
| 		vector<string> elems; | ||||
| 		split_string(app_data, ';', elems); | ||||
| 		if(elems.size() != 4) { | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		vector<string> tuner; | ||||
| 		split_string(elems[2], ',', tuner); | ||||
| 		if(tuner.size() < 4) { | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		rtsp->level = atoi(tuner[1].c_str()); | ||||
| 		rtsp->quality = atoi(tuner[3].c_str()); | ||||
|  | ||||
| 		return; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| int rtsp_read(void *buf, unsigned buf_size) { | ||||
| 	sockaddr addr; | ||||
| 	socklen_t addr_len = sizeof(addr); | ||||
| 	int ret = rtsp->udp_sock.recvfrom((char *)buf, buf_size, (sockaddr *)&addr, &addr_len); | ||||
|  | ||||
| 	char rtcp_buf[RTCP_BUFFER_SIZE]; | ||||
| 	int rtcp_len = rtsp->rtcp_sock.recvfrom(rtcp_buf, RTCP_BUFFER_SIZE, (sockaddr *)&addr, &addr_len); | ||||
| 	parse_rtcp(rtcp_buf, rtcp_len); | ||||
|  | ||||
| 	// TODO: check ip | ||||
|  | ||||
| 	return ret; | ||||
| @@ -377,7 +453,7 @@ static void rtsp_teardown() { | ||||
| 		rtsp->tcp_sock.send(ss.str()); | ||||
|  | ||||
| 		if (rtsp_handle() != RTSP_RESULT_OK) { | ||||
| 			kodi->Log(LOG_ERROR, "Failed to teardown RTSP session"); | ||||
| 			libKodi->Log(LOG_ERROR, "Failed to teardown RTSP session"); | ||||
| 			return; | ||||
| 		} | ||||
| 	} | ||||
| @@ -389,7 +465,16 @@ void rtsp_close() | ||||
| 		rtsp_teardown(); | ||||
| 		rtsp->tcp_sock.close(); | ||||
| 		rtsp->udp_sock.close(); | ||||
| 		rtsp->rtcp_sock.close(); | ||||
| 		delete rtsp; | ||||
| 		rtsp = NULL; | ||||
| 	} | ||||
| } | ||||
|  | ||||
| void rtsp_fill_signal_status(PVR_SIGNAL_STATUS& signal_status) { | ||||
| 	if(rtsp) { | ||||
| 		strncpy(signal_status.strServiceName, rtsp->name.c_str(), PVR_ADDON_NAME_STRING_LENGTH - 1); | ||||
| 		signal_status.iSNR = 0x1111 * rtsp->quality; | ||||
| 		signal_status.iSignal = 0x101 * rtsp->level; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -2,9 +2,11 @@ | ||||
| #define _RTSP_CLIENT_HPP_ | ||||
|  | ||||
| #include <string> | ||||
| #include <xbmc_pvr_types.h> | ||||
|  | ||||
| bool rtsp_open(const std::string& url_str); | ||||
| bool rtsp_open(const std::string& name, const std::string& url_str); | ||||
| void rtsp_close(); | ||||
| int rtsp_read(void *buf, unsigned buf_size); | ||||
| void rtsp_fill_signal_status(PVR_SIGNAL_STATUS& signal_status); | ||||
|  | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user