diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..c68515a --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,24 @@ +project(pvr.octonet) + +cmake_minimum_required(VERSION 2.6) + +enable_language(CXX) + +find_package(kodi REQUIRED) +find_package(kodiplatform REQUIRED) +find_package(platform REQUIRED) + +include_directories( + ${kodiplatform_INCLUDE_DIRS} + ${platform_INCLUDE_DIRS} + ${KODI_INCLUDE_DIR}) + +set(DEPLIBS + ${platform_LIBRARIES}) + +set(OCTONET_SOURCES + src/client.cpp) + +build_addon(pvr.octonet OCTONET DEPLIBS) + +include(CPack) diff --git a/pvr.octonet/addon.xml b/pvr.octonet/addon.xml new file mode 100644 index 0000000..b5cad6f --- /dev/null +++ b/pvr.octonet/addon.xml @@ -0,0 +1,23 @@ + + + + + + + + + Kodi PVR Addon für DigitalDevices Octonet Streams + Kodi PVR Addon for DigitalDevices Octonet Streams + all + + diff --git a/pvr.octonet/resources/language/resource.language.en_gb/strings.po b/pvr.octonet/resources/language/resource.language.en_gb/strings.po new file mode 100644 index 0000000..8d44017 --- /dev/null +++ b/pvr.octonet/resources/language/resource.language.en_gb/strings.po @@ -0,0 +1,21 @@ +# Kodi Media Center language file +# Addon Name: PVR Octonet Client +# Addon id: pvr.octonet +# Addon Provider: Julian Scheel +msgid "" +msgstr "" +"Project-Id-Version: KODI Main\n" +"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/kodi-main/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Octonet Server Address" +msgstr "" diff --git a/pvr.octonet/resources/language/resource.language.en_us/strings.po b/pvr.octonet/resources/language/resource.language.en_us/strings.po new file mode 100644 index 0000000..8d44017 --- /dev/null +++ b/pvr.octonet/resources/language/resource.language.en_us/strings.po @@ -0,0 +1,21 @@ +# Kodi Media Center language file +# Addon Name: PVR Octonet Client +# Addon id: pvr.octonet +# Addon Provider: Julian Scheel +msgid "" +msgstr "" +"Project-Id-Version: KODI Main\n" +"Report-Msgid-Bugs-To: http://trac.kodi.tv/\n" +"POT-Creation-Date: YEAR-MO-DA HO:MI+ZONE\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Kodi Translation Team\n" +"Language-Team: English (United Kingdom) (http://www.transifex.com/projects/p/kodi-main/language/en_GB/)\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=UTF-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Language: en_GB\n" +"Plural-Forms: nplurals=2; plural=(n != 1);\n" + +msgctxt "#30000" +msgid "Octonet Server Address" +msgstr "" diff --git a/pvr.octonet/resources/settings.xml b/pvr.octonet/resources/settings.xml new file mode 100644 index 0000000..7e1e6fb --- /dev/null +++ b/pvr.octonet/resources/settings.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/src/client.cpp b/src/client.cpp new file mode 100644 index 0000000..d5b2719 --- /dev/null +++ b/src/client.cpp @@ -0,0 +1,290 @@ +/* + * Copyright (C) 2015 Julian Scheel + * Copyright (C) 2015 jusst technologies GmbH + * Copyright (C) 2015 Digital Devices GmbH + * + * 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 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + */ + +#include "client.h" +#include +#include +#include +#include + +using namespace ADDON; + +/* setting variables with defaults */ +std::string octonetAddress = ""; + +/* internal state variables */ +ADDON_STATUS addonStatus = ADDON_STATUS_UNKNOWN; +CHelper_libXBMC_addon *kodi = NULL; +CHelper_libXBMC_pvr *pvr = NULL; + +/* KODI Core Addon functions + * see xbmc_addon_dll.h */ + +extern "C" { + +void ADDON_ReadSettings(void) +{ + char buffer[2048]; + if (kodi->GetSetting("octonetAddress", &buffer)) + octonetAddress = buffer; +} + +ADDON_STATUS ADDON_Create(void *callbacks, void* props) +{ + if (callbacks == NULL || props == NULL) + 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); + 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__); + SAFE_DELETE(pvr); + SAFE_DELETE(kodi); + return ADDON_STATUS_PERMANENT_FAILURE; + } + + kodi->Log(LOG_DEBUG, "%s: Creating octonet pvr addon", __func__); + ADDON_ReadSettings(); + + addonStatus = ADDON_STATUS_OK; + return addonStatus; +} + +void ADDON_Stop() {} /* no-op */ + +void ADDON_Destroy() +{ + delete pvr; + delete kodi; + addonStatus = ADDON_STATUS_UNKNOWN; +} + +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 + * changed */ + 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 */ + +} + + +/* KODI PVR Addon functions + * see xbmc_pvr_dll.h */ +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; + + return PVR_ERROR_NO_ERROR; +} + +const char* GetBackendName(void) +{ + return "DigitalDevice Octonet PVR Addon"; +} + +const char* GetBackendVersion(void) +{ + return XBMC_PVR_API_VERSION; +} + +const char* GetConnectionString(void) +{ + return "connected"; // FIXME: translate? +} + +PVR_ERROR GetDriveSpace(long long* iTotal, long long* iUsed) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR CallMenuHook(const PVR_MENUHOOK& menuhook, const PVR_MENUHOOK_DATA &item) { return PVR_ERROR_NOT_IMPLEMENTED; } + +/* EPG */ +PVR_ERROR GetEPGForChannel(ADDON_HANDLE handle, const PVR_CHANNEL& channel, time_t iStart, time_t iEnd) { return PVR_ERROR_NOT_IMPLEMENTED; } + +/* Channel groups */ +int GetChannelGroupsAmount(void) { return -1; } +PVR_ERROR GetChannelGroups(ADDON_HANDLE handle, bool bRadio) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR GetChannelGroupMembers(ADDON_HANDLE handle, const PVR_CHANNEL_GROUP& group) { return PVR_ERROR_NOT_IMPLEMENTED; } + +/* Channels */ +PVR_ERROR OpenDialogChannelScan(void) { return PVR_ERROR_NOT_IMPLEMENTED; } + +int GetChannelsAmount(void) +{ + // FIXME: This is a dummy + return 2; +} + +PVR_ERROR GetChannels(ADDON_HANDLE handle, bool bRadio) +{ + // FIXME: This is a dummy + if (!bRadio) { + PVR_CHANNEL chan; + memset(&chan, 0, sizeof(PVR_CHANNEL)); + + chan.iUniqueId = 1; + chan.bIsRadio = bRadio; + chan.iChannelNumber = 1; + snprintf(chan.strChannelName, sizeof(chan.strChannelName) - 1, + "Das Erste"); + snprintf(chan.strStreamURL, sizeof(chan.strStreamURL) - 1, + "rtsp://172.27.1.40:8554/channel/1"); + + pvr->TransferChannelEntry(handle, &chan); + } else { + PVR_CHANNEL chan; + memset(&chan, 0, sizeof(PVR_CHANNEL)); + + chan.iUniqueId = 2; + chan.bIsRadio = bRadio; + chan.iChannelNumber = 2; + snprintf(chan.strChannelName, sizeof(chan.strChannelName) - 1, + "NDR 2"); + snprintf(chan.strStreamURL, sizeof(chan.strStreamURL) - 1, + "rtsp://172.27.1.40:8554/channel/10"); + + pvr->TransferChannelEntry(handle, &chan); + } + + return PVR_ERROR_NO_ERROR; +} + +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; } + +/* Recordings */ +int GetRecordingsAmount(bool deleted) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR GetRecordings(ADDON_HANDLE handle, bool deleted) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR DeleteRecording(const PVR_RECORDING& recording) { return PVR_ERROR_NOT_IMPLEMENTED; } +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 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; } +PVR_ERROR GetRecordingEdl(const PVR_RECORDING&, PVR_EDL_ENTRY edl[], int *size) { return PVR_ERROR_NOT_IMPLEMENTED; } +int GetTimersAmount(void) { return PVR_ERROR_NOT_IMPLEMENTED; } +PVR_ERROR GetTimers(ADDON_HANDLE handle) { return PVR_ERROR_NOT_IMPLEMENTED; } +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 handling */ +/* entirely unused, as we use standard RTSP+TS mux, which can be handlded by + * Kodi core */ +bool OpenLiveStream(const PVR_CHANNEL& channel) { return false; } +void CloseLiveStream(void) {} +int ReadLiveStream(unsigned char* pBuffer, unsigned int iBufferSize) { return -1; } +long long SeekLiveStream(long long iPosition, int iWhence) { return -1; } +long long PositionLiveStream(void) { return -1; } +long long LengthLiveStream(void) { return -1; } +int GetCurrentClientChannel(void) { return -1; } +bool SwitchChannel(const PVR_CHANNEL& channel) { return false; } +PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS& signalStatus) { return PVR_ERROR_NOT_IMPLEMENTED; } +const char* GetLiveStreamURL(const PVR_CHANNEL& channel) { return NULL; } +PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES* pProperties) { 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 */ +/* entirey unused, as we use TS */ +void DemuxReset(void) {} +void DemuxAbort(void) {} +void DemuxFlush(void) {} +DemuxPacket* DemuxRead(void) { return NULL; } + +/* Various helper functions */ +unsigned int GetChannelSwitchDelay(void) { return 0; } +bool CanPauseStream() { return false; } +bool CanSeekStream() { return false; } + +/* Callbacks */ +void PauseStream(bool bPaused) {} +bool SeekTime(int time, bool backwards, double *startpts) { return false; } +void SetSpeed(int speed) {} + +time_t GetPlayingTime() { return 0; } +time_t GetBufferTimeStart() { return 0; } +time_t GetBufferTimeEnd() { return 0; } + +const char* GetBackendHostname() +{ + return octonetAddress.c_str(); +} + +} diff --git a/src/client.h b/src/client.h new file mode 100644 index 0000000..394e56e --- /dev/null +++ b/src/client.h @@ -0,0 +1,31 @@ +#pragma once +/* + * Copyright (C) 2015 Julian Scheel + * Copyright (C) 2015 jusst technologies GmbH + * Copyright (C) 2015 Digital Devices GmbH + * + * 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 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, + * USA. + * + */ + +#include "kodi/libXBMC_addon.h" +#include "kodi/libXBMC_pvr.h" + +extern ADDON::CHelper_libXBMC_addon *kodi; +extern CHelper_libXBMC_pvr *pvr; + +/* IP or hostname of the octonet to be connected to */ +extern std::string octonetAddress;