diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ffc7f0e --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.pbxproj -crlf -diff diff --git a/.gitignore b/.gitignore index bcc3307..a82fba6 100644 --- a/.gitignore +++ b/.gitignore @@ -42,6 +42,7 @@ config.log *.vcxproj.*.user *.vcxproj.user *.obj +*.idb *ReSharper* *.idb @@ -62,16 +63,22 @@ config.log .libs/ .deps/ +# Eclipse project files. Not needed as they are generated in two clicks if needed. +.settings +.project +.cproject + # / /.dummy /.dummy.in /Makefile /Makefile.include /aclocal.m4 -/autom4te.cache/ +autom4te.cache /build-aux/config.guess /build-aux/config.sub /build-aux/install-sh +/build-aux/ltmain.sh /build-aux/missing /build-aux/ltmain.sh /autotools @@ -110,6 +117,7 @@ config.log /addons/visualization.waveform/Waveform_win32.vis /addons/visualization.itunes/iTunes.mvis /addons/script.module.pil/ +/addons/pvr.*/*.pvr # /xbmc/guilib/ /xbmc/guilib/Makefile @@ -145,6 +153,17 @@ config.log /lib/asap/xbmc/xbmc_asap.res +# /lib/addons/ +/lib/addons/library.xbmc.addon/Makefile +/lib/addons/library.xbmc.gui/Makefile +/lib/addons/library.xbmc.pvr/Makefile +/lib/addons/library.xbmc.addon/project/VS2010Express/Release +/lib/addons/library.xbmc.addon/project/VS2010Express/Debug +/lib/addons/library.xbmc.gui/project/VS2010Express/Release +/lib/addons/library.xbmc.gui/project/VS2010Express/Debug +/lib/addons/library.xbmc.pvr/project/VS2010Express/Release +/lib/addons/library.xbmc.pvr/project/VS2010Express/Debug + # /lib/cmyth/ lib/cmyth/Makefile @@ -212,6 +231,11 @@ lib/cmyth/Makefile /lib/libass/libass/Makefile.in /lib/libass/libtool /lib/libass/ltmain.sh +/lib/libass/m4/libtool.m4 +/lib/libass/m4/ltoptions.m4 +/lib/libass/m4/ltsugar.m4 +/lib/libass/m4/ltversion.m4 +/lib/libass/m4/lt~obsolete.m4 /lib/libass/missing /lib/libass/shave/libtool.m4 /lib/libass/shave/ltoptions.m4 @@ -295,6 +319,7 @@ lib/cmyth/Makefile /lib/libapetag/config.h /lib/libapetag/install-sh /lib/libapetag/libtool +/lib/libapetag/m4/lt~obsolete.m4 /lib/libapetag/stamp-h1 # /project @@ -1123,6 +1148,17 @@ lib/cmyth/Makefile /lib/libXDAAP/libXDAAP_win32/Debug /lib/libXDAAP/libXDAAP_win32/Release +# /xbmc/osx/ +/xbmc/osx/Makefile + +# /portable_data +/portable_data + +# /xbmc/pvrclients +/xbmc/pvrclients/Makefile.include +/xbmc/pvrclients/*/.dependencies +/xbmc/pvrclients/*/Makefile + /xbmc/screensavers/Makefile /xbmc/screensavers/rsxs-0.9/Makefile @@ -1220,3 +1256,21 @@ lib/cmyth/Makefile /xbmc/visualizations/XBMCProjectM/libprojectM/config.inp /xbmc/win32/git_rev.h + +/addons/library.xbmc.addon/libXBMC_addon.dll +/addons/library.xbmc.addon/libXBMC_addon.lib +/addons/library.xbmc.gui/libXBMC_gui.dll +/addons/library.xbmc.gui/libXBMC_gui.lib +/addons/library.xbmc.pvr/libXBMC_pvr.dll +/addons/library.xbmc.pvr/libXBMC_pvr.lib + +/addons/pvr.team-mediaportal.tvserver/XBMC_MPTV.lib +/addons/pvr.hts/XBMC_Tvheadend_win32.lib +/addons/pvr.vdr.streamdev/XBMC_VDR_win32.lib + +/xbmc/pvrclients/MediaPortal/project/VS2010Express/Debug +/xbmc/pvrclients/MediaPortal/project/VS2010Express/Release +/xbmc/pvrclients/tvheadend/project/VS2010Express/Debug +/xbmc/pvrclients/tvheadend/project/VS2010Express/Release +/xbmc/pvrclients/vdr-streamdev/project/VS2010Express/Debug +/xbmc/pvrclients/vdr-streamdev/project/VS2010Express/Release diff --git a/Makefile.in b/Makefile.in index 9d850e4..bfd10e0 100755 --- a/Makefile.in +++ b/Makefile.in @@ -42,6 +42,7 @@ DIRECTORY_ARCHIVES=$(DVDPLAYER_ARCHIVES) \ xbmc/cores/playercorefactory/playercorefactory.a \ xbmc/dbwrappers/dbwrappers.a \ xbmc/dialogs/dialogs.a \ + xbmc/epg/epg.a \ xbmc/filesystem/MusicDatabaseDirectory/musicdatabasedirectory.a \ xbmc/filesystem/VideoDatabaseDirectory/videodatabasedirectory.a \ xbmc/filesystem/filesystem.a \ @@ -70,6 +71,13 @@ DIRECTORY_ARCHIVES=$(DVDPLAYER_ARCHIVES) \ xbmc/playlists/playlists.a \ xbmc/powermanagement/powermanagement.a \ xbmc/programs/programs.a \ + xbmc/pvr/addons/pvraddons.a \ + xbmc/pvr/channels/pvrchannels.a \ + xbmc/pvr/dialogs/pvrdialogs.a \ + xbmc/pvr/pvr.a \ + xbmc/pvr/recordings/pvrrecordings.a \ + xbmc/pvr/timers/pvrtimers.a \ + xbmc/pvr/windows/pvrwindows.a \ xbmc/rendering/rendering.a \ xbmc/settings/settings.a \ xbmc/storage/storage.a \ @@ -157,6 +165,19 @@ ifneq (@DISABLE_GOOM@,1) VIS_DIRS+=xbmc/visualizations/Goom endif +PVR_DIRS=\ + xbmc/pvrclients/MediaPortal \ + xbmc/pvrclients/mythtv \ + xbmc/pvrclients/mythtv-cmyth \ + xbmc/pvrclients/vdr-vnsi \ + xbmc/pvrclients/tvheadend \ + xbmc/pvrclients/pvr-demo + +LIBADDON_DIRS=\ + lib/addons/library.xbmc.addon \ + lib/addons/library.xbmc.pvr \ + lib/addons/library.xbmc.gui \ + CONFLUENCE_MEDIA=addons/skin.confluence/media SKIN_DIRS=$(CONFLUENCE_MEDIA) @@ -166,7 +187,7 @@ SKIN_DIRS+=$(TOUCHED_MEDIA) endif DIRS= $(BIN_DIRS) $(EC_DIRS) $(XBMCTEX_DIRS) $(DVDPCODECS_DIRS) $(PAPCODECS_DIRS) \ - $(LIB_DIRS) $(SS_DIRS) $(VIS_DIRS) $(SKIN_DIRS) + $(LIB_DIRS) $(SS_DIRS) $(VIS_DIRS) $(PVR_DIRS) $(LIBADDON_DIRS) $(SKIN_DIRS) LIBS=@LIBS@ CFLAGS=@CFLAGS@ @@ -187,8 +208,8 @@ all : Makefile externals xbmc.bin xbmc-xrandr skins include Makefile.include -.PHONY : dllloader exports visualizations screensavers eventclients papcodecs \ - dvdpcodecs imagelib codecs externals force skins +.PHONY : dllloader exports pvrclients visualizations screensavers eventclients \ + papcodecs dvdpcodecs imagelib codecs externals force libaddon skins # hack targets to keep build system up to date Makefile : config.status $(addsuffix .in, $(AUTOGENERATED_MAKEFILES)) @@ -249,6 +270,17 @@ visualizations: $(VIS_DIRS) screensavers: $(SS_DIRS) +pvrclients: exports + $(MAKE) -C xbmc/pvrclients/MediaPortal + $(MAKE) -C xbmc/pvrclients/mythtv + $(MAKE) -C xbmc/pvrclients/mythtv-cmyth + $(MAKE) -C xbmc/pvrclients/vdr-vnsi + $(MAKE) -C xbmc/pvrclients/tvheadend + $(MAKE) -C xbmc/pvrclients/pvr-demo +libaddon: exports + $(MAKE) -C lib/addons/library.xbmc.addon + $(MAKE) -C lib/addons/library.xbmc.gui + $(MAKE) -C lib/addons/library.xbmc.pvr libpython: dllloader $(MAKE) -C xbmc/interfaces/python $(MAKE) -C xbmc/interfaces/python/xbmcmodule @@ -294,17 +326,16 @@ imagelib: dllloader codecs: papcodecs dvdpcodecs libs: cmyth libid3tag imagelib libexif system/libcpluff-@ARCH@.so -externals: codecs libs visualizations screensavers +externals: libaddon codecs libs pvrclients visualizations screensavers xcode_depends: \ - codecs libs visualizations screensavers eventclients skins \ + codecs libs pvrclients visualizations screensavers eventclients libaddon skins \ lib/libsquish/libsquish.a \ lib/libapetag/.libs/libapetag.a \ lib/libRTV/librtv.a \ lib/libXDAAP/libxdaap.a \ lib/SlingboxLib/SlingboxLib.a - OBJSXBMC =$(DIRECTORY_ARCHIVES) OBJSXBMC+=lib/libapetag/.libs/libapetag.a @@ -317,6 +348,8 @@ DYNOBJSXBMC= \ xbmc/cores/DllLoader/exports/exports.a \ xbmc/settings/settings.a \ xbmc/video/video.a \ + xbmc/pvr/addons/pvraddons.a \ + xbmc/pvr/windows/pvrwindows.a \ xbmc/guilib/guilib.a # must be dynamic to avoid linker errors OBJSXBMC:=$(filter-out $(DYNOBJSXBMC), $(OBJSXBMC)) @@ -373,13 +406,13 @@ install-arch: @# Arch dependent files ifeq ($(findstring freebsd,@ARCH@), freebsd) @find -E system addons -type f -not -iregex ".*svn.*" \ - -iregex ".*@ARCH@.*|.*\.vis|.*\.xbs" \ + -iregex ".*@ARCH@.*|.*\.pvr|.*\.vis|.*\.xbs" \ -exec sh -c "install -d \"$(DESTDIR)$(libdir)/xbmc/\`dirname '{}'\`\"" \; \ -and \ -exec install "{}" $(DESTDIR)$(libdir)/xbmc/"{}" \; \ -exec printf " -- %-75.75s\r" "{}" \; else - @find system addons -regextype posix-extended -type f -not -iregex ".*svn.*" -iregex ".*@ARCH@.*|.*\.vis|.*\.xbs" -exec install -D "{}" $(DESTDIR)$(libdir)/xbmc/"{}" \; -printf " -- %-75.75f\r" + @find system addons -regextype posix-extended -type f -not -iregex ".*svn.*" -iregex ".*@ARCH@.*|.*\.pvr|.*\.vis|.*\.xbs" -exec install -D "{}" $(DESTDIR)$(libdir)/xbmc/"{}" \; -printf " -- %-75.75f\r" endif install-scripts: @@ -402,13 +435,14 @@ install-datas: install-scripts @# Arch independent files ifeq ($(findstring bsd,@ARCH@), bsd) @find -E addons language media sounds userdata system -type f \ + -not -iregex ".*@ARCH@.*|.*\.pvr|.*\.vis|.*\.xbs|.*svn.*|.*\.so|.*\.dll" \ -not -iregex ".*@ARCH@.*|.*\.vis|.*\.xbs|.*svn.*|.*\.so|.*\.dll" \ -exec sh -c "install -d \"$(DESTDIR)$(datarootdir)/xbmc/\`dirname '{}'\`\"" \; \ -and \ -exec install -m 0644 "{}" $(DESTDIR)$(datarootdir)/xbmc/"{}" \; \ -exec printf " -- %-75.75s\r" "{}" \; else - @find addons language media sounds userdata system -regextype posix-extended -type f -not -iregex ".*@ARCH@.*|.*\.vis|.*\.xbs|.*svn.*|.*\.so|.*\.dll" -exec install -D -m 0644 "{}" $(DESTDIR)$(datarootdir)/xbmc/"{}" \; -printf " -- %-75.75f\r" + @find addons language media sounds userdata system -regextype posix-extended -type f -not -iregex ".*@ARCH@.*|.*\.pvr|.*\.vis|.*\.xbs|.*svn.*|.*\.so|.*\.dll" -exec install -D -m 0644 "{}" $(DESTDIR)$(datarootdir)/xbmc/"{}" \; -printf " -- %-75.75f\r" endif @# Icons and links @install -d $(DESTDIR)$(datarootdir)/applications @@ -425,6 +459,8 @@ uninstall: @rm -rf $(DESTDIR)$(datarootdir)/xbmc $(DESTDIR)$(bindir)/xbmc @rm -rf $(DESTDIR)$(bindir)/xbmc-standalone @rm -rf $(DESTDIR)$(datarootdir)/xsessions/XBMC.desktop + @rm -rf $(libdir)/libXBMC_* + @rm -rf $(prefix)/include/xbmc @echo "Done!" clean-xbmc.bin: @@ -444,8 +480,12 @@ clean-screensavers: for d in $(SS_DIRS); do if test -f $$d/Makefile; then $(MAKE) -C $$d clean; fi; done clean-visualisations: for d in $(VIS_DIRS); do if test -f $$d/Makefile; then $(MAKE) -C $$d clean; fi; done +clean-pvrclients: + for d in $(PVR_DIRS); do if test -f $$d/Makefile; then $(MAKE) -C $$d clean; fi; done +clean-libaddons: + for d in $(LIBADDON_DIRS); do if test -f $$d/Makefile; then $(MAKE) -C $$d clean; fi; done clean-codecs: clean-dvdpcodecs clean-papcodecs clean-externals: clean-codecs clean-eventclients clean-xbmctex clean-libs \ - clean-screensavers clean-visualisations + clean-pvrclients clean-screensavers clean-visualisations clean-libaddons diff --git a/XBMC-ATV2.xcodeproj/project.pbxproj b/XBMC-ATV2.xcodeproj/project.pbxproj index c606ca0..f1737df 100644 Binary files a/XBMC-ATV2.xcodeproj/project.pbxproj and b/XBMC-ATV2.xcodeproj/project.pbxproj differ diff --git a/XBMC-IOS.xcodeproj/project.pbxproj b/XBMC-IOS.xcodeproj/project.pbxproj index 9ba2d9f..cc04f37 100644 Binary files a/XBMC-IOS.xcodeproj/project.pbxproj and b/XBMC-IOS.xcodeproj/project.pbxproj differ diff --git a/XBMC.xcodeproj/project.pbxproj b/XBMC.xcodeproj/project.pbxproj index 114d104..66f0833 100644 Binary files a/XBMC.xcodeproj/project.pbxproj and b/XBMC.xcodeproj/project.pbxproj differ diff --git a/addons/library.xbmc.addon/dlfcn-win32.cpp b/addons/library.xbmc.addon/dlfcn-win32.cpp new file mode 100644 index 0000000..a6cf2c2 --- /dev/null +++ b/addons/library.xbmc.addon/dlfcn-win32.cpp @@ -0,0 +1,263 @@ +/* + * dlfcn-win32 + * Copyright (c) 2007 Ramiro Polla + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "dlfcn-win32.h" + +/* Note: + * MSDN says these functions are not thread-safe. We make no efforts to have + * any kind of thread safety. + */ + +/* I have no special reason to have set MAX_GLOBAL_OBJECTS to this value. Any + * comments are welcome. + */ +#define MAX_OBJECTS 255 + +static HMODULE global_objects[MAX_OBJECTS]; + +/* This function adds an object to the list of global objects. + * The implementation is very simple and slow. + * TODO: should failing this function be enough to fail the call to dlopen( )? + */ +static void global_object_add( HMODULE hModule ) +{ + int i; + + for( i = 0 ; i < MAX_OBJECTS ; i++ ) + { + if( !global_objects[i] ) + { + global_objects[i] = hModule; + break; + } + } +} + +static void global_object_rem( HMODULE hModule ) +{ + int i; + + for( i = 0 ; i < MAX_OBJECTS ; i++ ) + { + if( global_objects[i] == hModule ) + { + global_objects[i] = 0; + break; + } + } +} + +/* Argument to last function. Used in dlerror( ) */ +static char last_name[MAX_PATH]; + +static int copy_string( char *dest, int dest_size, const char *src ) +{ + int i = 0; + + if( src && dest ) + { + for( i = 0 ; i < dest_size-1 ; i++ ) + { + if( !src[i] ) + break; + else + dest[i] = src[i]; + } + } + dest[i] = '\0'; + + return i; +} + +void *dlopen( const char *file, int mode ) +{ + HMODULE hModule; + UINT uMode; + + /* Do not let Windows display the critical-error-handler message box */ + uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); + + if( file == 0 ) + { + /* Save NULL pointer for error message */ + _snprintf_s( last_name, MAX_PATH, MAX_PATH, "0x%p", file ); + + /* POSIX says that if the value of file is 0, a handle on a global + * symbol object must be provided. That object must be able to access + * all symbols from the original program file, and any objects loaded + * with the RTLD_GLOBAL flag. + * The return value from GetModuleHandle( ) allows us to retrieve + * symbols only from the original program file. For objects loaded with + * the RTLD_GLOBAL flag, we create our own list later on. + */ + hModule = GetModuleHandle( NULL ); + } + else + { + char lpFileName[MAX_PATH]; + int i; + + /* MSDN says backslashes *must* be used instead of forward slashes. */ + for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ ) + { + if( !file[i] ) + break; + else if( file[i] == '/' ) + lpFileName[i] = '\\'; + else + lpFileName[i] = file[i]; + } + lpFileName[i] = '\0'; + + /* Save file name for error message */ + copy_string( last_name, sizeof(last_name), lpFileName ); + + /* POSIX says the search path is implementation-defined. + * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely + * to UNIX's search paths (start with system folders instead of current + * folder). + */ + hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL, + LOAD_WITH_ALTERED_SEARCH_PATH ); + /* If the object was loaded with RTLD_GLOBAL, add it to list of global + * objects, so that its symbols may be retrieved even if the handle for + * the original program file is passed. POSIX says that if the same + * file is specified in multiple invocations, and any of them are + * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the + * symbols will remain global. + */ + + if( hModule && (mode & RTLD_GLOBAL) ) + global_object_add( hModule ); + } + + /* Return to previous state of the error-mode bit flags. */ + SetErrorMode( uMode ); + + return (void *) hModule; +} + +int dlclose( void *handle ) +{ + HMODULE hModule = (HMODULE) handle; + BOOL ret; + + /* Save handle for error message */ + _snprintf_s( last_name, MAX_PATH, MAX_PATH, "0x%p", handle ); + + ret = FreeLibrary( hModule ); + + /* If the object was loaded with RTLD_GLOBAL, remove it from list of global + * objects. + */ + if( ret ) + global_object_rem( hModule ); + + /* dlclose's return value in inverted in relation to FreeLibrary's. */ + ret = !ret; + + return (int) ret; +} + +void *dlsym( void *handle, const char *name ) +{ + FARPROC symbol; + HMODULE myhandle = (HMODULE) handle; + + /* Save symbol name for error message */ + copy_string( last_name, sizeof(last_name), name ); + + symbol = GetProcAddress( myhandle, name ); +#if 0 + if( symbol == NULL ) + { + HMODULE hModule; + + /* If the handle for the original program file is passed, also search + * in all globally loaded objects. + */ + + hModule = GetModuleHandle( NULL ); + + if( hModule == handle ) + { + int i; + + for( i = 0 ; i < MAX_OBJECTS ; i++ ) + { + if( global_objects[i] != 0 ) + { + symbol = GetProcAddress( global_objects[i], name ); + if( symbol != NULL ) + break; + } + } + } + + + CloseHandle( hModule ); + } +#endif + return (void*) symbol; +} + +char *dlerror( void ) +{ + DWORD dwMessageId; + /* POSIX says this function doesn't have to be thread-safe, so we use one + * static buffer. + * MSDN says the buffer cannot be larger than 64K bytes, so we set it to + * the limit. + */ + static char lpBuffer[65535]; + DWORD ret; + + dwMessageId = GetLastError( ); + + if( dwMessageId == 0 ) + return NULL; + + /* Format error message to: + * "": + */ + ret = copy_string( lpBuffer, sizeof(lpBuffer), "\"" ); + ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, last_name ); + ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, "\": " ); + ret += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId, + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), + lpBuffer+ret, sizeof(lpBuffer)-ret, NULL ); + + if( ret > 1 ) + { + /* POSIX says the string must not have trailing */ + if( lpBuffer[ret-2] == '\r' && lpBuffer[ret-1] == '\n' ) + lpBuffer[ret-2] = '\0'; + } + + /* POSIX says that invoking dlerror( ) a second time, immediately following + * a prior invocation, shall result in NULL being returned. + */ + SetLastError(0); + + return lpBuffer; +} + diff --git a/addons/library.xbmc.addon/dlfcn-win32.h b/addons/library.xbmc.addon/dlfcn-win32.h new file mode 100644 index 0000000..f906343 --- /dev/null +++ b/addons/library.xbmc.addon/dlfcn-win32.h @@ -0,0 +1,46 @@ +#pragma once +/* + * dlfcn-win32 + * Copyright (c) 2007 Ramiro Polla + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DLFCN_H +#define DLFCN_H + +/* POSIX says these are implementation-defined. + * To simplify use with Windows API, we treat them the same way. + */ + +#define RTLD_LAZY 0 +#define RTLD_NOW 0 + +#define RTLD_GLOBAL (1 << 1) +#define RTLD_LOCAL (1 << 2) + +/* These two were added in The Open Group Base Specifications Issue 6. + * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. + */ + +#define RTLD_DEFAULT 0 +#define RTLD_NEXT 0 + +void *dlopen ( const char *file, int mode ); +int dlclose( void *handle ); +void *dlsym ( void *handle, const char *name ); +char *dlerror( void ); + +#endif /* DLFCN-WIN32_H */ diff --git a/addons/library.xbmc.addon/libXBMC_addon.h b/addons/library.xbmc.addon/libXBMC_addon.h new file mode 100644 index 0000000..de727b7 --- /dev/null +++ b/addons/library.xbmc.addon/libXBMC_addon.h @@ -0,0 +1,192 @@ +#pragma once +/* + * Copyright (C) 2005-2010 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 +#include +#include +#include +#include + +#ifdef _WIN32 // windows +#include "dlfcn-win32.h" +#define ADDON_DLL "\\library.xbmc.addon\\libXBMC_addon" ADDON_HELPER_EXT +#define ADDON_HELPER_PLATFORM "win32" +#define ADDON_HELPER_EXT ".dll" +#else +#if defined(__APPLE__) // osx +#define ADDON_HELPER_PLATFORM "osx" +#if defined(__POWERPC__) +#define ADDON_HELPER_ARCH "powerpc" +#elif defined(__arm__) +#define ADDON_HELPER_ARCH "arm" +#else +#define ADDON_HELPER_ARCH "x86" +#endif +#else // linux +#define ADDON_HELPER_PLATFORM "linux" +#if defined(__x86_64__) +#define ADDON_HELPER_ARCH "x86_64" +#elif defined(_POWERPC) +#define ADDON_HELPER_ARCH "powerpc" +#elif defined(_POWERPC64) +#define ADDON_HELPER_ARCH "powerpc64" +#elif defined(_ARMEL) +#define ADDON_HELPER_ARCH "arm" +#elif defined(_MIPSEL) +#define ADDON_HELPER_ARCH "mipsel" +#else +#define ADDON_HELPER_ARCH "i486" +#endif +#endif +#include // linux+osx +#define ADDON_HELPER_EXT ".so" +#define ADDON_DLL "/library.xbmc.addon/libXBMC_addon-" ADDON_HELPER_ARCH "-" ADDON_HELPER_PLATFORM ADDON_HELPER_EXT +#endif + +#ifdef LOG_DEBUG +#undef LOG_DEBUG +#endif +#ifdef LOG_INFO +#undef LOG_INFO +#endif +#ifdef LOG_NOTICE +#undef LOG_NOTICE +#endif +#ifdef LOG_ERROR +#undef LOG_ERROR +#endif + +namespace ADDON +{ + typedef enum addon_log + { + LOG_DEBUG, + LOG_INFO, + LOG_NOTICE, + LOG_ERROR + } addon_log_t; + + typedef enum queue_msg + { + QUEUE_INFO, + QUEUE_WARNING, + QUEUE_ERROR + } queue_msg_t; + + class CHelper_libXBMC_addon + { + public: + CHelper_libXBMC_addon() + { + m_libXBMC_addon = NULL; + m_Handle = NULL; + } + + ~CHelper_libXBMC_addon() + { + if (m_libXBMC_addon) + { + XBMC_unregister_me(); + dlclose(m_libXBMC_addon); + } + } + + bool RegisterMe(void *Handle) + { + m_Handle = Handle; + + std::string libBasePath; + libBasePath = ((cb_array*)m_Handle)->libPath; + libBasePath += ADDON_DLL; + + m_libXBMC_addon = dlopen(libBasePath.c_str(), RTLD_LAZY); + if (m_libXBMC_addon == NULL) + { + fprintf(stderr, "Unable to load %s\n", dlerror()); + return false; + } + + XBMC_register_me = (int (*)(void *HANDLE)) + dlsym(m_libXBMC_addon, "XBMC_register_me"); + if (XBMC_register_me == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + XBMC_unregister_me = (void (*)()) + dlsym(m_libXBMC_addon, "XBMC_unregister_me"); + if (XBMC_unregister_me == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Log = (void (*)(const addon_log_t loglevel, const char *format, ... )) + dlsym(m_libXBMC_addon, "XBMC_log"); + if (Log == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + GetSetting = (bool (*)(const char* settingName, void *settingValue)) + dlsym(m_libXBMC_addon, "XBMC_get_setting"); + if (GetSetting == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + QueueNotification = (void (*)(const queue_msg_t loglevel, const char *format, ... )) + dlsym(m_libXBMC_addon, "XBMC_queue_notification"); + if (QueueNotification == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + UnknownToUTF8 = (void (*)(std::string &str)) + dlsym(m_libXBMC_addon, "XBMC_unknown_to_utf8"); + if (UnknownToUTF8 == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + GetLocalizedString = (const char* (*)(int dwCode)) + dlsym(m_libXBMC_addon, "XBMC_get_localized_string"); + if (GetLocalizedString == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + GetDVDMenuLanguage = (const char* (*)()) + dlsym(m_libXBMC_addon, "XBMC_get_dvd_menu_language"); + if (GetDVDMenuLanguage == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + GetLocalizedDate = (const char* (*)(time_t time, bool bLongDate, bool bWithShortNames)) + dlsym(m_libXBMC_addon, "XBMC_get_localized_date"); + if (GetLocalizedDate == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + GetLocalizedTime = (const char* (*)(time_t time, bool bWithSeconds)) + dlsym(m_libXBMC_addon, "XBMC_get_localized_time"); + if (GetLocalizedTime == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + return XBMC_register_me(m_Handle) > 0; + } + + void (*Log)(const addon_log_t loglevel, const char *format, ... ); + bool (*GetSetting)(const char* settingName, void *settingValue); + void (*QueueNotification)(const queue_msg_t type, const char *format, ... ); + void (*UnknownToUTF8)(std::string &str); + const char* (*GetLocalizedString)(int dwCode); + const char* (*GetDVDMenuLanguage)(); + const char* (*GetLocalizedDate)(time_t time, bool bLongDate, bool bWithShortNames); + const char* (*GetLocalizedTime)(time_t time, bool bWithSeconds); + + protected: + int (*XBMC_register_me)(void *HANDLE); + void (*XBMC_unregister_me)(); + + private: + void *m_libXBMC_addon; + void *m_Handle; + struct cb_array + { + const char* libPath; + }; + }; +}; diff --git a/addons/library.xbmc.gui/libXBMC_gui.h b/addons/library.xbmc.gui/libXBMC_gui.h new file mode 100644 index 0000000..bb9d658 --- /dev/null +++ b/addons/library.xbmc.gui/libXBMC_gui.h @@ -0,0 +1,352 @@ +#pragma once +/* + * Copyright (C) 2005-2010 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 +#include +#include +#include +#include +#include "../library.xbmc.addon/libXBMC_addon.h" + +typedef void* GUIHANDLE; + +#ifdef _WIN32 +#define GUI_HELPER_DLL "\\library.xbmc.gui\\libXBMC_gui" ADDON_HELPER_EXT +#else +#define GUI_HELPER_DLL "/library.xbmc.gui/libXBMC_gui-" ADDON_HELPER_ARCH "-" ADDON_HELPER_PLATFORM ADDON_HELPER_EXT +#endif + +#define ADDON_ACTION_PREVIOUS_MENU 10 +#define ADDON_ACTION_CLOSE_DIALOG 51 + +class CAddonGUIWindow; +class CAddonGUISpinControl; +class CAddonGUIListContainer; +class CAddonGUIRadioButton; +class CAddonGUIProgressControl; +class CAddonListItem; + +class CHelper_libXBMC_gui +{ +public: + CHelper_libXBMC_gui() + { + m_libXBMC_gui = NULL; + m_Handle = NULL; + } + + ~CHelper_libXBMC_gui() + { + if (m_libXBMC_gui) + { + GUI_unregister_me(); + dlclose(m_libXBMC_gui); + } + } + + bool RegisterMe(void *Handle) + { + m_Handle = Handle; + + std::string libBasePath; + libBasePath = ((cb_array*)m_Handle)->libPath; + libBasePath += GUI_HELPER_DLL; + + m_libXBMC_gui = dlopen(libBasePath.c_str(), RTLD_LAZY); + if (m_libXBMC_gui == NULL) + { + fprintf(stderr, "Unable to load %s\n", dlerror()); + return false; + } + + GUI_register_me = (int (*)(void *HANDLE)) + dlsym(m_libXBMC_gui, "GUI_register_me"); + if (GUI_register_me == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + GUI_unregister_me = (void (*)()) + dlsym(m_libXBMC_gui, "GUI_unregister_me"); + if (GUI_unregister_me == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Lock = (void (*)()) + dlsym(m_libXBMC_gui, "GUI_lock"); + if (Lock == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Unlock = (void (*)()) + dlsym(m_libXBMC_gui, "GUI_unlock"); + if (Unlock == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + GetScreenHeight = (int (*)()) + dlsym(m_libXBMC_gui, "GUI_get_screen_height"); + if (GetScreenHeight == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + GetScreenWidth = (int (*)()) + dlsym(m_libXBMC_gui, "GUI_get_screen_width"); + if (GetScreenWidth == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + GetVideoResolution = (int (*)()) + dlsym(m_libXBMC_gui, "GUI_get_video_resolution"); + if (GetVideoResolution == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Dialog_showYesNo = (int (*)(const char* heading, const char* line0, const char* line1, const char* line2, int* bCanceled, const char* noLabel, const char* yesLabel)) + dlsym(m_libXBMC_gui, "GUI_Dialog_ShowYesNo"); + if (Dialog_showYesNo == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Window_create = (CAddonGUIWindow* (*)(const char *xmlFilename, const char *defaultSkin, bool forceFallback, bool asDialog)) + dlsym(m_libXBMC_gui, "GUI_Window_create"); + if (Window_create == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Window_destroy = (void (*)(CAddonGUIWindow* p)) + dlsym(m_libXBMC_gui, "GUI_Window_destroy"); + if (Window_destroy == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Control_getSpin = (CAddonGUISpinControl* (*)(CAddonGUIWindow *window, int controlId)) + dlsym(m_libXBMC_gui, "GUI_control_get_spin"); + if (Control_getSpin == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Control_releaseSpin = (void (*)(CAddonGUISpinControl* p)) + dlsym(m_libXBMC_gui, "GUI_control_release_spin"); + if (Control_releaseSpin == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Control_getListContainer= (CAddonGUIListContainer* (*)(CAddonGUIWindow *window, int controlId)) + dlsym(m_libXBMC_gui, "GUI_control_get_listcontainer"); + if (Control_getListContainer == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Control_releaseListContainer = (void (*)(CAddonGUIListContainer* p)) + dlsym(m_libXBMC_gui, "GUI_control_release_listcontainer"); + if (Control_releaseListContainer == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Control_getRadioButton = (CAddonGUIRadioButton* (*)(CAddonGUIWindow *window, int controlId)) + dlsym(m_libXBMC_gui, "GUI_control_get_radiobutton"); + if (Control_getRadioButton == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Control_releaseRadioButton = (void (*)(CAddonGUIRadioButton* p)) + dlsym(m_libXBMC_gui, "GUI_control_release_radiobutton"); + if (Control_releaseRadioButton == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Control_getProgress = (CAddonGUIProgressControl* (*)(CAddonGUIWindow *window, int controlId)) + dlsym(m_libXBMC_gui, "GUI_control_get_progress"); + if (Control_getProgress == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Control_releaseProgress = (void (*)(CAddonGUIProgressControl* p)) + dlsym(m_libXBMC_gui, "GUI_control_release_progress"); + if (Control_releaseProgress == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + ListItem_create = (CAddonListItem* (*)(const char *label, const char *label2, const char *iconImage, const char *thumbnailImage, const char *path)) + dlsym(m_libXBMC_gui, "GUI_ListItem_create"); + if (ListItem_create == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + ListItem_destroy = (void (*)(CAddonListItem* p)) + dlsym(m_libXBMC_gui, "GUI_ListItem_destroy"); + if (ListItem_destroy == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + return GUI_register_me(m_Handle) > 0; + } + + void (*Lock)(); + void (*Unlock)(); + int (*GetScreenHeight)(); + int (*GetScreenWidth)(); + int (*GetVideoResolution)(); + int (*Dialog_showYesNo)(const char* heading, const char* line0, const char* line1, const char* line2, int* bCanceled, const char* noLabel, const char* yesLabel); + CAddonGUIWindow* (*Window_create)(const char *xmlFilename, const char *defaultSkin, bool forceFallback, bool asDialog); + void (*Window_destroy)(CAddonGUIWindow* p); + CAddonGUISpinControl* (*Control_getSpin)(CAddonGUIWindow *window, int controlId); + void (*Control_releaseSpin)(CAddonGUISpinControl* p); + CAddonGUIListContainer* (*Control_getListContainer)(CAddonGUIWindow *window, int controlId); + void (*Control_releaseListContainer)(CAddonGUIListContainer* p); + CAddonGUIRadioButton* (*Control_getRadioButton)(CAddonGUIWindow *window, int controlId); + void (*Control_releaseRadioButton)(CAddonGUIRadioButton* p); + CAddonGUIProgressControl* (*Control_getProgress)(CAddonGUIWindow *window, int controlId); + void (*Control_releaseProgress)(CAddonGUIProgressControl* p); + CAddonListItem* (*ListItem_create)(const char *label, const char *label2, const char *iconImage, const char *thumbnailImage, const char *path); + void (*ListItem_destroy)(CAddonListItem* p); + +protected: + int (*GUI_register_me)(void *HANDLE); + void (*GUI_unregister_me)(); + +private: + void *m_libXBMC_gui; + void *m_Handle; + struct cb_array + { + const char* libPath; + }; +}; + +class CAddonGUISpinControl +{ +public: + CAddonGUISpinControl(CAddonGUIWindow *window, int controlId); + virtual ~CAddonGUISpinControl(void) {} + + virtual void SetVisible(bool yesNo); + virtual void SetText(const char *label); + virtual void Clear(); + virtual void AddLabel(const char *label, int iValue); + virtual int GetValue(); + virtual void SetValue(int iValue); + +private: + CAddonGUIWindow *m_Window; + int m_ControlId; + GUIHANDLE m_SpinHandle; +}; + +class CAddonGUIListContainer +{ +public: + CAddonGUIListContainer(CAddonGUIWindow *window, int controlId); + ~CAddonGUIListContainer() {} + + virtual void SetVisible(bool yesNo); + virtual void AddItem(CAddonListItem *item); + virtual void AddItems(CAddonListItem* items[],int size); + virtual CAddonListItem* GetItem(int index); + virtual int GetSelected(); + virtual void ResetList(); + +private: + CAddonGUIWindow *m_Window; + int m_ControlId; + GUIHANDLE m_ListHandle; + GUIHANDLE m_Items; +}; + +class CAddonGUIRadioButton +{ +public: + CAddonGUIRadioButton(CAddonGUIWindow *window, int controlId); + ~CAddonGUIRadioButton() {} + + virtual void SetVisible(bool yesNo); + virtual void SetText(const char *label); + virtual void SetSelected(bool yesNo); + virtual bool IsSelected(); + +private: + CAddonGUIWindow *m_Window; + int m_ControlId; + GUIHANDLE m_ButtonHandle; +}; + +class CAddonGUIProgressControl +{ +public: + CAddonGUIProgressControl(CAddonGUIWindow *window, int controlId); + virtual ~CAddonGUIProgressControl(void) {} + + virtual void SetPercentage(float fPercent); + virtual float GetPercentage() const; + virtual void SetInfo(int iInfo); + virtual int GetInfo() const; + virtual std::string GetDescription() const; + +private: + CAddonGUIWindow *m_Window; + int m_ControlId; + GUIHANDLE m_ProgressHandle; +}; + +/*Please note that CAddonListItem will leak memory if it is not assigned to a list.*/ +class CAddonListItem +{ +friend class CAddonGUIWindow; +friend class CAddonGUIListContainer; + +public: + CAddonListItem(const char *label, const char *label2, const char *iconImage, const char *thumbnailImage, const char *path); + virtual ~CAddonListItem(void){} + + virtual const char *GetLabel(); + virtual void SetLabel(const char *label); + virtual const char *GetLabel2(); + virtual void SetLabel2(const char *label); + virtual void SetIconImage(const char *image); + virtual void SetThumbnailImage(const char *image); + virtual void SetInfo(const char *Info); + virtual void SetProperty(const char *key, const char *value); + virtual const char *GetProperty(const char *key) const; + virtual void SetPath(const char *Path); + +// {(char*)"select(); +// {(char*)"isSelected(); +protected: + CAddonListItem(GUIHANDLE ListItemHandle); + GUIHANDLE m_ListItemHandle; +}; + +class CAddonGUIWindow +{ +friend class CAddonGUISpinControl; +friend class CAddonGUIListContainer; +friend class CAddonGUIRadioButton; +friend class CAddonGUIProgressControl; + +public: + CAddonGUIWindow(const char *xmlFilename, const char *defaultSkin, bool forceFallback, bool asDialog); + ~CAddonGUIWindow(); + + virtual bool Show(); + virtual void Close(); + virtual void DoModal(); + virtual bool SetFocusId(int iControlId); + virtual int GetFocusId(); + virtual bool SetCoordinateResolution(int res); + virtual void SetProperty(const char *key, const char *value); + virtual void SetPropertyInt(const char *key, int value); + virtual void SetPropertyBool(const char *key, bool value); + virtual void SetPropertyDouble(const char *key, double value); + virtual const char *GetProperty(const char *key) const; + virtual int GetPropertyInt(const char *key) const; + virtual bool GetPropertyBool(const char *key) const; + virtual double GetPropertyDouble(const char *key) const; + virtual void ClearProperties(); + virtual int GetListSize(); + virtual void ClearList(); + virtual GUIHANDLE AddStringItem(const char *name, int itemPosition = -1); + virtual void AddItem(GUIHANDLE item, int itemPosition = -1); + virtual void AddItem(CAddonListItem *item, int itemPosition = -1); + virtual void RemoveItem(int itemPosition); + virtual GUIHANDLE GetListItem(int listPos); + virtual void SetCurrentListPosition(int listPos); + virtual int GetCurrentListPosition(); + virtual void SetControlLabel(int controlId, const char *label); + virtual void AddContextMenuButton(int controlId,unsigned int contextButtonId,const char* label); + + virtual bool OnClick(int controlId); + virtual bool OnFocus(int controlId); + virtual bool OnInit(); + virtual bool OnAction(int actionId); + virtual bool OnContextMenu(int controlId,int itemNumber, unsigned int contextButtonId); + + GUIHANDLE m_cbhdl; + bool (*CBOnInit)(GUIHANDLE cbhdl); + bool (*CBOnFocus)(GUIHANDLE cbhdl, int controlId); + bool (*CBOnClick)(GUIHANDLE cbhdl, int controlId); + bool (*CBOnAction)(GUIHANDLE cbhdl, int actionId); + bool (*CBOnContextMenu)(GUIHANDLE cbhdl,int controlId,int itemNumber, unsigned int contextButtonId); + +protected: + GUIHANDLE m_WindowHandle; +}; + diff --git a/addons/library.xbmc.pvr/libXBMC_pvr.h b/addons/library.xbmc.pvr/libXBMC_pvr.h new file mode 100644 index 0000000..aa679b8 --- /dev/null +++ b/addons/library.xbmc.pvr/libXBMC_pvr.h @@ -0,0 +1,170 @@ +#pragma once +/* + * Copyright (C) 2005-2010 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 +#include +#include +#include +#include +#include "xbmc_pvr_types.h" +#include "../library.xbmc.addon/libXBMC_addon.h" + +#ifdef _WIN32 +#define PVR_HELPER_DLL "\\library.xbmc.pvr\\libXBMC_pvr" ADDON_HELPER_EXT +#else +#define PVR_HELPER_DLL "/library.xbmc.pvr/libXBMC_pvr-" ADDON_HELPER_ARCH "-" ADDON_HELPER_PLATFORM ADDON_HELPER_EXT +#endif + +#define DVD_TIME_BASE 1000000 +#define DVD_NOPTS_VALUE (-1LL<<52) // should be possible to represent in both double and __int64 + +class CHelper_libXBMC_pvr +{ +public: + CHelper_libXBMC_pvr() + { + m_libXBMC_pvr = NULL; + m_Handle = NULL; + } + + ~CHelper_libXBMC_pvr() + { + if (m_libXBMC_pvr) + { + PVR_unregister_me(); + dlclose(m_libXBMC_pvr); + } + } + + bool RegisterMe(void *Handle) + { + m_Handle = Handle; + + std::string libBasePath; + libBasePath = ((cb_array*)m_Handle)->libPath; + libBasePath += PVR_HELPER_DLL; + + m_libXBMC_pvr = dlopen(libBasePath.c_str(), RTLD_LAZY); + if (m_libXBMC_pvr == NULL) + { + fprintf(stderr, "Unable to load %s\n", dlerror()); + return false; + } + + PVR_register_me = (int (*)(void *HANDLE)) + dlsym(m_libXBMC_pvr, "PVR_register_me"); + if (PVR_register_me == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + PVR_unregister_me = (void (*)()) + dlsym(m_libXBMC_pvr, "PVR_unregister_me"); + if (PVR_unregister_me == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + TransferEpgEntry = (void (*)(const PVR_HANDLE handle, const EPG_TAG *epgentry)) + dlsym(m_libXBMC_pvr, "PVR_transfer_epg_entry"); + if (TransferEpgEntry == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + TransferChannelEntry = (void (*)(const PVR_HANDLE handle, const PVR_CHANNEL *chan)) + dlsym(m_libXBMC_pvr, "PVR_transfer_channel_entry"); + if (TransferChannelEntry == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + TransferTimerEntry = (void (*)(const PVR_HANDLE handle, const PVR_TIMER *timer)) + dlsym(m_libXBMC_pvr, "PVR_transfer_timer_entry"); + if (TransferTimerEntry == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + TransferRecordingEntry = (void (*)(const PVR_HANDLE handle, const PVR_RECORDING *recording)) + dlsym(m_libXBMC_pvr, "PVR_transfer_recording_entry"); + if (TransferRecordingEntry == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + AddMenuHook = (void (*)(PVR_MENUHOOK *hook)) + dlsym(m_libXBMC_pvr, "PVR_add_menu_hook"); + if (AddMenuHook == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + Recording = (void (*)(const char *Name, const char *FileName, bool On)) + dlsym(m_libXBMC_pvr, "PVR_recording"); + if (Recording == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + TriggerTimerUpdate = (void (*)()) + dlsym(m_libXBMC_pvr, "PVR_trigger_timer_update"); + if (TriggerTimerUpdate == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + TriggerRecordingUpdate = (void (*)()) + dlsym(m_libXBMC_pvr, "PVR_trigger_recording_update"); + if (TriggerRecordingUpdate == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + TriggerChannelUpdate = (void (*)()) + dlsym(m_libXBMC_pvr, "PVR_trigger_channel_update"); + if (TriggerChannelUpdate == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + TriggerChannelGroupsUpdate = (void (*)()) + dlsym(m_libXBMC_pvr, "PVR_trigger_channel_groups_update"); + if (TriggerChannelGroupsUpdate == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + TransferChannelGroup = (void (*)(const PVR_HANDLE handle, const PVR_CHANNEL_GROUP *group)) + dlsym(m_libXBMC_pvr, "PVR_transfer_channel_group"); + if (TransferChannelGroup == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + TransferChannelGroupMember = (void (*)(const PVR_HANDLE handle, const PVR_CHANNEL_GROUP_MEMBER *member)) + dlsym(m_libXBMC_pvr, "PVR_transfer_channel_group_member"); + if (TransferChannelGroupMember == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + +#ifdef USE_DEMUX + FreeDemuxPacket = (void (*)(DemuxPacket* pPacket)) + dlsym(m_libXBMC_pvr, "PVR_free_demux_packet"); + if (FreeDemuxPacket == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } + + AllocateDemuxPacket = (DemuxPacket* (*)(int iDataSize)) + dlsym(m_libXBMC_pvr, "PVR_allocate_demux_packet"); + if (AllocateDemuxPacket == NULL) { fprintf(stderr, "Unable to assign function %s\n", dlerror()); return false; } +#endif + + return PVR_register_me(m_Handle) > 0; + } + + void (*TransferEpgEntry)(const PVR_HANDLE handle, const EPG_TAG *epgentry); + void (*TransferChannelEntry)(const PVR_HANDLE handle, const PVR_CHANNEL *chan); + void (*TransferTimerEntry)(const PVR_HANDLE handle, const PVR_TIMER *timer); + void (*TransferRecordingEntry)(const PVR_HANDLE handle, const PVR_RECORDING *recording); + void (*AddMenuHook)(PVR_MENUHOOK *hook); + void (*Recording)(const char *Name, const char *FileName, bool On); + void (*TriggerTimerUpdate)(); + void (*TriggerRecordingUpdate)(); + void (*TriggerChannelUpdate)(); + void (*TriggerChannelGroupsUpdate)(); + void (*TransferChannelGroup)(const PVR_HANDLE handle, const PVR_CHANNEL_GROUP *group); + void (*TransferChannelGroupMember)(const PVR_HANDLE handle, const PVR_CHANNEL_GROUP_MEMBER *member); +#ifdef USE_DEMUX + void (*FreeDemuxPacket)(DemuxPacket* pPacket); + DemuxPacket* (*AllocateDemuxPacket)(int iDataSize); +#endif + +protected: + int (*PVR_register_me)(void *HANDLE); + void (*PVR_unregister_me)(); + +private: + void *m_libXBMC_pvr; + void *m_Handle; + struct cb_array + { + const char* libPath; + }; +}; diff --git a/addons/pvr.demo/addon.xml b/addons/pvr.demo/addon.xml new file mode 100644 index 0000000..6a850be --- /dev/null +++ b/addons/pvr.demo/addon.xml @@ -0,0 +1,19 @@ + + + + + + + + Pulse-Eight Demo PVR Client + Pulse-Eight Demo PVR Client + Just contains stubs + linux + + diff --git a/addons/pvr.hts/addon.xml b/addons/pvr.hts/addon.xml new file mode 100644 index 0000000..66cf72b --- /dev/null +++ b/addons/pvr.hts/addon.xml @@ -0,0 +1,22 @@ + + + + + + + + XBMC's frontend for Tvheadend + Tvheadend frontend; supporting streaming of Live TV & Recordings, EPG, Timers + This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. + all + + diff --git a/addons/pvr.hts/icon.png b/addons/pvr.hts/icon.png new file mode 100644 index 0000000..a990063 Binary files /dev/null and b/addons/pvr.hts/icon.png differ diff --git a/addons/pvr.hts/pthreadVC2.dll b/addons/pvr.hts/pthreadVC2.dll new file mode 100644 index 0000000..fdea676 Binary files /dev/null and b/addons/pvr.hts/pthreadVC2.dll differ diff --git a/addons/pvr.hts/pthreadVC2d.dll b/addons/pvr.hts/pthreadVC2d.dll new file mode 100644 index 0000000..6fffdc4 Binary files /dev/null and b/addons/pvr.hts/pthreadVC2d.dll differ diff --git a/addons/pvr.hts/resources/language/Dutch/strings.xml b/addons/pvr.hts/resources/language/Dutch/strings.xml new file mode 100644 index 0000000..a6a3455 --- /dev/null +++ b/addons/pvr.hts/resources/language/Dutch/strings.xml @@ -0,0 +1,15 @@ + + + + Tvheadend server naam of IP adres + HTTP poort + HTSP poort + Gebruikersnaam + Wachtwoord + Verbinding timeout in seconden + Antwoord timeout in seconden + + + Verbinding met '%s' verbroken + Verbinding met '%s' hersteld + diff --git a/addons/pvr.hts/resources/language/English/strings.xml b/addons/pvr.hts/resources/language/English/strings.xml new file mode 100644 index 0000000..5b69906 --- /dev/null +++ b/addons/pvr.hts/resources/language/English/strings.xml @@ -0,0 +1,15 @@ + + + + Tvheadend hostname or IP address + HTTP port + HTSP port + Username + Password + Connect timeout in seconds + Response timeout in seconds + + + Disconnected from '%s' + Reconnected to '%s' + diff --git a/addons/pvr.hts/resources/language/Finnish/strings.xml b/addons/pvr.hts/resources/language/Finnish/strings.xml new file mode 100644 index 0000000..d3bb391 --- /dev/null +++ b/addons/pvr.hts/resources/language/Finnish/strings.xml @@ -0,0 +1,15 @@ + + + + Tvheadend-palvelimen nimi tai IP-osoite + HTTP-portti + HTSP-portti + Käyttäjänimi + Salasana + Yhteyden aikakatkaisu sekunneissa + Vastauksen aikakatkaisu sekunneissa + + + Yhteys katkaistu palvelimeen '%s' + Yhdistetty palvelimeen '%s' + diff --git a/addons/pvr.hts/resources/language/German/strings.xml b/addons/pvr.hts/resources/language/German/strings.xml new file mode 100644 index 0000000..b2ba2ea --- /dev/null +++ b/addons/pvr.hts/resources/language/German/strings.xml @@ -0,0 +1,16 @@ + + + + Tvheadend Hostname oder IP + HTTP Port + HTSP Port + Benutzername + Passwort + + Verbindungszeit Überschreitung in Sekunden + Antwortzeit Überschreitung in Sekunden + + + Getrennt von '%s' + Wiederverbunden mit '%s' + diff --git a/addons/pvr.hts/resources/settings.xml b/addons/pvr.hts/resources/settings.xml new file mode 100644 index 0000000..3ef0839 --- /dev/null +++ b/addons/pvr.hts/resources/settings.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/addons/pvr.mythtv.cmyth/Thumbs.db b/addons/pvr.mythtv.cmyth/Thumbs.db new file mode 100644 index 0000000..e742505 Binary files /dev/null and b/addons/pvr.mythtv.cmyth/Thumbs.db differ diff --git a/addons/pvr.mythtv.cmyth/addon.xml b/addons/pvr.mythtv.cmyth/addon.xml new file mode 100644 index 0000000..a5c28f5 --- /dev/null +++ b/addons/pvr.mythtv.cmyth/addon.xml @@ -0,0 +1,23 @@ + + + + + + + + XBMC's frontend for MythTV (using cmyth lib) + MythTV frontend; supporting streaming of Live TV & Recordings, EPG, Timers + This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. + all + + + diff --git a/addons/pvr.mythtv.cmyth/icon.png b/addons/pvr.mythtv.cmyth/icon.png new file mode 100644 index 0000000..821f8c5 Binary files /dev/null and b/addons/pvr.mythtv.cmyth/icon.png differ diff --git a/addons/pvr.mythtv.cmyth/pthreadVC2.dll b/addons/pvr.mythtv.cmyth/pthreadVC2.dll new file mode 100644 index 0000000..fdea676 Binary files /dev/null and b/addons/pvr.mythtv.cmyth/pthreadVC2.dll differ diff --git a/addons/pvr.mythtv.cmyth/pthreadVC2d.dll b/addons/pvr.mythtv.cmyth/pthreadVC2d.dll new file mode 100644 index 0000000..2b4f50e Binary files /dev/null and b/addons/pvr.mythtv.cmyth/pthreadVC2d.dll differ diff --git a/addons/pvr.mythtv.cmyth/resources/language/Danish/strings.xml b/addons/pvr.mythtv.cmyth/resources/language/Danish/strings.xml new file mode 100644 index 0000000..8abb3b3 --- /dev/null +++ b/addons/pvr.mythtv.cmyth/resources/language/Danish/strings.xml @@ -0,0 +1,11 @@ + + + + MythTV Backend Hostname eller IP + MythTV Backend Port + MythTV Database Brugernavn + MythTV Database Adgangskode + MythTV Database Navn + Inkluder mere fejlfindings-information i log-filen + + diff --git a/addons/pvr.mythtv.cmyth/resources/language/English/strings.xml b/addons/pvr.mythtv.cmyth/resources/language/English/strings.xml new file mode 100644 index 0000000..36d4806 --- /dev/null +++ b/addons/pvr.mythtv.cmyth/resources/language/English/strings.xml @@ -0,0 +1,18 @@ + + + + MythTV Backend Hostname or IP + MythTV Backend Port + MythTV Database Username + MythTV Database Password + MythTV Database name + Include more debug information in the log + Recording Rules + Do you still want to delete? + This will delete the recording rule and an additional %i timer(s). + Allow live TV to move scheduled shows + Minimum duration of a recording to be considered a movie + Perl Regular Expression used to extract the foldernames and title for series + Perl Regular Expression used to detect if the title+subtitle is a series + + diff --git a/addons/pvr.mythtv.cmyth/resources/language/German/strings.xml b/addons/pvr.mythtv.cmyth/resources/language/German/strings.xml new file mode 100644 index 0000000..ffb17c3 --- /dev/null +++ b/addons/pvr.mythtv.cmyth/resources/language/German/strings.xml @@ -0,0 +1,14 @@ + + + + MythTV Backend Hostname oder IP + MythTV Backend Port + MythTV Datenbank Benutzer + MythTV Datenbank Passwort + MythTV Datenbank Name + Schreibe ausführlichere debugging Informationen in die Log-Datei + Aufnahme-Regeln + Möchtest du immer noch löschen? + Dieser Vorgang löscht die Aufnahmeregel und zusätzlich %i Aufnahmetermine. + Erlaube dem Live-TV etwaige geplante Aufnahmen zu verschieben + diff --git a/addons/pvr.mythtv.cmyth/resources/settings.xml b/addons/pvr.mythtv.cmyth/resources/settings.xml new file mode 100644 index 0000000..6664b7a --- /dev/null +++ b/addons/pvr.mythtv.cmyth/resources/settings.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/addons/pvr.mythtv.cmyth/resources/skins/skin.confluence/720p/DialogRecordingRulesSettings.xml b/addons/pvr.mythtv.cmyth/resources/skins/skin.confluence/720p/DialogRecordingRulesSettings.xml new file mode 100644 index 0000000..24316d6 --- /dev/null +++ b/addons/pvr.mythtv.cmyth/resources/skins/skin.confluence/720p/DialogRecordingRulesSettings.xml @@ -0,0 +1,155 @@ + + 15 + + 1 + 275 + 30 + + dialogeffect + + + background image + 0 + 0 + 730 + 660 + DialogBack.png + + + Dialog Header image + 40 + 16 + 650 + 40 + dialogheader.png + + + header label + 40 + 20 + 650 + 30 + font13_title + + center + center + selected + black + + + Close Window button + 640 + 15 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 10 + 10 + 10 + 10 + system.getbool(input.enablemouse) + + + control area + 30 + 70 + 670 + 510 + 5 + 9001 + 9001 + 9001 + 9001 + + + 160 + 590 + + OK Button + 0 + 0 + 200 + 40 + center + center + font12_title + + 29 + 29 + 5 + 5 + + + Cancel Button + 210 + 0 + 200 + 40 + center + center + font12_title + + 28 + 28 + 5 + 5 + + + + Default Button + 40 + font13 + grey2 + white + button-focus2.png + button-nofocus.png + + + Default RadioButton + 40 + font13 + grey2 + white + button-focus2.png + button-nofocus.png + + + Default spincontrolex + 40 + grey2 + white + button-focus2.png + button-nofocus.png + font13 + center + yes + + + Default Slider + 40 + button-focus2.png + button-nofocus.png + font13 + grey2 + white + + + Default Seperator + 2 + separator2.png + + + Default Edit + 40 + font13 + grey2 + white + button-focus2.png + button-nofocus.png + + + \ No newline at end of file diff --git a/addons/pvr.mythtv.cmyth/resources/skins/skin.confluence/720p/RecordingRules.xml b/addons/pvr.mythtv.cmyth/resources/skins/skin.confluence/720p/RecordingRules.xml new file mode 100644 index 0000000..f2fb9fb --- /dev/null +++ b/addons/pvr.mythtv.cmyth/resources/skins/skin.confluence/720p/RecordingRules.xml @@ -0,0 +1,339 @@ + + 14 + + + CommonTVBackground + + true + + 0 + 0 + 1280 + 720 + special://skin/backgrounds/media-overlay.png + Player.HasVideo + !Skin.HasSetting(ShowBackgroundVideo) + + + 0 + 0 + 1280 + 720 + Player.HasAudio + !Skin.HasSetting(ShowBackgroundVis) + + + 0 + 0 + 1280 + 720 + Player.HasVideo + !Skin.HasSetting(ShowBackgroundVideo) + + + ContentPanelBackgroundsPVR + + Recording Rules group + VisibleFadeEffect + + 80 + 60 + + Channel header label + 0 + 20 + 220 + 20 + font13_title + white + black + center + center + + + + Time header label + 580 + 20 + 300 + 20 + font13_title + white + black + center + center + + + + Search header label + 220 + 20 + 300 + 20 + font13_title + white + black + center + center + + + + Status header label + 940 + 20 + 150 + 20 + font13_title + white + black + center + center + + + + separator image + 0 + 50 + 1100 + 1 + 88FFFFFF + separator2.png + + + 0 + 55 + 1100 + 480 + 14 + 14 + 35 + 73 + 73 + 200 + + + 0 + 0 + 1100 + 41 + MenuItemNF.png + + + 220 + 0 + 300 + 40 + 33FFFFFF + StackFO.png + + + 940 + 0 + 155 + 40 + 33FFFFFF + StackFO.png + + + 0 + 8 + 50 + 26 + !IsEmpty(ListItem.Date) + $INFO[ListItem.Icon] + + + 50 + 0 + 150 + 40 + font12 + left + center + selected + ListItem.Property(channel) + + + 370 + 0 + 290 + 40 + font12 + center + center + selected + ListItem.Property(search) + + + 730 + 0 + 400 + 40 + font12 + center + center + selected + ListItem.Property(time) + + + 1018 + 0 + 170 + 40 + font12 + center + center + selected + ListItem.Property(status) + + + + + 0 + 0 + 1100 + 41 + MenuItemNF.png + + + 220 + 0 + 300 + 40 + 33FFFFFF + StackFO.png + !Control.HasFocus(14) + + + 980 + 0 + 120 + 40 + 33FFFFFF + StackFO.png + !Control.HasFocus(14) + + + 220 + 0 + 300 + 40 + 88FFFFFF + StackFO.png + Control.HasFocus(14) + + + 940 + 0 + 155 + 40 + 88FFFFFF + StackFO.png + Control.HasFocus(14) + + + 0 + 8 + 50 + 26 + !IsEmpty(ListItem.Date) + $INFO[ListItem.Icon] + + + 50 + 0 + 150 + 40 + font12 + left + center + selected + ListItem.Property(channel) + + + 370 + 0 + 290 + 40 + font12 + center + center + selected + ListItem.Property(search) + + + 730 + 0 + 400 + 40 + font12 + center + center + selected + ListItem.Property(time) + + + 1018 + 0 + 150 + 40 + font12 + center + center + selected + ListItem.Property(status) + + + + + 1105 + 50 + 25 + 480 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 11 + 35 + false + vertical + + + separator image + 55 + 540 + 1010 + 1 + 88FFFFFF + separator2.png + + + Done + 55 + 545 + 128 + 30 + + font13_title + right + center + MenuItemNF.png + MenuItemFO.png + + + + Page Count Label + 40r + 53r + 500 + 20 + font12 + grey + false + right + center + + Window_OpenClose_Animation + + + + \ No newline at end of file diff --git a/addons/pvr.mythtv/addon.xml b/addons/pvr.mythtv/addon.xml new file mode 100644 index 0000000..dac8f16 --- /dev/null +++ b/addons/pvr.mythtv/addon.xml @@ -0,0 +1,23 @@ + + + + + + + + XBMC's frontend for MythTV + MythTV frontend; supporting streaming of Live TV & Recordings, EPG, Timers + This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. + all + + + diff --git a/addons/pvr.mythtv/icon.png b/addons/pvr.mythtv/icon.png new file mode 100644 index 0000000..821f8c5 Binary files /dev/null and b/addons/pvr.mythtv/icon.png differ diff --git a/addons/pvr.mythtv/resources/language/English/strings.xml b/addons/pvr.mythtv/resources/language/English/strings.xml new file mode 100644 index 0000000..bb3167c --- /dev/null +++ b/addons/pvr.mythtv/resources/language/English/strings.xml @@ -0,0 +1,7 @@ + + + + MythTV Backend Hostname or IP + MythXML Port + + diff --git a/addons/pvr.mythtv/resources/language/Finnish/strings.xml b/addons/pvr.mythtv/resources/language/Finnish/strings.xml new file mode 100644 index 0000000..02d2863 --- /dev/null +++ b/addons/pvr.mythtv/resources/language/Finnish/strings.xml @@ -0,0 +1,6 @@ + + + + MythTV-palvelimen nimi tai IP-osoite + MythXML-portti + diff --git a/addons/pvr.mythtv/resources/language/German/strings.xml b/addons/pvr.mythtv/resources/language/German/strings.xml new file mode 100644 index 0000000..9de6f92 --- /dev/null +++ b/addons/pvr.mythtv/resources/language/German/strings.xml @@ -0,0 +1,7 @@ + + + + MythTV Backend Hostname oder IP + MythXML Port + + diff --git a/addons/pvr.mythtv/resources/settings.xml b/addons/pvr.mythtv/resources/settings.xml new file mode 100644 index 0000000..1620968 --- /dev/null +++ b/addons/pvr.mythtv/resources/settings.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/addons/pvr.team-mediaportal.tvserver/LICENSE.txt b/addons/pvr.team-mediaportal.tvserver/LICENSE.txt new file mode 100644 index 0000000..4f8e8eb --- /dev/null +++ b/addons/pvr.team-mediaportal.tvserver/LICENSE.txt @@ -0,0 +1,282 @@ + + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS +------------------------------------------------------------------------- diff --git a/addons/pvr.team-mediaportal.tvserver/addon.xml b/addons/pvr.team-mediaportal.tvserver/addon.xml new file mode 100644 index 0000000..3b845b1 --- /dev/null +++ b/addons/pvr.team-mediaportal.tvserver/addon.xml @@ -0,0 +1,23 @@ + + + + + + + + XBMC frontend for the MediaPortal TV Server (ffmpeg/rtsp only version) + MediaPortal TV Server frontend. Supports streaming of Live TV & Recordings, listening to Radio channels, EPG and Timers. + MediaPortal TV Server frontend. Ondersteunt het bekijken van Live TV en opnames, het luisteren van radio zenders, het tonen van de EPG en het inplannen/beheren van nieuwe opnames (Timers). + This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. + all + + diff --git a/addons/pvr.team-mediaportal.tvserver/changelog.txt b/addons/pvr.team-mediaportal.tvserver/changelog.txt new file mode 100644 index 0000000..6074a08 --- /dev/null +++ b/addons/pvr.team-mediaportal.tvserver/changelog.txt @@ -0,0 +1,89 @@ +v1.2.2.11: +- Fixed: Day of the week mismatch for timers between MePo and XBMC. Credits: jajoflo +- Added: Trigger recording update on timer retrieval so the recording list is kept up to date when there is a new recording. Credits: jajoflo +- Fixed: tv group retrieval requested radio groups +- Added: add support for recording genre field +- Fixed: fixes for recording filepath split-up +- Added: show an error message when the recording filename or playback URL is empty + +v1.2.2.110: +- Added: use channel icons from MediaPortal (Windows, localhost only) +- Changed: switch from libPlatform + libTcpSocket to platform library + +v1.2.2.109: +- Fixed: fix mimetype for tv channels +- Fixed: make sure that OpenLiveStream does not return true due to m_iCurrentChannel when the TSReader fails in a later stage +- Fixed: compilation IOS/OSX/Linux +- Fixed: compile fixes for API move into ADDON namespace +- Added: show localized error messages when OpenLiveStream fails +- Added: signal status support +- Fixed: Don't return encrypted channels as group members when FTA only option is turned on +- Added: add more debug log information about the addon settings and status +- Added: add support for direct recording playback from network shares (smb, Windows only) +- Added: implement support for recording subdirectories +- Fixed: don't return radio channels/channelgroup/channelgroup mappings when radio support is disabled + +v1.1.3.107: +- Added: add additional checks for communication errors +- Fixed: trigger also a recording list update on timer changes +- Fixed: add a mutex to prevent mixing up backend communication on concurrent access +- Fixed: stack overflow while closing a live stream +- Fixed: tv/radio playback after recording playback +- Added: EPG genre string-to-id translation table (addons/pvr.team-mediaportal.tvserver/resources/genre_translation.xml) +- Added: EPG genre string support +- Added: Retrieve TV/Radio card settings from the backend +- Added: support for TVServerXBMC v1.1.x.105-107 +- Fixed: several memory leaks +- Changed: sources adapted for PVR API changes + +v1.1.3.103: +- Fixed: trigger timer and recording list update on changes from XBMC side +- Fixed: check for empty recordings list +- Fixed: check for empty timer list +- Fixed: limit EPG request to the requested period +- Fixed: use tuning details to retrieve the channel number from the backend +- Added: support for TVServerXBMC v1.1.x.104 +- Changed: sources adapted for PVR API changes + +v1.1.2.102: +- Added: Channel group support +- Fixed: live stream playback +- Fixed: recording retrieval +- Changed: sources adapted for PVR API changes + +v1.1.2.101: +- Fixed: "Include radio" setting +- Changed: cleanup unused settings + +v1.1.0.100 +- Rewrite: timer code +- Changed: BackendName +- Fixed: Retrieve more details for timers (repeat, lifetime, ...) +- Fixed: Playback of radio channels with a webstream URL (added via the MediaPortal TV-server) +- Fixed: "Free-to-air only" setting +- Support for TVServerXBMC v1.1.0.100 + +v1.1.0.98 +- Log more information on socket related problems + +v1.1.0.97 +- Fixed: Use uri decode for ip-address in hostname field + +v1.1.0.96 +- Fixed: allow spaces in groupnames, recording names and timer titles +- Fixed: GetTimerInfo +- Add debug messages for empty channel list + +v1.1.0.95 +- Fix time mismatch between XBMC and MediaPortal TV Server for new timers (scheduled recordings) +- Send genre strings to XBMC for unrecognised genres. No colors in EPG, but at least the text is now ok. + +v1.1.0.90 +- Faster channel switching (around 2 sec faster) +- Decrease CPU uage when a buffer underrun occurs + +v1.1.0.75 +- PVR client should abort connection when the TVServerXBMC version is too old + +v1.1.0.60 +- Fix PVR client destroy \ No newline at end of file diff --git a/addons/pvr.team-mediaportal.tvserver/icon.png b/addons/pvr.team-mediaportal.tvserver/icon.png new file mode 100644 index 0000000..42f6e37 Binary files /dev/null and b/addons/pvr.team-mediaportal.tvserver/icon.png differ diff --git a/addons/pvr.team-mediaportal.tvserver/resources/genre_translation.xml b/addons/pvr.team-mediaportal.tvserver/resources/genre_translation.xml new file mode 100644 index 0000000..ca6cedd --- /dev/null +++ b/addons/pvr.team-mediaportal.tvserver/resources/genre_translation.xml @@ -0,0 +1,128 @@ + + + + + + movie/drama (general) + detective/thriller + comedy + soap/melodram/folkloric + adult movie/drama + news/current affairs (general) + documentary + show/game show (general) + sports (general) + childrens's/youth program (general) + cartoon/puppets + music/ballet/dance (general) + arts/culture (without music, general) + religion + magazines/reports/documentary + education/science/factual topics (general) + nature/animals/environment + + + + diff --git a/addons/pvr.team-mediaportal.tvserver/resources/language/Dutch/strings.xml b/addons/pvr.team-mediaportal.tvserver/resources/language/Dutch/strings.xml new file mode 100644 index 0000000..951c6f5 --- /dev/null +++ b/addons/pvr.team-mediaportal.tvserver/resources/language/Dutch/strings.xml @@ -0,0 +1,44 @@ + + + + Mediaportal hostnaam + Mediaportal XBMC plugin poort + Toon alleen vrij te ontvangen kanalen + Toon radio + + Verbindingstimeout (s) + Importeer alleen TV kanalen uit groep + Importeer alleen radio kanalen uit groep + Converteer hostnaam naar IP adres + EPG: Genre tekst inlezen (traag) + Wachttijd na kanaal tunen(ms) + Opnames direct afspelen (niet streamen) + Mediaportal directory met opnames + + + Verbinding + MediaPortal + + + Uw TVServerXBMC plugin '%s' is te oud. U heeft minimaal versie '%s' of nieuwer nodig! + Uw TVServerXBMC plugin is te oud. U heeft minimaal versie '%s' of nieuwer nodig! + Afspelen opname mislukt. Lege URL of bestandsnaam. + + + Alle kaarten zijn bezet + Kanaal is gecodeerd + Geen video of audio gedetecteerd + Geen signaal + Onbekende fout + Graph starten mislukt + Onbekend kanaal + Geen tuning details + Kanaal is niet gekoppeld aan een kaart + Kaart is uitgeschakeld + Verbinding met slave verbroken + Niet de eigenaar + Aanmaken Graph mislukt + SW Encoder ontbreekt + Geen vrije diskruimte + Geen PMT gevonden + diff --git a/addons/pvr.team-mediaportal.tvserver/resources/language/English/strings.xml b/addons/pvr.team-mediaportal.tvserver/resources/language/English/strings.xml new file mode 100644 index 0000000..2fb3a1a --- /dev/null +++ b/addons/pvr.team-mediaportal.tvserver/resources/language/English/strings.xml @@ -0,0 +1,44 @@ + + + + Mediaportal Hostname + Mediaportal XBMC plugin Port + Free-to-air only + Include Radio + + Connect timeout (s) + Import only TV Channels from group + Import only Radio Channels from group + Convert hostname to IP-adress + EPG: Read genre strings (slow) + Wait time after tuning a channel (ms) + Play recordings directly (no streaming) + Mediaportal recordings directory + + + Connection + MediaPortal + + + Your TVServerXBMC version '%s' is too old. Please upgrade to '%s' or higher! + Your TVServerXBMC version is too old. Please upgrade to '%s' or higher! + Recording playback failed. Empty URL of filename. + + + All cards are busy + Channel is scrambled + No video or audio detected + No signal detected + Unknown error + Unable to start graph + Unknown channel + No tuning details + Channel is not mapped to any card + Card is disabled + Connection to slave failed + Not the owner + Graph building failed + SW Encoder missing + No free disk space + No PMT found + diff --git a/addons/pvr.team-mediaportal.tvserver/resources/language/Finnish/strings.xml b/addons/pvr.team-mediaportal.tvserver/resources/language/Finnish/strings.xml new file mode 100644 index 0000000..c151b01 --- /dev/null +++ b/addons/pvr.team-mediaportal.tvserver/resources/language/Finnish/strings.xml @@ -0,0 +1,25 @@ + + + + Mediaportal-palvelimen nimi + Mediaportal XBMC-lisäosan portti + Vain ilmaiskanavat + Sisällytä radiokanavat + + Yhteyden aikakatkaisu (s) + Tuo ainoastaan TV-kanavat ryhmästä + Tuo ainoastaan radiokanavat ryhmästä + Muunna palvelimen nimi IP-osoitteeksi + Ohjelmaopas: Lue lajityyppi merkkijonoista (hidas) + Odotusaika kanavan virittämisen jälkeen (ms) + Toista nauhoitukset suoraan (ei streamausta) + Mediaportal-nauhoitusten kansio + + + Yhteys + MediaPortal + + + TVServerXBMC:n versio v%s on liian vanha. Päivitä vähintään versioon v%s tai uudempaan! + TVServerXBMC:n versio on liian vanha. Päivitä vähintään versioon v%s tai uudempaan! + diff --git a/addons/pvr.team-mediaportal.tvserver/resources/language/German/strings.xml b/addons/pvr.team-mediaportal.tvserver/resources/language/German/strings.xml new file mode 100644 index 0000000..7121c24 --- /dev/null +++ b/addons/pvr.team-mediaportal.tvserver/resources/language/German/strings.xml @@ -0,0 +1,21 @@ + + + + Mediaportal Hostname oder IP + Mediaportal Port + Nur frei empfangbare Kanäle + Zeige Radiokanäle + + Verbindungszeitüberlauf (s) + Importiere nur TV Kanäle aus Gruppe + Importiere nur Radiokanäle aus Gruppe + Konvertiere Hostname nach IP-Adresse + EPG: Genre Texte hochladen (langsam) + Wartezeit, nachdem ein Kanal abgestimmt worden ist (ms) + Aufnahmen aus Ordner lesen + Mediaportal Aufnahmeordner + + + Ihre TVServerXBMC plugin v%s ist zu alt. Sie brauchen mindestens Version v%s! + Ihre TVServerXBMC plugin Version ist zu alt. Sie brauchen mindestens Version v%s! + diff --git a/addons/pvr.team-mediaportal.tvserver/resources/language/Italian/strings.xml b/addons/pvr.team-mediaportal.tvserver/resources/language/Italian/strings.xml new file mode 100644 index 0000000..a1880c6 --- /dev/null +++ b/addons/pvr.team-mediaportal.tvserver/resources/language/Italian/strings.xml @@ -0,0 +1,25 @@ + + + + Nome del server Mediaportal + Porta del plugin Mediaportal di XBMC + Solo Free-to-air + Includi Radio + + Timeout per la connessione (s) + Importa solo canali TV dal gruppo + Importa solo canali radio dal gruppo + Converti il nome del server nell'indirizzo IP + EPG: Leggi le stringhe dei generi (lento) + Tempo di attesa dopo il tuning di un canale (ms) + Registra direttamente (nessuno streaming) + Cartella di salvataggio per Mediaportal + + + Connessione + MediaPortal + + + La tua versione di TVServerXBMC v%s troppo vecchia. Per favore, aggiornala a v%s o superiore! + La tua versione di TVServerXBMC troppo vecchia. Per favore, aggiornala a v%s o superiore! + diff --git a/addons/pvr.team-mediaportal.tvserver/resources/settings.xml b/addons/pvr.team-mediaportal.tvserver/resources/settings.xml new file mode 100644 index 0000000..419c61b --- /dev/null +++ b/addons/pvr.team-mediaportal.tvserver/resources/settings.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/addons/pvr.vdr.vnsi/addon.xml b/addons/pvr.vdr.vnsi/addon.xml new file mode 100644 index 0000000..a0b1e03 --- /dev/null +++ b/addons/pvr.vdr.vnsi/addon.xml @@ -0,0 +1,23 @@ + + + + + + + + PVR client to connect VDR to XBMC over the VNSI interface + VDR frontend; supporting streaming of Live TV & Recordings, EPG, Timers over the VNSI plugin + Erlaubt das wiedergeben von Live TV und Aufnahmen mittels VDR auf XBMC. Des weiteren werden EPG, Kanalsuche und Timer unterstützt. + This is unstable software! The authors are in no way responsible for failed recordings, incorrect timers, wasted hours, or any other undesirable effects.. + all + + diff --git a/addons/pvr.vdr.vnsi/icon.png b/addons/pvr.vdr.vnsi/icon.png new file mode 100644 index 0000000..d310dde Binary files /dev/null and b/addons/pvr.vdr.vnsi/icon.png differ diff --git a/addons/pvr.vdr.vnsi/pthreadVC2.dll b/addons/pvr.vdr.vnsi/pthreadVC2.dll new file mode 100644 index 0000000..fdea676 Binary files /dev/null and b/addons/pvr.vdr.vnsi/pthreadVC2.dll differ diff --git a/addons/pvr.vdr.vnsi/pthreadVC2d.dll b/addons/pvr.vdr.vnsi/pthreadVC2d.dll new file mode 100644 index 0000000..6fffdc4 Binary files /dev/null and b/addons/pvr.vdr.vnsi/pthreadVC2d.dll differ diff --git a/addons/pvr.vdr.vnsi/resources/language/Dutch/strings.xml b/addons/pvr.vdr.vnsi/resources/language/Dutch/strings.xml new file mode 100644 index 0000000..7a88831 --- /dev/null +++ b/addons/pvr.vdr.vnsi/resources/language/Dutch/strings.xml @@ -0,0 +1,48 @@ + + + + VDR hostnaam of IP adres + VNSI Poort + Prioriteit + Character Set Conversie + Connectie timeout (s) + Berichten vanuit VDR toestaan + Lees opnames van directory^M + VDR opname directory^M + Kanalen scannen + Kanalen scan - opties + kanalen scan starten + Bron Type + TV kanalen + Radio kanalen + FTA kanalen + Gecodeerde kanalen + HD kanalen + Land + Kabel Inversion + Kabel Symbolrate + Kabel modulation + Antenne Inversion + Sateliet + ATSC type + Terug + Kanalen zoeken - bezig... %i %% + Type: + Device: + Scan: %i + Signaal: %i %% + Nieuwe kanalen: %i + Alle kanalen: %i + Analoge TV + Analoge Radio + Transponder: + Nieuwe kanalen + Kanalen zoeken - Klaar + Geen device beschikbaar - exiting + Geen DVB-S2 apparaat beschikbaar - We vallen terug op DVB-S + Bezig + Gestopt + Klaar + Kanalen scan - Geanuleerd + Kanalen scan - Fout + diff --git a/addons/pvr.vdr.vnsi/resources/language/English/strings.xml b/addons/pvr.vdr.vnsi/resources/language/English/strings.xml new file mode 100644 index 0000000..1553912 --- /dev/null +++ b/addons/pvr.vdr.vnsi/resources/language/English/strings.xml @@ -0,0 +1,51 @@ + + + + VDR Hostname or IP + VNSI Port + Priority + Character Set Conversion + Connect timeout (s) + Allow VDR Messages + Read recordings from directory + VDR recordings directory + Channel search + Channel search - Settings + Start Channel search + Source Type + TV channels + Radio channels + FTA channels + Scrambled channels + HD channels + Country + Cable Inversion + Cable Symbolrate + Cable modulation + Terr Inversion + Satellite + ATSC Type + Back + Channel search - running... %i %% + Type: + Device: + Scan: %i + Signal: %i %% + New channels: %i + All channels: %i + Analog TV + Analog Radio + Transponder: + New channels + Channel search - Finished + No device available - exiting + No DVB-S2 device available - trying fallback to DVB-S + Running + Stopped + Finished + Channel search - Canceled + Channel search - Error + Lost connection to VDR Server + Connection to VDR Server restored + Create channel groups automatically on the server + diff --git a/addons/pvr.vdr.vnsi/resources/language/Finnish/strings.xml b/addons/pvr.vdr.vnsi/resources/language/Finnish/strings.xml new file mode 100644 index 0000000..c21e4c0 --- /dev/null +++ b/addons/pvr.vdr.vnsi/resources/language/Finnish/strings.xml @@ -0,0 +1,51 @@ + + + + VDR-palvelimen nimi tai IP-osoite + VNSI-portti + Tärkeysaste + Kirjainmerkistön muunnos + Yhteyden aikakatkaisu (s) + Salli VDR-palvelimen viestit + Lue nauhoitukset kansiosta + VDR-nauhoitusten kansio + Kanavahaku + Kanavahaun asetukset + Aloita kanavahaku + Lähteen tyyppi + TV-kanavat + Radiokanavat + Ilmaiskanavat + Salatut kanavat + HD-kanavat + Maa + Kaapeliverkon inversio + Kaapeliverkon symbolinopeus + Kaapeliverkon modulointi + Antenniverkon inversio + Satelliitti + ATSC tyyppi + Takaisin + Kanavahaku käynnissä... %i %% + Tyyppi: + Laite: + Haku: %i + Signaali: %i %% + Uudet kanavat: %i + Kaikki kanavat: %i + Analoginen TV + Analoginen radio + Transponder: + Uudet kanavat + Kanavahaku valmis + Ei laitetta saatavilla - lopetetaan + Ei DVB-S2 laitetta saatavilla - kokeillaan DVB-S + Käynnissä + Pysäytetty + Valmis + Kanavahaku peruutettu + Kanavahaku virhe + Yhteys VDR-palvelimeen menetetty + Yhteys VDR-palvelimeen palautettu + Luo kanavaryhmät automaattisesti palvelimella + diff --git a/addons/pvr.vdr.vnsi/resources/language/German/strings.xml b/addons/pvr.vdr.vnsi/resources/language/German/strings.xml new file mode 100644 index 0000000..48f6834 --- /dev/null +++ b/addons/pvr.vdr.vnsi/resources/language/German/strings.xml @@ -0,0 +1,51 @@ + + + + VDR Hostname oder IP + VNSI Port + Priorität + Textkonvertierung (UTF-8) + Verbindungszeitüberlauf (s) + VDR Nachrichten erlauben + Aufnahmen aus Ordner lesen + VDR Aufnahmeordner + Kanalsuche + Kanalsuche - Einstellungen + Kanalsuche starten + Empfangsart + TV Kanäle + Radio Kanäle + Frei empfangbare Kanäle + Verschlüsselte Kanäle + HD Kanäle + Land + Kabel Inversion + Kabel Symbolrate + Kabel Modulation + Terrestrisch Inversion + Satellit + ATSC Type + Zurück + Kanalsuche - läuft... %i %% + Empfangsart: + Gerät: + Fortschritt: %i + Signal: %i %% + Neue Kanäle: %i + Alle Kanäle: %i + Analog TV + Analog Radio + Transponder: + Neue Kanäle + Kanalsuche - Abgeschlossen + Kein Empfangsgerät verfügbar + Kein DVB-S2 Empfangsgerät verfügbar - versuche DVB-S + Läuft... + Angehalten + Fertig + Kanalsuche - Abgebrochen + Kanalsuche - Fehler + Verbindung zum VDR Server unterbrochen + Verbindung zum VDR Server wiederhergestellt + Kanalgruppen automatisch am Server erzeugen + diff --git a/addons/pvr.vdr.vnsi/resources/settings.xml b/addons/pvr.vdr.vnsi/resources/settings.xml new file mode 100644 index 0000000..557f54c --- /dev/null +++ b/addons/pvr.vdr.vnsi/resources/settings.xml @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/addons/pvr.vdr.vnsi/resources/skins/Confluence/720p/ChannelScan.xml b/addons/pvr.vdr.vnsi/resources/skins/Confluence/720p/ChannelScan.xml new file mode 100644 index 0000000..e4f6338 --- /dev/null +++ b/addons/pvr.vdr.vnsi/resources/skins/Confluence/720p/ChannelScan.xml @@ -0,0 +1,733 @@ + + 5 + no + 2 + + CommonSettingsBackground + CommonMediaPlayingBackground + + 90 + 50 + + + + + + + + + + 0 + 0 + 1100 + 640 + DialogBack.png + + + LOGO + 30 + 15 + 220 + 80 + keep + Confluence_Logo.png + + + 268 + 10 + 790 + 618 + black-back2.png + + + 268 + 10 + 804 + 70 + stretch + GlassTitleBar.png + + + header label + 300 + 20 + 740 + 30 + font16caps + + left + center + white + black + + + Start/Stop Channel search + 10 + 90 + 260 + 60 + 13 + + font13_title + right + center + MenuItemNF.png + MenuItemFO.png + 2 + 10 + 6 + 6 + + + Cancel + 10 + 150 + 260 + 60 + 13 + + font13_title + right + center + MenuItemNF.png + MenuItemFO.png + 10 + 10 + 5 + 5 + IsEmpty(Window.Property(Scanning)) + + + IsEmpty(Window.Property(Scanning)) + + Source Type + 268 + 80 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + center + + 5 + 5 + 22 + 11 + + + Default RadioButton + 268 + 120 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + + 5 + 5 + 10 + 12 + Conditional + + + Default RadioButton + 268 + 160 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + + 5 + 5 + 11 + 13 + Conditional + Conditional + + + Default RadioButton + 268 + 200 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + + 5 + 5 + 12 + 14 + Conditional + Conditional + Conditional + + + Default RadioButton + 268 + 240 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + + 5 + 5 + 13 + 15 + Conditional + Conditional + Conditional + Conditional + + + Default RadioButton + 268 + 280 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + + 5 + 5 + 14 + 16 + Conditional + Conditional + Conditional + Conditional + Conditional + + + Country selection + 268 + 320 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + center + + 5 + 5 + 15 + 17 + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + + + Satellite selection + 268 + 360 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + center + + 5 + 5 + 16 + 18 + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + + + DVB-C Inversion + 268 + 400 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + center + + 5 + 5 + 17 + 29 + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + + + DVB-C Symbolrate + 268 + 440 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + center + + 5 + 5 + 18 + 20 + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + + + DVB-C QAM + 268 + 480 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + center + + 5 + 5 + 29 + 21 + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + + + DVB-T Inversion + 268 + 520 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + center + + 5 + 5 + 20 + 22 + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + + + ATSC Type + 268 + 560 + 790 + 40 + font13 + grey2 + white + MenuItemFO.png + MenuItemNF.png + center + + 5 + 5 + 21 + 10 + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + Conditional + + + + !IsEmpty(Window.Property(Scanning)) + + Progressbar + 275 + 60 + 780 + 14 + + + type label + 275 + 85 + 250 + 30 + font13 + + left + center + grey + black + + + type value + 1040 + 85 + 500 + 30 + font13 + + right + center + white + black + + + device label + 275 + 115 + 250 + 30 + font13 + + left + center + white + black + + + device value + 1040 + 115 + 500 + 30 + font13 + + right + center + white + black + + + transponder label + 275 + 145 + 250 + 30 + font13 + + left + center + white + black + + + transponder value + 1040 + 145 + 500 + 30 + font13 + + right + center + white + black + + + Progressbar + 30 + 160 + 220 + 50 + + + Signal label + 40 + 168 + 250 + 30 + font13 + + left + center + white + black + + + 215 + 170 + 30 + 30 + stretch + amt-overlay-watched.png + !IsEmpty(Window.Property(Locked)) + + + 290 + 180 + 750 + 400 + 2 + 2 + 10 + 60 + 60 + 200 + + + 0 + 0 + 750 + 40 + stretch + MenuItemNF.png + + + 710 + 5 + 40 + 30 + stretch + OverlayLocked.png + !IsEmpty(ListItem.Property(IsEncrypted)) + + + 690 + 7 + 60 + 25 + stretch + OverlayHD.png + Conditional + !IsEmpty(ListItem.Property(IsHD)) + + + 0 + 2 + 36 + 36 + stretch + DefaultVideoCover.png + IsEmpty(ListItem.Property(IsRadio)) + + + 0 + 2 + 36 + 36 + stretch + DefaultAlbumCover.png + !IsEmpty(ListItem.Property(IsRadio)) + + + 45 + 0 + 500 + 40 + font14 + left + center + grey2 + selected + ListItem.Label + + + + + 0 + 0 + 750 + 40 + stretch + MenuItemNF.png + !Control.HasFocus(2) + VisibleFadeEffect + + + 0 + 0 + 750 + 40 + stretch + MenuItemFO.png + Control.HasFocus(2) + VisibleFadeEffect + + + 710 + 5 + 40 + 30 + stretch + OverlayLocked.png + !IsEmpty(ListItem.Property(IsEncrypted)) + + + 690 + 7 + 60 + 25 + stretch + OverlayHD.png + Conditional + !IsEmpty(ListItem.Property(IsHD)) + + + 0 + 2 + 36 + 36 + stretch + DefaultVideoCover.png + IsEmpty(ListItem.Property(IsRadio)) + + + 0 + 2 + 36 + 36 + stretch + DefaultAlbumCover.png + !IsEmpty(ListItem.Property(IsRadio)) + + + 45 + 0 + 500 + 40 + font14 + left + center + grey2 + selected + ListItem.Label + + + + + 1060 + 180 + 25 + 410 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 2 + 10 + true + vertical + + + Page Count Label + 1040 + 600 + 500 + 20 + font12 + grey + false + right + center + + + + Status Label + 275 + 590 + 500 + 20 + font14 + yellow + false + left + center + + + + + BehindDialogFadeOut + + 60 + 0 + WindowClose + WindowOpen + + 0 + 0 + 250 + 35 + header.png + + + WindowTitleCommons + 220 + + + + WindowTitleHomeButton + Clock + + diff --git a/addons/skin.confluence/720p/DialogButtonMenu.xml b/addons/skin.confluence/720p/DialogButtonMenu.xml index 0884883..0ae22e8 100644 --- a/addons/skin.confluence/720p/DialogButtonMenu.xml +++ b/addons/skin.confluence/720p/DialogButtonMenu.xml @@ -63,9 +63,9 @@ PreviousMenu DialogCloseButton-focus.png DialogCloseButton.png - 13 + 2 13 - 9 + 13 2 system.getbool(input.enablemouse) @@ -222,7 +222,7 @@ font13 System.HasLocks - + 340 70 System.HasAlarm(shutdowntimer) @@ -246,7 +246,39 @@ - + + Inhibit idle shutdown + 340 + 40 + grey2 + white + center + 290 + ShutdownButtonFocus.png + ShutdownButtonNoFocus.png + XBMC.InhibitIdleShutdown(true) + no + font13 + + System.HasShutdown +!System.IsInhibit + + + Allow idle shutdown + 340 + 40 + grey2 + white + center + 290 + ShutdownButtonFocus.png + ShutdownButtonNoFocus.png + XBMC.InhibitIdleShutdown(false) + no + font13 + + System.HasShutdown + System.IsInhibit + + background bottom image 0 340 diff --git a/addons/skin.confluence/720p/DialogExtendedProgressBar.xml b/addons/skin.confluence/720p/DialogExtendedProgressBar.xml new file mode 100644 index 0000000..412d92c --- /dev/null +++ b/addons/skin.confluence/720p/DialogExtendedProgressBar.xml @@ -0,0 +1,48 @@ + + + WindowOpen + WindowClose + + + 720 + 0 + conditional + conditional + + 0 + -10 + 400 + 70 + InfoMessagePanel.png + + + Header Label + 15 + 4 + 370 + 18 + font10_title + selected + left + center + + + Title Label + 15 + 20 + 370 + 20 + font10 + left + center + + + progress control + 15 + 42 + 370 + 8 + + + + \ No newline at end of file diff --git a/addons/skin.confluence/720p/DialogPVRChannelManager.xml b/addons/skin.confluence/720p/DialogPVRChannelManager.xml new file mode 100644 index 0000000..d1ffa67 --- /dev/null +++ b/addons/skin.confluence/720p/DialogPVRChannelManager.xml @@ -0,0 +1,539 @@ + + 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 + IsEmpty(Window.Property(IsRadio)) + + + header label + 40 + 20 + 820 + 30 + font13_title + + center + center + selected + black + !IsEmpty(Window.Property(IsRadio)) + + + Close Window button + 810 + 15 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 10 + 10 + 10 + 10 + system.getbool(input.enablemouse) + + + 20 + 70 + + 0 + 5 + 25 + 470 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 9002 + 20 + false + vertical + + + 25 + 0 + 430 + 475 + button-nofocus.png + + + 30 + 5 + 420 + 470 + 20 + 20 + 60 + 9002 + 60 + 200 + + + 0 + 0 + 420 + 40 + button-nofocus.png + + + 5 + 5 + 30 + 30 + $INFO[ListItem.Property(Icon)] + ListItem.Property(ActiveChannel) + + + 5 + 5 + 30 + 30 + 77FFFFFF + $INFO[ListItem.Property(Icon)] + !ListItem.Property(ActiveChannel) + + + 45 + 0 + 335 + 40 + font12 + left + center + white + selected + + ListItem.Property(ActiveChannel) + + + 45 + 0 + 335 + 40 + font12 + left + center + grey3 + selected + + !ListItem.Property(ActiveChannel) + + + 390 + 10 + 20 + 20 + OverlayWatched.png + ListItem.Property(Changed) + + + + + 0 + 0 + 420 + 60 + button-focus2.png + conditional + + + 5 + 5 + 30 + 30 + $INFO[ListItem.Property(Icon)] + ListItem.Property(ActiveChannel) + + + 5 + 5 + 30 + 30 + 77FFFFFF + $INFO[ListItem.Property(Icon)] + !ListItem.Property(ActiveChannel) + + + 45 + 0 + 335 + 40 + font12 + left + center + white + selected + + ListItem.Property(ActiveChannel) + + + 45 + 0 + 335 + 40 + font12 + left + center + grey3 + selected + + !ListItem.Property(ActiveChannel) + + + 390 + 10 + 20 + 20 + OverlayWatched.png + ListItem.Property(Changed) + + + 5 + 30 + 410 + 30 + font12 + left + center + grey2 + selected + + + + + + Page Count Label + 30 + 485 + 420 + 20 + font12 + grey + false + center + center + + + + + + 490 + 70 + + channel options Header + 0 + 0 + 380 + 20 + font12 + + left + center + blue + black + + + Channel activated + 0 + 25 + 380 + 35 + font12 + white + white + black + left + center + button-focus2.png + button-nofocus.png + no + + 20 + 60 + 9000 + 8 + + + Channel name + 0 + 65 + 380 + 35 + font12 + white + white + black + button-focus2.png + button-nofocus.png + + 60 + 20 + 7 + 9 + + + Channel logo Button + 0 + 105 + 380 + 35 + font12 + button-focus2.png + button-nofocus.png + + 20 + 60 + 8 + 12 + + + Current Channel Icon + 345 + 107 + 30 + 30 + keep + ListItem.Property(Icon) + + + EPG activated + 0 + 145 + 380 + 35 + font12 + white + white + black + left + center + button-focus2.png + button-nofocus.png + no + + 20 + 60 + 9 + 13 + + + EPG source + 0 + 185 + 380 + 35 + font12 + button-focus2.png + button-nofocus.png + + 60 + 20 + 12 + 30 + + + + 490 + 360 + + channel options Header + 0 + 0 + 380 + 20 + font12 + + left + center + blue + black + + + Group Manager Button + 0 + 25 + 190 + 35 + font12 + button-focus2.png + button-nofocus.png + center + + 20 + 34 + 13 + 31 + + + TV/Radio Button + 195 + 25 + 185 + 35 + font12 + IsEmpty(Window.Property(IsRadio)) + button-focus2.png + button-nofocus.png + center + + 30 + 60 + 13 + 31 + + + TV/Radio Button + 195 + 25 + 185 + 35 + font12 + !IsEmpty(Window.Property(IsRadio)) + button-focus2.png + button-nofocus.png + center + + 30 + 60 + 13 + 31 + + + Edit channel Button + 0 + 65 + 380 + 35 + font12 + button-focus2.png + button-nofocus.png + center + + 20 + 60 + 30 + 32 + + + Delete channel Button + 0 + 105 + 380 + 35 + font12 + button-focus2.png + button-nofocus.png + center + + 20 + 60 + 31 + 33 + + + New channel Button + 0 + 145 + 380 + 35 + font12 + button-focus2.png + button-nofocus.png + center + + 20 + 60 + 32 + 9000 + + + + + 70 + 590 + + OK Button + 0 + 0 + 250 + 40 + + font12_title + center + center + 6 + 5 + 33 + 7 + + + Apply changes Button + 260 + 0 + 250 + 40 + + font12_title + center + center + 4 + 6 + 33 + 7 + + + Cancel Button + 520 + 0 + 250 + 40 + + font12_title + center + center + 5 + 4 + 33 + 7 + + + + diff --git a/addons/skin.confluence/720p/DialogPVRChannelsOSD.xml b/addons/skin.confluence/720p/DialogPVRChannelsOSD.xml new file mode 100644 index 0000000..4d86a0a --- /dev/null +++ b/addons/skin.confluence/720p/DialogPVRChannelsOSD.xml @@ -0,0 +1,296 @@ + + 11 + + 1 + 780 + 30 + + dialogeffect + + + + background image + 0 + 0 + 480 + 660 + DialogBack2.png + + + Close Window button + 390 + 15 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 2 + 2 + 2 + 2 + system.getbool(input.enablemouse) + + + Dialog Header image + 40 + 16 + 400 + 40 + dialogheader.png + + + header label + 40 + 16 + 430 + 40 + font12_title + + center + center + blue + black + !pvr.IsPlayingRadio + + + header label + 40 + 16 + 430 + 40 + font12_title + + center + center + blue + black + pvr.IsPlayingRadio + + + 30 + 70 + 410 + 520 + 60 + 60 + 11 + 11 + list + 60 + 200 + + + 0 + 0 + 410 + 60 + button-nofocus.png + VisibleFadeEffect + + + 5 + 0 + 40 + 30 + font12 + left + center + grey + grey + ListItem.ChannelNumber + + + 5 + 35 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 50 + 0 + 350 + 25 + font13 + white + selected + left + center + + + + 50 + 25 + 350 + 20 + font12 + grey + grey + left + center + + IsEmpty(Listitem.Icon) + + + 50 + 25 + 300 + 20 + font12 + grey + grey + left + center + + !IsEmpty(Listitem.Icon) + + + Progressbar + 50 + 50 + 300 + 6 + 88FFFFFF + ListItem.Progress + + + 355 + 4 + 50 + 50 + $INFO[ListItem.Icon] + + + + + 0 + 0 + 410 + 60 + button-nofocus.png + !Control.HasFocus(11) + VisibleFadeEffect + + + 0 + 0 + 410 + 60 + button-focus2.png + Control.HasFocus(11) + VisibleFadeEffect + + + 5 + 0 + 40 + 30 + font12 + left + center + grey + grey + ListItem.ChannelNumber + + + 5 + 35 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 50 + 0 + 350 + 25 + font13 + white + selected + left + center + + + + 50 + 25 + 350 + 20 + font12 + grey + grey + left + center + + IsEmpty(Listitem.Icon) + + + 50 + 25 + 300 + 20 + font12 + grey + grey + left + center + + !IsEmpty(Listitem.Icon) + + + Progressbar + 50 + 50 + 300 + 6 + 88FFFFFF + ListItem.Progress + + + 355 + 4 + 50 + 50 + $INFO[ListItem.Icon] + + + + + 440 + 70 + 25 + 520 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 11 + 11 + 61 + 61 + false + vertical + + + Page Count Label + 450 + 610 + 400 + 20 + font12 + grey + false + right + center + + Window_OpenClose_Animation + + + + \ No newline at end of file diff --git a/addons/skin.confluence/720p/DialogPVRGroupManager.xml b/addons/skin.confluence/720p/DialogPVRGroupManager.xml new file mode 100644 index 0000000..5cdaaab --- /dev/null +++ b/addons/skin.confluence/720p/DialogPVRGroupManager.xml @@ -0,0 +1,433 @@ + + 29 + + + !Window.IsVisible(FileBrowser) + WindowOpen + WindowClose + + 130 + 0 + 1150 + 720 + MediaBladeSub.png + + + Close Window button + 180 + 0 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 9000 + 9000 + 9000 + 9000 + system.getbool(input.enablemouse) + + + WindowOpen + WindowClose + + header label + 160 + 40 + 1080 + 30 + font24_title + + center + center + selected + black + + + Group list + 160 + 80 + + name label + 0 + 0 + 340 + 70 + font13 + + center + center + blue + + + 0 + 75 + 340 + 460 + button-nofocus.png + + + 5 + 80 + 330 + 450 + 13 + 13 + 29 + 73 + 73 + 200 + + + 0 + 0 + 330 + 40 + button-nofocus.png + + + 10 + 0 + 310 + 40 + font12 + left + center + grey2 + selected + ListItem.Label + + + + + 0 + 0 + 330 + 40 + button-nofocus.png + !Control.HasFocus(13) + + + 0 + 0 + 330 + 40 + button-focus2.png + Control.HasFocus(13) + + + 10 + 0 + 310 + 40 + font12 + left + center + white + selected + ListItem.Label + + + + + 340 + 75 + 25 + 460 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 13 + 11 + 73 + 73 + false + vertical + + + + Channels list + 525 + 80 + + name label + 0 + 0 + 340 + 70 + font13 + center + center + blue + + + 0 + 75 + 340 + 460 + button-nofocus.png + + + 5 + 85 + 330 + 450 + 11 + 11 + 73 + 71 + 71 + 200 + + + 0 + 0 + 330 + 40 + button-nofocus.png + + + 32 + 32 + 5 + 4 + $INFO[ListItem.Icon] + + + 40 + 0 + 280 + 40 + font12 + left + center + grey2 + selected + + + + + + 0 + 0 + 330 + 40 + button-nofocus.png + !Control.HasFocus(11) + + + 0 + 0 + 330 + 40 + button-focus2.png + Control.HasFocus(11) + + + 32 + 32 + 5 + 4 + $INFO[ListItem.Icon] + + + 40 + 0 + 280 + 40 + font12 + left + center + white + selected + + + + + + 340 + 75 + 25 + 460 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 11 + 12 + 71 + 71 + false + vertical + + + + Grouped Channels list + 890 + 80 + + name label + 0 + 0 + 340 + 70 + font13 + center + center + blue + + + 0 + 75 + 340 + 460 + button-nofocus.png + + + 5 + 85 + 330 + 450 + 12 + 12 + 71 + 72 + 72 + 200 + + + 0 + 0 + 330 + 40 + button-nofocus.png + + + 32 + 32 + 5 + 4 + $INFO[ListItem.Icon] + + + 40 + 0 + 280 + 40 + font12 + left + center + grey2 + selected + + + + + + 0 + 0 + 330 + 40 + button-nofocus.png + !Control.HasFocus(12) + + + 0 + 0 + 330 + 40 + button-focus2.png + Control.HasFocus(12) + + + 32 + 32 + 5 + 4 + $INFO[ListItem.Icon] + + + 40 + 0 + 280 + 40 + font12 + left + center + white + selected + + + + + + 340 + 75 + 25 + 460 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 12 + 26 + 72 + 72 + false + vertical + + + + 160 + 660 + 1080 + 40 + 2 + center + horizontal + 72 + 13 + 9000 + 9000 + + Add Group + 230 + ButtonInfoDialogsCommonValues + + + + Rename Group + 230 + ButtonInfoDialogsCommonValues + + + + Delete Group + 230 + ButtonInfoDialogsCommonValues + + + + OK + 230 + ButtonInfoDialogsCommonValues + + + + + + SideBladeRight + Clock + + + Fake Label used to pass on name label + false + + + \ No newline at end of file diff --git a/addons/skin.confluence/720p/DialogPVRGuideInfo.xml b/addons/skin.confluence/720p/DialogPVRGuideInfo.xml new file mode 100644 index 0000000..24cc03c --- /dev/null +++ b/addons/skin.confluence/720p/DialogPVRGuideInfo.xml @@ -0,0 +1,226 @@ + + 7 + + 1 + 20 + 30 + ![Window.IsVisible(FullscreenVideo) | Window.IsVisible(Visualisation)] + + dialogeffect + + + + background image + 0 + 0 + 730 + 660 + DialogBack2.png + Window.IsVisible(FullscreenVideo) | Window.IsVisible(Visualisation) + + + background image + 0 + 0 + 730 + 660 + DialogBack.png + ![Window.IsVisible(FullscreenVideo) | Window.IsVisible(Visualisation)] + + + Dialog Header image + 40 + 16 + 650 + 40 + dialogheader.png + + + header label + 40 + 20 + 650 + 30 + font13_title + + center + center + selected + black + + + Close Window button + 640 + 15 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 10 + 10 + 10 + 10 + system.getbool(input.enablemouse) + + + Title label + 40 + 70 + 650 + 30 + font13_title + + center + center + blue + black + + + + 40 + 120 + + Time description + 170 + 0 + 170 + 25 + right + center + font13 + blue + + + + Time value + 180 + 0 + 470 + 25 + left + center + font13 + white + + + + Duration + 170 + 35 + 170 + 25 + right + center + font13 + blue + + + + Duration value + 180 + 35 + 470 + 25 + left + center + font13 + white + + + + Channel Name + 170 + 70 + 170 + 25 + right + center + font13 + blue + + + + Channel Value + 180 + 70 + 470 + 25 + left + center + font13 + white + + + + Genre + 170 + 105 + 170 + 25 + right + center + font13 + blue + + + + Genre value + 180 + 105 + 470 + + left + font13 + true + + + + Plot value + 40 + 275 + 650 + 295 + font12 + justify + white + black + - + true + + + + 40 + 590 + 640 + 40 + 5 + center + horizontal + 9000 + 9000 + 60 + 60 + + Switch to Channel + ButtonInfoDialogsCommonValues + + + + Record + ButtonInfoDialogsCommonValues + + + + OK + ButtonInfoDialogsCommonValues + + + + + + SideBladeRight + + \ No newline at end of file diff --git a/addons/skin.confluence/720p/DialogPVRGuideOSD.xml b/addons/skin.confluence/720p/DialogPVRGuideOSD.xml new file mode 100644 index 0000000..8cd50ea --- /dev/null +++ b/addons/skin.confluence/720p/DialogPVRGuideOSD.xml @@ -0,0 +1,253 @@ + + 11 + + 1 + 780 + 30 + + dialogeffect + + + + background image + 0 + 0 + 480 + 660 + DialogBack2.png + + + Close Window button + 390 + 15 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 2 + 2 + 2 + 2 + system.getbool(input.enablemouse) + + + Dialog Header image + 40 + 16 + 400 + 40 + dialogheader.png + + + header label + 40 + 16 + 430 + 40 + font12_title + + center + center + blue + black + + + Selected item's date + 40 + 60 + 430 + 30 + font11 + grey2 + + center + center + + + 30 + 100 + 410 + 490 + 60 + 60 + 11 + 11 + list + 60 + 200 + + + 0 + 0 + 410 + 30 + button-nofocus.png + VisibleFadeEffect + + + 10 + 0 + 100 + 30 + font13 + grey2 + selected + left + center + + + + 120 + 5 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 120 + 5 + 20 + 20 + PVR-HasTimer.png + ListItem.HasTimer + !ListItem.IsRecording + + + 400 + 0 + 300 + 30 + font12 + grey2 + selected + right + center + + ![ListItem.IsRecording | ListItem.HasTimer] + + + 400 + 0 + 250 + 30 + font12 + grey2 + selected + right + center + + ListItem.IsRecording | ListItem.HasTimer + + + + + 0 + 0 + 410 + 30 + button-nofocus.png + !Control.HasFocus(11) + VisibleFadeEffect + + + 0 + 0 + 410 + 30 + button-focus2.png + Control.HasFocus(11) + VisibleFadeEffect + + + 10 + 0 + 100 + 30 + font13 + grey2 + selected + left + center + + + + 120 + 5 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 120 + 5 + 20 + 20 + PVR-HasTimer.png + ListItem.HasTimer + !ListItem.IsRecording + + + 400 + 0 + 300 + 30 + font12 + grey2 + selected + right + center + + ![ListItem.IsRecording | ListItem.HasTimer] + + + 400 + 0 + 250 + 30 + font12 + grey2 + selected + right + center + + ListItem.IsRecording | ListItem.HasTimer + + + + + 440 + 100 + 25 + 490 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 11 + 11 + 61 + 61 + false + vertical + + + Page Count Label + 450 + 610 + 400 + 20 + font12 + grey + false + right + center + + Window_OpenClose_Animation + + + + diff --git a/addons/skin.confluence/720p/DialogPVRGuideSearch.xml b/addons/skin.confluence/720p/DialogPVRGuideSearch.xml new file mode 100644 index 0000000..9eda477 --- /dev/null +++ b/addons/skin.confluence/720p/DialogPVRGuideSearch.xml @@ -0,0 +1,456 @@ + + 9 + + 1 + 210 + 65 + + dialogeffect + + + background image + 0 + 0 + 865 + 605 + DialogBack.png + + + Dialog Header image + 40 + 16 + 785 + 40 + dialogheader.png + + + header label + 40 + 20 + 785 + 30 + font13_title + + center + center + selected + black + !pvr.IsPlayingRadio + + + Close Window button + 775 + 15 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 3 + 3 + 3 + 3 + system.getbool(input.enablemouse) + + + Search string + 30 + 60 + 320 + 40 + font12caps + + left + center + blue + black + + + 30 + 100 + 800 + 50 + stretch + KeyboardEditArea.png + + + Search string + 35 + 105 + 790 + 40 + font13 + white + black + - + - + left + 9 + 9 + 26 + 10 + + + Search help + 30 + 155 + 800 + 70 + left + font12 + grey2 + + + + 30 + 230 + + Include Description + 0 + 0 + 35 + 400 + font12 + white + white + black + button-focus2.png + button-nofocus.png + left + center + + 12 + 12 + 9 + 11 + + + Case Sensitive + 0 + 35 + 35 + 400 + font12 + white + white + black + button-focus2.png + button-nofocus.png + left + center + + 13 + 13 + 10 + 14 + + + Start Date + 0 + 70 + 400 + 35 + font12 + white + white + black + button-focus2.png + button-nofocus.png + + 16 + 16 + 11 + 15 + + + Stop Date + 0 + 105 + 400 + 35 + font12 + white + white + black + button-focus2.png + button-nofocus.png + + 17 + 17 + 14 + 18 + + + Genre + 0 + 140 + 400 + 35 + font12 + button-focus2.png + button-nofocus.png + + 19 + 19 + 15 + 20 + + + Include unknown Genres + 0 + 175 + 35 + 400 + font12 + white + white + black + left + center + button-focus2.png + button-nofocus.png + no + + 21 + 21 + 18 + 22 + + + FTA only + 0 + 210 + 35 + 400 + font12 + white + white + black + left + center + button-focus2.png + button-nofocus.png + no + + 23 + 23 + 20 + 24 + + + Ignore Timers + 0 + 245 + 35 + 400 + font12 + white + white + black + left + center + button-focus2.png + button-nofocus.png + no + + 27 + 27 + 22 + 26 + + + + 440 + 230 + + Min Duration + 0 + 0 + 400 + 35 + font12 + button-focus2.png + button-nofocus.png + + 10 + 10 + 9 + 13 + + + Max Duration + 0 + 35 + 400 + 35 + font12 + button-focus2.png + button-nofocus.png + + 11 + 11 + 12 + 16 + + + Start time + 0 + 70 + 400 + 35 + font12 + white + white + black + button-focus2.png + button-nofocus.png + + 14 + 14 + 13 + 17 + + + Stop time + 0 + 105 + 400 + 35 + font12 + white + white + black + button-focus2.png + button-nofocus.png + + 15 + 15 + 16 + 19 + + + avoid repeats + 0 + 140 + 400 + 35 + font12 + white + white + black + left + center + button-focus2.png + button-nofocus.png + no + + 18 + 18 + 17 + 21 + + + Groups + 0 + 175 + 400 + 35 + font12 + button-focus2.png + button-nofocus.png + + 20 + 20 + 19 + 23 + + + Channels + 0 + 210 + 400 + 35 + font12 + button-focus2.png + button-nofocus.png + + 22 + 22 + 21 + 27 + + + Ignore Recordings + 0 + 245 + 35 + 400 + font12 + white + white + black + left + center + button-focus2.png + button-nofocus.png + no + + 24 + 24 + 23 + 26 + + + + 540 + 125 + + Defaults Button + 0 + 0 + 200 + 40 + center + center + font12_title + + 26 + 25 + 24 + 9 + + + Cancel Button + 210 + 0 + 200 + 40 + center + center + font12_title + + 28 + 26 + 27 + 9 + + + Search Button + 420 + 0 + 200 + 40 + center + center + font12_title + + 25 + 28 + 27 + 9 + + + + \ No newline at end of file diff --git a/addons/skin.confluence/720p/DialogPVRRecordingInfo.xml b/addons/skin.confluence/720p/DialogPVRRecordingInfo.xml new file mode 100644 index 0000000..83c3d6b --- /dev/null +++ b/addons/skin.confluence/720p/DialogPVRRecordingInfo.xml @@ -0,0 +1,267 @@ + + 10 + + 1 + 275 + 30 + + dialogeffect + + + background image + 0 + 0 + 730 + 660 + DialogBack2.png + Window.IsVisible(FullscreenVideo) | Window.IsVisible(Visualisation) + + + background image + 0 + 0 + 730 + 660 + DialogBack.png + ![Window.IsVisible(FullscreenVideo) | Window.IsVisible(Visualisation)] + + + Dialog Header image + 40 + 16 + 650 + 40 + dialogheader.png + + + header label + 40 + 20 + 650 + 30 + font13_title + + center + center + selected + black + + + Close Window button + 640 + 15 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 10 + 10 + 10 + 10 + system.getbool(input.enablemouse) + + + Title label + 40 + 70 + 650 + 30 + font13_title + + center + center + blue + black + + + 40 + 140 + + Start Date + 170 + 0 + 160 + 25 + right + center + font13 + blue + + + + Start date value + 180 + 0 + 470 + 25 + left + center + font13 + white + + + + Start time + 170 + 35 + 160 + 25 + right + center + font13 + blue + + + + Start Time value + 180 + 35 + 470 + 25 + left + center + font13 + white + + + + Channel Name + 170 + 70 + 160 + 25 + right + center + font13 + blue + + + + Channel Value + 180 + 70 + 470 + 25 + left + center + font13 + white + + + + Duration + 170 + 105 + 160 + 25 + right + center + font13 + blue + + + + Duration value + 180 + 105 + 470 + + left + font13 + true + + + Genre + 170 + 140 + 160 + 25 + right + center + font13 + blue + + + + Genre value + 180 + 140 + 470 + + left + font13 + true + + + Subtitle value + 40 + 185 + 650 + + center + font13 + blue + true + !IsEmpty(ListItem.PlotOutline) + + + + 610 + 370 + 400 + 30 + font12 + grey + black + true + right + center + + + + Next page button + 620 + 375 + page + - + 60 + 60 + 9000 + 9000 + - + true + + + PLOT + 40 + 400 + 650 + 180 + font12 + justify + 60 + + + + 40 + 590 + 640 + 40 + 5 + center + horizontal + 9000 + 9000 + 60 + 60 + + OK + ButtonInfoDialogsCommonValues + + + + + \ No newline at end of file diff --git a/addons/skin.confluence/720p/DialogPVRTimerSettings.xml b/addons/skin.confluence/720p/DialogPVRTimerSettings.xml new file mode 100644 index 0000000..219ac5c --- /dev/null +++ b/addons/skin.confluence/720p/DialogPVRTimerSettings.xml @@ -0,0 +1,155 @@ + + 29 + + 1 + 275 + 30 + + dialogeffect + + + background image + 0 + 0 + 730 + 660 + DialogBack.png + + + Dialog Header image + 40 + 16 + 650 + 40 + dialogheader.png + + + header label + 40 + 20 + 650 + 30 + font13_title + + center + center + selected + black + + + Close Window button + 640 + 15 + 64 + 32 + + - + PreviousMenu + DialogCloseButton-focus.png + DialogCloseButton.png + 10 + 10 + 10 + 10 + system.getbool(input.enablemouse) + + + control area + 30 + 70 + 670 + 510 + 5 + 9001 + 9001 + 9001 + 9001 + + + 160 + 590 + + OK Button + 0 + 0 + 200 + 40 + center + center + font12_title + + 29 + 29 + 5 + 5 + + + Cancel Button + 210 + 0 + 200 + 40 + center + center + font12_title + + 28 + 28 + 5 + 5 + + + + Default Button + 40 + font13 + grey2 + white + button-focus2.png + button-nofocus.png + + + Default RadioButton + 40 + font13 + grey2 + white + button-focus2.png + button-nofocus.png + + + Default spincontrolex + 40 + grey2 + white + button-focus2.png + button-nofocus.png + font13 + center + yes + + + Default Slider + 40 + button-focus2.png + button-nofocus.png + font13 + grey2 + white + + + Default Seperator + 2 + separator2.png + + + Default Edit + 40 + font13 + grey2 + white + button-focus2.png + button-nofocus.png + + + \ No newline at end of file diff --git a/addons/skin.confluence/720p/Home.xml b/addons/skin.confluence/720p/Home.xml index ee9f44e..72267d3 100644 --- a/addons/skin.confluence/720p/Home.xml +++ b/addons/skin.confluence/720p/Home.xml @@ -111,6 +111,150 @@ black + + + 490r + 40 + Container(9000).HasFocus(12) + [PVR.IsRecording | PVR.HasNonRecordingTimer] + VisibleFadeEffect + Window_OpenClose_Animation + conditional + + conditional + PVR.HasNonRecordingTimer + + 0 + -5 + 490 + 90 + gradient.png + + + 400 + 0 + 80 + 80 + keep + $INFO[PVR.NextRecordingChannelIcon] + ThumbBorder.png + 4 + + + 365 + 5 + 25 + 25 + keep + PVR-HasTimer.png + + + Next Timer Header label + 355 + 5 + 25 + 400 + + right + center + font12_title + blue + black + + + NextRecordingDateTime + 390 + 30 + 25 + 400 + + right + center + font12 + true + black + + + NextRecordingTitle Channel + 390 + 50 + 25 + 800 + + right + center + font12_title + black + true + + + + PVR.IsRecording + + 0 + -5 + 490 + 90 + gradient.png + + + 400 + 0 + 80 + 80 + keep + $INFO[PVR.NowRecordingChannelIcon] + ThumbBorder.png + 4 + + + 360 + 5 + 30 + 25 + keep + PVR-IsRecording.png + + + Is Recording Header label + 350 + 5 + 25 + 400 + + right + center + font12_title + blue + black + + + NextRecordingDateTime + 390 + 30 + 25 + 400 + + right + center + font12 + true + black + + + NextRecordingTitle Channel + 390 + 50 + 30 + 800 + + right + center + font12_title + black + true + + + 0 @@ -119,7 +263,47 @@ VisibleFadeEffect Window_OpenClose_Animation - !VideoPlayer.Content(Movies) + !VideoPlayer.Content(Episodes) + !VideoPlayer.Content(Movies) + !VideoPlayer.Content(Episodes) + !VideoPlayer.Content(LiveTV) + + Cover image + 20 + 45 + 150 + 300 + keep + $INFO[VideoPlayer.Cover] + ThumbBorder.png + 5 + + + Title label + 190 + 285 + 30 + 1000 + + left + center + font13_title + white + black + + + Time Label + 190 + 310 + 30 + 300 + + left + center + font12 + white + black + + + + VideoPlayer.Content(LiveTV) Cover image 20 @@ -132,6 +316,19 @@ 5 + Channel label + 190 + 265 + 25 + 660 + + left + center + font12 + white + black + + Title label 190 285 @@ -304,8 +501,10 @@ 35 CCFFFFFF HomeSubEnd.png + Conditional + !VideoPlayer.Content(LiveTV) 35 9003 9000 @@ -408,6 +607,129 @@ XBMC.PlayerControl(Next) + + VideoPlayer.Content(LiveTV) + 0 + 9003 + 9000 + 603 + + Background image + 0 + 0 + 245 + 35 + HomeSubNF.png + CCFFFFFF + + + 10 + 2 + 30 + 30 + + OSDChannelUPFO.png + OSDChannelUPNF.png + 607 + 602 + 9003 + 9000 + XBMC.PlayerControl(Previous) + + + 40 + 2 + 30 + 30 + + OSDChannelDownFO.png + OSDChannelDownNF.png + 601 + 603 + 9003 + 9000 + XBMC.PlayerControl(Next) + + + 70 + 2 + 30 + 30 + + OSDStopFO.png + OSDStopNF.png + 602 + 604 + 9003 + 9000 + down + XBMC.PlayerControl(Stop) + + + 100 + 2 + 30 + 30 + + OSDRecordOffFO.png + OSDRecordOffNF.png + 603 + 605 + 9003 + 9000 + XBMC.PlayerControl(record) + + + + 130 + 2 + 30 + 30 + + OSDRewindFO.png + OSDRewindNF.png + 604 + 608 + 9003 + 9000 + 50 + XBMC.PlayerControl(Rewind) + + + 190 + 2 + 30 + 30 + + OSDForwardFO.png + OSDForwardNF.png + 608 + 600 + 9003 + 9000 + 50 + XBMC.PlayerControl(Forward) + + + 160 + 2 + 30 + 30 + + OSDPauseFO.png + OSDPauseNF.png + Player.Paused | Player.Forwarding | Player.Rewinding + OSDPlayFO.png + OSDPlayNF.png + 605 + 606 + 9003 + 9000 + 50 + XBMC.PlayerControl(Play) + + + CCFFFFFF Go to fullscreen Playback @@ -494,6 +816,13 @@ HomeSubMenuCommonValues + 9014 + 9014 + Container(9000).HasFocus(12) + HomeSubMenuLiveTV + + + HomeSubMenuCommonValues 9013 9013 Container(9000).HasFocus(4) @@ -598,6 +927,13 @@ $INFO[Skin.String(Home_Custom_Back_Pictures_Folder)] !Skin.HasSetting(HomeMenuNoPicturesButton) + + + ActivateWindow(PVR) + special://skin/backgrounds/tv.jpg + $INFO[Skin.String(Home_Custom_Back_TV_Folder)] + System.GetBool(pvrmanager.enabled) + ActivateWindow(Videos) @@ -962,12 +1298,31 @@ ActivateWindow(ShutdownMenu) home-power-FO.png home-power.png - 21 + 22 21 + 21 + 21 + !System.IsInhibit + + + Power push button + 55 + 15 + 43 + 43 + + - + - + ActivateWindow(ShutdownMenu) + home-power-inhibit-FO.png + home-power-inhibit.png + 20 + 22 9002 9003 + System.IsInhibit - + Favourites push button 10 15 @@ -979,7 +1334,7 @@ ActivateWindow(Favourites) home-favourites-FO.png home-favourites.png - 20 + 21 20 9002 9003 diff --git a/addons/skin.confluence/720p/IncludesBackgroundBuilding.xml b/addons/skin.confluence/720p/IncludesBackgroundBuilding.xml index a1122d0..c0d9e22 100644 --- a/addons/skin.confluence/720p/IncludesBackgroundBuilding.xml +++ b/addons/skin.confluence/720p/IncludesBackgroundBuilding.xml @@ -47,6 +47,29 @@ Window_OpenClose_Animation + + + 0 + 0 + 1280 + 720 + $INFO[Skin.String(Home_Custom_Back_TV_Folder)] + 10000 + true + 1000 + + + 0 + 0 + 1280 + 720 + $INFO[ListItem.Property(Fanart_Image)] + backgroundfade + FanartCrossfadeTime + !Skin.HasSetting(HideBackGroundFanart) + !IsEmpty(ListItem.Property(Fanart_Image)) + Window_OpenClose_Animation + + 0 @@ -360,4 +383,101 @@ + + + 0 + 100r + 1280 + 100 + floor.png + WindowOpen + WindowClose + + + Window_OpenClose_Animation + + VisibleFadeEffect + Control.IsVisible(10) | Control.IsVisible(14) | Control.IsVisible(15) | Control.IsVisible(16) | Control.IsVisible(17) + + 55 + 60 + 1170 + 600 + ContentPanel.png + + + 55 + 652 + 1170 + 64 + ContentPanelMirror.png + + + + VisibleFadeEffect + Control.IsVisible(11) | Control.IsVisible(12) + + 50 + 60 + 450 + 600 + ContentPanel.png + + + 50 + 652 + 450 + 64 + ContentPanelMirror.png + + + 510 + 60 + 730 + 600 + ContentPanel.png + + + 510 + 652 + 730 + 64 + ContentPanelMirror.png + + + + VisibleFadeEffect + Control.IsVisible(13) + + 50 + 60 + 840 + 600 + ContentPanel.png + + + 50 + 652 + 840 + 64 + ContentPanelMirror.png + + + 900 + 60 + 330 + 600 + ContentPanel.png + + + 900 + 652 + 330 + 64 + ContentPanelMirror.png + + + + + \ No newline at end of file diff --git a/addons/skin.confluence/720p/IncludesHomeMenuItems.xml b/addons/skin.confluence/720p/IncludesHomeMenuItems.xml index 1012367..ed15e17 100644 --- a/addons/skin.confluence/720p/IncludesHomeMenuItems.xml +++ b/addons/skin.confluence/720p/IncludesHomeMenuItems.xml @@ -223,16 +223,56 @@ - + 35 35 HomeSubEnd.png - + ButtonHomeSubCommonValues ActivateWindow(Pictures,Addons,return) + + 35 + 35 + HomeSubEnd.png + + + + + 35 + 35 + HomeSubEnd.png + + + ButtonHomeSubCommonValues + + ActivateWindow(PVR) + Setfocus(32) + Setfocus(11) + + + ButtonHomeSubCommonValues + + ActivateWindow(PVR) + Setfocus(33) + Setfocus(12) + + + ButtonHomeSubCommonValues + + ActivateWindow(PVR) + Setfocus(34) + Setfocus(13) + + + ButtonHomeSubCommonValues + + ActivateWindow(PVR) + Setfocus(35) + Setfocus(14) + 35 35 diff --git a/addons/skin.confluence/720p/MusicOSD.xml b/addons/skin.confluence/720p/MusicOSD.xml index 9171ff7..49fc84b 100644 --- a/addons/skin.confluence/720p/MusicOSD.xml +++ b/addons/skin.confluence/720p/MusicOSD.xml @@ -306,8 +306,8 @@ 45 - - OSDRecordFO.png - OSDRecordNF.png + OSDRecordOffFO.png + OSDRecordOffNF.png 703 600 1000 @@ -318,4 +318,4 @@ - \ No newline at end of file + diff --git a/addons/skin.confluence/720p/MyPVR.xml b/addons/skin.confluence/720p/MyPVR.xml new file mode 100644 index 0000000..32200a7 --- /dev/null +++ b/addons/skin.confluence/720p/MyPVR.xml @@ -0,0 +1,256 @@ + + 32 + no + + CommonTVBackground + + !Control.IsVisible(11) + !Control.IsVisible(12) + + 0 + 0 + 1280 + 720 + special://skin/backgrounds/media-overlay.png + Player.HasVideo + !Skin.HasSetting(ShowBackgroundVideo) + + + 0 + 0 + 1280 + 720 + Player.HasAudio + !Skin.HasSetting(ShowBackgroundVis) + + + 0 + 0 + 1280 + 720 + Player.HasVideo + !Skin.HasSetting(ShowBackgroundVideo) + + + ContentPanelBackgroundsPVR + + Small Media Window + 530 + 80 + Control.IsVisible(11) | Control.IsVisible(12) + VisibleFadeEffect + Window_OpenClose_Animation + + 0 + 0 + 690 + 400 + button-nofocus.png + + + 5 + 5 + 680 + 390 + $INFO[Skin.String(Home_Custom_Back_TV_Folder)] + VisibleFadeEffect + !Player.HasVideo + + + 5 + 5 + 680 + 390 + Player.HasVideo + WindowClose + + + 1 + 1 + 688 + 35 + black-back.png + DDFFFFFF + Player.HasVideo + + + Current Video label + 30 + 1 + 650 + 35 + font12 + grey2 + center + center + + Player.HasVideo + + + + + + Window_OpenClose_Animation + EPGTimelineView--> + LiveTVChannelView + LiveRadioChannelView + LiveTVRecordingsView + LiveTVTimersView + LiveTVGuideChannelView + LiveTVGuideNowNextView + LiveTVSearchView + + CommonNowPlaying + BehindDialogFadeOut + ScrollOffsetLabel + + + 0 + 0 + 1280 + 720 + black-back.png + Visible + Hidden + Window.IsActive(FileBrowser) | Window.IsActive(PVRGuideInfo) | Window.IsActive(PVRRecordingInfo) | Window.IsActive(PVRTimerSetting) | Window.IsActive(PVRGroupManager) | Window.IsActive(PVRGuideSearch) + + + + -250 + SideBladeLeft + + 0 + 110 + 250 + 600 + 9000 + 50 + 9000 + 9000 + 0 + + 250 + 35 + font12caps + + blue + center + center + + + TV Channels + 0 + 0 + 235 + ButtonCommonValues + + + + Radio Channels + 0 + 40 + 235 + ButtonCommonValues + + 12 + 12 + + + TV Guide + 0 + 80 + 235 + ButtonCommonValues + + + + Recordings + 0 + 120 + 235 + ButtonCommonValues + + + + Timers + 0 + 160 + 235 + ButtonCommonValues + + + + Search + 0 + 200 + 235 + ButtonCommonValues + + + CommonNowPlaying_Controls + + + + + 500 + 0 + !IsEmpty(Control.GetLabel(30)) + VisibleFadeEffect + WindowClose + WindowOpen + + 0 + 0 + 250 + 35 + header.png + + + WindowTitleCommons + 220 + + + + + 240 + 0 + WindowClose + WindowOpen + + 0 + 0 + 300 + 35 + header.png + + + WindowTitleCommons + 270 + + + + + 40 + 0 + WindowClose + WindowOpen + + 0 + 0 + 250 + 35 + header.png + + + WindowTitleCommons + 220 + + + + + WindowTitleHomeButton + Clock + + diff --git a/addons/skin.confluence/720p/PlayerControls.xml b/addons/skin.confluence/720p/PlayerControls.xml index 7f1899e..540872f 100644 --- a/addons/skin.confluence/720p/PlayerControls.xml +++ b/addons/skin.confluence/720p/PlayerControls.xml @@ -1,5 +1,5 @@ - 603 + 100 dialogeffect Player.HasMedia + Window.IsActive(PlayerControls) + !Window.IsActive(FullscreenVideo) + !Window.IsActive(Visualisation) @@ -18,6 +18,8 @@ 25 162 + 603 + !VideoPlayer.Content(LiveTV) 0 0 @@ -31,6 +33,7 @@ 300 200 XBMC.PlayerControl(Previous) + !VideoPlayer.Content(LiveTV) 40 @@ -45,6 +48,7 @@ 300 200 XBMC.PlayerControl(Rewind) + !VideoPlayer.Content(LiveTV) 80 @@ -62,6 +66,7 @@ 300 200 XBMC.PlayerControl(Play) + !VideoPlayer.Content(LiveTV) 120 @@ -77,6 +82,7 @@ 200 down XBMC.PlayerControl(Stop) + !VideoPlayer.Content(LiveTV) 160 @@ -91,6 +97,7 @@ 300 200 XBMC.PlayerControl(Forward) + !VideoPlayer.Content(LiveTV) 200 @@ -105,6 +112,7 @@ 300 200 XBMC.PlayerControl(Next) + !VideoPlayer.Content(LiveTV) 240 @@ -112,8 +120,8 @@ 40 40 - OSDRecordFO.png - OSDRecordNF.png + OSDRecordOffFO.png + OSDRecordOffNF.png 605 607 300 @@ -121,6 +129,7 @@ XBMC.PlayerControl(record) Player.CanRecord Conditional + !VideoPlayer.Content(LiveTV) 365 @@ -135,6 +144,7 @@ 608 100 100 + !VideoPlayer.Content(LiveTV) 365 @@ -144,6 +154,7 @@ OSDRepeatNF.png !Playlist.IsRepeat + !Playlist.IsRepeatOne !Control.HasFocus(607) + !VideoPlayer.Content(LiveTV) 365 @@ -153,6 +164,7 @@ OSDRepeatFO.png !Playlist.IsRepeat + !Playlist.IsRepeatOne Control.HasFocus(607) + !VideoPlayer.Content(LiveTV) 365 @@ -162,6 +174,7 @@ OSDRepeatOneNF.png Playlist.IsRepeatOne !Control.HasFocus(607) + !VideoPlayer.Content(LiveTV) 365 @@ -171,6 +184,7 @@ OSDRepeatOneFO.png Playlist.IsRepeatOne Control.HasFocus(607) + !VideoPlayer.Content(LiveTV) 365 @@ -180,6 +194,7 @@ OSDRepeatAllNF.png Playlist.IsRepeat !Control.HasFocus(607) + !VideoPlayer.Content(LiveTV) 365 @@ -189,6 +204,7 @@ OSDRepeatAllFO.png Playlist.IsRepeat Control.HasFocus(607) + !VideoPlayer.Content(LiveTV) 405 @@ -206,6 +222,130 @@ 600 100 100 + !VideoPlayer.Content(LiveTV) + + + + 25 + 162 + 700 + VideoPlayer.Content(LiveTV) + + 0 + 0 + 40 + 40 + + OSDRewindFO.png + OSDRewindNF.png + 706 + 702 + 300 + 200 + XBMC.PlayerControl(Rewind) + VideoPlayer.Content(LiveTV) + false + Conditional + + + 40 + 0 + 40 + 40 + + OSDStopFO.png + OSDStopNF.png + 701 + 703 + 300 + 200 + down + XBMC.PlayerControl(Stop) + VideoPlayer.Content(LiveTV) + + + 80 + 0 + 40 + 40 + + OSDPauseFO.png + OSDPauseNF.png + Player.Paused | Player.Forwarding | Player.Rewinding + OSDPlayFO.png + OSDPlayNF.png + 702 + 704 + 300 + 200 + XBMC.PlayerControl(Play) + VideoPlayer.Content(LiveTV) + false + Conditional + + + 120 + 0 + 40 + 40 + + OSDForwardFO.png + OSDForwardNF.png + 703 + 700 + 300 + 200 + XBMC.PlayerControl(Forward) + VideoPlayer.Content(LiveTV) + false + Conditional + + + 200 + 0 + 40 + 40 + + OSDChannelUPFO.png + OSDChannelUPNF.png + 704 + 705 + 300 + 200 + XBMC.PlayerControl(Previous) + VideoPlayer.Content(LiveTV) + + + 240 + 0 + 40 + 40 + + OSDChannelDownFO.png + OSDChannelDownNF.png + 700 + 706 + 300 + 200 + XBMC.PlayerControl(Next) + VideoPlayer.Content(LiveTV) + + + 280 + 0 + 40 + 40 + + OSDRecordOffFO.png + OSDRecordOffNF.png + 705 + 701 + 300 + 200 + XBMC.PlayerControl(record) + Player.CanRecord + Conditional + VideoPlayer.Content(LiveTV) @@ -229,4 +369,4 @@ SmallVideoInfo - \ No newline at end of file + diff --git a/addons/skin.confluence/720p/Settings.xml b/addons/skin.confluence/720p/Settings.xml index e55cf06..2a1ce69 100644 --- a/addons/skin.confluence/720p/Settings.xml +++ b/addons/skin.confluence/720p/Settings.xml @@ -129,42 +129,48 @@ special://skin/backgrounds/videos.jpg + + 31409 + ActivateWindow(PVRSettings) + special://skin/backgrounds/tv.jpg + + 31402 ActivateWindow(MusicSettings) special://skin/backgrounds/music.jpg - + 31403 ActivateWindow(PicturesSettings) special://skin/backgrounds/pictures.jpg - + 31404 ActivateWindow(WeatherSettings) special://skin/backgrounds/weather.jpg - + 31408 ActivateWindow(AddonBrowser) special://skin/backgrounds/addons.jpg - + 31405 ActivateWindow(NetworkSettings) special://skin/backgrounds/network.jpg - + 31406 ActivateWindow(SystemSettings) special://skin/backgrounds/system.jpg - + 31407 ActivateWindow(1111) diff --git a/addons/skin.confluence/720p/SettingsSystemInfo.xml b/addons/skin.confluence/720p/SettingsSystemInfo.xml index a90a9f0..c5834ea 100644 --- a/addons/skin.confluence/720p/SettingsSystemInfo.xml +++ b/addons/skin.confluence/720p/SettingsSystemInfo.xml @@ -147,6 +147,21 @@ false + + Button PVR + 60 + 241 + 0 + right + center + font13_title + grey2 + white + MenuItemFO.png + MenuItemNF.png + false + + 268 diff --git a/addons/skin.confluence/720p/VideoFullScreen.xml b/addons/skin.confluence/720p/VideoFullScreen.xml index e12ec81..703d424 100644 --- a/addons/skin.confluence/720p/VideoFullScreen.xml +++ b/addons/skin.confluence/720p/VideoFullScreen.xml @@ -3,7 +3,7 @@ - [Player.ShowInfo | Window.IsActive(VideoOSD)] + ![Window.IsVisible(123) | Window.IsVisible(124) | Window.IsVisible(125)] + [Player.ShowInfo | Window.IsActive(VideoOSD)] + ![Window.IsVisible(123) | Window.IsVisible(124) | Window.IsVisible(125) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide)] VisibleChange 0 @@ -24,7 +24,21 @@ white black - Player.ChapterCount + Player.ChapterCount + !VideoPlayer.Content(LiveTV) + + + Channel Group label + 30 + 5 + 1000 + 25 + left + center + font13 + white + black + + VideoPlayer.Content(LiveTV) Clock label @@ -81,11 +95,35 @@ 910 25 left + center font13 white black - conditional + ![VideoPlayer.Content(LiveTV) + Player.Recording] + conditional + + + 0 + 50 + 25 + keep + PVR-IsRecording.png + VideoPlayer.Content(LiveTV) + Player.Recording + + + Heading label + 50 + 0 + 860 + 25 + left + center + font13 + + white + black + VideoPlayer.Content(LiveTV) + Player.Recording Studio label @@ -126,6 +164,19 @@ black VideoPlayer.Content(MusicVideos) + + LiveTV Info label + 20 + 30 + 910 + 25 + left + font12 + + grey2 + black + VideoPlayer.Content(LiveTV) + 20 60 @@ -176,13 +227,28 @@ font12 grey true - !Window.IsVisible(VideoOSD) + !Window.IsVisible(VideoOSD) + !VideoPlayer.Content(LiveTV) + VisibleChange + + + 0 + 120 + 910 + 25 + + center + center + font12 + grey + true + !Window.IsVisible(VideoOSD) + VideoPlayer.Content(LiveTV) VisibleChange 330 85r + !VideoPlayer.Content(LiveTV) | [VideoPlayer.Content(LiveTV) + VideoPlayer.HasEpg] 0 0 @@ -233,7 +299,6 @@ 0 1280 140 - AAFFFFFF black-back.png @@ -270,5 +335,252 @@ + + 440 + 100 + 400 + 100 + font13caps + TV Channel Group Select Button + OverlayDialogBackground.png + 503 + 503 + 500 + 500 + VisibleFadeEffect + + + Player.ShowCodec + VideoPlayer.Content(LiveTV) + system.getbool(pvrplayback.signalquality) + 165 + + media info background image + 0 + 0 + 1280 + 220 + black-back.png + + + Header + 50 + 5 + 1200 + 25 + + left + center + font13_title + blue + + + Backend + 50 + 40 + 165 + 25 + + left + center + font12 + grey2 + + + Backend value + 220 + 40 + 1000 + 25 + + left + center + font12 + white + + + Device + 50 + 65 + 165 + 25 + + left + center + font12 + grey2 + + + Device value + 220 + 65 + 1000 + 25 + + left + center + font12 + white + + + Status + 50 + 90 + 165 + 25 + + left + center + font12 + grey2 + + + Status value + 220 + 90 + 1000 + 25 + + left + center + font12 + white + + + Signal + 50 + 115 + 165 + 25 + + left + center + font12 + grey2 + + + Progressbar + 220 + 122 + 910 + 14 + PVR.ActStreamProgrSignal + + + Signal value + 1200 + 115 + 180 + 25 + + left + center + font12 + white + + + SNR + 50 + 140 + 165 + 25 + + left + center + font12 + grey2 + + + Progressbar + 220 + 147 + 910 + 14 + - + PVR.ActStreamProgrSNR + + + SNR value + 1200 + 140 + 180 + 25 + + left + center + font12 + white + + + BER + 50 + 165 + 165 + 25 + + left + center + font12 + grey2 + + + BER value + 220 + 165 + 1000 + 25 + + left + center + font12 + white + + + UNC + 430 + 165 + 165 + 25 + + left + center + font12 + grey2 + + + UNC value + 600 + 165 + 1000 + 25 + + left + center + font12 + white + + + Encryption + 50 + 190 + 165 + 25 + + left + center + font12 + grey2 + + + Encryption value + 220 + 190 + 1000 + 25 + + left + center + font12 + white + + - \ No newline at end of file + diff --git a/addons/skin.confluence/720p/VideoOSD.xml b/addons/skin.confluence/720p/VideoOSD.xml index 3cb999a..fa55abe 100644 --- a/addons/skin.confluence/720p/VideoOSD.xml +++ b/addons/skin.confluence/720p/VideoOSD.xml @@ -1,5 +1,5 @@ - 602 + 100 dialogeffect 1 @@ -39,13 +39,16 @@ osd_slider_nibNF.png osd_slider_nib.png VisibleChange - ![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(VideoBookmarks)] + ![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(VideoBookmarks) | VideoPlayer.Content(LiveTV)] + 325 50r + 602 VisibleChange ![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(VideoBookmarks)] + !VideoPlayer.Content(LiveTV) 0 0 @@ -141,11 +144,181 @@ PlayerControl(Next) + + + + 190 + 50r + 601 + VisibleChange + ![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(VideoBookmarks) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide)] + VideoPlayer.Content(LiveTV) + + 0 + 0 + 45 + 45 + + - + OSDChannelUPFO.png + OSDChannelUPNF.png + 704 + 601 + 1000 + 1000 + PlayerControl(Previous) + + + 45 + 0 + 45 + 45 + + - + OSDChannelDownFO.png + OSDChannelDownNF.png + 600 + 607 + 1000 + 1000 + PlayerControl(Next) + + + + 90 + 0 + 45 + 45 + + OSDRewindFO.png + OSDRewindNF.png + 601 + 608 + 1000 + 1000 + XBMC.PlayerControl(Rewind) + + + 180 + 0 + 45 + 45 + + OSDForwardFO.png + OSDForwardNF.png + 608 + 602 + 1000 + 1000 + XBMC.PlayerControl(Forward) + + + 135 + 0 + 45 + 45 + + OSDPauseFO.png + OSDPauseNF.png + Player.Paused | Player.Forwarding | Player.Rewinding + OSDPlayFO.png + OSDPlayNF.png + 606 + 609 + 1000 + 1000 + XBMC.PlayerControl(Play) + + + + 225 + 0 + 45 + 45 + + 208 + - + OSDPauseFO.png + OSDPauseNF.png + Player.Paused | Player.Forwarding | Player.Rewinding + OSDPlayFO.png + OSDPlayNF.png + 609 + 603 + 1000 + 1000 + PlayerControl(Play) + False + + + 270 + 0 + 45 + 45 + + 208 + - + OSDStopFO.png + OSDStopNF.png + 602 + 604 + 1000 + 1000 + PlayerControl(Stop) + + + 315 + 0 + 45 + 45 + + - + OSDChannelListFO.png + OSDChannelListNF.png + 603 + 605 + 1000 + 1000 + ActivateWindow(PVROSDChannels) + Dialog.Close(VideoOSD) + + + 360 + 0 + 45 + 45 + + - + OSDepgFO.png + OSDepgNF.png + 604 + 701 + 1000 + 1000 + ActivateWindow(PVROSDGuide) + Dialog.Close(VideoOSD) + + + 425 + 0 + 450 + 45 + + center + center + font12 + grey + false + + + + 250r 50r VisibleChange ![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(VideoBookmarks)] + !VideoPlayer.Content(LiveTV) 0 0 @@ -231,5 +404,80 @@ Conditional + + + + 200r + 50r + VisibleChange + ![Window.IsVisible(SliderDialog) | Window.IsVisible(OSDVideoSettings) | Window.IsVisible(OSDAudioSettings) | Window.IsVisible(VideoBookmarks) | Window.IsVisible(PVROSDChannels) | Window.IsVisible(PVROSDGuide)] + VideoPlayer.Content(LiveTV) + + 0 + 0 + 45 + 45 + + - + OSDTeleTextFO.png + OSDTeleTextNF.png + 605 + 702 + 1000 + 1000 + ActivateWindow(Teletext) + + + 45 + 0 + 45 + 45 + + - + OSDVideoFO.png + OSDVideoNF.png + 701 + 703 + 1000 + 1000 + ActivateWindow(OSDVideoSettings) + + + 90 + 0 + 45 + 45 + + - + OSDAudioFO.png + OSDAudioNF.png + 702 + 704 + 1000 + 1000 + ActivateWindow(OSDAudioSettings) + + + 135 + 0 + 45 + 45 + + 208 + - + OSDRecordOffFO.png + OSDRecordOffNF.png + Player.Recording + OSDRecordOnFO.png + OSDRecordOnNF.png + 703 + 600 + 1000 + 1000 + PlayerControl(Record) + Player.CanRecord + Conditional + + - \ No newline at end of file + diff --git a/addons/skin.confluence/720p/ViewsPVR.xml b/addons/skin.confluence/720p/ViewsPVR.xml new file mode 100644 index 0000000..db97def --- /dev/null +++ b/addons/skin.confluence/720p/ViewsPVR.xml @@ -0,0 +1,2378 @@ + + + + TV Channels group + Control.IsVisible(11) + VisibleFadeEffect + + 530 + 490 + + 0 + 0 + 690 + 20 + font13 + white + black + true + center + center + + + + 80 + 22 + 80 + 20 + right + center + font10_title + blue + Container(11).ListItem.HasEpg + + + + Progressbar + 85 + 30 + 510 + 8 + Container(11).ListItem.HasEpg + Container(11).ListItem.Progress + + + 600 + 22 + 80 + 20 + left + center + font10_title + blue + Container(11).ListItem.HasEpg + + + + Plot Value for TVShow + 0 + 43 + 690 + 80 + font12 + justify + white + black + - + + true + + + 690 + 140 + 690 + 20 + font12 + grey2 + right + center + false + + + + + 70 + 85 + 390 + 541 + 32 + 70 + 11 + 11 + list + 70 + 200 + + + 0 + 0 + 390 + 61 + MenuItemNF.png + VisibleFadeEffect + + + 5 + -4 + 40 + 35 + font12 + left + center + grey + grey + ListItem.ChannelNumber + + + 50 + 0 + 270 + 25 + font13 + white + selected + left + center + + + + 50 + 25 + 330 + 20 + font12 + grey + grey + left + center + + IsEmpty(Listitem.Icon) + + + 50 + 25 + 280 + 20 + font12 + grey + grey + left + center + + !IsEmpty(Listitem.Icon) + + + Progressbar + 50 + 48 + 280 + 6 + 88FFFFFF + ListItem.HasEpg + ListItem.Progress + + + 340 + 4 + 50 + 50 + $INFO[ListItem.Icon] + + + 5 + 37 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + + + 0 + 0 + 390 + 61 + MenuItemNF.png + !Control.HasFocus(11) + VisibleFadeEffect + + + 0 + 0 + 390 + 61 + MenuItemFO.png + Control.HasFocus(11) + VisibleFadeEffect + + + 5 + -4 + 40 + 35 + font12 + left + center + grey + grey + ListItem.ChannelNumber + + + 50 + 0 + 270 + 25 + font13 + white + selected + left + center + + + + 50 + 25 + 330 + 20 + font12 + grey + grey + left + center + + IsEmpty(Listitem.Icon) + + + 50 + 25 + 280 + 20 + font12 + grey + grey + left + center + + !IsEmpty(Listitem.Icon) + + + Progressbar + 50 + 48 + 280 + 6 + 88FFFFFF + ListItem.HasEpg + ListItem.Progress + + + 340 + 4 + 50 + 50 + $INFO[ListItem.Icon] + + + 5 + 37 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + + + 465 + 85 + 25 + 540 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 11 + 32 + false + vertical + + + Page Count Label + 40r + 53r + 500 + 20 + font12 + grey + false + right + center + + Window_OpenClose_Animation + + + + + + + Radio Channels group + Control.IsVisible(12) + VisibleFadeEffect + + 530 + 490 + + 0 + 0 + 690 + 20 + font13 + white + black + true + center + center + + + + 80 + 22 + 80 + 20 + right + center + font10_title + blue + + + + Progressbar + 85 + 30 + 510 + 8 + Container(12).ListItem.Progress + + + 600 + 22 + 80 + 20 + left + center + font10_title + blue + + + + Plot Value for TVShow + 0 + 43 + 690 + 80 + font12 + justify + white + black + - + + true + + + 690 + 140 + 690 + 20 + font12 + grey2 + right + center + false + + + + + 70 + 85 + 390 + 541 + 33 + 71 + 12 + 12 + list + 71 + 200 + + + 0 + 0 + 390 + 61 + MenuItemNF.png + VisibleFadeEffect + + + 5 + -4 + 40 + 35 + font12 + left + center + grey + grey + ListItem.ChannelNumber + + + 50 + 0 + 270 + 25 + font13 + white + selected + left + center + + + + 50 + 25 + 330 + 20 + font12 + grey + grey + left + center + + IsEmpty(Listitem.Icon) + + + 50 + 25 + 280 + 20 + font12 + grey + grey + left + center + + !IsEmpty(Listitem.Icon) + + + Progressbar + 50 + 48 + 280 + 6 + 88FFFFFF + ListItem.Progress + + + 340 + 4 + 50 + 50 + $INFO[ListItem.Icon] + + + 5 + 37 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + + + 0 + 0 + 390 + 61 + MenuItemNF.png + !Control.HasFocus(12) + VisibleFadeEffect + + + 0 + 0 + 390 + 61 + MenuItemFO.png + Control.HasFocus(12) + VisibleFadeEffect + + + 5 + -4 + 40 + 35 + font12 + left + center + grey + grey + ListItem.ChannelNumber + + + 50 + 0 + 270 + 25 + font13 + white + selected + left + center + + + + 50 + 25 + 330 + 20 + font12 + grey + grey + left + center + + IsEmpty(Listitem.Icon) + + + 50 + 25 + 280 + 20 + font12 + grey + grey + left + center + + !IsEmpty(Listitem.Icon) + + + Progressbar + 50 + 48 + 280 + 6 + 88FFFFFF + ListItem.Progress + + + 340 + 4 + 50 + 50 + $INFO[ListItem.Icon] + + + 5 + 37 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + + + 465 + 85 + 25 + 540 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 12 + 33 + false + vertical + + + Page Count Label + 40r + 53r + 500 + 20 + font12 + grey + false + right + center + + Window_OpenClose_Animation + + + + + + + Recordings group + Control.IsVisible(13) + VisibleFadeEffect + + 70 + 75 + 760 + 561 + 34 + 72 + 13 + 13 + list + 72 + 200 + + + 0 + 0 + 760 + 41 + MenuItemNF.png + VisibleFadeEffect + + + 10 + 5 + 30 + 30 + $INFO[ListItem.Icon] + + + 50 + 0 + 605 + 40 + font13 + grey2 + selected + left + center + + + + 725 + 0 + 500 + 40 + font12 + grey2 + selected + right + center + + + + 730 + 14 + 20 + 16 + $INFO[ListItem.Overlay] + + + + + 0 + 0 + 760 + 41 + MenuItemFO.png + Control.HasFocus(13) + VisibleFadeEffect + + + 0 + 0 + 760 + 41 + MenuItemNF.png + VisibleFadeEffect + !Control.HasFocus(13) + + + 560 + 5 + 200 + 31 + MediaItemDetailBG.png + Control.HasFocus(13) + !IsEmpty(ListItem.Date) + + + 10 + 5 + 30 + 30 + $INFO[ListItem.Icon] + + + 50 + 0 + 630 + 40 + font13 + white + selected + left + center + + + + 725 + 0 + 500 + 40 + font12 + grey2 + selected + right + center + + + + 730 + 14 + 20 + 16 + $INFO[ListItem.Overlay] + + + + + 850 + 78 + 25 + 560 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 13 + 34 + false + vertical + + + Page Count Label + 40r + 53r + 500 + 20 + font12 + grey + false + right + center + + Window_OpenClose_Animation + + + 910 + 80 + + 10 + 0 + 290 + 230 + keep + IconCrossfadeTime + $INFO[Container(13).ListItem.Icon] + ThumbShadow.png + 8 + + + 10 + 230 + 290 + 25 + + center + center + font13 + blue + black + false + 1000 + + + Description Value for TV Show + 10 + 270 + 290 + 280 + font12 + justify + white + + Skin.HasSetting(AutoScroll) + + + + + + + + TV Guide Timeline + Control.IsVisible(10) + VisibleFadeEffect + + EPG Grid + 80 + 81 + 1120 + 555 + 10 + 350 + 40 + 6 + 31 + 31 + 10 + 10 + + + 40 + 29 + 0 + 0 + button-nofocus.png + + + 10 + 0 + 34 + 29 + font12 + center + selected + left + + + + + UnFocus + + 0 + 0 + 270 + 52 + button-nofocus.png + + + 5 + 5 + 40 + 35 + font12 + left + center + grey + grey + ListItem.ChannelNumber + + + 45 + 4 + 45 + 44 + $INFO[ListItem.Icon] + + + 94 + 0 + 160 + 52 + special12 + center + selected + left + + + + + OnFocus + + 0 + 0 + 270 + 52 + button-focus.png + + + 5 + 5 + 40 + 35 + font12 + left + center + grey + grey + ListItem.ChannelNumber + + + 45 + 4 + 45 + 44 + $INFO[ListItem.Icon] + + + 94 + 0 + 160 + 52 + special12 + center + selected + left + + + + + + 40 + 52 + 0 + 0 + stretch + epg-genres/$INFO[ListItem.Property(GenreType)].png + + + 6 + 3 + 30 + 25 + font12 + center + selected + left + ListItem.Label + + + 5 + 28 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 5 + 28 + 20 + 20 + PVR-HasTimer.png + ListItem.HasTimer + !ListItem.IsRecording + + + + + 40 + 52 + 0 + 0 + folder-focus.png + + + 40 + 52 + 0 + 0 + stretch + epg-genres/$INFO[ListItem.Property(GenreType)].png + + + 6 + 3 + 30 + 25 + font12 + center + selected + left + ListItem.Label + + + 5 + 28 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 5 + 28 + 20 + 20 + PVR-HasTimer.png + ListItem.HasTimer + !ListItem.IsRecording + + + + + + + + + Timers group + Control.IsVisible(14) + VisibleFadeEffect + + 80 + 60 + + Channel header label + 0 + 20 + 220 + 20 + font13_title + white + black + center + center + + + + Title header label + 220 + 20 + 300 + 20 + font13_title + white + black + center + center + + + + Schedule Time header label + 580 + 20 + 300 + 20 + font13_title + white + black + center + center + + + + Status header label + 940 + 20 + 150 + 20 + font13_title + white + black + center + center + + + + separator image + 0 + 50 + 1100 + 1 + 88FFFFFF + separator2.png + + + 0 + 55 + 1100 + 480 + 14 + 14 + 35 + 73 + 73 + 200 + + + 0 + 0 + 1100 + 41 + MenuItemNF.png + + + 220 + 0 + 300 + 40 + 33FFFFFF + StackFO.png + + + 940 + 0 + 155 + 40 + 33FFFFFF + StackFO.png + + + 0 + 8 + 50 + 26 + !IsEmpty(ListItem.Date) + $INFO[ListItem.Icon] + + + 50 + 0 + 150 + 40 + font12 + left + center + selected + ListItem.ChannelName + + + 370 + 0 + 290 + 40 + font12 + center + center + selected + ListItem.Label + + + 730 + 0 + 400 + 40 + font12 + center + center + selected + ListItem.Date + + + 1018 + 0 + 170 + 40 + font12 + center + center + selected + ListItem.Comment + + + + + 0 + 0 + 1100 + 41 + MenuItemNF.png + + + 220 + 0 + 300 + 40 + 33FFFFFF + StackFO.png + !Control.HasFocus(14) + + + 980 + 0 + 120 + 40 + 33FFFFFF + StackFO.png + !Control.HasFocus(14) + + + 220 + 0 + 300 + 40 + 88FFFFFF + StackFO.png + Control.HasFocus(14) + + + 940 + 0 + 155 + 40 + 88FFFFFF + StackFO.png + Control.HasFocus(14) + + + 0 + 8 + 50 + 26 + !IsEmpty(ListItem.Date) + $INFO[ListItem.Icon] + + + 50 + 0 + 150 + 40 + font12 + left + center + selected + ListItem.ChannelName + + + 370 + 0 + 290 + 40 + font12 + center + center + selected + ListItem.Label + + + 730 + 0 + 400 + 40 + font12 + center + center + selected + ListItem.Date + + + 1018 + 0 + 150 + 40 + font12 + center + center + selected + ListItem.Comment + + + + + 1105 + 50 + 25 + 480 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 11 + 35 + false + vertical + + + separator image + 55 + 540 + 1010 + 1 + 88FFFFFF + separator2.png + + + Next timer date + 55 + 545 + 1010 + 30 + font13 + center + center + true + white + + PVR.HasTimer + + + + Page Count Label + 40r + 53r + 500 + 20 + font12 + grey + false + right + center + + Window_OpenClose_Animation + + + + + + + TV Search group + Control.IsVisible(17) + VisibleFadeEffect + + 80 + 60 + + Channel label + 0 + 20 + 250 + 20 + font13_title + white + black + center + center + + + + Title + 290 + 20 + 350 + 20 + font13_title + white + black + left + center + + + + Time label + 920 + 20 + 300 + 20 + font13_title + white + black + right + center + + + + Status header label + 960 + 20 + 140 + 20 + font13_title + white + black + center + center + + + + separator image + 0 + 50 + 1100 + 1 + 88FFFFFF + separator2.png + + + 0 + 55 + 1100 + 520 + 17 + 17 + 36 + 77 + 77 + 200 + + + 0 + 0 + 1100 + 41 + MenuItemNF.png + + + 0 + 0 + 250 + 40 + 33FFFFFF + StackFO.png + + + 960 + 0 + 140 + 40 + 33FFFFFF + StackFO.png + + + 10 + 5 + 30 + 30 + ListItem.Icon + + + 50 + 0 + 190 + 35 + font12 + left + center + grey2 + selected + ListItem.ChannelName + + + 260 + 0 + 650 + 35 + font13 + left + center + grey2 + selected + ListItem.Label + + + 950 + 0 + 500 + 40 + font12 + right + center + grey2 + selected + ListItem.Date + + + 970 + 10 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 1005 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.IsRecording + + + 970 + 10 + 20 + 20 + PVR-HasTimer.png + ListItem.HasTimer + !ListItem.IsRecording + + + 1000 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.HasTimer + + + + + 0 + 0 + 1100 + 41 + MenuItemNF.png + + + 0 + 0 + 250 + 40 + 33FFFFFF + StackFO.png + !Control.HasFocus(17) + + + 960 + 0 + 140 + 40 + 33FFFFFF + StackFO.png + !Control.HasFocus(17) + + + 0 + 0 + 250 + 40 + 88FFFFFF + StackFO.png + Control.HasFocus(17) + + + 960 + 0 + 140 + 40 + 88FFFFFF + StackFO.png + Control.HasFocus(17) + + + 10 + 5 + 30 + 30 + ListItem.Icon + + + 50 + 0 + 190 + 35 + font12 + left + center + grey2 + selected + ListItem.ChannelName + + + 260 + 0 + 650 + 35 + font13 + left + center + white + selected + ListItem.Label + + + 950 + 0 + 500 + 40 + font12 + right + center + white + selected + ListItem.Date + + + 970 + 10 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 1005 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.IsRecording + + + 970 + 10 + 20 + 20 + PVR-HasTimer.png + ListItem.HasTimer + !ListItem.IsRecording + + + 1000 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.HasTimer + + + + + 1105 + 50 + 25 + 520 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 16 + 36 + false + vertical + + + + Page Count Label + 40r + 53r + 500 + 20 + font12 + grey + false + right + center + + + + + + + + TV Guide Channel + Control.IsVisible(15) + VisibleFadeEffect + + 80 + 60 + + Date Time label + 0 + 20 + 300 + 20 + font13_title + white + black + center + center + + + + Title + 300 + 20 + 600 + 20 + font13_title + white + black + center + center + + + + Status header label + 960 + 20 + 140 + 20 + font13_title + white + black + center + center + + + + separator image + 0 + 50 + 1100 + 1 + 88FFFFFF + separator2.png + + + 0 + 60 + 1100 + 500 + 15 + 15 + 31 + 75 + 75 + 200 + + + 0 + 0 + 1100 + 41 + MenuItemNF.png + + + 0 + 0 + 300 + 40 + 33FFFFFF + StackFO.png + + + 960 + 0 + 140 + 40 + 33FFFFFF + StackFO.png + + + 150 + 0 + 280 + 40 + font12 + center + center + grey2 + selected + ListItem.Label2 + + + 310 + 0 + 640 + 40 + font13 + left + center + grey2 + selected + ListItem.Label + + + 970 + 10 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 1005 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.IsRecording + + + 970 + 10 + 20 + 20 + PVR-HasTimer.png + ListItem.HasTimer + !ListItem.IsRecording + + + 1000 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.HasTimer + + + + + 0 + 1 + 1100 + 98 + AAFFFFFF + black-back2.png + + + 0 + 0 + 1100 + 101 + MenuItemNF.png + + + 0 + 0 + 300 + 40 + AAFFFFFF + StackFO.png + !Control.HasFocus(15) + + + 960 + 0 + 140 + 40 + AAFFFFFF + StackFO.png + !Control.HasFocus(15) + + + 0 + 0 + 300 + 40 + 88FFFFFF + StackFO.png + Control.HasFocus(15) + + + 960 + 0 + 140 + 40 + 88FFFFFF + StackFO.png + Control.HasFocus(15) + + + 150 + 0 + 280 + 40 + font12 + center + center + white + selected + ListItem.Label2 + + + 310 + 0 + 640 + 40 + font13 + left + center + white + selected + ListItem.Label + + + Plot Value for TVShow + 50 + 40 + 1000 + 60 + font12 + justify + grey2 + black + - + + + + 970 + 10 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 1005 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.IsRecording + + + 970 + 10 + 20 + 20 + PVR-HasTimer.png + ListItem.HasTimer + !ListItem.IsRecording + + + 1000 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.HasTimer + + + + + 1105 + 60 + 25 + 500 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 15 + 31 + false + vertical + + + + Page Count Label + 40r + 53r + 500 + 20 + font12 + grey + false + right + center + + + + + + + + TV Guide Now/Next + Control.IsVisible(16) + VisibleFadeEffect + + 80 + 60 + + Time label + 0 + 20 + 100 + 20 + font13_title + white + black + center + center + + + + Channel label + 100 + 20 + 250 + 20 + font13_title + white + black + center + center + + + + Title + 350 + 20 + 550 + 20 + font13_title + white + black + center + center + + + + Status header label + 960 + 20 + 140 + 20 + font13_title + white + black + center + center + + + + separator image + 0 + 50 + 1100 + 1 + 88FFFFFF + separator2.png + + + 0 + 60 + 1100 + 500 + 16 + 16 + 31 + 76 + 76 + 200 + + + 0 + 0 + 1100 + 41 + MenuItemNF.png + + + 100 + 0 + 250 + 40 + 33FFFFFF + StackFO.png + + + 960 + 0 + 140 + 40 + 33FFFFFF + StackFO.png + + + 50 + 0 + 100 + 40 + font12 + center + center + grey2 + selected + ListItem.StartTime + + + 110 + 5 + 30 + 30 + ListItem.Icon + + + 150 + 0 + 190 + 35 + font12 + left + center + grey2 + selected + ListItem.ChannelName + + + 360 + 0 + 590 + 35 + font13 + left + center + grey2 + selected + ListItem.Label + + + 970 + 10 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 1005 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.IsRecording + + + 970 + 10 + 20 + 20 + PVR-HasTimer.png + ListItem.HasTimer + !ListItem.IsRecording + + + 1000 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.HasTimer + + + + + 0 + 1 + 1100 + 98 + AAFFFFFF + black-back2.png + + + 0 + 0 + 1100 + 100 + MenuItemNF.png + + + 100 + 0 + 250 + 40 + AAFFFFFF + StackFO.png + !Control.HasFocus(16) + + + 960 + 0 + 140 + 40 + AAFFFFFF + StackFO.png + !Control.HasFocus(16) + + + 100 + 0 + 250 + 40 + 88FFFFFF + StackFO.png + Control.HasFocus(16) + + + 960 + 0 + 140 + 40 + 88FFFFFF + StackFO.png + Control.HasFocus(16) + + + 50 + 0 + 100 + 40 + font12 + center + center + white + selected + ListItem.StartTime + + + 110 + 5 + 30 + 30 + ListItem.Icon + + + 150 + 0 + 190 + 35 + font12 + left + center + white + selected + ListItem.ChannelName + + + 360 + 0 + 590 + 35 + font13 + left + center + white + selected + ListItem.Label + + + Plot Value for TVShow + 50 + 40 + 1000 + 60 + font12 + justify + grey2 + black + - + + + + 970 + 10 + 30 + 20 + PVR-IsRecording.png + ListItem.IsRecording + + + 1005 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.IsRecording + + + 970 + 10 + 20 + 20 + PVR-HasTimer.png + ListItem.HasTimer + !ListItem.IsRecording + + + 1000 + 0 + 80 + 40 + font10 + left + center + grey2 + selected + + ListItem.HasTimer + + + + + 1105 + 60 + 25 + 500 + ScrollBarV.png + ScrollBarV_bar.png + ScrollBarV_bar_focus.png + ScrollBarNib.png + ScrollBarNib.png + 16 + 31 + false + vertical + + + + Page Count Label + 40r + 53r + 500 + 20 + font12 + grey + false + right + center + + + + + \ No newline at end of file diff --git a/addons/skin.confluence/720p/custom_SkinSetting_1111.xml b/addons/skin.confluence/720p/custom_SkinSetting_1111.xml index e5d699d..931bac3 100644 --- a/addons/skin.confluence/720p/custom_SkinSetting_1111.xml +++ b/addons/skin.confluence/720p/custom_SkinSetting_1111.xml @@ -751,6 +751,14 @@ $INFO[Skin.String(Home_Custom_Back_TVShow_Folder)] Skin.HasSetting(HomeMenuNoTVShowsButton) + Library.HasContent(TVShows) + + + Home_Custom_Back_TV_Folder + - + special://skin/backgrounds/tv.jpg + $INFO[Skin.String(Home_Custom_Back_TV_Folder)] + System.GetBool(pvrmanager.enabled) + Home_Custom_Back_Music_Folder diff --git a/addons/skin.confluence/720p/defaults.xml b/addons/skin.confluence/720p/defaults.xml index ed1111d..05c80e5 100644 --- a/addons/skin.confluence/720p/defaults.xml +++ b/addons/skin.confluence/720p/defaults.xml @@ -123,6 +123,7 @@ grey3 7 center + no 490 diff --git a/addons/skin.confluence/720p/includes.xml b/addons/skin.confluence/720p/includes.xml index b563db5..4843834 100644 --- a/addons/skin.confluence/720p/includes.xml +++ b/addons/skin.confluence/720p/includes.xml @@ -6,6 +6,7 @@ + @@ -28,7 +29,7 @@ black-back.png Visible Hidden - Window.IsActive(MovieInformation) | Window.IsActive(MusicInformation) | Window.IsActive(SongInformation) | Window.IsActive(FileBrowser) | Window.IsActive(TextViewer) | Window.IsActive(AddonSettings) | Window.IsActive(ContentSettings) | Window.IsActive(SelectDialog) | Window.IsActive(FileStackingDialog) | Window.IsActive(MediaSource) | Window.IsActive(PictureInfo) | Window.IsActive(PlayerControls) | Window.IsActive(VirtualKeyboard) | Window.IsActive(NumericInput) | Window.IsActive(ProfileSettings) | Window.IsActive(LockSettings) | Window.IsActive(SmartPlaylistEditor) | Window.IsActive(SmartPlaylistRule) | Window.IsActive(script-Apple_Movie_Trailers-settings.xml) | Window.IsActive(script-Apple_Movie_Trailers-chooser.xml) | Window.IsActive(script-Apple_Movie_Trailers-search.xml) | Window.IsActive(script-Apple_Movie_Trailers-showtimes.xml) | Window.IsActive(script-XBMC_Lyrics-settings.xml) | Window.IsActive(script-RSS_Editor-rssEditor.xml) | Window.IsActive(script-RSS_Editor-setEditor.xml) | Window.IsActive(AddonInformation) | Window.IsActive(Peripherals) | Window.IsActive(PeripheralSettings) + Window.IsActive(MovieInformation) | Window.IsActive(MusicInformation) | Window.IsActive(SongInformation) | Window.IsActive(FileBrowser) | Window.IsActive(TextViewer) | Window.IsActive(AddonSettings) | Window.IsActive(ContentSettings) | Window.IsActive(SelectDialog) | Window.IsActive(FileStackingDialog) | Window.IsActive(MediaSource) | Window.IsActive(PictureInfo) | Window.IsActive(PlayerControls) | Window.IsActive(VirtualKeyboard) | Window.IsActive(NumericInput) | Window.IsActive(ProfileSettings) | Window.IsActive(LockSettings) | Window.IsActive(SmartPlaylistEditor) | Window.IsActive(SmartPlaylistRule) | Window.IsActive(script-Apple_Movie_Trailers-settings.xml) | Window.IsActive(script-Apple_Movie_Trailers-chooser.xml) | Window.IsActive(script-Apple_Movie_Trailers-search.xml) | Window.IsActive(script-Apple_Movie_Trailers-showtimes.xml) | Window.IsActive(script-XBMC_Lyrics-settings.xml) | Window.IsActive(script-RSS_Editor-rssEditor.xml) | Window.IsActive(script-RSS_Editor-setEditor.xml) | Window.IsActive(AddonInformation) | Window.IsActive(Peripherals) | Window.IsActive(PeripheralSettings) | Window.IsActive(PVRChannelManager) @@ -246,6 +247,19 @@ black Player.HasVideo + VideoPlayer.Content(MusicVideos) + + 85 + 30r + 700 + 20 + + left + center + font12 + grey + black + Player.HasVideo + VideoPlayer.Content(LiveTV) + @@ -513,8 +527,124 @@ Fake Button to fix Player Controls Navigation false + + 250 + 90 + VideoPlayer.Content(LiveTV) + VisibleFadeEffect + + 20 + 2 + 39 + 39 + + OSDChannelUPFO.png + OSDChannelUPNF.png + 50 + 601 + 610 + 611 + XBMC.PlayerControl(Previous) + + + 60 + 2 + 39 + 39 + + OSDChannelDownFO.png + OSDChannelDownNF.png + 600 + 603 + 610 + 611 + XBMC.PlayerControl(Next) + + + 100 + 2 + 39 + 39 + + OSDStopFO.png + OSDStopNF.png + 601 + 604 + 610 + 611 + down + XBMC.PlayerControl(Stop) + + + 180 + 2 + 39 + 39 + + OSDRecordOffFO.png + OSDRecordOffNF.png + 603 + 50 + 610 + 611 + XBMC.PlayerControl(record) + Player.CanRecord + Conditional + + + + 20 + 42 + 39 + 39 + + OSDRewindFO.png + OSDRewindNF.png + 603 + 607 + 610 + 611 + 50 + XBMC.PlayerControl(Rewind) + + + 60 + 42 + 39 + 39 + + OSDForwardFO.png + OSDForwardNF.png + 607 + 600 + 610 + 611 + 50 + XBMC.PlayerControl(Forward) + + + 100 + 42 + 39 + 39 + + OSDPauseFO.png + OSDPauseNF.png + Player.Paused | Player.Forwarding | Player.Rewinding + OSDPlayFO.png + OSDPlayNF.png + 605 + 606 + 610 + 611 + 50 + XBMC.PlayerControl(Play) + + + [Player.HasAudio | Player.HasVideo] + !VideoPlayer.Content(LiveTV) VisibleFadeEffect 250 45 diff --git a/addons/skin.confluence/backgrounds/tv.jpg b/addons/skin.confluence/backgrounds/tv.jpg new file mode 100644 index 0000000..9414690 Binary files /dev/null and b/addons/skin.confluence/backgrounds/tv.jpg differ diff --git a/addons/skin.confluence/language/Czech/strings.xml b/addons/skin.confluence/language/Czech/strings.xml index 2d5551d..e67752a 100644 --- a/addons/skin.confluence/language/Czech/strings.xml +++ b/addons/skin.confluence/language/Czech/strings.xml @@ -2,7 +2,7 @@ - + Změnit @@ -166,9 +166,22 @@ [B]MOŽNOSTI SYSTÉMU[/B][CR][CR]Nastavení obrazovky · Konfigurace výstupu zvuku · Nastavení dálkového ovládání[CR]Možnosti úsporného režimu · Ukládání informací o ladění · Rodičovský zámek [B]MOŽNOSTI VZHLEDU[/B][CR][CR]Přizpůsobení vzhledu Confluence · Správa sekcí na úvodní obrazovce[CR]Nastavení pozadí vzhledu [B]MOŽNOSTI DOPLŇKŮ[/B][CR][CR]Správa nainstalovaných doplňků · Vyhledávání a instalace doplňků z xbmc.org[CR]Nastavení doplňků + [B]MOŽNOSTI PŘEHRÁVÁNÍ TELEVIZNÍHO STREAMU[/B][CR][CR]Změnit zobrazení přes celou obrazovku · Správa EPG dat Přihlášení uživatele[CR]Pokračujte výběrem profilu + + Časovače + Naplánovaný čas + Televize + Přidat skupinu + Přejmenovat skupinu + Smazat skupinu + Dostupné[CR]skupiny + Skupina programů + Timer Set + Nastavení programu + Mapy počasí Předpověď na 36 hodin diff --git a/addons/skin.confluence/language/Dutch/strings.xml b/addons/skin.confluence/language/Dutch/strings.xml index b328697..d735a59 100644 --- a/addons/skin.confluence/language/Dutch/strings.xml +++ b/addons/skin.confluence/language/Dutch/strings.xml @@ -168,6 +168,17 @@ [B]ADD-ONS CONFIGUREREN[/B][CR][CR]Beheer uw geïnstalleerde Add-ons · Zoek en installeer Add-ons via xbmc.org · Wijzig Add-oninstellingen Selecteer uw XBMC-gebruikersprofiel[CR]om in te loggen + + + Geplande opnames + Opname starttijd + Televisie + Groep toevoegen + Groep hernoemen + Groep verwijderen + Beschikbare[CR]Groepen + Groep + Geplande opname ingesteld Weer Kaarten diff --git a/addons/skin.confluence/language/English/strings.xml b/addons/skin.confluence/language/English/strings.xml index d32977a..ab4678b 100644 --- a/addons/skin.confluence/language/English/strings.xml +++ b/addons/skin.confluence/language/English/strings.xml @@ -162,8 +162,21 @@ [B]CONFIGURE SYSTEM SETTINGS[/B][CR][CR]Setup and calibrate displays Configure audio output Setup remote controls[CR]Set power saving options Enable debugging Setup master lock [B]CONFIGURE SKIN SETTINGS[/B][CR][CR]Setup the Confluence skin Add and remove home menu items[CR]Change skin backgrounds [B]CONFIGURE ADD-ONS[/B][CR][CR]Manage your installed Add-ons Browse for and install Add-ons from xbmc.org[CR]Modify Add-on settings + [B]CONFIGURE TV SETTINGS[/B][CR][CR]Change fullscreen info Manage EPG data settings Select your XBMC user Profile[CR]to login and continue + + + Recording Timers + Scheduled Time + Live TV + Add Group + Rename Group + Delete Group + Available[CR]Groups + Channel Group + Timer Set + Channel Options Weather Maps @@ -177,4 +190,4 @@ Chance of Precipitation Fetching forecast info... - + diff --git a/addons/skin.confluence/language/Finnish/strings.xml b/addons/skin.confluence/language/Finnish/strings.xml index ed70f2c..5191c52 100644 --- a/addons/skin.confluence/language/Finnish/strings.xml +++ b/addons/skin.confluence/language/Finnish/strings.xml @@ -164,9 +164,22 @@ [B]Muokkaa järjestelmän asetuksia[/B][CR][CR]Aseta ja kalibroi näyttö · Määritä äänilähtö · Aseta kauko-ohjaus[CR]Aseta sähkönsäästöasetukset · Ota debuggaus käyttöön · Muokkaa pääkäyttäjän lukituksia [B]Muokkaa ulkoasun asetuksia[/B][CR][CR]Aseta Confluence-ulkoasun asetukset · Lisää ja poista päävalikon kohteita[CR]Vaihda ulkoasun taustakuvia [B]Muokkaa lisäosia[/B][CR][CR]Hallitse asennettuja lisäosia · Valitse ja asenna lisäosia xbmc.org:sta[CR]Muokkaa lisäosien asetuksia + [B]Muokkaa TV-asetuksia[/B][CR][CR]Aseta kanavien toiston asetukset · Hallitse ohjelmaoppaan asetuksia Valitse XBMC-käyttäjäprofiili[CR]kirjautuaksesi sisään + + Nauhoitusajastukset + Kellonaika + TV-lähetys + Lisää ryhmä + Muuta ryhmän nimeä + Poista ryhmä + Saatavilla olevat[CR]ryhmät + Kanavaryhmä + Ajastettu + Kanavan valinnat + Sääkartat 36 tunnin ennuste diff --git a/addons/skin.confluence/language/French/strings.xml b/addons/skin.confluence/language/French/strings.xml index 293d29a..674225a 100644 --- a/addons/skin.confluence/language/French/strings.xml +++ b/addons/skin.confluence/language/French/strings.xml @@ -161,9 +161,22 @@ [B]CONFIGURATION DES PARAMÈTRES SYSTÈME[/B][CR][CR]Configurer les sorties vidéo et audio · Configurer les périphériques de contrôle[CR]Définir les options de gestion d'énergie · Activer le débogage · Configurer la sécurité [B]CONFIGURATION DES PARAMÈTRES THÈME[/B][CR][CR]Configuration du skin Confluence · Ajouter et supprimer des éléments du menu d'accueil[CR]Changer les arrière-plans du skin [B]CONFIGURATION DES ADD-ONS[/B][CR][CR]Gérer les Add-ons installés· Recherche et installation d'Add-ons depuis xbmc.org[CR]Modifier les paramètres Add-on + [B]CONFIGURATION DES PARAMÈTRES TV[/B][CR][CR]Changer l'affichage plein écran · Gestion des paramètres de l'EPG Sélectionnez un profil d'utilisateur[CR]pour vous connecter et continuer - + + + Programmations + Date/Heure + TV + Ajouter un Groupe + Renommer le Groupe + Supprimer le Groupe + Groupes[CR]Disponibles + Groupe de chaînes + Programmer + Paramètres de la chaîne + Cartes Météo Prévisions sur 36 Heures @@ -175,5 +188,4 @@ Bulletin vidéo [COLOR=grey2](affichage en plein écran)[/COLOR] Risque de pluie Récupération des prévisions météo... - diff --git a/addons/skin.confluence/language/German/strings.xml b/addons/skin.confluence/language/German/strings.xml index e698959..855f347 100644 --- a/addons/skin.confluence/language/German/strings.xml +++ b/addons/skin.confluence/language/German/strings.xml @@ -6,7 +6,8 @@ Power Optionen In Arbeit... Verberge Info - Anzeige Optionen + Ansichtsoptionen + Plugins Vollbild @@ -36,8 +37,8 @@ Aktuelle Einstellung Visualisierungs Einstellungen Schluss Zeit - Sortieren: Aufsteigend - Sortieren: Absteigend + Sortiere: Aufsteigend + Sortiere: Absteigend Öffne Wiedergabeliste Sichere Wiedergabeliste @@ -66,7 +67,7 @@ Zeige kürzlich hinzugefügte Videos Hauptfenster Programme-Untermenü - Verstecke Hintergrund Fanart + Verberge Hintegrund Fanart BUTTON BESCHRIFTUNG Wetter Seite @@ -86,6 +87,8 @@ Homefenster Bilder-Untermenü + Untertitel Add-on + Musik OSD Video OSD @@ -148,9 +151,23 @@ [B]KONFIGURIERE NETZWERK EINSTELLUNGEN[/B][CR][CR]Einrichten der Steuerung von XBMC via UPnP und HTTP · Konfiguriere Datei Zugriff[CR]Setze Internet Zugriffs Optionen [B]KONFIGURIERE SYSTEM EINSTELLUNGEN[/B][CR][CR]Setze und kalibriere Displays · Konfiguriere Audioausgabe · Setze Fernbedienungs Einstellungen · Setze Energiespar Optionen · Aktiviere Debugging · Einrichten Master Sperre [B]KONFIGURIERE SKIN EINSTELLUNGEN[/B][CR][CR]Einrichten des Confluence Skin · Hinzufügen und entfernen der Home Menü Einträge[CR]Wechseln der Skin Hintergründe - [B]KONFIGURIERE ADD-ONS[/B][CR][CR]Organisiere die installierten Add-ons · Installiere Add-ons von xbmc.org[CR]Add-on Einstellungen anpassen + [B]KONFIGURIERE ERWEITERUNGEN[/B][CR][CR]Organisiere die installierten Add-ons · Installiere Add-ons von xbmc.org[CR]Add-on Einstellungen anpassen + [B]KONFIGURIERE TV EINSTELLUNGEN[/B][CR][CR]Verändere Vollbild Modus · Verwalte EPG Daten Einstellungen + Wähle Dein XBMC Benutzer Profil[CR]Zum Anmelden und Weitermachen + + Recording Timers + Scheduled Time + Live TV + Gruppe hinzufügen + Gruppe umbenennen + Gruppe löschen + Verfügbare[CR]Gruppen + Kanalgruppe + Timer Set + Kanal Optionen + Wetterkarten 36 Stunden Prognose Stündliche Prognose diff --git a/addons/skin.confluence/language/Greek/strings.xml b/addons/skin.confluence/language/Greek/strings.xml index cba0444..f3f7754 100644 --- a/addons/skin.confluence/language/Greek/strings.xml +++ b/addons/skin.confluence/language/Greek/strings.xml @@ -1,5 +1,5 @@ - - + + Αλλαγή Αγαπητό @@ -7,16 +7,17 @@ Επιλογές λειτουργίας Απασχολημένο... Απόκρυψη Πληροφοριών + Προβολή Επιλογών + Plugin + Πλήρης Οθόνη - Επεκτάσεις - - Πρόσφατα αναρτημένα - Αρχεία βίντεο - Αρχεία μουσικής + Προστέθηκαν πρόσφατα + Βίντεο - Αρχεία + Μουσική - Αρχεία Αναπαραγωγή Σελίδα Αντικείμενα - Πρόσθετες επιλογές + Διάφορες επιλογές Τοποθεσία @@ -28,124 +29,152 @@ Πληροφορίες - Τώρα αναπαράγεται + Τώρα Εκτελείται - Αναπαράγεται + ΑΝΑΠΑΡΑΓΩΓΗ ΠΑΥΣΗ - ΠΡΟΩΘΗΣΗ ΜΠΡΟΣΤΑ - ΠΡΟΩΘΗΣΗ ΠΙΣΩ - Ιδιότητες ήχου - Τρέχουσα απεικονίση - Απεικονίσεις + ΜΠΡΟΣΤΑ + ΠΙΣΩ + Ιδιότητες Ήχου + Τρέχον Προκαθορισμένο + Προκαθορισμένες Οπτικοποιήσεις Χρόνος λήξης + Ταξ.: Αύξουσα + Ταξ.: Φθίνουσα Άνοιγμα λίστας αναπαραγωγής Αποθήκευση λίστας αναπαραγωγής Κλείσιμο λίστας αναπαραγωγής - Σύστημα αρχείων μουσικής + Μουσικά αρχεία συστήματος Τρέχουσα λίστα αναπαραγωγής - Αυτό το αρχείο είναι στοιβαγμένο, επιλέξτε το κομμάτι που επιθυμείτε για αναπαραγωγή. - Επιλέχθηκε η τρέχουσα - + Αυτό το αρχείο είναι στοιβαγμένο, επιλέξτε από που να γίνει αναπαραγωγή. + Τρέχουσα Επιλογή + Επιλογές αρχικής οθόνης Υπόβαθρο - Εμφάνιση "Παύση" κατά την παρουσίαση φωτογραφιών - Αναπαραγωγή Διαφημιστικών ταινιών σε παράθυρο[COLOR=grey3](Μόνο οι πληροφορίες βίντεο)[/COLOR] - - Πρόσθετες επιλογές + Εμφάνιση 'Παύσης' σε παρουσίαση διαφανειών + Αναπαραγωγή Διαφημιστικών σε παράθυρο [COLOR=grey3](Μόνο οι πληροφορίες βίντεο)[/COLOR] + Το πλήκτρο "Βίντεο" πάντα οδηγεί στα "Αρχεία" βίντεο + Διάφορες επιλογές Απόκρυψη των αναγνώσιμων σημαιών από τα ονόματα αρχείων βίντεο [COLOR=grey3](Blu-ray, HD-DVD)[/COLOR] - Απόκρυψη πλήκτρων από το κεντρικό μενού επιλογών + + Απόκρυψη πλήκτρων του Κεντρικού Μενού Υπόβαθρα αρχικής οθόνης - Επεξεργασία υπόβαθρου για το αρχικό πλήκτρο + Επεξεργασία υποβάθρου για το αρχικό πλήκτρο Απόκρυψη Επιλογές - Εικόνα - Φάκελος + Μία Εικόνα + Πολλαπλές εικόνες Προσαρμογή Εμφάνιση των πρόσφατα προστιθέμενων βίντεο - Υπομενού αρχικής οθόνης - + Υπομενού Εφαρμογών αρχικής οθόνης + Απόκρυψη Fanart υποβάθρου ΕΤΙΚΕΤΑ ΠΛΗΚΤΡΟΥ - - Οθόνη καιρού - Χρήση του "Αφίσα" αντί του "Πανό" για τις τηλεοπτικές σειρές - Εμφάνιση ως υπόβαθρο το βίντεο που "Τώρα αναπαράγεται" - Εμφάνιση ως υπόβαθρο η απεικόνιση που "Τώρα αναπαράγεται" + + Σελίδα Καιρού + Χρήση "Αφισών" αντί για "Πανό" για τις τηλεοπτικές σειρές + Εμφάνιση ως υπόβαθρο το βίντεο που "Τώρα Εκτελείται" + Εμφάνιση ως υπόβαθρο η οπτικοποίηση που "Τώρα Εκτελείται" - - - Στίχοι XBMC - - + Αναπαραγωγή τραγουδιών σειρών (πρόσθετο TvTunes) + TvTunes + Στίχοι + + + + Πρόσθετο στίχων + Πρόσθετο υποτίτλων + Υπομενού Βίντεο αρχικής οθόνης + Υπομενού Μουσικής αρχικής οθόνης + Υπομενού Εικόνων αρχικής οθόνης - Aπεικόνισεις οθόνης (OSD) Μουσική - Aπεικόνισεις οθόνης (OSD) Βίντεο + Aπεικονίσεις οθόνης (OSD) Μουσικής + Aπεικονίσεις οθόνης (OSD) Βίντεο Συντομεύσεις Κατηγορίες - Εμφάνιση συντελεστών + Εμφάνιση διανομής Επιλογή τραγουδιού Επιλογή Συνδέσμων - Προέλευση στίχων τραγουδιού + Προέλευση στίχων - Τρέχουσες συνθήκες + Τρέχουσα θερμοκρασία Τελευταία ενημέρωση Μενού - - Φωτογραφίες - Δεν εντοπίσθηκε δίσκος πολυμέσων + Πηγή δεδομένων + Εικόνα + Δεν εντοπίστηκε οπτικός δίσκος Εξαγωγή Απόκρυψη Fanart Λεπτομέρειες ταινίας - Δεσμευμένη μνήμη: + Χρήση μνήμης: Αριθμός κομματιού - Μη διαθέσιμη[CR][CR]εικόνα Fanart[CR][CR]Για να ορίσετε πιέστε το πλήκτρο - Ενεργός καταγραφέας - Επιλογή καταγραφέα - Επιλόγες αναζήτησης περιεχομένου + Εικόνα Fanart[CR][CR]Μη διαθέσιμη[CR][CR] Πιέστε το πλήκτρο για να θέσετε + Τρέχον Scraper + Επιλογή Scraper + Επιλογές Σάρωσης Περιεχομένου Βασικό Ορισμός διαδρομής Fanart Μικρό Fanart Επιλεγμένο προφίλ - Τελευταία είσοδος στο - Επιλογέας τραγουδιών Karaoke - Αιθέριο - Πρόσφατες ταινίες - Πρόσφατα επεισόδια + Τελευταία είσοδος + Επιλογέας τραγουδιού Karaoke + Πρώτη Προβολή + Νεώτερες Ταινίες + Νεώτερα Επεισόδια Επιλογές λίστας αναπαραγωγής Δημιουργήθηκε Ανάλυση - Προστέθηκε πρόσφατα - [B]Εφαρμογή χρονοδιακόπτη![/B] [COLOR=grey2] - Αυτόματος τερματισμός λειτουργίας σε[/COLOR] - Πιέστε το πλήκτρο για να αναπαραχθεί[CR][CR]το διαφημιστικό ταινίας + Προστέθηκαν Πρόσφατα + [B]Εφαρμογή χρονοδιακόπτη![/B] [COLOR=grey2] - Αυτόματος τερματισμός συστήματος σε[/COLOR] + Πιέστε το πλήκτρο για αναπαραγωγή[CR][CR]του Διαφημιστικού Ταινίας + Λεπτομέρειες Άλμπουμ Παύση Διακοπή - Προώθηση μπροστά - Προώθηση πίσω + Μπροστά + Πίσω Μενού ταινίας Λήψη υποτίτλων + + Προεπιλογή + Προεπιλογή χωρίς Κεφαλαία + Βασισμένη σε Arial + - [B]ΠΡΟΣΑΡΜΟΓΗ ΡΥΘΜΙΣΕΩΝ ΕΞΑΤΟΜΙΚΕΥΣΗΣ[/B][CR][CR]Αλλαγή κελύφους · Αλλαγή χώρας και γλώσσας συστήματος · Ορισμός των γενικών επιλόγων εμφάνισης[CR]Προσαρμογή της προφύλαξης οθόνης - [B]ΠΡΟΣΑΡΜΟΓΗ ΡΥΘΜΙΣΕΩΝ ΒΙΝΤΕΟ[/B][CR][CR]Διαχείριση της συλλογής βίντεο · Διαμόρφωση γραμματοσειράς υποτίτλων[CR]Προσαρμογή της ποιότητας ανάλυσης των βίντεο και ρύθμιση του αναπαραγωγέα - [B]ΠΡΟΣΑΡΜΟΓΗ ΡΥΘΜΙΣΕΩΝ ΜΟΥΣΙΚΗΣ[/B][CR][CR]Διαχείριση της συλλογής τραγουδιών · Eπιλογές εμφάνισης της λίστας μουσικής[CR]Προσαρμογή ρυθμίσεων και αλλαγή γραμματοσειράς για Karaoke - [B]ΠΡΟΣΑΡΜΟΓΗ ΡΥΘΜΙΣΕΩΝ ΦΩΤΟΓΡΑΦΙΩΝ[/B][CR][CR]Ρύθμιση επιλογών προβολής φωτογραφιών · Ρύθμιση παρουσίασης διαφανειών - [B]ΠΡΟΣΑΡΜΟΓΗ ΡΥΘΜΙΣΕΩΝ ΚΑΙΡΟΥ[/B][CR][CR]Ορισμός τριών πόλεων για τις οποίες θα γίνει πρόγνωση καιρού - [B]ΠΡΟΣΑΡΜΟΓΗ ΡΥΘΜΙΣΕΩΝ ΔΙΚΤΥΟΥ[/B][CR][CR]Προσαρμογή πρωτοκόλλων επικοινωνίας και μεταφοράς κοινόχρηστων αρχείων[CR]Ρύθμιση κοινόχρηστων αρχείων πολυμέσων · Ορισμός ρυθμίσεων δικτύου - [B]ΠΡΟΣΑΡΜΟΓΗ ΡΥΘΜΙΣΕΩΝ ΣΥΣΤΗΜΑΤΟΣ[/B][CR][CR]Βαθμονόμιση γραφικού περιβάλλοντος · Ρύθμιση υλικού ήχου · Εγκατάσταση τηλεχειριστηρίων[CR]Αλλαγή και τροποποίηση του τρόπου τερματισμού του προγράμματος · Ρύθμιση κεντρικού κλειδώματος - [B]ΠΡΟΣΑΡΜΟΓΗ ΡΥΘΜΙΣΕΩΝ ΚΕΛΥΦΟΥΣ[/B][CR][CR]Αλλαγή και τροποποίηση υπόβαθρων · Προσθήκη ή απομάκρυνση πλήκτρων από την αρχική οθόνη[CR]Δημιουργία συντομεύσεων προς τα scripts προκειμένου να ενσωματωθούν στο κέλυφος - [B]ΠΡΟΣΑΡΜΟΓΗ ΡΥΘΜΙΣΕΩΝ ΠΡΟΣΘΕΤΩΝ[/B][CR][CR]Διαχείριση των Πρόσθετων σας · Αναζήτηση και εγκατάσταση Πρόσθετων από το XBMC.org[CR]Τροποποίηση ρυθμίσεων των Πρόσθετων + [B]ΡΥΘΜΙΣΕΙΣ ΕΞΑΤΟΜΙΚΕΥΣΗΣ[/B][CR][CR]Αλλαγή κελύφους · Αλλαγή χώρας και γλώσσας συστήματος · Επιλογές καταλόγου αρχείων[CR]Προσαρμογή της προφύλαξης οθόνης + [B]ΡΥΘΜΙΣΕΙΣ ΒΙΝΤΕΟ[/B][CR][CR]Διαχείριση της συλλογής βίντεο · Ρύθμιση αναπαραγωγής βίντεο · Επιλογές καταλόγου ταινιών[CR]Ρύθμιση γραμματοσειράς υποτίτλων + [B]ΡΥΘΜΙΣΕΙΣ ΜΟΥΣΙΚΗΣ[/B][CR][CR]Διαχείριση της συλλογής τραγουδιών · Ρύθμιση αναπαραγωγής μουσικής · Επιλογές καταλόγου μουσικής[CR]Ρύθμιση υποβολής τραγουδιού · Επιλογές karaoke + [B]ΡΥΘΜΙΣΕΙΣ ΕΙΚΟΝΩΝ[/B][CR][CR]Επιλογές καταλόγου εικόνων · Ρύθμιση παρουσίασης διαφανειών + [B]ΡΥΘΜΙΣΕΙΣ ΚΑΙΡΟΥ[/B][CR][CR]Ορισμός τριών πόλεων για τις οποίες θα γίνεται πρόγνωση καιρού + [B]ΡΥΘΜΙΣΕΙΣ ΔΙΚΤΥΟΥ[/B][CR][CR]Ρύθμιση χειρισμού του XBMC μέσω UPnP και HTTP · Ρύθμιση κοινής χρήσης αρχείων[CR]Ορισμός ρυθμίσεων διαδικτύου + [B]ΡΥΘΜΙΣΕΙΣ ΣΥΣΤΗΜΑΤΟΣ[/B][CR][CR]Διαμόρφωση και βαθμονόμηση οθονών · Ρύθμιση εξόδου ήχου · Εγκατάσταση τηλεχειριστηρίων · Ρύθμιση εξοικονόμησης ενέργειας · Ενεργοποίηση καταγραφής σφαλμάτων (debug) · Ρύθμιση κεντρικού κλειδώματος + [B]ΡΥΘΜΙΣΕΙΣ ΚΕΛΥΦΟΥΣ[/B][CR][CR]Ρύθμιση του κελύφους Confluence · Προσθήκη και απομάκρυνση αντικειμένων από την αρχική οθόνη[CR]Αλλαγή υποβάθρου κελύφους + [B]ΡΥΘΜΙΣΕΙΣ ΠΡΟΣΘΕΤΩΝ[/B][CR][CR]Διαχείριση εγκατεστημένων Πρόσθετων · Αναζήτηση και εγκατάσταση Πρόσθετων από το xbmc.org[CR]Τροποποίηση ρυθμίσεων των Πρόσθετων + + Επιλέξτε προφίλ χρήστη για το XBMC[CR]για να συνδεθείτε και να συνεχίσετε - Επιλέξτε προφίλ χρήστη για το XBMC[CR]για να συνδεθείτε και συνεχίστε - + + Χάρτες Καιρού + 36ωρη Πρόβλεψη + Ωριαία Πρόβλεψη + Πρόβλεψη Σαββατοκύριακου + Πρόβλεψη 10 ημερών + Πρόβλεψη + Χάρτες & Βίντεο + Βίντεο Πρόβλεψης [COLOR=grey2](Πλήρης Οθόνη)[/COLOR] + Πιθανότητα Υετού + Ανάκτηση πρόβλεψης καιρού... + + diff --git a/addons/skin.confluence/language/Japanese/strings.xml b/addons/skin.confluence/language/Japanese/strings.xml index da68259..f80b29c 100644 --- a/addons/skin.confluence/language/Japanese/strings.xml +++ b/addons/skin.confluence/language/Japanese/strings.xml @@ -1,148 +1,182 @@  - - - + + + + - Change Your + Love Hate - 電源設定 + 電源オプション 処理中... - Hide INFO - Plugins - 最近追加 + 情報を隠す + 表示オプション + + プラグイン + + 最新の追加 ビデオ - ファイル ミュージック - ファイル - Playing + 再生中 ページ アイテム - Misc Options - Location - Poster Wrap - Fanart - Full list - Pic Thumbs - Image Wrap - Info - Now Playing + その他のオプション + 地域 + + + ポスターラップ + ファンアート + フルリスト + サムネール + イメージラップ + 情報 + + + 現在再生中 + 再生中 静止中 早送り 巻戻し - Audio Properties - Current Preset + オーディオ設定 + 現在の設定 Visualization Presets End Time - Open playlist - Save playlist - Close playlist - System music files - Current playlist - This file is stacked, select the part you want to play from. - Current Selected - - - メニュー画面設定 + ソート: 昇順 + ソート: 降順 + + + プレイリストを開く + プレイリストを保存 + プレイリストを閉じる + システム音楽ファイル + 現在のプレイリスト + このファイル内から再生したいパートを選択してください。 + 現在選択中 + + + + ホーム画面オプション 背景 - ピクチャスライドショーで"静止中"と表示 - Play Trailers in a window [COLOR=grey3](Video Information Dialog Only)[/COLOR] - + ピクチャスライドショーで「静止中」と表示 + ウィンドウ内で予告を再生 [COLOR=grey3](ビデオ情報ダイアログのみ)[/COLOR] + 「ビデオ」ボタンで常に「ファイル」を選択 その他の設定 Hide Flagging read from video filenames [COLOR=grey3](Blu-ray, HD-DVD)[/COLOR] - Hide Main Menu Buttons - Media backgrounds - Edit Background for Media Type - Hide - Options - Single Image - Multi Image - Customizer - - + メインメニューから隠すボタン + メディア別の背景設定 + 編集するメディアタイプを選択 + 隠す + オプション + 単一イメージ + 複数イメージ + カスタマイズ + 最近追加したビデオを表示 - Home Page Programs Submenu - - - BUTTON LABEL - - - Weather Page + ホーム画面「プログラム」のサブメニュー + 背景のファンアートを隠す + ボタンラベル + + 天気予報ページ Use "Posters" instead of "Banners" for TV Shows - Show Background "Now Playing" Video - Show Background "Now Playing" Visualization - - - - - Lyrics - - - - - Use Horizontal Home Menu - Lyrics Add-on - Subtitle Add-on - Music OSD - Video OSD - Shortcuts - Categories - Show Cast - Choose Your Song - Section Links - Lyrics Source - Current Temp - Last Updated - Menu - - - Picture - No Disc Media Detected - Eject - Hide Fanart - Movie Details - Memory Used: - Track Number - Fanart image[CR][CR]Unavailable[CR][CR] Click button to set - Current Scraper - Choose a Scraper - Content Scanning Options - Basic + 背景に「現在再生中」ビデオを表示 + 背景に「現在再生中」視覚化を表示 + Play TV theme songs in video library (TvTunes add-on) + TvTunes + 歌詞 + + + + + 歌詞アドオン + 字幕アドオン + ホーム画面「ビデオ』のサブメニュー + ホーム画面「ミュージック』のサブメニュー + ホーム画面「ピクチャ』のサブメニュー + + ミュージック OSD + ビデオ OSD + + + ショートカット + カテゴリ + キャストを表示 + 曲を選択 + セクションリンク + 歌詞の情報源 + + + 現在の気温 + 最終更新時刻 + メニュー + 気象データ提供元 + ピクチャ + ディスクメディアが検出されませんでした + イジェクト + ファンアートを隠す + ムービーの詳細 + メモリ使用量: + トラック番号 + ファンアート画像[CR][CR]使用不可[CR][CR] ボタンを押して設定 + 現在のメタデータスクレーパー + メタデータスクレーパーを選択 + コンテントスキャンオプション + 標準 - Set Fanart Path - Small Fanart - Selected Profile + ファンアートのパスを設定 + 小さなファンアート + 選択されたプロファイル 最終ログイン - Karaoke Song Selector - Aired - Latest Movies - Latest Episodes - Playlist Options - Created - Resolution + カラオケソングセレクター + 放映日 + 最新ムービー + 最新エピソード + プレイリストオプション + 制作日 + 解像度 最近追加 - [B]Timer set![/B] [COLOR=grey2] - System auto shutdown in[/COLOR] - Click button to play[CR][CR]Movie trailer - Pause - Stop - Fast Forward - Rewind - Movie menu - Download Subtitles - - - Skin default - Skin default with no Caps - Arial based + [B]タイマーセット完了![/B] [COLOR=grey2] - システムがシャットダウンします[/COLOR] + ボタンを押して再生[CR][CR]ムービー予告編 + アルバム詳細 + + + 一時停止 + 停止 + 早送り + 巻き戻し + ムービーメニュー + 字幕をダウンロード + + + + スキンのデフォルト + スキンのデフォルト (小文字のみ) + Arial ベース + + [B]外観設定[/B][CR][CR]スキン選択 - 言語と地域の設定 - ファイル一覧設定変更[CR]スクリーンセーバー設定 [B]ビデオ設定[/B][CR][CR]ビデオライブラリ管理 - ビデオ再生設定 - ビデオ一覧設定変更[CR]字幕用フォント変更 [B]ミュージック設定[/B][CR][CR]ミュージックライブラリ管理 - ミュージック再生設定 - ミュージック一覧設定変更[CR]楽曲送信設定 - カラオケ設定 [B]ピクチャ設定[/B][CR][CR]ピクチャ一覧設定変更[CR]スライドショー設定 [B]天気予報設定[/B][CR][CR]天気情報取得都市選択[CR]天気予報プラグイン選択 - [B]ネットワーク設定[/B][CR][CR]UPnPおよびHTTPによるXBMCの操作設定 - ファイル共有設定[CR]インターネット接続設定 + [B]ネットワーク設定[/B][CR][CR]UPnP および HTTP による XBMCの操作設定 - ファイル共有設定[CR]インターネット接続設定 [B]システム設定[/B][CR][CR]画面の設定・調整 - オーディオ出力設定 - リモートコントローラー設定[CR]省電力設定 - デバッグの有効化 - マスターロック設定 - [B]スキン設定[/B][CR][CR]Confluenceスキン設定 - ホームメニュー項目の追加と削除[CR]スキン背景設定 + [B]スキン設定[/B][CR][CR]Confluence スキン設定 - ホームメニュー項目の追加と削除[CR]スキン背景設定 [B]アドオン設定[/B][CR][CR]インストール済みアドオン管理 - xbmc.orgからアドオンを検索・インストール[CR]アドオン設定変更 - Select your XBMC user Profile[CR]to login and continue + XBMC ユーザープロファイルを選択して[CR]ログインしてください + + + 天気図 + 36時間予報 + 1時間ごとの予報 + 週末の予報 + 10日予報 + 予報 + 天気図 & ビデオ + ビデオ予報 [COLOR=grey2](フルスクリーン再生)[/COLOR] + 降水確率 + 天気予報データ取得中... + diff --git a/addons/skin.confluence/language/Portuguese (Brazil)/strings.xml b/addons/skin.confluence/language/Portuguese (Brazil)/strings.xml index baf62a5..2c93aa0 100644 --- a/addons/skin.confluence/language/Portuguese (Brazil)/strings.xml +++ b/addons/skin.confluence/language/Portuguese (Brazil)/strings.xml @@ -59,7 +59,7 @@ Fundo Exibir "Pausado" em exibição de imagens (slideshow) Tocar trailers em uma janela [COLOR=grey3](Só Diálogo de Informações do Vídeo)[/COLOR] - + "Botão Videos" sempre vai para arquivos de vídeos Opções diversas Ocultar marcadores lidos do arquivo de vídeo [COLOR=grey3](Blu-ray, HD-DVD)[/COLOR] Ocultar botões do Menu Principal @@ -72,6 +72,7 @@ Personalizador Exibir vídeos adicionados recentemente Submenu Programas da Página Principal + Ocultar fanart fundo da visualização RÓTULO DE BOTÃO Página do Tempo Usar "Pôsters" ao invés de "Faixas" para Seriados diff --git a/addons/skin.confluence/language/Slovak/strings.xml b/addons/skin.confluence/language/Slovak/strings.xml index a27326a..09a872f 100644 --- a/addons/skin.confluence/language/Slovak/strings.xml +++ b/addons/skin.confluence/language/Slovak/strings.xml @@ -1,203 +1,164 @@ - - - + + + + + + - Zmeniť Milovať Nenávidieť Napájanie - Pracujem... Skryť informácie - Nastavenie zobrazenia + Možnosti zobrazenia Pluginy Celá obrazovka - Posledné pridané - Video - Súbory - Music - Súbory - Prehráva sa + Hudba - Súbory + Práve hrá Strana Položky - Ďaľšie nastavenia - - Umiestnenie - - + Ďalšie možnosti + Mesto Obaly Fanart Celý Zoznam Náhľady - Obrázky - Info - - - Práve hráme - + Informácie + Práve hrá Prehráva sa PAUZA - PRETÁČA SA DOPREDU PRETÁČA SA DOZADU Vlastnosti zvuku Aktuálna predvolba Predvolby Vizualizácií - Film končí - - Zoradiť: Vzostupne - Zoradiť: Zostupne - - - + Koniec filmu + Ukázať: Vzostupne + Ukázať: Zostupne Otvoriť playlist Uložiť playlist Zatvoriť playlist - Hudobné súbory systému Aktuálny playlist Tento súbor sa skladá z viac častí. Vyberte tu, od ktorej chcete spustit prehrávaníe. Aktuálne vybraný - - - + + Informácie na Domovskej stránke - Pozadie - Zobraziť "PAUZA" pri prezentácií obrázkov - Prehrávať trailer v okne [COLOR=grey3](iba z okna Informácie o videu)[/COLOR] - "Videá" tlačítko vždy ide do "Súbory" + Zobrazovať 'Pauza' pri prezentácií obrázkov + Prehrávať ukážky v okne [COLOR=grey3](iba z okna Detailné Informácie)[/COLOR] + Odkaz 'Videá' automaticky otvorí podmenu 'Súbory' Rôzne nastavenia - Nezobrazovať ikonky zdroja videí [COLOR=grey3](Blu-ray, HD-DVD)[/COLOR] - - Schovať tlačítka hlavného menu + Nezobrazovať ikonky zdroja videa [COLOR=grey3](Blu-ray, HD-DVD)[/COLOR] + Skryť položky hlavného menu Pozadie Domovskej stránky - Zmeniť pozadie domovskej stránky - sekcia - Schovať + Zmeniť pozadie domovskej stránky, pozadie sekciíam + Skryť Možnosti Jeden obrázok - Viac obrázkov Prispôsobenie - - Zobraziť Posledné pridané + + + Zobrazovať Posledné pridané Domovská stránka - Schovať Fanart na pozadí - + Skryť Fanart na pozadí NÁZOV POLOŽKY - + + Počasie - Použiť u TV seriálov klasické náhlady namiesto širokouhlých - Zobraziť na pozadí "Práve hráme" Video - Zobraziť na pozadí "Práve hráme" Vizualizáciu - + Používať klasické náhľady 'Plagáty' namiesto 'Banerov' + Zobrazovať práve prehrávané video na pozadí + Zobrazovať vizualizáciu na pozadí Prehrávať skladbu TV seriálu vo video knižnici (TvTunes doplnok) TvTunes Texty skladieb - - - - - Texty skladieb Doplnok - Titulky Doplnok - Domovská stránka Videá Podmenu - Domovská stránka Hudba Podmenu - Domovská stránka Obrázky Podmenu - + + + + + + + Doplnok Texty skladieb + Doplnok Titulky + Domovská stránka / podmenu videá + Domovská stránka / podmenu hudba + Domovská stránka / podmenu obrázky Hudobný OSD Video OSD - - Odkazy Kategórie - Zobraziť účinkujúcich - + Zobrazovať účinkujúcich Vyberte Vašu skladbu Odkazy Sekcií Zdroj textov skladieb - - Aktuálna teplota Naposledy aktualizované - Menu - + Počasie Vám prináša Obrázok Židny disk nie je vložený Vysunúť - Schovať Fanart - - Detaili o filme + Skryť Fanart + Informácie Použitá pamäť: Číslo skladby Fanart obrázok[CR][CR]Nedostupný[CR][CR] Klik pre nastavenie Aktuálny sťahovač Vyber sťahovač - Možnosti vyhľadávania obsahu Základné - - Umiestneni FanArtu + + + Nájsť FanArt Malý Fanart Vybratý Profil - Posledné prihlásenie Výber Karaoke skladby Vysielané Posledné Filmy Posledné Epizódy Nastavenia Playlistu - Vytvorené Rozlíšenie Posledné pridané [B]Časovač nastavený![/B] [COLOR=grey2] - Systém sa automaticky vypne za[/COLOR] - Pre prehratie traileru[CR][CR]stlačte tlačítko + Pre spustenie ukážky[CR][CR]stlačte tlačítko Album Details - - Pauza Zastaviť Pretočiť dopredu Pretočiť dozadu Menu filmu - Stiahnuť titulky - - - - Predvolený Skin - Predvolený Skin bez Caps + + + Predvolený vzhľad + Predvolený vzhľad bez veľkých písmen Arial - - [B]MOŽNOSTI PROSTREDIA[/B][CR][CR]Zmena vzhľadu · Výber jazyka a oblasti · Možnosti zobrazenia súborov[CR]Nastavenie šporiča obrazovky - [B]MOŽNOSTI VIDEA[/B][CR][CR]Správa knižnice videí · Možnosti prehrávania videa · Možnosti zobrazenia video súborov[CR]Nastavenie fontu titulkov - [B]MOŽNOSTI HUDBY[/B][CR][CR]Správa knižnice hudby · Možnosti prehrávania hudby · Možnosti zobrazenia hud. súborov[CR]Služby pre odosielanie informácií o prehrávaných skladbách · Nastavenie karaoke - [B]MOŽNOSTI OBRÁZKOV[/B][CR][CR]Možnosti zobrazenia obrázkov · Konfigurácia prezentácie - [B]MOŽNOSTI POČASIA[/B][CR][CR]Nastavenie oblastí pre predpoveď počasia - + [B]MOŽNOSTI VIDEA[/B][CR][CR]Správa knižnice videí · Možnosti prehrávania videa · Zobrazenie video súborov[CR]Nastavenie titulkov + [B]MOŽNOSTI HUDBY[/B][CR][CR]Správa knižnice hudby · Možnosti prehrávania hudby · Zobrazenie hudobných súborov[CR]Služby pre odosielanie informácií o prehrávaných skladbách · Karaoke nastavenia + [B]MOŽNOSTI OBRÁZKOV[/B][CR][CR]Možnosti zobrazenia obrázkov · Nastavenie prezentácie + [B]MOŽNOSTI POČASIA[/B][CR][CR]Nastavenie oblastí pre ktoré si prajete získavať predpoveď počasia [B]MOŽNOSTI SIETE[/B][CR][CR]Možnosti ovládania XBMC cez UPnP a HTTP · Nastavenie zdieľania médií[CR]Nastavenie prístupu na internet - [B]MOŽNOSTI SYSTÉMU[/B][CR][CR]Nastavenie a kalibrácia obrazovky · Konfigurácia výstupu zvuku · Nastavenie ovládača[CR]Možnosti úsporného režimu · Ukladanie informácií · Konfigurácia rodičovského zámku - [B]MOŽNOSTI VZHĽADU[/B][CR][CR]Prispôsobenie vzhľadu Confluence · Správa sekcií na domovskej stránke[CR]Nastavenia pozadí vzhľadu + [B]MOŽNOSTI SYSTÉMU[/B][CR][CR]Nastavenie obrazovky · Nastavenie zvukového výstupu[CR]Možnosti úsporného režimu · Ukladanie informácií · Konfigurácia rodičovského zámku + [B]MOŽNOSTI VZHĽADU[/B][CR][CR]Prispôsobenie vzhľadu Confluence · Správa sekcií na domovskej stránke[CR]Nastavenie pozadia vzhľadu [B]MOŽNOSTI DOPLNKOV[/B][CR][CR]Správa nainštalovaných doplnkov · Vyhľadávanie a inštalácia doplnkov z xbmc.org[CR]Nastavenie doplnkov - Prihlásenie užívateľa[CR]Pokračujte výberom profilu - - - - Mapy Počasia - 36 Hodinová Predpoveď - Hodinová Predpoveď + Mapy počasia + 36 Hodinová predpoveď + Hodinová predpoveď Predpoveď na víkend Predpoveď na 10 dní Predpoveď - Mapy & Video Video Predpoveď [COLOR=grey2](Prehrávanie na celej obrazovke)[/COLOR] Šanca zrážok - Zisťujem info o počasí... - - + Zisťujem informácie o počasí... + \ No newline at end of file diff --git a/addons/skin.confluence/language/Slovenian/strings.xml b/addons/skin.confluence/language/Slovenian/strings.xml index 4ff3252..e75f9f0 100644 --- a/addons/skin.confluence/language/Slovenian/strings.xml +++ b/addons/skin.confluence/language/Slovenian/strings.xml @@ -162,8 +162,21 @@ [B]PRILAGODITE NASTAVITVE SISTEMA[/B][CR][CR]Nastavite in prilagodite zaslon • Nastavite zvočni izhod • Nastavite oddaljeno upravljanje[CR]Nastavite varčevanje z energijo • Vključite razhroščevanje • Določite glavno geslo [B]PRILAGODITE NASTAVITVE PREOBLEKE[/B][CR][CR]Nastavite preobleko Confluence • Dodajte in odstranite elemente na domačem oknu[CR]Spremenite ozadja preobleke [B]PRILAGODITE DODATKE[/B][CR][CR]Upravljajte nameščene dodatke • Brskajte in namestite nove dodatke iz xbmc.org[CR]Nastavite dodatke + [B]PRILAGODITE NASTAVITVE TV[/B][CR][CR]Spremenite informacije v celozaslonskem načinu • Upravljajte z nastavitvami EPG Izberite vaš XBMC uporabniški profil[CR]za prijavo in nadaljujte + + + Časovniki snemanja + Nastavljen čas + TV v živo + Dodaj skupino + Preimenuj skupino + Izbriši skupino + Skupina[CR]na razpolago + Skupina programov + Nastavljen časovnik + Možnosti programa Vremenska slika diff --git a/addons/skin.confluence/media/OSDChannelDownFO.png b/addons/skin.confluence/media/OSDChannelDownFO.png new file mode 100644 index 0000000..5116c32 Binary files /dev/null and b/addons/skin.confluence/media/OSDChannelDownFO.png differ diff --git a/addons/skin.confluence/media/OSDChannelDownNF.png b/addons/skin.confluence/media/OSDChannelDownNF.png new file mode 100644 index 0000000..6795c43 Binary files /dev/null and b/addons/skin.confluence/media/OSDChannelDownNF.png differ diff --git a/addons/skin.confluence/media/OSDChannelListFO.png b/addons/skin.confluence/media/OSDChannelListFO.png new file mode 100644 index 0000000..a08bc13 Binary files /dev/null and b/addons/skin.confluence/media/OSDChannelListFO.png differ diff --git a/addons/skin.confluence/media/OSDChannelListNF.png b/addons/skin.confluence/media/OSDChannelListNF.png new file mode 100644 index 0000000..8339fdc Binary files /dev/null and b/addons/skin.confluence/media/OSDChannelListNF.png differ diff --git a/addons/skin.confluence/media/OSDChannelUPFO.png b/addons/skin.confluence/media/OSDChannelUPFO.png new file mode 100644 index 0000000..a3e6dba Binary files /dev/null and b/addons/skin.confluence/media/OSDChannelUPFO.png differ diff --git a/addons/skin.confluence/media/OSDChannelUPNF.png b/addons/skin.confluence/media/OSDChannelUPNF.png new file mode 100644 index 0000000..47e6e33 Binary files /dev/null and b/addons/skin.confluence/media/OSDChannelUPNF.png differ diff --git a/addons/skin.confluence/media/OSDRecord2.png b/addons/skin.confluence/media/OSDRecord2.png deleted file mode 100644 index cb4fcf9..0000000 Binary files a/addons/skin.confluence/media/OSDRecord2.png and /dev/null differ diff --git a/addons/skin.confluence/media/OSDRecordFO.png b/addons/skin.confluence/media/OSDRecordFO.png deleted file mode 100644 index fd2bb18..0000000 Binary files a/addons/skin.confluence/media/OSDRecordFO.png and /dev/null differ diff --git a/addons/skin.confluence/media/OSDRecordNF.png b/addons/skin.confluence/media/OSDRecordNF.png deleted file mode 100644 index db3d575..0000000 Binary files a/addons/skin.confluence/media/OSDRecordNF.png and /dev/null differ diff --git a/addons/skin.confluence/media/OSDRecordOff.png b/addons/skin.confluence/media/OSDRecordOff.png deleted file mode 100644 index cb73c77..0000000 Binary files a/addons/skin.confluence/media/OSDRecordOff.png and /dev/null differ diff --git a/addons/skin.confluence/media/OSDRecordOffFO.png b/addons/skin.confluence/media/OSDRecordOffFO.png new file mode 100644 index 0000000..fd2bb18 Binary files /dev/null and b/addons/skin.confluence/media/OSDRecordOffFO.png differ diff --git a/addons/skin.confluence/media/OSDRecordOffNF.png b/addons/skin.confluence/media/OSDRecordOffNF.png new file mode 100644 index 0000000..db3d575 Binary files /dev/null and b/addons/skin.confluence/media/OSDRecordOffNF.png differ diff --git a/addons/skin.confluence/media/OSDRecordOnFO.png b/addons/skin.confluence/media/OSDRecordOnFO.png new file mode 100644 index 0000000..cb4fcf9 Binary files /dev/null and b/addons/skin.confluence/media/OSDRecordOnFO.png differ diff --git a/addons/skin.confluence/media/OSDRecordOnNF.png b/addons/skin.confluence/media/OSDRecordOnNF.png new file mode 100644 index 0000000..b335818 Binary files /dev/null and b/addons/skin.confluence/media/OSDRecordOnNF.png differ diff --git a/addons/skin.confluence/media/OSDTeleTextFO.png b/addons/skin.confluence/media/OSDTeleTextFO.png new file mode 100644 index 0000000..53eb576 Binary files /dev/null and b/addons/skin.confluence/media/OSDTeleTextFO.png differ diff --git a/addons/skin.confluence/media/OSDTeleTextNF.png b/addons/skin.confluence/media/OSDTeleTextNF.png new file mode 100644 index 0000000..111c068 Binary files /dev/null and b/addons/skin.confluence/media/OSDTeleTextNF.png differ diff --git a/addons/skin.confluence/media/OSDepgFO.png b/addons/skin.confluence/media/OSDepgFO.png new file mode 100644 index 0000000..141f7ad Binary files /dev/null and b/addons/skin.confluence/media/OSDepgFO.png differ diff --git a/addons/skin.confluence/media/OSDepgNF.png b/addons/skin.confluence/media/OSDepgNF.png new file mode 100644 index 0000000..cf9a86b Binary files /dev/null and b/addons/skin.confluence/media/OSDepgNF.png differ diff --git a/addons/skin.confluence/media/PVR-HasTimer.png b/addons/skin.confluence/media/PVR-HasTimer.png new file mode 100644 index 0000000..99c2ee9 Binary files /dev/null and b/addons/skin.confluence/media/PVR-HasTimer.png differ diff --git a/addons/skin.confluence/media/PVR-IsRecording.png b/addons/skin.confluence/media/PVR-IsRecording.png new file mode 100644 index 0000000..e64b346 Binary files /dev/null and b/addons/skin.confluence/media/PVR-IsRecording.png differ diff --git a/addons/skin.confluence/media/StackNF.png b/addons/skin.confluence/media/StackNF.png index 17e50526..0cbcd83 100644 Binary files a/addons/skin.confluence/media/StackNF.png and b/addons/skin.confluence/media/StackNF.png differ diff --git a/addons/skin.confluence/media/epg-genres/0.png b/addons/skin.confluence/media/epg-genres/0.png new file mode 100644 index 0000000..80c6192 Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/0.png differ diff --git a/addons/skin.confluence/media/epg-genres/112.png b/addons/skin.confluence/media/epg-genres/112.png new file mode 100644 index 0000000..7701fc6 Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/112.png differ diff --git a/addons/skin.confluence/media/epg-genres/128.png b/addons/skin.confluence/media/epg-genres/128.png new file mode 100644 index 0000000..3071d4e Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/128.png differ diff --git a/addons/skin.confluence/media/epg-genres/144.png b/addons/skin.confluence/media/epg-genres/144.png new file mode 100644 index 0000000..a9325a6 Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/144.png differ diff --git a/addons/skin.confluence/media/epg-genres/16.png b/addons/skin.confluence/media/epg-genres/16.png new file mode 100644 index 0000000..ffaae9e Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/16.png differ diff --git a/addons/skin.confluence/media/epg-genres/160.png b/addons/skin.confluence/media/epg-genres/160.png new file mode 100644 index 0000000..8d825ab Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/160.png differ diff --git a/addons/skin.confluence/media/epg-genres/176.png b/addons/skin.confluence/media/epg-genres/176.png new file mode 100644 index 0000000..7ae6320 Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/176.png differ diff --git a/addons/skin.confluence/media/epg-genres/192.png b/addons/skin.confluence/media/epg-genres/192.png new file mode 100644 index 0000000..80c6192 Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/192.png differ diff --git a/addons/skin.confluence/media/epg-genres/208.png b/addons/skin.confluence/media/epg-genres/208.png new file mode 100644 index 0000000..80c6192 Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/208.png differ diff --git a/addons/skin.confluence/media/epg-genres/224.png b/addons/skin.confluence/media/epg-genres/224.png new file mode 100644 index 0000000..80c6192 Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/224.png differ diff --git a/addons/skin.confluence/media/epg-genres/240.png b/addons/skin.confluence/media/epg-genres/240.png new file mode 100644 index 0000000..80c6192 Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/240.png differ diff --git a/addons/skin.confluence/media/epg-genres/32.png b/addons/skin.confluence/media/epg-genres/32.png new file mode 100644 index 0000000..be2bc8e Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/32.png differ diff --git a/addons/skin.confluence/media/epg-genres/48.png b/addons/skin.confluence/media/epg-genres/48.png new file mode 100644 index 0000000..57b4dee Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/48.png differ diff --git a/addons/skin.confluence/media/epg-genres/64.png b/addons/skin.confluence/media/epg-genres/64.png new file mode 100644 index 0000000..d85eb05 Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/64.png differ diff --git a/addons/skin.confluence/media/epg-genres/80.png b/addons/skin.confluence/media/epg-genres/80.png new file mode 100644 index 0000000..cdd6da3 Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/80.png differ diff --git a/addons/skin.confluence/media/epg-genres/96.png b/addons/skin.confluence/media/epg-genres/96.png new file mode 100644 index 0000000..ba92ae3 Binary files /dev/null and b/addons/skin.confluence/media/epg-genres/96.png differ diff --git a/addons/skin.confluence/media/epg-genres/genre-numbers.txt b/addons/skin.confluence/media/epg-genres/genre-numbers.txt new file mode 100644 index 0000000..031732b --- /dev/null +++ b/addons/skin.confluence/media/epg-genres/genre-numbers.txt @@ -0,0 +1,18 @@ +Genre Numbers set internally by XBMC + +0 = other/unknown +16 = moviedrama +32 = news +48 = show +64 = sports +80 = child +96 = music +112 = arts +128 = social +144 = science +160 = hobby +176 = special +192 = other/unknown +208 = other/unknown +224 = other/unknown +240 = other/unknown diff --git a/addons/skin.confluence/media/gradient.png b/addons/skin.confluence/media/gradient.png new file mode 100644 index 0000000..7db158f Binary files /dev/null and b/addons/skin.confluence/media/gradient.png differ diff --git a/addons/skin.confluence/media/home-power-inhibit-FO.png b/addons/skin.confluence/media/home-power-inhibit-FO.png new file mode 100644 index 0000000..3656ffa Binary files /dev/null and b/addons/skin.confluence/media/home-power-inhibit-FO.png differ diff --git a/addons/skin.confluence/media/home-power-inhibit.png b/addons/skin.confluence/media/home-power-inhibit.png new file mode 100644 index 0000000..b90d844 Binary files /dev/null and b/addons/skin.confluence/media/home-power-inhibit.png differ diff --git a/addons/webinterface.default/js/iscroll.js b/addons/webinterface.default/js/iscroll.js new file mode 100644 index 0000000..693e0e7 --- /dev/null +++ b/addons/webinterface.default/js/iscroll.js @@ -0,0 +1,709 @@ +/** + * + * Find more about the scrolling function at + * http://cubiq.org/iscroll + * + * Copyright (c) 2010 Matteo Spinelli, http://cubiq.org/ + * Released under MIT license + * http://cubiq.org/dropbox/mit-license.txt + * + * Version 3.6 - Last updated: 2010.08.24 + * + */ + +(function(){ +function iScroll (el, options) { + var that = this, i; + that.element = typeof el == 'object' ? el : document.getElementById(el); + that.wrapper = that.element.parentNode; + + that.element.style.webkitTransitionProperty = '-webkit-transform'; + that.element.style.webkitTransitionTimingFunction = 'cubic-bezier(0,0,0.25,1)'; + that.element.style.webkitTransitionDuration = '0'; + that.element.style.webkitTransform = translateOpen + '0,0' + translateClose; + + // Default options + that.options = { + bounce: has3d, + momentum: has3d, + checkDOMChanges: true, + topOnDOMChanges: false, + hScrollbar: has3d, + vScrollbar: has3d, + fadeScrollbar: isIphone || isIpad || !isTouch, + shrinkScrollbar: isIphone || isIpad || !isTouch, + desktopCompatibility: false, + overflow: 'hidden', + snap: false + }; + + // User defined options + if (typeof options == 'object') { + for (i in options) { + that.options[i] = options[i]; + } + } + + if (that.options.desktopCompatibility) { + that.options.overflow = 'hidden'; + } + + that.wrapper.style.overflow = that.options.overflow; + + that.refresh(); + + window.addEventListener('onorientationchange' in window ? 'orientationchange' : 'resize', that, false); + + if (isTouch || that.options.desktopCompatibility) { + that.element.addEventListener(START_EVENT, that, false); + that.element.addEventListener(MOVE_EVENT, that, false); + that.element.addEventListener(END_EVENT, that, false); + } + + if (that.options.checkDOMChanges) { + that.element.addEventListener('DOMSubtreeModified', that, false); + } +} + +iScroll.prototype = { + x: 0, + y: 0, + enabled: true, + + handleEvent: function (e) { + var that = this; + + switch (e.type) { + case START_EVENT: + that.touchStart(e); + break; + case MOVE_EVENT: + that.touchMove(e); + break; + case END_EVENT: + that.touchEnd(e); + break; + case 'webkitTransitionEnd': + that.transitionEnd(); + break; + case 'orientationchange': + case 'resize': + that.refresh(); + break; + case 'DOMSubtreeModified': + that.onDOMModified(e); + break; + } + }, + + onDOMModified: function (e) { + var that = this; + + // (Hopefully) execute onDOMModified only once + if (e.target.parentNode != that.element) { + return; + } + + setTimeout(function () { that.refresh(); }, 0); + + if (that.options.topOnDOMChanges && (that.x!=0 || that.y!=0)) { + that.scrollTo(0,0,'0'); + } + }, + + refresh: function () { + var that = this, + resetX = this.x, resetY = this.y, + snap; + + that.scrollWidth = that.wrapper.clientWidth; + that.scrollHeight = that.wrapper.clientHeight; + that.scrollerWidth = that.element.offsetWidth; + that.scrollerHeight = that.element.offsetHeight; + that.maxScrollX = that.scrollWidth - that.scrollerWidth; + that.maxScrollY = that.scrollHeight - that.scrollerHeight; + that.directionX = 0; + that.directionY = 0; + + if (that.scrollX) { + if (that.maxScrollX >= 0) { + resetX = 0; + } else if (that.x < that.maxScrollX) { + resetX = that.maxScrollX; + } + } + if (that.scrollY) { + if (that.maxScrollY >= 0) { + resetY = 0; + } else if (that.y < that.maxScrollY) { + resetY = that.maxScrollY; + } + } + // Snap + if (that.options.snap) { + that.maxPageX = -Math.floor(that.maxScrollX/that.scrollWidth); + that.maxPageY = -Math.floor(that.maxScrollY/that.scrollHeight); + + snap = that.snap(resetX, resetY); + resetX = snap.x; + resetY = snap.y; + } + + if (resetX!=that.x || resetY!=that.y) { + that.setTransitionTime('0'); + that.setPosition(resetX, resetY, true); + } + + that.scrollX = that.scrollerWidth > that.scrollWidth; + that.scrollY = !that.scrollX || that.scrollerHeight > that.scrollHeight; + + // Update horizontal scrollbar + if (that.options.hScrollbar && that.scrollX) { + that.scrollBarX = that.scrollBarX || new scrollbar('horizontal', that.wrapper, that.options.fadeScrollbar, that.options.shrinkScrollbar); + that.scrollBarX.init(that.scrollWidth, that.scrollerWidth); + } else if (that.scrollBarX) { + that.scrollBarX = that.scrollBarX.remove(); + } + + // Update vertical scrollbar + if (that.options.vScrollbar && that.scrollY && that.scrollerHeight > that.scrollHeight) { + that.scrollBarY = that.scrollBarY || new scrollbar('vertical', that.wrapper, that.options.fadeScrollbar, that.options.shrinkScrollbar); + that.scrollBarY.init(that.scrollHeight, that.scrollerHeight); + } else if (that.scrollBarY) { + that.scrollBarY = that.scrollBarY.remove(); + } + }, + + setPosition: function (x, y, hideScrollBars) { + var that = this; + + that.x = x; + that.y = y; + + that.element.style.webkitTransform = translateOpen + that.x + 'px,' + that.y + 'px' + translateClose; + + // Move the scrollbars + if (!hideScrollBars) { + if (that.scrollBarX) { + that.scrollBarX.setPosition(that.x); + } + if (that.scrollBarY) { + that.scrollBarY.setPosition(that.y); + } + } + }, + + setTransitionTime: function(time) { + var that = this; + + time = time || '0'; + that.element.style.webkitTransitionDuration = time; + + if (that.scrollBarX) { + that.scrollBarX.bar.style.webkitTransitionDuration = time; + that.scrollBarX.wrapper.style.webkitTransitionDuration = has3d && that.options.fadeScrollbar ? '300ms' : '0'; + } + if (that.scrollBarY) { + that.scrollBarY.bar.style.webkitTransitionDuration = time; + that.scrollBarY.wrapper.style.webkitTransitionDuration = has3d && that.options.fadeScrollbar ? '300ms' : '0'; + } + }, + + touchStart: function(e) { + var that = this, + matrix; + + e.preventDefault(); + e.stopPropagation(); + + if (!that.enabled) { + return; + } + + that.scrolling = true; // This is probably not needed, but may be useful if iScroll is used in conjuction with other frameworks + + that.moved = false; + that.dist = 0; + + that.setTransitionTime('0'); + + // Check if the scroller is really where it should be + if (that.options.momentum || that.options.snap) { + matrix = new WebKitCSSMatrix(window.getComputedStyle(that.element).webkitTransform); + if (matrix.e != that.x || matrix.f != that.y) { + document.removeEventListener('webkitTransitionEnd', that, false); + that.setPosition(matrix.e, matrix.f); + that.moved = true; + } + } + + that.touchStartX = isTouch ? e.changedTouches[0].pageX : e.pageX; + that.scrollStartX = that.x; + + that.touchStartY = isTouch ? e.changedTouches[0].pageY : e.pageY; + that.scrollStartY = that.y; + + that.scrollStartTime = e.timeStamp; + + that.directionX = 0; + that.directionY = 0; + }, + + touchMove: function(e) { + var that = this, + pageX = isTouch ? e.changedTouches[0].pageX : e.pageX, + pageY = isTouch ? e.changedTouches[0].pageY : e.pageY, + leftDelta = that.scrollX ? pageX - that.touchStartX : 0, + topDelta = that.scrollY ? pageY - that.touchStartY : 0, + newX = that.x + leftDelta, + newY = that.y + topDelta; + + if (!that.scrolling) { + return; + } + + //e.preventDefault(); + e.stopPropagation(); // Stopping propagation just saves some cpu cycles (I presume) + + that.touchStartX = pageX; + that.touchStartY = pageY; + + // Slow down if outside of the boundaries + if (newX >= 0 || newX < that.maxScrollX) { + newX = that.options.bounce ? Math.round(that.x + leftDelta / 3) : (newX >= 0 || that.maxScrollX>=0) ? 0 : that.maxScrollX; + } + if (newY >= 0 || newY < that.maxScrollY) { + newY = that.options.bounce ? Math.round(that.y + topDelta / 3) : (newY >= 0 || that.maxScrollY>=0) ? 0 : that.maxScrollY; + } + + if (that.dist > 5) { // 5 pixels threshold is needed on Android, but also on iPhone looks more natural + that.setPosition(newX, newY); + that.moved = true; + that.directionX = leftDelta > 0 ? -1 : 1; + that.directionY = topDelta > 0 ? -1 : 1; + } else { + that.dist+= Math.abs(leftDelta) + Math.abs(topDelta); + } + }, + + touchEnd: function(e) { + var that = this, + time = e.timeStamp - that.scrollStartTime, + point = isTouch ? e.changedTouches[0] : e, + target, ev, + momentumX, momentumY, + newDuration = 0, + newPositionX = that.x, newPositionY = that.y, + snap; + + if (!that.scrolling) { + return; + } + that.scrolling = false; + + if (!that.moved) { + that.resetPosition(); + + if (isTouch) { + // Find the last touched element + target = point.target; + while (target.nodeType != 1) { + target = target.parentNode; + } + + // Create the fake event + target.style.pointerEvents = 'auto'; + ev = document.createEvent('MouseEvents'); + ev.initMouseEvent('click', true, true, e.view, 1, + point.screenX, point.screenY, point.clientX, point.clientY, + e.ctrlKey, e.altKey, e.shiftKey, e.metaKey, + 0, null); + ev._fake = true; + target.dispatchEvent(ev); + } + + return; + } + + if (!that.options.snap && time > 250) { // Prevent slingshot effect + that.resetPosition(); + return; + } + + if (that.options.momentum) { + momentumX = that.scrollX === true + ? that.momentum(that.x - that.scrollStartX, + time, + that.options.bounce ? -that.x + that.scrollWidth/5 : -that.x, + that.options.bounce ? that.x + that.scrollerWidth - that.scrollWidth + that.scrollWidth/5 : that.x + that.scrollerWidth - that.scrollWidth) + : { dist: 0, time: 0 }; + + momentumY = that.scrollY === true + ? that.momentum(that.y - that.scrollStartY, + time, + that.options.bounce ? -that.y + that.scrollHeight/5 : -that.y, + that.options.bounce ? (that.maxScrollY < 0 ? that.y + that.scrollerHeight - that.scrollHeight : 0) + that.scrollHeight/5 : that.y + that.scrollerHeight - that.scrollHeight) + : { dist: 0, time: 0 }; + + newDuration = Math.max(Math.max(momentumX.time, momentumY.time), 1); // The minimum animation length must be 1ms + newPositionX = that.x + momentumX.dist; + newPositionY = that.y + momentumY.dist; + } + + if (that.options.snap) { + snap = that.snap(newPositionX, newPositionY); + newPositionX = snap.x; + newPositionY = snap.y; + newDuration = Math.max(snap.time, newDuration); + } + + that.scrollTo(newPositionX, newPositionY, newDuration + 'ms'); + }, + + transitionEnd: function () { + var that = this; + document.removeEventListener('webkitTransitionEnd', that, false); + that.resetPosition(); + }, + + resetPosition: function () { + var that = this, + resetX = that.x, + resetY = that.y; + + if (that.x >= 0) { + resetX = 0; + } else if (that.x < that.maxScrollX) { + resetX = that.maxScrollX; + } + + if (that.y >= 0 || that.maxScrollY > 0) { + resetY = 0; + } else if (that.y < that.maxScrollY) { + resetY = that.maxScrollY; + } + + if (resetX != that.x || resetY != that.y) { + that.scrollTo(resetX, resetY); + } else { + if (that.moved) { + that.onScrollEnd(); // Execute custom code on scroll end + that.moved = false; + } + + // Hide the scrollbars + if (that.scrollBarX) { + that.scrollBarX.hide(); + } + if (that.scrollBarY) { + that.scrollBarY.hide(); + } + } + }, + + snap: function (x, y) { + var that = this, time; + + if (that.directionX > 0) { + x = Math.floor(x/that.scrollWidth); + } else if (that.directionX < 0) { + x = Math.ceil(x/that.scrollWidth); + } else { + x = Math.round(x/that.scrollWidth); + } + that.pageX = -x; + x = x * that.scrollWidth; + if (x > 0) { + x = that.pageX = 0; + } else if (x < that.maxScrollX) { + that.pageX = that.maxPageX; + x = that.maxScrollX; + } + + if (that.directionY > 0) { + y = Math.floor(y/that.scrollHeight); + } else if (that.directionY < 0) { + y = Math.ceil(y/that.scrollHeight); + } else { + y = Math.round(y/that.scrollHeight); + } + that.pageY = -y; + y = y * that.scrollHeight; + if (y > 0) { + y = that.pageY = 0; + } else if (y < that.maxScrollY) { + that.pageY = that.maxPageY; + y = that.maxScrollY; + } + + // Snap with constant speed (proportional duration) + time = Math.round(Math.max( + Math.abs(that.x - x) / that.scrollWidth * 500, + Math.abs(that.y - y) / that.scrollHeight * 500 + )); + + return { x: x, y: y, time: time }; + }, + + scrollTo: function (destX, destY, runtime) { + var that = this; + + if (that.x == destX && that.y == destY) { + that.resetPosition(); + return; + } + + that.moved = true; + that.setTransitionTime(runtime || '350ms'); + that.setPosition(destX, destY); + + if (runtime==='0' || runtime=='0s' || runtime=='0ms') { + that.resetPosition(); + } else { + document.addEventListener('webkitTransitionEnd', that, false); // At the end of the transition check if we are still inside of the boundaries + } + }, + + scrollToPage: function (pageX, pageY, runtime) { + var that = this, snap; + + if (!that.options.snap) { + that.pageX = -Math.round(that.x / that.scrollWidth); + that.pageY = -Math.round(that.y / that.scrollHeight); + } + + if (pageX == 'next') { + pageX = ++that.pageX; + } else if (pageX == 'prev') { + pageX = --that.pageX; + } + + if (pageY == 'next') { + pageY = ++that.pageY; + } else if (pageY == 'prev') { + pageY = --that.pageY; + } + + pageX = -pageX*that.scrollWidth; + pageY = -pageY*that.scrollHeight; + + snap = that.snap(pageX, pageY); + pageX = snap.x; + pageY = snap.y; + + that.scrollTo(pageX, pageY, runtime || '500ms'); + }, + + scrollToElement: function (el, runtime) { + el = typeof el == 'object' ? el : this.element.querySelector(el); + + if (!el) { + return; + } + + var that = this, + x = that.scrollX ? -el.offsetLeft : 0, + y = that.scrollY ? -el.offsetTop : 0; + + if (x >= 0) { + x = 0; + } else if (x < that.maxScrollX) { + x = that.maxScrollX; + } + + if (y >= 0) { + y = 0; + } else if (y < that.maxScrollY) { + y = that.maxScrollY; + } + + that.scrollTo(x, y, runtime); + }, + + momentum: function (dist, time, maxDistUpper, maxDistLower) { + var friction = 2.5, + deceleration = 1.2, + speed = Math.abs(dist) / time * 1000, + newDist = speed * speed / friction / 1000, + newTime = 0; + + // Proportinally reduce speed if we are outside of the boundaries + if (dist > 0 && newDist > maxDistUpper) { + speed = speed * maxDistUpper / newDist / friction; + newDist = maxDistUpper; + } else if (dist < 0 && newDist > maxDistLower) { + speed = speed * maxDistLower / newDist / friction; + newDist = maxDistLower; + } + + newDist = newDist * (dist < 0 ? -1 : 1); + newTime = speed / deceleration; + + return { dist: Math.round(newDist), time: Math.round(newTime) }; + }, + + onScrollEnd: function () {}, + + destroy: function (full) { + var that = this; + + window.removeEventListener('onorientationchange' in window ? 'orientationchange' : 'resize', that, false); + that.element.removeEventListener(START_EVENT, that, false); + that.element.removeEventListener(MOVE_EVENT, that, false); + that.element.removeEventListener(END_EVENT, that, false); + document.removeEventListener('webkitTransitionEnd', that, false); + + if (that.options.checkDOMChanges) { + that.element.removeEventListener('DOMSubtreeModified', that, false); + } + + if (that.scrollBarX) { + that.scrollBarX = that.scrollBarX.remove(); + } + + if (that.scrollBarY) { + that.scrollBarY = that.scrollBarY.remove(); + } + + if (full) { + that.wrapper.parentNode.removeChild(that.wrapper); + } + + return null; + } +}; + +function scrollbar (dir, wrapper, fade, shrink) { + var that = this, style; + + that.dir = dir; + that.fade = fade; + that.shrink = shrink; + that.uid = ++uid; + + // Create main scrollbar + that.bar = document.createElement('div'); + + style = 'position:absolute;top:0;left:0;-webkit-transition-timing-function:cubic-bezier(0,0,0.25,1);pointer-events:none;-webkit-transition-duration:0;-webkit-transition-delay:0;-webkit-transition-property:-webkit-transform;z-index:10;background:rgba(0,0,0,0.5);' + + '-webkit-transform:' + translateOpen + '0,0' + translateClose + ';' + + (dir == 'horizontal' ? '-webkit-border-radius:3px 2px;min-width:6px;min-height:5px' : '-webkit-border-radius:2px 3px;min-width:5px;min-height:6px'); + + that.bar.setAttribute('style', style); + + // Create scrollbar wrapper + that.wrapper = document.createElement('div'); + style = '-webkit-mask:-webkit-canvas(scrollbar' + that.uid + that.dir + ');position:absolute;z-index:10;pointer-events:none;overflow:hidden;opacity:0;-webkit-transition-duration:' + (fade ? '300ms' : '0') + ';-webkit-transition-delay:0;-webkit-transition-property:opacity;' + + (that.dir == 'horizontal' ? 'bottom:2px;left:2px;right:7px;height:5px' : 'top:2px;right:2px;bottom:7px;width:5px;'); + that.wrapper.setAttribute('style', style); + + // Add scrollbar to the DOM + that.wrapper.appendChild(that.bar); + wrapper.appendChild(that.wrapper); +} + +scrollbar.prototype = { + init: function (scroll, size) { + var that = this, + ctx; + + // Create scrollbar mask + if (that.dir == 'horizontal') { + if (that.maxSize != that.wrapper.offsetWidth) { + that.maxSize = that.wrapper.offsetWidth; + ctx = document.getCSSCanvasContext("2d", "scrollbar" + that.uid + that.dir, that.maxSize, 5); + ctx.fillStyle = "rgb(0,0,0)"; + ctx.beginPath(); + ctx.arc(2.5, 2.5, 2.5, Math.PI/2, -Math.PI/2, false); + ctx.lineTo(that.maxSize-2.5, 0); + ctx.arc(that.maxSize-2.5, 2.5, 2.5, -Math.PI/2, Math.PI/2, false); + ctx.closePath(); + ctx.fill(); + } + } else { + if (that.maxSize != that.wrapper.offsetHeight) { + that.maxSize = that.wrapper.offsetHeight; + ctx = document.getCSSCanvasContext("2d", "scrollbar" + that.uid + that.dir, 5, that.maxSize); + ctx.fillStyle = "rgb(0,0,0)"; + ctx.beginPath(); + ctx.arc(2.5, 2.5, 2.5, Math.PI, 0, false); + ctx.lineTo(5, that.maxSize-2.5); + ctx.arc(2.5, that.maxSize-2.5, 2.5, 0, Math.PI, false); + ctx.closePath(); + ctx.fill(); + } + } + + that.size = Math.max(Math.round(that.maxSize * that.maxSize / size), 6); + that.maxScroll = that.maxSize - that.size; + that.toWrapperProp = that.maxScroll / (scroll - size); + that.bar.style[that.dir == 'horizontal' ? 'width' : 'height'] = that.size + 'px'; + }, + + setPosition: function (pos) { + var that = this; + + if (that.wrapper.style.opacity != '1') { + that.show(); + } + + pos = Math.round(that.toWrapperProp * pos); + + if (pos < 0) { + pos = that.shrink ? pos + pos*3 : 0; + if (that.size + pos < 7) { + pos = -that.size + 6; + } + } else if (pos > that.maxScroll) { + pos = that.shrink ? pos + (pos-that.maxScroll)*3 : that.maxScroll; + if (that.size + that.maxScroll - pos < 7) { + pos = that.size + that.maxScroll - 6; + } + } + + pos = that.dir == 'horizontal' + ? translateOpen + pos + 'px,0' + translateClose + : translateOpen + '0,' + pos + 'px' + translateClose; + + that.bar.style.webkitTransform = pos; + }, + + show: function () { + if (has3d) { + this.wrapper.style.webkitTransitionDelay = '0'; + } + this.wrapper.style.opacity = '1'; + }, + + hide: function () { + if (has3d) { + this.wrapper.style.webkitTransitionDelay = '350ms'; + } + this.wrapper.style.opacity = '0'; + }, + + remove: function () { + this.wrapper.parentNode.removeChild(this.wrapper); + return null; + } +}; + +// Is translate3d compatible? +var has3d = ('WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix()), + // Device sniffing + isIphone = (/iphone/gi).test(navigator.appVersion), + isIpad = (/ipad/gi).test(navigator.appVersion), + isAndroid = (/android/gi).test(navigator.appVersion), + isTouch = isIphone || isIpad || isAndroid, + // Event sniffing + START_EVENT = isTouch ? 'touchstart' : 'mousedown', + MOVE_EVENT = isTouch ? 'touchmove' : 'mousemove', + END_EVENT = isTouch ? 'touchend' : 'mouseup', + // Translate3d helper + translateOpen = 'translate' + (has3d ? '3d(' : '('), + translateClose = has3d ? ',0)' : ')', + // Unique ID + uid = 0; + +// Expose iScroll to the world +window.iScroll = iScroll; +})(); \ No newline at end of file diff --git a/configure.in b/configure.in index bca9239..4e178d3 100755 --- a/configure.in +++ b/configure.in @@ -572,9 +572,9 @@ if test "$host_vendor" = "apple" ; then LIBS="$LIBS -framework ApplicationServices" fi elif test "$use_arch" = "arm"; then - CFLAGS="$CFLAGS -mfloat-abi=softfp -mno-apcs-stack-check" - CXXFLAGS="$CXXFLAGS -mfloat-abi=softfp -mno-apcs-stack-check" - FFMPEG_EXTRACFLAGS="-mfloat-abi=softfp" + CFLAGS="$CFLAGS -mno-apcs-stack-check" + CXXFLAGS="$CXXFLAGS -mno-apcs-stack-check" + FFMPEG_EXTRACFLAGS="" if test "$use_tegra" = "yes"; then # Compile for ARMv7a architecture, need to test gcc for vfpv3-d16 support SAVE_CFLAGS="$CFLAGS" @@ -589,9 +589,6 @@ elif test "$use_arch" = "arm"; then CXXFLAGS="$CXXFLAGS -Wa,-march=armv6 -mtune=cortex-a8 -mthumb-interwork" use_cpu=cortex-a8]) else - # Compile for ARMv7a architecture, CortexA8 cpu and check for enabled NEON coprocessor - CFLAGS="$CFLAGS -Wa,-march=armv7a -mcpu=cortex-a8" - CXXFLAGS="$CXXFLAGS -Wa,-march=armv7a -mcpu=cortex-a8" if test "$use_neon" = "yes"; then CFLAGS="$CFLAGS -mfpu=neon -mvectorize-with-neon-quad" CXXFLAGS="$CXXFLAGS -mfpu=neon -mvectorize-with-neon-quad" @@ -1248,7 +1245,11 @@ if test "$use_external_ffmpeg" = "yes"; then AC_DEFINE([USE_EXTERNAL_FFMPEG], [1], [Whether to use external FFmpeg libraries.]) # Disable vdpau support if external libavcodec doesn't have it - AC_CHECK_LIB([avcodec], [ff_vdpau_vc1_decode_picture],, + AC_RUN_IFELSE( + AC_LANG_PROGRAM([[#include ]], + [[avcodec_register_all(); + AVCodec *codec = avcodec_find_decoder_by_name("vc1_vdpau"); + return (codec) ? 0 : 1;]]),, [if test "x$use_vdpau" = "xyes"; then AC_MSG_ERROR($ffmpeg_vdpau_not_supported) else @@ -1256,6 +1257,23 @@ if test "$use_external_ffmpeg" = "yes"; then AC_MSG_RESULT($ffmpeg_vdpau_not_supported) fi]) + # Other headers to include if available. + AC_CHECK_HEADERS([libavutil/mathematics.h],,) + + # Check if exists and defines old + # av_vsrc_buffer_add_frame() from SoC. This avoids multiple declarations of + # av_vsrc_buffer_add_frame(). + AC_COMPILE_IFELSE( + AC_LANG_SOURCE([[ + #include + void foo(void) + { + AVRational a; + av_vsrc_buffer_add_frame(NULL, NULL, 0, a); + } + ]]), AC_DEFINE([USE_OLD_AV_VSRC_BUFFER_ADD_FRAME], + [1], [Check if SoC av_vsrc_buffer_add_frame() is defined in libavfilter/vsrc_buffer.h.]),) + # Check for 'PIX_FMT_VDPAU_MPEG4' from libavutil if test "x$use_vdpau" != "xno"; then AC_LANG_PUSH([C++]) @@ -1894,6 +1912,16 @@ OUTPUT_FILES="Makefile \ xbmc/visualizations/OpenGLSpectrum/Makefile \ xbmc/visualizations/WaveForm/Makefile \ xbmc/visualizations/iTunes/Makefile \ + xbmc/pvrclients/Makefile.include \ + xbmc/pvrclients/MediaPortal/Makefile \ + xbmc/pvrclients/mythtv/Makefile \ + xbmc/pvrclients/pvr-demo/Makefile \ + xbmc/pvrclients/mythtv-cmyth/Makefile \ + xbmc/pvrclients/tvheadend/Makefile \ + xbmc/pvrclients/vdr-vnsi/Makefile \ + lib/addons/library.xbmc.addon/Makefile \ + lib/addons/library.xbmc.gui/Makefile \ + lib/addons/library.xbmc.pvr/Makefile \ tools/Linux/xbmc.sh \ tools/Linux/xbmc-standalone.sh \ tools/TexturePacker/Makefile \ diff --git a/language/Czech/strings.xml b/language/Czech/strings.xml index f226720..deed7ce 100644 --- a/language/Czech/strings.xml +++ b/language/Czech/strings.xml @@ -3,7 +3,7 @@ - + Programy Obrázky @@ -1545,7 +1545,449 @@ Zobrazovat odpočet do uspání + Přepnout na kanál + Oddělte jednotlivá hledaná slova klíčovými slovy AND, OR, NOT. + nebo pro vyhledání přesné fráze přesně vepište přesně text (např. "Čaroděj ze země Oz"). + Najít podobné programy + Načítání EPG + Informace o PVR streamu + Přijímající zařízení + Stav zařízení + Kvalita signálu + SNR + BER + UNC + PVR Backend + Volně šířené programy + Fixed + Šifrování + PVR Backend %i - %s + Nahrané pořady + Složka pro umístění náhledů + Programy + Televize + Rádio + Skryté + Televize + Rádia + Plánovaná nahrávání + Naplánovat nové nahrávání... + Žádné výsledky vyhledávání + Žádné EPG + Kanál + Právě teď + Následuje + Časová osa + Informace + Již běží nahrávání tohoto programu. + Program nelze z nějakého důvodu spustit. Více informací v logu. + Nahrávka nelze z nějakého důvodu přehrát. Více informací v logu. + Zobrazit kvalitu signálu + Toto bohužel není PVR backendem podporováno. + Opravdu chcete skrýt tuto stanici? + Plánovač + Opravdu chcete přejmenovat tuto nahrávku? + Opravdu chcete přejmenovat tento časovač? + Nahrávání + Prosím zkontrolujte Vaše nastavení nebo mrkněte do logu pro více informací. + Není aktivní žádný PVR klient. Buď se teprve spouští, nebo není žádný nakonfigurován. Popřípadě mrkněte do logu pro více informací. + Nová stanice + Informace o programu + Upravit skupiny + Zobrazit stanici + Zobrazit viditelné stanice + Zobrazit skryté stanice + Přesunout stanici do: + Podrobnosti o nahrávce + Skrýt stanici + Žádné informace + Nový časovač + Upravit časovač + Časovač je aktivní + Zastavit nahrávání + Odstranit časovat + Nový časovač + Řadit dle: Stanice + Skočit na začátek + Skočit na konec + Výchozí zobrazení EPG + Načítání seznamu TV nahrávek + Tato položka se již nahrává. + Tato nahrávka nelze z nějakého důvodu smazat. Mrkněte do logu pro více informací. + EPG + Skenovat EPG informace každých + Aktualizovat EPG každých + Neukládat EPG data do databáze XBMC + Zpomalit přepínání programů o + Aktivní: + Název: + Složka: + Rádio: + Televize: + Den: + Začátek: + Konec: + Priorita: + Doba trvání (dnů): + První den: + Neznámý kanál %u + Po-__-__-__-__-__-__ + __-Út-__-__-__-__-__ + __-__-St-__-__-__-__ + __-__-__-Čt-__-__-__ + __-__-__-__-Pá-__-__ + __-__-__-__-__-So-__ + __-__-__-__-__-__-Ne + Po-Út-St-Čt-Pá-__-__ + Po-Út-St-Čt-Pá-So-__ + Po-Út-St-Čt-Pá-So-Ne + __-__-__-__-__-So-Ne + Zadejte název nahrávky + Upozornění + Nastaven časovač + Opravdu chcete tento kanál odstranit? Včetně všech nastavených časovačů pro tento kanál. + Tato stanice je zrovna používaná pro přehrávání. + Prosím přepněte na jinou stanici. + Vyhledat chybějící ikonky + Zadejte jméno složky pro nahrávky programů + Velikost: + Příští časovač nastaven na + v + Recordings not in sync. Check the log for details. + Časovač se nepodařilo uložit. Detaily se nacházejí v logu. + Nastala neočekávaná chyba. Zkuste to později, nebo mrkněte do logu pro podrobnosti. + Chyba PVR backendu. Detaily se nacházejí v logu. + Timers not in sync. Detaily se nacházejí v logu. + Další + Verze + Adresa + Velikost disku + Vyhledat programy + Během prohledávání kanálů není možné PVR používat. + Na jakém serveru chcete vyhledávat? + Počet klientů + Předejít opakování + Tento časovač právě nahrává. Přesto ho chcete odstranit? + Pouze volně šířené programy + Ignorovat nastavené časovače + Ignorovat běžící nahrávání + Čas začátku + Čas ukončení + Datum začátku + Datum ukončení + Minimální délka nahrávání + Maximální délka nahrávání + Zahrnout neznámé/neurčené žánry + Vyhledat text + Zahrnout popis + Záleží na velikosti písmen + Stanice nedostupná + Nenastaveny žádné skupiny + Nejdříve musíte vytvořit novou skupinu programů. + Název nové skupiny + Skupina + Vyhledávání + Nastavit skupiny programů + Nejsou nastaveny žádné skupiny + Seskupeno + Skupiny + PVR backend tuto akci nepodporuje. Mrkněte do logu pro podrobnosti. + Stanice + Po + Út + St + Čt + + So + Ne + od + Příští nahrávání + Právě se nahrává + od + do + Aktivní + Nahrávání aktivní + Nahrávky + Nahrávání se nepodařilo spustit. Mrkněte do logu pro podrobnosti. + Přepnout sem + PVR informace + Vyhledat chybějící ikonky programů + Přepínat stanice bez potřeby stisku tlačítka OK + Skrýt boxík s informacemi o videu + Timeout when starting playback + Spustit nahrávání na pozadí + Výchozí délka nahrávání (instantní nahrávání) + Výchozí priorita nahrávání + Výchozí životnost nahrávky + Spouštět plánované nahrávání dřív o + Končit plánované nahrávání později o + Přehrávání + Zobrazovat informace o kanálu při jejich přepínání + Automaticky skrývat informace o kanálu + Televize + Menu/OSD + Počet dní zobrazených v EPG + Délka zobrazení informací o kanálu + Resetovat databázi PVR + Všechna data v PVR databázi budou smazána. Tedy nastavení PVR, kanálů apod. + Resetovat databázi EPG + EPG se maže z databáze + Po startu spustit posledně naladěný kanál + Na pozadí + Služba PVR + Žádný z připojených PVR backendů nepodporuje vyhledávání stanic. + Vyhledávání stanic se nezdařilo spustit. Mrkněte do logu pro podrobnosti. + Pokračovat? + Client actions + PVR client specific actions + Nahrávání začalo: %s + Nahrávání skončilo: %s + Správce programů + Zdroj EPG: + Název: + Ikona: + Upravit stanici + Nová stanice + Správa skupin + Povolit EPG: + Skupina: + Zadejte jméno nové stanice + XBMC virtuální backend + Klient + Smazat stanici + Tento seznam obsahuje změny + Zvolit backend + Zadejte platnou URL adresu nového kanálu + PVR backend nepodporuje plánování. + Všechna rádia + Všechny televize + Viditelný + Neseskupené stanice + Stanice v + Synchronizovat skupiny stanic s backendy + EPG + Nepodařilo se aktivovat žádný PVR doplněk. Zkontrolujte nastavení nebo mrkněte do logu. + Nahrávání zrušeno + Nahrávání naplánováno + Nahrávání spuštěno + Nahrávání dokončeno + Nahrávání smazáno + Zavřít OSD při přepnutí stanice + Neaktualizovat EPG během sledování TV + Pořadí stanic vždy převzít z nastavení backendů + Smazat výsledky vyhledávání + Zobrazit upozornění na změny časovačů + Převzít čísla stanic z nastavení backendu (lze pouze pokud používáte jediný PVR doplněk) + Manažer PVR se spouští + načítání programů + načítání časovačů + načítání nahrávek + spouštění procesů na pozadí + Nemáte aktivovaný žádný PVR plugin + TV sekce v XBMC byla aktivována, aniž by byl povolen některý + PVR doplněk (frontend). Aktivujte alespoň jeden frontend + pro možnost využívání PVR funkcionality v XBMC. + + Přepnout Backend do stavu nečinnosti po + Nastavit příkaz pro probuzení (cmd [timestamp]) + Probudit backend před začátkem nahrávání + Denně probouzet + Čas probuzení (HH:MM:SS) + + Jiné + Film/Drama + Detektivní/Thriller + Dobrodružný/Western/Válečný + Sci-Fi/Fantasy/Horor + Komedie + Telenovela/Melodrama/Folklór + Romantický + Vážný/Klasický/Duchovní/Historický + Pro dospělé + + + + + + + + Zprávy – komentáře + Zprávy – počasí + News Magazine + Documentary + Discussion/Interview/Debate + + + + + + + + + + + + Představení/Soutěž + Soutěž + Estráda + Talk show + + + + + + + + + + + + + Sport + Speciální událost + Sportovní magazín + Fotbal + Tenis/squash + Týmové sporty + Atletika + Automobilové sporty + Vodní sporty + Zimní sporty + Jezdectví + Bojovné sporty + + + + + Program pro děti + Program pro předškolní děti + Zábavný pořad pro děti 6 – 14 let + Zábavný pořad pro děti 10 – 16 let + Naučný/výukový program + Kreslený/Loutkový + + + + + + + + + + + Hudba/Balet/Tanec + Rock/Pop + Vážná/klasická hudba + Lidová hudba + Muzikál/Opera + Balet + + + + + + + + + + + Umění/Kultura + Herecké umění + Krásná umění + Náboženský + Popular Culture/Traditional Arts + Literatura + Film/Kino + Experimentální film/video + Broadcasting/Press + New Media + Arts/Culture Magazines + Móda + + + + + Social/Political/Economics + Magazín/Dokumentární + Economics/Social Advisory + Významná osobnost + + + + + + + + + + + + + Výukový/věda/fakta + Příroda/zvířata/životní prostředí + Technologie/přírodní vědy + Lékařství/fyziologie/psychologie + Expedice + Společenské/Duchovní vědy + Further Education + Jazyky + + + + + + + + + Volný čas + Turistika/Cestování + Řemeslo + Motorismus + Fitness a zdraví + Vaření + Reklama/Teleshopping + Zahradničení + + + + + + + + + Special Characteristics + Original Language + Black & White + Neuvedený + Živé vysílání + + + + + + + + + + + + Drama + Detektivní/Thriller + Dobrodružný/Western/Válečný + Sci-Fi/Fantasy/Horor + Komedie + Telenovela/Melodrama/Folklór + Romantický + Vážný/Klasický/Duchovní/Historický + Pro dospělé + + + + + + + Složka pro ukládání hudby Použít externí DVD přehrávač diff --git a/language/Dutch/strings.xml b/language/Dutch/strings.xml index f1e3419..643e4ef 100644 --- a/language/Dutch/strings.xml +++ b/language/Dutch/strings.xml @@ -1,5 +1,10 @@ + + + + + Programma's Afbeeldingen @@ -1010,7 +1015,7 @@ Opnieuw opstarten Minimaliseren Actie voor aan/uitknop - Systeem Uitschakelen + Uitschakelen Er is een andere sessie actief, wellicht SSH? Verwisselbare harde schijf aankoppelen? @@ -1102,10 +1107,8 @@ Besturingssysteem: Kloksnelheid: - Video-encoder: Schermresolutie: - A/V-kabel: DVD-regio: @@ -1250,7 +1253,7 @@ Uit %.1f Seconde %.1f Seconden - + Type Apple afstandsbediening Gebruik afstandsbediening om XBMC zelf op te staren @@ -1539,13 +1542,546 @@ Spline36 Spline36 geoptimaliseerd Software menging + Auto - ION geoptimaliseerd Kwaliteitsverbetering video Uitschakeltijd beeldscherm - + %i MB + %i uren + %i dagen Kanaal wijzigen - + Scheid de zoekwoorden door middel van AND, OR en/of NOT om de zoekopdracht te specificeren. + Of gebruik zinnen om op een tekst te zoeken, bijv. "Toen was geluk heel gewoon". + Zoek vergelijkbaar programma + Gids van clients wordt geladen + PVR stream informatie + Ontvanger + Status ontvanger + Signaalkwaliteit + SNR + BER + UNC + Server + Ongecodeerd + Vast + Versleuteling + Server %i - %s + TV Opnames + Standaard map voor TV thumbnails + Kanalen + TV + Radio + Verborgen + TV kanalen + Radio kanalen + Toekomstige opnames + Voeg opname toe... + Geen zoekresultaten + Geen gids aanwezig + TV gids + Nu + Straks + Tijdslijn + Informatie + Opname is al gestart + Kanaal kan niet worden weergegeven + Opname kan niet worden weergegeven + Toon signaal kwaliteit + Op dit moment niet ondersteund! + Bevestig verbergen van het kanaal + Geplande opname + Hernoem opname? + Hernoem geplande opname? + Opname + Controleer de instellingen van de server + Geen PVR clients beschikbaar + Nieuw kanaal + Programma info + Beheer groepen + Toon kanaal + Toon normale kanalen + Toon verborgen kanalen + Verplaats kanaal naar: + Opname informatie + Verberg kanaal + Geen informatie beschikbaar! + Nieuwe geplande opname + Pas geplande opname aan + Geplande opname aan/uit + Stop opname + Annuleer opname + Opnemen + Sorteer op: Kanaal + Ga naar begin + Ga naar einde + Standaardgids + Opname informatie wordt geladen + Dit programma wordt al opgenomen + Kon de opname niet verwijderen + TV gids + TV gids scan timeout + TV gids update timeout + TV gids niet opslaan in de database + Stel wisselen kanaal uit + Actief: + Naam: + Map: + Radio: + Kanaal: + Dag: + Begin: + Einde: + Prioriteit: + Levensduur (dagen): + Eerste dag: + Onbekend kanaal: %u + Ma-__-__-__-__-__-__ + __-Di-__-__-__-__-__ + __-__-Wo-__-__-__-__ + __-__-__-Do-__-__-__ + __-__-__-__-Vr-__-__ + __-__-__-__-__-Za-__ + __-__-__-__-__-__-Zo + Ma-Di-Wo-Do-Vr-__-__ + Ma-Di-Wo-Do-Vr-Za-__ + Ma-Di-Wo-Do-Vr-Za-Zo + __-__-__-__-__-Za-Zo + Naam van de opname + Waarschuwing + Opname aanwezig + Verwijder kanaal en opname? + Kanaal wordt afgespeeld + Schakel over naar een ander kanaal! + Zoek missende iconen + Geef naam van de opname map + Grootte: + Volgende opname op + om + Opnames niet gesynchroniseerd + Kon de opname niet opslaan! + Probeer nog eens... + Server fout! + Opnames niet gesynchroniseerd + Volgende + Versie + Adres + Schijf grootte + Zoek naar kanalen + Kan de instellingen van de TV niet aanpassen tijdens het zoeken! + Op welke server wilt u zoeken? + Client nummer + Vermijd herhalingen + Opname loopt nog. Wilt u deze verwijderen? + Alleen ongecodeerd + Negeer bij lopende opnames + Negeer bij opgenomen programma's + Starttijd + Eindtijd + Startdatum + Einddatum + Minimale lengte + Maximale lengte + Neem onbekende genres op + Zoekopdracht + Neem omschrijving op + Hoofdlettergevoelig + Kanaal niet beschikbaar + Geen groepen gedifinieerd + Maak er eerst een aan + Naam nieuwe groep + Groep + Zoek in gids + Beheer groepen + Geen groepen + Gegroepeerd + Groepen + PVR-Server is niet compatibel! + Kanaal + Ma + Di + Wo + Do + Vr + Za + Zo + van + Volgende opname + Wordt nu opgenomen + van + tot + op + Wordt opgenomen + Opnames + Kan de opname niet starten + Wijzig kanaal + PVR informatie + Zoek missende iconen + Wijzig kanaal zonder op OK te drukken + Verberg video lengte informatie + Scan timeout voor kanaal afspelen + Start afspelen geminimaliseerd + Lengte directe opname + Standaard prioriteit + Standaard levensduur + Marge opname begin + Marge opname einde + Afspelen + Info bij wisselen kanaal + Timeout kanaal informatie + TV + Menu/OSD + Weergegeven dagen in de TV gids + Kanaal info tijd + Wis TV database + Alle gegevens in de TV database worden gewist + Wis TV gids en lees nieuwe in + TV gids wordt gewist + Hervat laatste kanaal bij opstarten + Geminimaliseerd + PVR service + Geen server ondersteunt het scannen naar kanalen + Kon het scannen naar kanalen niet starten + Hervatten? + Client acties + PVR client specifieke acties + Opname gestart om: %s + Opname beeindigd om: %s + Beheer kanalen + TV gids bron: + Naam kanaal: + Kanaal icoon: + Pas kanaal aan + Nieuw kanaal + Beheer groepen + Activeer TV gids: + Groep: + Voer de naam van het nieuwe kanaal in + XBMC intern virtueel kanaal + Client + Verwijder kanaal + Lijst bevat wijzigigen + Selecteer client voor het kanaal + Voer een geldige URL in voor het kanaal + De PVR server ondersteunt geen timers! + Alle radio kanalen + Alle TV kanalen + Zichtbare + Ongegroepeerde kanalen + Kanalen in + Synchroniseer groepen met backends + Gids + Kon geen PVR client inschakelen. Kijk je instellingen na of je log. + Opname geannuleerd + Opname gepland + Opname gestart + Opname voltooid + Opname verwijderd + Sluit kanelen OSD na wijzigen kanaal + Geen EPG updates tijdens het afspelen van een TV stream + Gebruik altijd de volgorde van kanalen van backend(s) + Zoekresultaten wissen + Toon een melding bij timer updates + Gebruik kanaalnummers van de backend (werkt alleen als 1 PVR addon actief is) + + Anders/Onbekend + Film/Drama + Detective/Thriller + Avontuur/Western/Oorlog + Science Fiction/Fantasie/Horror + Komedie + Soap/Melodrama/Folklore + Romantisch + Serieus/Klassiek/Religie/Historische Film/Drama + Volwassenen Film/Drama + + + + + + + + + + + + + + + Nieuws/Actualiteiten + Nieuws/Weer + Nieuws magazine + Documentaire + Discussie/Interview/Debat + + + + + + + + + + + + + + + + + + + + + + + Show/Spelshow + Spelshow/Quiz/Wedstrijd + Variété + Praatprogramma + + + + + + + + + + + + + + + + + + + + + + + + + Sport + Speciaal + Sport Magazine + Voetbal + Tennis/Squash + Team Sport + Atletiek + Motorsport + Watersport + Wintersport + Ruitersport + Vechtsport + + + + + + + + + Kinderen/jeugdprogramma's + Peuter programma's + Entertainment programma's voor 6 tot 14 + Entertainment programma's voor 10 tot 16 + Informatie/Educatie/School Programma's + Cartoons/Marionetten + + + + + + + + + + + + + + + + + + + + + Muziek/Ballet/Dans + Rock/Pop + Serieus/Klassieke muziek + Folklore/Tradionele muziek + Muziek/Opera + Ballet + + + + + + + + + + + + + + + + + + + + + Kunst/Cultuur + Uitvoerende kunsten + Fijne kunsten + Religie + Populaire cultuur/Tradionele kunst + Literatuur + Film/Cinema + Experimentele film/Video + Uitzending/Pers + Nieuwe media + Kunst/Cultuur magazines + Mode + + + + + + + + + Sociaal/Politiek/Economisch + Magazines/Verslagen/Documentaires + Economisch/Maatschappelijk advies + Opmerkelijke personen + + + + + + + + + + + + + + + + + + + + + + + + + Educatie/Wetenschap/Feiten + Natuur/Dieren/Milieu + Technologie/Natuurwetenschappen + Geneeskunde/Physiologie/Psychologie + Buitenland/Expedities + Sociale/Spirituele wetenschap + Verder leren + Talen + + + + + + + + + + + + + + + + + Vrije tijd/Hobbies + Tourisme/Reizen + Handwerk + Autorijden + Fitness & Gezondheid + Koken + Reclame/Winkelen + Tuinieren + + + + + + + + + + + + + + + + + Bijzondere kenmerken + Oude talen + Zwart/Wit + Niet gepubliceerd + Live uitzending + + + + + + + + + + + + + + + + + + + + + + + Drama + Detective/Thriller + Avontuur/Western/Oorlog + Science Fiction/Fantasie/Horror + Comedy + Soap/Melodrama/Folklore + Romantisch + Serieus/Klassiek-Regionaal/Historisch + Volwassenen + + + + + + + + + + + + + + + Opgeslagen muziek map... Andere DVD-speler gebruiken - Locatie van de DVD-speler @@ -1765,6 +2301,8 @@ LCD dimmen tijdens afspelen Onbekend of onboard (beveiligd) LCD dimmen tijdens pauze + Video - Bibliotheek + Sorteer: ID Video - Bibliotheek @@ -2182,6 +2720,7 @@ Albuminformatie Artiestinformatie Processen + PVR clients Configureren Uitschakelen @@ -2404,3 +2943,4 @@ Adapter gevonden, maar libcec is niet beschikbaar Gebruik de taalinstelling van de TV + diff --git a/language/English/strings.xml b/language/English/strings.xml index ca2ac4d..42ad8c0 100644 --- a/language/English/strings.xml +++ b/language/English/strings.xml @@ -1,5 +1,5 @@ - + Programs Pictures @@ -1008,6 +1008,8 @@ Minimize Power button action Power off System + Inhibit idle shutdown + Allow idle shutdown Is another session active, perhaps over ssh? Mounted removable harddrive @@ -1537,13 +1539,469 @@ DXVA Best Spline36 Spline36 optimized + Software Blend + Auto - ION Optimized Post-processing Display sleep timeout + %i MByte + %i hours + %i days + + Switch to channel + Separate the search words by using AND, OR and/or NOT. + or use phrases to find an exact match, like "The wizard of Oz". + Find similar programme + Importing EPG from clients + PVR stream information + Receiving device + Device status + Signal quality + SNR + BER + UNC + PVR Backend + Free to air + Fixed + Encryption + PVR Backend %i - %s + TV recordings + Default folder for PVR thumbnails + Channels + TV + Radio + Hidden + TV channels + Radio channels + Upcoming recordings + Add timer... + No search results + No EPG entries + Channel + Now + Next + Timeline + Information + Already started recording on this channel + This channel cannot be played. Check the log for details. + This recording cannot be played. Check the log for details. + Show signal quality + Not supported by the PVR backend. + Are you sure you want to hide this channel? + Timer + Are you sure you want to rename this recording? + Are you sure you want to rename this timer? + Recording + Please check your configuration or check the log for details. + No PVR clients have been started yet. Wait for the PVR clients to start up or check the log for details. + New channel + Programme info + Group management + Show channel + Show visible channels + Show hidden channels + Move channel to: + Recording information + Hide channel + No information available + New timer + Edit timer + Timer enabled + Stop recording + Delete timer + Add timer + Sort by: Channel + Go to begin + Go to end + Default EPG window + Loading recordings from clients + This event is already being recorded. + This recording could not be deleted. Check the log for details. + EPG + EPG scan timeout + EPG update interval + Do not store the EPG in the database + Delay channel switch + Active: + Name: + Folder: + Radio: + Channel: + Day: + Begin: + End: + Priority: + Lifetime (days): + First day: + Unknown channel %u + Mo-__-__-__-__-__-__ + __-Tu-__-__-__-__-__ + __-__-We-__-__-__-__ + __-__-__-Th-__-__-__ + __-__-__-__-Fr-__-__ + __-__-__-__-__-Sa-__ + __-__-__-__-__-__-Su + Mo-Tu-We-Th-Fr-__-__ + Mo-Tu-We-Th-Fr-Sa-__ + Mo-Tu-We-Th-Fr-Sa-Su + __-__-__-__-__-Sa-Su + Enter the name for the recording + Warning + Timer present + Are you sure you want to delete this channel, including all timers on this channel? + This channel is currently being used for playback. + Please switch to another channel. + Scan for missing icons + Enter the name of the folder for the recording + Size: + Next timer on + at + Recordings not in sync. Check the log for details. + Couldn't save timer. Check the log for details. + An unexpected error occurred. Try again later or check the log for details. + PVR backend error. Check the log for details. + Timers not in sync. Check the log for details. + Next + Version + Address + Disksize + Search for channels + Cannot use PVR functions while searching. + On which server you want to search? + Client number + Avoid repeats + This timer is still recording. Are you sure you want to delete this timer? + Free to air channels only + Ignore present timers + Ignore present recordings + Start time + End time + Start date + End date + Minimum duration + Maximum duration + Include unknown genres + Search string + Include description + Case sensitive + Channel unavailable + No groups defined + Please create a group first + Name of the new group + Group + Search guide + Group management + No groups defined + Grouped + Groups + The PVR backend does not support this action. Check the log for details. + Channel + Mo + Tu + We + Th + Fr + Sa + Su + from + Next recording + Currently recording + from + to + On + Recording active + Recordings + Cannot start recording. Check the log for details. + Switch + PVR information + Scan for missing icons + Switch channel without pressing OK + Hide video information box + Timeout when starting playback + Start playback minimized + Instant recording duration + Default recording priority + Default recording lifetime + Margin at the start of a recording + Margin at the end of a recording + Playback + Show channel information when switching channels + Automatically hide channel information + TV + Menu/OSD + Days to display in the EPG + Channel information duration + Reset the PVR database + All data in the PVR database is being erased + Reset the EPG database + EPG is being reset + Continue last channel on startup + Minimized + PVR service + None of the connected PVR backends supports scanning for channels. + The channel scan cannot be started. Check the log for details. + Continue? + Client actions + PVR client specific actions + Recording started on: %s + Recording finished on: %s + Channel manager + EPG source: + Channel name: + Channel icon: + Edit channel + New channel + Group management + Activate EPG: + Group: + Enter the name of the new channel + XBMC virtual backend + Client + Delete channel + This list contains changes + Select backend + Enter a valid URL for the new channel + The PVR backend does not support timers. + All radio channels + All TV channels + Visible + Ungrouped channels + Channels in + Synchronise channel groups with backends + EPG + No PVR add-on could be enabled. Check your settings or the log for more info. + Recording aborted + Recording scheduled + Recording started + Recording completed + Recording deleted + Close channel OSD after switching channels + Prevent EPG updates while playing a TV stream + Always use the channel order from the backend(s) + Clear search results + Display a notification on timer updates + Use backend channels numbers (only works with 1 enabled PVR addon) + PVR manager is starting up + importing channels + importing timers + importing recordings + starting background threads + No PVR add-on enabled + The PVR manager has been enabled without any + enabled PVR add-on. Enable at least one add-on + in order to use the PVR functionality. + + Backend idle time + Set wakup command (cmd [timestamp]) + Wakup before recording + Daily wakeup + Daily wakeup time (HH:MM:SS) + Filter channels + Loading EPG from database + Update EPG information + Schedule EPG update for this channel? + EPG update scheduled for channel + EPG update failed for channel + Start recording + Stop recording + + Other/Unknown + Movie/Drama + Detective/Thriller + Adventure/Western/War + Science Fiction/Fantasy/Horror + Comedy + Soap/Melodrama/Folkloric + Romance + Serious/Classical/Religious/Historical Movie/Drama + Adult Movie/Drama + + + + + + + + News/Current Affairs + News/Weather Report + News Magazine + Documentary + Discussion/Interview/Debate + + + + + + + + + + + + Show/Game Show + Game Show/Quiz/Contest + Variety Show + Talk Show + + + + + + + + + + + + + Sports + Special Event + Sport Magazine + Football + Tennis/Squash + Team Sports + Athletics + Motor Sport + Water Sport + Winter Sports + Equestrian + Martial Sports + + + + + Children's/Youth Programmes + Pre-school Children's Programmes + Entertainment Programmes for 6 to 14 + Entertainment Programmes for 10 to 16 + Informational/Educational/School Programme + Cartoons/Puppets + + + + + + + + + + + Music/Ballet/Dance + Rock/Pop + Serious/Classical Music + Folk/Traditional Music + Musical/Opera + Ballet + + + + + + + + + + + Arts/Culture + Performing Arts + Fine Arts + Religion + Popular Culture/Traditional Arts + Literature + Film/Cinema + Experimental Film/Video + Broadcasting/Press + New Media + Arts/Culture Magazines + Fashion + + + + + Social/Political/Economics + Magazines/Reports/Documentary + Economics/Social Advisory + Remarkable People + + + + + + + + + + + + + Education/Science/Factual + Nature/Animals/Environment + Technology/Natural Sciences + Medicine/Physiology/Psychology + Foreign Countries/Expeditions + Social/Spiritual Sciences + Further Education + Languages + + + + + + + + + Leisure/Hobbies + Tourism/Travel + Handicraft + Motoring + Fitness & Health + Cooking + Advertisement/Shopping + Gardening + + + + + + + + + Special Characteristics + Original Language + Black & White + Unpublished + Live Broadcast + + + + + + + + + + + + Drama + Detective/Thriller + Adventure/Western/War + Science Fiction/Fantasy/Horror + Comedy + Soap/Melodrama/Folkloric + Romance + Serious/ClassicalReligion/Historical + Adult + + + + + + + Saved music folder Use external DVD player @@ -2182,6 +2640,7 @@ Album information Artist information Services + PVR clients Configure Disable @@ -2217,7 +2676,7 @@ Would you like to enable this Add-on? Would you like to disable this Add-on? Add-on update available! - Enabled Add-ons + Installed Add-ons Auto update Add-on enabled Add-on updated diff --git a/language/Finnish/strings.xml b/language/Finnish/strings.xml index 22c0631..d0bfce0 100644 --- a/language/Finnish/strings.xml +++ b/language/Finnish/strings.xml @@ -1011,6 +1011,8 @@ Pienennä Virtakytkimen toiminto Sammuta järjestelmä + Estä sammuttaminen toimettomana + Salli sammuttaminen toimettomana Onko toinen istunto käynnissä, ehkä ssh:n kautta? Liitetty siirrettävä kiintolevy @@ -1541,12 +1543,460 @@ Spline36 Spline36 optimoitu Ohjelmistopohjainen sekoitus + Automaattinen - ION optimoitu Videon jälkikäsittely Näytön pimennyksen viive + %i Mtavua + %i tuntia + %i päivää + + Vaihda kanavalle + Erottele eri hakusanat käyttämällä "AND", "OR" ja/tai "NOT" -operaattoreita hakulauseessasi. + Tai käytä lainausmerkkejä löytääksesi kokonaisia virkkeitä esim. "The wizard of Oz". + Etsi samankaltaisia ohjelmia + Tuodaan ohjelmaoppaan tiedot asiakkailta + PVR-virran tiedot + Vastaanottava laite + Vastaanoton tila + Signaalin laatu + Signaali-kohinasuh. + Bittivirhesuhde + Korjaamat. lohkot + PVR-taustaosa + Vapaa kanava + Kiinteä + Salausjärjestelmä + PVR-taustaosa %i - %s + Nauhoitukset + PVR-pienoiskuvakkeiden oletuskansio + Kanavat + TV + Radio + Piilotetut + TV-kanavat + Radiokanavat + Tulevat nauhoitukset + Lisää ajastus... + Ei hakutuloksia + Ei ohjelmatietoja + Kanava + Nyt + Seuraavaksi + Aikajana + Tietoja + Tämän kanavan nauhoittaminen on jo aloitettu + Kanavaa ei voi toistaa. Katso lokitiedostosta lisätietoja. + Nauhoitusta ei voi toistaa. Katso lokitiedostosta lisätietoja. + Näytä signaalin laatu + PVR-taustaosa ei tue toimintoa. + Haluatko varmasti piilottaa tämän kanavan? + Ajastukset + Haluatko varmasti muuttaa tämän nauhoituksen nimen? + Haluatko varmasti muuttaa tämän ajastuksen nimen? + Nauhoitus + Tarkista asetukset tai katso lokitiedostosta lisätietoja. + PVR-asiakkaita ei ole käynnistetty vielä. Odota kunnes PVR-asiakkaat käynnistyy tai katso lokitiedostosta lisätietoja. + Uusi kanava + Ohjelman tiedot + Ryhmien hallinta + Näytä kanava + Näytä näkyvät kanavat + Näytä piilotetut kanavat + Siirrä kanava paikkaan: + Nauhoituksen tiedot + Piilota kanava + Ei tietoja saatavilla + Uusi ajastus + Muokkaa ajastusta + Ajastus käytössä + Pysäytä nauhoitus + Poista ajastus + Lisää ajastus + Järjestä: Kanavan mukaan + Mene alkuun + Mene loppuun + Ohjelmaoppaan oletusnäkymä + Ladataan nauhoitusten tietoja asiakkailta + Tämän ohjelman nauhoitus on jo aloitettu. + Tätä nauhoitusta ei voitu poistaa. Katso lokitiedostosta lisätietoja. + Ohjelmaopas + Ohjelmatietojen haun aikakatkaisu + Ohjelmatietojen päivitysväli + Älä tallenna ohjelmatietoja tietokantaan + Viivytä kanavanvaihtoa + Käytössä: + Nimi: + Kansio: + Radio: + Kanava: + Päivämäärä: + Alkaa: + Loppuu: + Tärkeys: + Elinikä (päivää): + Ensimmäinen päivä: + Tuntematon kanava %u + Ma-__-__-__-__-__-__ + __-Ti-__-__-__-__-__ + __-__-Ke-__-__-__-__ + __-__-__-To-__-__-__ + __-__-__-__-Pe-__-__ + __-__-__-__-__-La-__ + __-__-__-__-__-__-Su + Ma-Ti-Ke-To-Pe-__-__ + Ma-Ti-Ke-To-Pe-La-__ + Ma-Ti-Ke-To-Pe-La-Su + __-__-__-__-__-La-Su + Anna nauhoitukselle nimi + Varoitus + Ajastus on olemassa + Haluatko varmasti poistaa tämän kanavan ja kaikki sen sisältämät ajastukset? + Tätä kanavaa toistetaan tällä hetkellä. + Vaihda toiselle kanavalle. + Hae puuttuvat kuvakkeet + Anna nauhoituskansion nimi + Koko: + Seuraava ajastus + klo + Nauhoitustiedot ei ole ajan tasalla. Katso lokitiedostosta lisätietoja. + Ajastusta ei voitu tallentaa. Katso lokitiedostosta lisätietoja. + Tapahtui odottamaton virhe. Yritä myöhemmin uudelleen tai katso lokitiedostosta lisätietoja. + PVR-taustaosan virhe. Katso lokitiedostosta lisätietoja. + Ajastustiedot ei ole ajan tasalla. Katso lokitiedostosta lisätietoja. + Seuraavaksi + Versio + Osoite + Levyn koko + Hae kanavia + PVR-toimintoja ei voi käyttää haun aikana. + Miltä palvelimelta haluat hakea? + Asiakas nro + Vältä uusintoja + Nauhoitus on vielä käynnissä. Haluatko varmasti poistaa tämän ajastuksen? + Vain vapaat kanavat + Älä huomioi nykyisiä ajastuksia + Älä huomioi nykyisiä nauhoituksia + Aloitusaika + Päättymisaika + Aloituspäivämäärä + Päättymispäivämäärä + Kesto vähintään + Kesto enintään + Sisällytä tuntemattomat lajityypit + Hakulause + Sisällytä kuvaus + Merkkikokoriippuvainen + Kanava ei saatavilla + Ryhmiä ei määritelty + Luo ensin ainakin yksi ryhmä + Uuden ryhmän nimi + Ryhmä + Etsi ohjelmaoppaasta + Ryhmien hallinta + Ei ryhmiä määriteltynä + Ryhmitelty + Ryhmät + PVR-taustaosa ei tue tätä toimintoa. Katso lokitiedostosta lisätietoja. + Kanava + Ma + Ti + Ke + To + Pe + La + Su + + Seuraava nauhoitus + Nauhoitetaan tällä hetkellä + klo + - + + Nauhoitus käynnissä + Nauhoitukset + Nauhoitusta ei voi aloittaa. Katso lokitiedostosta lisätietoja. + Vaihda + PVR-tietoja + Hae puuttuvat kuvakkeet + Kanavan vaihto ilman OK-näppäintä + Piilota videon tietolaatikko + Toiston aloituksen aikakatkaisu + Aloita toisto pienennettynä + Pikanauhoituksen kestoaika + Nauhoituksen oletustärkeys + Nauhoituksen oletuselinikä + Lisäaika nauhoituksen alkuun + Lisäaika nauhoituksen loppuun + Toisto + Näytä kanavan tiedot kanavanvaihdon yhteydessä + Piilota kanavan tiedot automaattisesti + TV + Valikko/OSD + Ohjelmaoppaan pituus + Kanavan tiedot ruudulla + Tyhjennä PVR-tietokanta + Kaikki PVR-tietokannan tiedot poistetaan! + Tyhjennä ohjelmaoppaan tietokanta + Ohjelmaoppaan tietokanta tyhjennetään! + Jatka edellisen kanavan katselua käynnistettäessä + Pienennetty + PVR-palvelu + Yksikään yhdistetty PVR-taustaosa ei tue kanavien hakemista. + Kanavahakua ei voitu aloittaa. Katso lokitiedostosta lisätietoja. + Jatketaanko? + Asiakkaan toiminnot + PVR-asiakaskohtaiset toiminnot + Nauhoitus alkoi: %s + Nauhoitus päättyi: %s + Kanavien hallinta + Ohjelmaoppaan lähde: + Kanavan nimi: + Kanavan kuvake: + Muokkaa kanavaa + Uusi kanava + Ryhmien hallinta + Ohjelmaopas käytössä: + Ryhmä: + Anna uuden kanavan nimi + XBMC:n virtuaalitaustaosa + Asiakas + Poista kanava + Lista sisältää muutoksia + Valitse taustaosa + Anna uuden kanavan osoite + PVR-taustaosa ei tue ajastuksia. + Kaikki radiokanavat + Kaikki TV-kanavat + Näkyvät + Ryhmittelemättömät kanavat + Kanavat ryhmässä + Synkronoi kanavaryhmät taustaosien kanssa + Ohjelmaopas + Yhtään PVR-lisäosaa ei voitu ottaa käyttöön. Tarkista asetukset tai katso lokitiedostosta lisätietoja. + Nauhoitus peruutettu + Nauhoitus ajastettu + Nauhoitus aloitettu + Nauhoitus päättynyt + Nauhoitus poistettu + Sulje OSD kanavanvaihdon jälkeen + Älä päivitä ohjelmaopasta TV:n toiston aikana + Käytä taustaosien kanavajärjestystä + Tyhjennä hakutulokset + Näytä ilmoitus ajastustietojen päivityksen yhteydessä + Käytä taustaosan kanavanumeroita (vain 1 PVR-lisäosa kerrallaan) + PVR-hallinta käynnistyy + tuodaan kanavat + tuodaan ajastukset + tuodaan nauhoitukset + käynnistetään taustasäikeet + Ei käytössä olevia PVR-lisäosia + PVR-hallinta on otettu käyttöön ilman yhtään + käytössä olevaa PVR-lisäosaa. Ota käyttöön vähintään + yksi lisäosa mikäli haluat käyttää PVR toimintoja. + + Taustaosan toimettomuusaika + Herätyskomento (komento [aikaleima]) + Herätysaika ennen nauhoitusta + Päivittäinen herätys + Päivittäinen herätysaika (TT:MM:SS) + Suodata kanavia + + Muu/Tuntematon + Elokuva/Draama + Salapoliisi/Jännitys + Seikkailu/Lännenelokuva/Sota + Sci-Fi/Fantasia/Kauhu + Komedia + Saippua/Tunteellinen/Perinteinen + Romanssi + Vakava/Klassinen/Uskonnollinen/Historiallinen elokuva/Draama + Aikuisten Elokuva/Draama + + + + + + + + Uutiset/Ajankohtaiset asiat + Uutiset/Säätiedot + Uutismakasiini + Dokumentti + Keskustelu/Haastattelu/Väittely + + + + + + + + + + + + Show/Pelishow + Pelishow/Tietovisa/Kilpailu + Vaihteleva show + Keskusteluohjelma + + + + + + + + + + + + + Urheilu + Erikoistapahtuma + Urheilumakasiini + Jalkapallo + Tennis/Squash + Joukkuelajit + Yleisurheilu + Moottoriurheilu + Vesiurheilu + Talviurheilu + Ratsastus + Kamppailulajit + + + + + Lasten/Nuorten ohjelmat + Esikouluikäisten lasten ohjelmat + Viihdeohjelmat 6-14 vuotiaille + Viihdeohjelmat 10-16 vuotiaille + Tiedottava/Opettavainen/Koulutusohjelma + Piirretty/Nukketeatteri + + + + + + + + + + + Musiikki/Baletti/Tanssi + Rock/Pop + Vakava/Klassinen Musiikki + Kansallinen/Perinteinen Musiikki + Musikaali/Ooppera + Baletti + + + + + + + + + + + Taide/Kulttuuri + Ilmaisu- ja näyttämötaiteet + Kaunotaiteet + Uskonto + Populaarikulttuuri/Perinteiset taiteet + Kirjallisuus + Filmi/Elokuva + Kokeellinen filmi/Video + Televisiointi/Lehdistö + Uusi media + Taide/Kulttuurimakasiinit + Muoti + + + + + Yhteiskunnallinen/Poliittinen/Taloustieto + Ajankohtaisohjelma/Katsaus/Dokumentti + Taloustieto/Yhteiskuntaneuvonta + Tunnettuja ihmisiä + + + + + + + + + + + + + Koulutus/Tiede/Asiaohjelma + Luonto/Eläimet/Ympäristö + Teknologia/Luonnontieteet + Lääketiede/Fysiologia/Psykologia + Ulkomaat/Tutkimusmatkat + Sosiaaliset/Hengelliset Tieteet + Jatko-opiskelu + Kielet + + + + + + + + + Vapaa-aika/Harrastukset + Turismi/Matkustus + Käsityö + Autoilu + Kuntoilu & Terveys + Ruuanlaitto + Mainokset/Ostokset + Puutarhan hoito + + + + + + + + + Erikoisominaisuudet + Alkuperäisellä kielellä + Mustavalkoinen + Julkaisematon + Suora lähetys + + + + + + + + + + + + Draama + Salapoliisi/Jännitys + Seikkailu/Lännenelokuva/Kauhu + Sci-Fi/Fantasia/Kauhu + Komedia + Saippua/Tunteellinen/Perinteinen + Romanssi + Vakava/Klassinen/Uskonnollinen/Historiallinen + Aikuiset + + + + + + + Tallennuskansio Käytä ulkoista DVD-toisto-ohjelmaa @@ -2185,6 +2635,7 @@ Albumitiedot Esittäjätiedot Palvelut + PVR-asiakkaat Asetukset Poista käytöstä diff --git a/language/French/strings.xml b/language/French/strings.xml index 64b3a5a..e90c52b 100644 --- a/language/French/strings.xml +++ b/language/French/strings.xml @@ -1545,9 +1545,435 @@ %i Mo %i heures %i jours - + + Changer de canal - + Séparez les mots clés par AND, OR et/ou NOT. + ou utilisez les guillements pour rechercher une correspondance exacte, comme "Le magicien d'Oz". + Chercher un programme similaire + Importation des données EPG + Information sur le stream PVR + Appareil de réception + Statut de l'appareil de réception + Qualité du signal + SNR + BER + UNC + Serveur PVR + Gratuite + Fixée + Cryptage + Serveur PVR %i - %s + Enregistrements TV + Dossier par défaut pour les miniatures + Chaînes + TV + Radio + Caché + Chaînes TV + Stations Radio + Prochains enregistrements + Ajouter une programmation... + Aucun résultat + Pas d'entrée EPG + Chaîne + Maintenant + Suivant + Calendrier + Information + Un enregistrement a déjà commencé sur cette chaîne + Cette chaîne ne peut pas être lue. Voir le log pour plus de détails. + Cet enregistrement ne peut pas être lue. Voir le log pour plus de détails. + Voir la qualité du signal + Non supporté par le serveur PVR. + Êtes-vous sûr de vouloir cacher cette chaîne ? + Programmation + Êtes-vous sûr de vouloir renommer cet enregistrement ? + Êtes-vous sûr de vouloir renommer cette programmaiton ? + Enregistrement + Veuillez vérifier votre configuration ou voir le log pour plus de détails. + Aucun client PVR n'a été démarré pour l'instant. Attendez que les clients PVR démarrent ou regardez le log pour plus de détails. + Nouvelle chaîne + Infos programme + Gestion des groupes + Voir la chaîne + Voir les chaînes visibles + Voir les chaînes cachées + Déplacer la chaîne vers : + Recording information + Cacher la chaîne + Pas d'information disponible + Nouvelle programmation + Modifier la programmation + Programmation activée + Arrêter l'enregistrement + Supprimer la programmation + Ajouter une programmation + Trier par : Chaîne + Aller au début + Aller à la fin + Fenêtre EPG par défaut + Chargement des enregistrements + Ce programme est déjà en cours d'enregistrement. + Cet enregistrement n'a pas pu être supprimé. Voir le log pour plus de détails. + EPG + Echec du scan EPG + Intervalle de mise à jour de l'EPG + Ne pas enregistrer l'EPG dans la base de données + Délai au changement de chaîne + Active : + Nom : + Dossier : + Radio : + Chaîne : + Jour : + Début : + Fin : + Priorité : + Durée de vie (jours) : + Premier jour : + Chaîne inconnue %u + Lu-__-__-__-__-__-__ + __-Ma-__-__-__-__-__ + __-__-Me-__-__-__-__ + __-__-__-Je-__-__-__ + __-__-__-__-Ve-__-__ + __-__-__-__-__-Sa-__ + __-__-__-__-__-__-Di + Lu-Ma-Me-Je-Ve-__-__ + Lu-Ma-Me-Je-Ve-Sa-__ + Lu-Ma-Me-Je-Ve-Sa-Di + __-__-__-__-__-Sa-Di + Entrez un nom pour l'enregistrement + Attention + Programmation existante + Êtes vous sûr de vouloir supprimer cette chaîne, ainsi que toutes les programmations associées ? + Cette chaîne est actuellement utilisée en lecture. + Veuillez changer de chaîne. + Scan des icônes manquants + Entrez le nom du dossier pour l'enregistrement + Taille : + Prochaine programmation le + à + Enregistrements non synchros. Voir le log pour plus de détails. + Impossible de sauvegarder la programmation. Voir le log pour plus de détails. + Erreur. Réessayez plus tard ou regardez le log pour plus de détails. + Erreur du serveur PVR. Voir le log pour plus de détails. + Programmations non synchros. Voir le log pour plus de détails. + Suivant + Version + Adresse + Taille du disque + Rechercher des chaînes + Impossible d'utiliser les fonctions PVR pendant + Sur quel serveur voulez-vous rechercher ? + Nombre de clients + Eviter les répétitions + L'enregistrement est encore en cours. Êtes-vous sûr de vouloir supprimer cette programmation ? + Chaînes gratuites seulement + Ignorer les programmations existantes + Ignorer les enregistrements existants + Heure de début + Heure de fin + Date de début + Date de fin + Durée minimum + Durée maximum + Inclure les genres inconnus + Recherche + Inclure la description + Sensible à la casse + Chaîne indisponible + Aucun groupe defini + Veuillez créer un groupe + Nom du nouveau groupe + Groupe + Rechercher dans le guide + Gestion des groupes + Aucun groupe défini + Groupé + Groupes + Le serveur PVR ne supporte pas cette action. Voir le log pour plus de détails. + Chaîne + Lu + Ma + Me + Je + Ve + Sa + Di + depuis + Prochain enregistrement + Enregistrement en cours + de + à + Sur + Enregistrement actif + Enregistrements + Impossible de démarrer l'enregistrement. Voir le log pour plus de détails. + Regarder + Information PVR + Scan des icônes manquants + Changer de chaîne sans appuyer sur OK + Cacher la boîte d'information vidéo + Temps d'attente maximum au démarrage de la lecture + Démarrer avec la lecture réduite + Durée par défaut des enregistrements instantannés + Priorité par défaut des enregistrements + Durée de vie par défaut des enregistrements + Marge au début de l'enregistrement + Marge à la fin de l'enregistrement + Lecture + Voir les informations sur la chaîne lors du zapping + Cacher automatiquement l'information des chaînes + TV + Menu/OSD + Jours à afficher dans l'EPG + Durée d'affichage des informations de la chaîne + Réinitialiser la base de données PVR + Toutes les données dans la base de données PVR vont être effacées + Réinitialiser la base de données EPG + L'EPG va être réinitialisé + Afficher la dernière chaîne au démarrage + Réduit + Service PVR + Aucun des serveur PVR connectés ne supporte le scan des chaînes. + Le scan des chaînes ne peut pas démarrer. Voir le log pour plus de détails. + la recherche. Continuer ? + Actions client + Actions spécifiques du client PVR + Enregistrement démarré le : %s + Enregistrement fini le : %s + Gestion des chaînes + Source EPG : + Nom de la chaine : + Icône de la chaîne : + Modifier la chaîne + Nouvelle chaîne + Gestion des groupes + Activer EPG : + Groupe : + Entrer le nom de la nouvelle chaîne + serveur virtuel XBMC + Client + Supprimer la chaîne + Cette liste contient des changements + Choisir le serveur + Entrez une URL valide pour la nouvelle chaîne + Le serveur PVR ne supporte pas les programmations. + Toutes les stations radio + Toutes les chaînes TV + Visible + Chaînes disponibles + Chaînes dans + Synchroniser les groupes de chaînes avec le serveur PVR + EPG + Aucun addon PVR n'a pu être activé. Voir le log pour plus de détails. + Enregistrement annulé + Enregistrement programmé + Enregistrement démarré + Enregistrement terminé + Enregistrement supprimé + Fermer l'OSD de la chaîne après le zapping + Désactiver les mises à jour d'EPG pendant la lecture d'une chaîne TV + Toujours utiliser l'ordre des chaînes du serveur PVR + Effacer les résultats + Afficher une notification au changement d'état des programmations + + Autre/Inconnu + Film/Drame + Policier/Thriller + Aventure/Western/Guerre + Science Fiction/Fantaisie/Horreur + Comédie + Série B/Mélodrame/Folklore + Romance + Serieux/Classique/Religion/Film Historique/Drame + Film pour Adultes/Drame + + + + + + + + Actualité + Bulletin Météo + Magazine d'actualité + Documentaire + Discussion/Interview/Débat + + + + + + + + + + + + Spectacle/Jeu Télévisé + Jeu Télévisé/Quizz/Concours + Emission de Variétés + Talk Show + + + + + + + + + + + + + Sports + Evénement spécial + Magazine Sportif + Football + Tennis/Squash + Sports en Equipe + Athlétisme + Sport Automobile + Sport Aquatique + Sports d'Hiver + Equitation + Arts Martiaux + + + + + Programme Enfants/Jeunes + Programme Bébés + Divertissement 6-14 ans + Divertissement 10-16 ans + Programme Educatif + Dessin Animé/Marionnettes + + + + + + + + + + + Musique/Ballet/Danse + Rock/Pop + Musique Classique + Folklore/Musique Traditionelle + Comédie Musicale/Opera + Ballet + + + + + + + + + + + Arts/Culture + Arts du Spectacle + Beaux Arts + Religion + Culture Populaire/Arts Traditionels + Littérature + Film/Cinéma + Film/Video Experimental + Diffusion/Presse + Nouveaux Médias + Magazine d'Art/Culture + Mode + + + + + Société/Politique/Economie + Magazine/Reportage/Documentaire + Economie/Société + People + + + + + + + + + + + + + Education/Science/Faits + Nature/Animaux/Environnement + Technologie/Sciences Naturelles + Médecine/Anatomie/Psychologie + Pays Etrangers/Expéditions + Société/Sciences Spirituelles + Enseignement Postscolaire + Langues + + + + + + + + + Loisirs + Tourisme/Voyages + Artisanat + Automobile + Fitness & Santé + Cuisine + Publicité/Shopping + Jardinage + + + + + + + + + Characteristiques Speciales + Langue Originale + Noir & Blanc + Non publié + Live + + + + + + + + + + + + Drame + Policier/Thriller + Aventure/Western/Guerre + Science Fiction/Fantaisie/Horreur + Comédie + Soap/Melodrame/Folklore + Romance + Documentaire/Religion/Historique + Adulte + + + + + + + + Dossier des enregistrements musique Utiliser un lecteur DVD externe Lecteur DVD externe diff --git a/language/German/strings.xml b/language/German/strings.xml index 94b203e..49fa3f2 100644 --- a/language/German/strings.xml +++ b/language/German/strings.xml @@ -1026,6 +1026,8 @@ Minimieren Power-Button Aktion Herunterfahren + Blockiere Herunterfahren + Erlaube Herunterfahren Ist noch eine weitere Sitzung aktiv (evtl. SSH)? Wechselfestplatte wurde angeschlossen @@ -1573,7 +1575,442 @@ Bildschirm Sleep Timeout + %i Stunden + %i Tage + + Zum Kanal wechseln + Benutzen Sie AND, OR und NOT in Verbindung mit Ihren Suchbegriffen, um detaillierter zu suchen. + Oder benutzen Sie ganze Sätze in Ausrufezeichen z.B.: "Der Zauberer von Oz". + Finde ähnliche Sendung + Lade EPG von den PVR-Klienten + PVR Empfang-Informationen + Empfangsgerät + Empfangsstatus + Signal Qualität + SNR + BER + UNC + Backend + Frei empfangbar + Fest + Verschlüsselung + Server %i - %s + TV Aufnahmen + Standardordner für TV Thumbnails + Kanäle + TV + Radio + Versteckte + TV Kanäle + Radio Kanäle + Bevorstehende Aufnahmen + Timer hinzufügen... + Es liegen keine Suchergebnisse vor + Es sind keine EPG Einträge vorhanden + Programm + Jetzt + Nächstes + Zeitleiste + Information + Aufnahme läuft bereits + Kanal konnte nicht wiedergegeben werden + Aufnahme konnte nicht wiedergegeben werden + Signalqualität anzeigen + Wird derzeit nicht unterstützt! + Verstecken bestätigen + Timer + Aufnahme umbenennen? + Timer umbenennen? + Aufnahme + Bitte überprüfen Sie ihre Einstellungen oder den Server + Keine PVR Klienten verfügbar + Neuer Kanal + Titel-Informationen + Gruppenverwaltung + Zeige Kanal + Zeige normale Kanäle + Zeige versteckte Kanäle + Kanal verschieben nach: + Aufnahme-Informationen + Kanal verstecken + Keine Informationen verfügbar! + Neuer Timer + Timer bearbeiten + Timer aktivieren/deaktivieren + Aufnahme abbrechen + Timer löschen + Timer hinzufügen + Nach Kanal + Gehe zum Anfang + Gehe zum Ende + Standard Programmanzeige + Lade Aufnahmeinformationen von den PVR-Klienten + Es ist bereits ein Timer vorhanden + Konnte Aufnahme nicht löschen! + EPG + Zeit bis zur EPG-Suche + Zeit bis zur EPG-Aktualisierung + Ignoriere Datenbank für PVR-Server EPG + Zeitlimit für Kanaleingabe + Aktiv: + Name: + Ordner: + Radio: + Kanal: + Tag: + Anfang: + Ende: + Priorität: + Erster Tag: + Unbekannter Kanal %u + Mo-__-__-__-__-__-__ + __-Di-__-__-__-__-__ + __-__-Mi-__-__-__-__ + __-__-__-Do-__-__-__ + __-__-__-__-Fr-__-__ + __-__-__-__-__-Sa-__ + __-__-__-__-__-__-So + Mo-Di-Mi-Do-Fr-__-__ + Mo-Di-Mi-Do-Fr-Sa-__ + Mo-Di-Mi-Do-Fr-Sa-So + __-__-__-__-__-Sa-So + Bitte geben Sie den Aufnahmenamen ein + Warnung + Timer vorhanden + Kanal und Timer löschen? + Kanalwiedergabe läuft + Bitte schalten Sie auf einen anderen Kanal! + Suche fehlende Kanallogos + Bitte geben Sie den Aufnahmeordner ein + Größe: + Nächster Timer am + um + Aufnahmen nicht synchron! + Konnte Timer nicht speichern! + Erneut versuchen... + Server Fehler! + Timers nicht synchron! + Danach + Version + Addresse + Festplattengröße + Kanäle suchen + TV ist während der Kanalsuche nicht möglich! + Auf welchem Server soll gesucht werden? + Klientnummer + Keine Wiederholungen + Timer zeichnet auf - trotzdem löschen? + Nur frei empfangbare Kanäle + Bei vorhandenem Timer ignorieren + Bei vorhandener Aufnahmen ignorieren + Start Uhrzeit + Stop Uhrzeit + Start Datum + Stop Datum + Minimale Dauer + Maximale Dauer + Inklusive unbekannter Genres + Suchbegriff + Inklusive Beschreibung + Groß-/Kleinschreibung + Kanal nicht verfügbar + Keine Gruppen definiert + Bitte erstellen Sie zuerst eine + Neuer Gruppenname + Gruppe + EPG durchsuchen + Gruppenverwaltung + Ungruppiert + Keine Gruppen + Gruppen + PVR-Server ist nicht kompatibel! + Kanal + Mo + Di + Mi + Do + Fr + Sa + So + ab + Nächste Aufnahme + Jetzige Aufnahme + von + bis + Auf + Aufnahme läuft + Aufnahmen + Konnte Aufnahme nicht starten + Umschalten + PVR-Informationen + Suche fehlende Kanallogos + Beim umschalten auf OK verzichten + Infobox für Videolänge verbergen + Suchüberlauf vor Kanalwiedergabe + Wiedergabe minimiert starten + Dauer der Direktaufzeichnung + Standard-Priorität + Standard-Lebensdauer + Vorlauf zum Timer-Beginn + Nachlauf am Timer-Ende + Wiedergabe + Info beim Kanalwechsel + Angeforderte Kanalinfo schließen + TV + Menü/OSD + Tage für TV-Programm Anzeige + Alte EPG-Daten anzeigen + Anzeigedauer für Kanalinfo + TV Datenbank zurücksetzten + Alle Daten in der Datenbank werden gelöscht + EPG Daten löschen und neu einlesen + Alle EPG Daten werden gelöscht + Nach Start letzten Kanal wiedergeben + Minimiert + PVR-Service + Keiner der PVR-Server unterstützt die Kanalsuche + Kanalsuche konnte nicht durchgeführt werden + Fortfahren? + Klientaktionen + PVR Klient spezifische Aktionen + Aufnahme gestarted auf: %s + Aufnahme beendet auf: %s + Kanalverwaltung + EPG Quelle: + Kanalname: + Kanallogo: + Kanal bearbeiten + Neuer Kanal + Gruppenverwaltung + EPG Aktivieren: + Gruppe: + Bitte geben Sie den neuen Kanalnamen ein + XBMC interner virtueller Kanal + Klient + Kanal löschen + Liste enthält Änderungen + Wählen Sie die Kanalquelle + Bitte geben Sie eine URL für den Kanal ein + Der PVR-Server unterstützt keine Timer! + Alle Radio Kanäle + Alle TV Kanäle + + Ungruppierte Kanäle + Kanäle in + Synchronisiere Kanalgruppen mit den Backends + + Es konnte kein PVR Add-on aktiviert werden. Überprüfen Sie Ihre Einstellungen und das Log. + Aufnahme abgebrochen + Aufnahme geplant + Aufnahme gestartet + Aufnahme beendet + Aufnahme gelöscht + Schließe das Kanal-OSD nach einem Kanalwechsel + Deaktiviere EPG Aktualisierungen während der TV Wiedergabe + Immer die Kanalreihenfolge der Backends verwenden + Zeige eine Benachrichtigung bei Timer Aktualisierungen + Verwenden Backend Kanal Nummerierung (funktioniert nur mit 1 aktiv PVR Addons) + + Backend Inaktivität + Aufwachzeit Kommando (cmd [timestamp]) + Vor Aufnahmebeginn aufwachen + Tägliches aufwachen + Tägliche Aufwachzeit (HH:MM:SS) + + Andere/Unbekannt + Movie/Drama + Detektivfilm/Thriller + Abenteuer/Western/Krieg + Science Fiction/Fantasy/Horror + Komödie + Seifenoper/Melodram/Folklore + Romanze + Serie/Klassik/Religion/Historienfilm + Erwachsenenfilm + + + + + + + + Nachrichten/Aktuelle Meldungen + Nachrichten/Wettervorhersage + Nachrichtenmagazin + Dokumentation + Diskussion/Interview/Debatte + + + + + + + + + + + + Show/Game Show + Game Show/Quiz/Contest + Varietevorführung + Talk Show + + + + + + + + + + + + + Sport + Sportveranstaltung + Sportmagazin + Fußball + Tennis/Squash + Team Sportarten + Athletik + Motorsport + Wassersport + Wintersport + Pferdesport + Kampfsport + + + + + Kinder- & Jugendprogramm + Unterhaltungsprogramm für Vorschulkinder + Unterhaltungsprogramm für 6 bis 14 Jährige + Unterhaltungsprogramm für 10 bis 16 Jährige + Information/Educational/Schulprogramm + Zeichentrick/Puppen + + + + + + + + + + + Musik/Ballet/Tanzen + Rock/Pop + Serious/Klassische Musik + Volksmusik/Tradionelle Musik + Musical/Oper + Ballet + + + + + + + + + + + Kunst/Kultur + Performing Arts + Bildende Kunst + Religion + Volkskultur/Traditionelle Kunst + Literatur + Film/Kino + Experimental Film/Video + Rundfunk/Presse + Neue Medien + Kunst/Kultur Magazin + Mode + + + + + Soziales/Politik/Wirtschaft + Magazin/Report/Dokumentation + Wirtschaft- & Sozialberatung + Bemerkenswerte Personen + + + + + + + + + + + + + Bildung/Wissenschaft/Fakten + Natur/Tiere/Umwelt + Technologie/Naturwissenschaften + Medizin/Physiologie/Psychologie + Ausland/Expeditionen + Sozial- & Geisteswissenschaften + Weiterbildung + Sprachen + + + + + + + + + Freizeit/Hobbys + Tourismus/Reisen + Handwerk + Auto + Fitness & Gesundheit + Kochen + Werbung/Einkaufen + Garten + + + + + + + + + Besondere Merkmale + Originalsprache + Schwarz/Weiß + Bisher unveröffentlicht + Livesendung + + + + + + + + + + + + Drama + Detektivfilm/Thriller + Abenteuer/Western/Krieg + Science Fiction/Fantasy/Horror + Komödie + Seifenoper/Melodram/Folklore + Romanze + Serie/Klassisch/Religion/Geschichte + Erwachsenenfilm + + + + + + + Ordner für CD-Kopien Externen DVD-Player verwenden @@ -2351,6 +2788,8 @@ Diese Datei ist gestapelt, wähle den Teil der abgespielt werden soll. Skriptpfad Benutzerdefinierten Skript Button aktivieren + Start fehlgeschlagen + Neue Verbindung erkannt Lautsprecherkonfiguration diff --git a/language/Greek/strings.xml b/language/Greek/strings.xml index a3c36a0..cd0e06d 100644 --- a/language/Greek/strings.xml +++ b/language/Greek/strings.xml @@ -1,8 +1,8 @@ - + Εφαρμογές - Φωτογραφίες + Εικόνες Μουσική Βίντεο Οδηγός τηλεόρασης @@ -82,7 +82,7 @@ Ταξ.: Μέγεθος Όχι Ναι - Παρουσίαση + Παρουσίαση διαφανειών Δημιουργία εικονιδίων Δημιουργία μικρογραφιών Συντομεύσεις @@ -103,7 +103,7 @@ Λειτουργία Αντικείμενα Γενικά - Παρουσίαση + Παρουσίαση διαφανειών Πληροφορίες συστήματος Απεικόνιση Άλμπουμ @@ -123,7 +123,7 @@ Τύπος: Στατική DHCP - Φυσική διεύθυνση + Διεύθυνση MAC Διεύθυνση IP Σύνδεση: Μονόδρομη @@ -136,19 +136,19 @@ Καμία σύνδεση Ελεύθερα Μη διαθέσιμο - Άνοιγμα μονάδας + Θύρα δίσκου ανοικτή Ανάγνωση Δεν υπάρχει δίσκος Υπάρχει δίσκος Κέλυφος Ανάλυση - Προσαρμογή του ρυθμού ανανέωσης + Προσαρμογή του ρυθμού ανανέωσης για να ταιριάζει με το βίντεο Ημερομηνία κυκλοφορίας Προβολή των βίντεο με αναλογία 4:3 ως - Διάθεση + Τάσεις Στυλ Τραγούδι @@ -169,21 +169,21 @@ Αναζήτηση... Δεν βρέθηκαν πληροφορίες! Επιλογή ταινίας: - Αναζήτηση πληροφοριών %s + Εύρεση πληροφοριών %s Φόρτωση πληροφοριών ταινίας Διεπαφή ιστού - Σύνθημα + Σλόγκαν Περίληψη πλοκής Ψήφοι - Ρόλοι και ηθοποιοί + Διανομή ρόλων Πλοκή Εκκίνηση Επόμενο Προηγούμενο - Βαθμονόμηση οθόνης… - Βαθμονόμηση βίντεο… + Βαθμονόμηση οθόνης... + Βαθμονόμηση βίντεο... Απάλυνση εικόνας Ποσοστό μεγέθυνσης Λόγος εικονοστοιχείων @@ -196,7 +196,7 @@ Κατακόρυφη μετατόπιση Δοκιμή μοτίβων... Αναζήτηση ονομάτων μουσικών κομματιών από το freedb.org - Ανακάτεμα λίστας αναπαραγωγής κατα τη φόρτωση + Ανακάτεμα λίστας αναπαραγωγής κατά τη φόρτωση Χρόνος ελάττωσης περιστροφής (Spindown) Φίλτρα βίντεο Κανένα @@ -205,22 +205,22 @@ Ανισοτροπικό Quincunx Gaussian cubic - Ελαχιστοποίηση + Σμίκρυνση Μεγέθυνση Εκκαθάριση λίστας αναπαραγωγής στη λήξη - Κατάσταση προβολής + Λειτουργία Προβολής Πλήρης οθόνη #%d Σε παράθυρο Ανανέωση βαθμολογίας Πλήρης οθόνη - Μέγεθος: (%i,%i)->(%i,%i) (Εστίαση x%2.2f) AR:%2.2f:1 (Εικονοστοιχεία: %2.2f:1) (ΚΜετατόπιση: %2.2f) + Μέγεθος: (%i,%i)->(%i,%i) (Εστίαση x%2.2f) AR:%2.2f:1 (Εικονοστοιχεία: %2.2f:1) (ΚΜετατόπιση: %2.2f) Scripts Γλώσσα Μουσική Οπτικοποίηση Επιλογή καταλόγου προορισμού - Στέρεο έξοδος σ' όλα τα ηχεία + Στέρεο έξοδος σε όλα τα ηχεία Αριθμός καναλιών - Δέκτης ικανός για αναπαραγωγή DTS CDDB @@ -229,13 +229,13 @@ Ενεργοποίηση ID3 ετικετών Άνοιγμα Shoutcast - Αναμονή για την έναρξη.... + Αναμονή για την έναρξη... Εξαγωγές Scripts - Έγκριση ελέγχου του XBMC από το HTTP + Έγκριση ελέγχου του XBMC μέσω HTTP Εγγραφή Διακοπή εγγραφής Ταξ.: Κομμάτι - Ταξ.: Έτος + Ταξ.: Χρόνος Ταξ.: Τίτλος Ταξ.: Καλλιτέχνης Ταξ.: Άλμπουμ @@ -248,8 +248,8 @@ Μετακινήστε τη μπάρα για να αλλάξει η θέση των υποτίτλων Αλλάξτε το σχήμα ώστε να είναι τέλειο τετράγωνο Αδυναμία φόρτωσης των ρυθμίσεων - Χρησιμοποίηση προεπιλεγμένων ρυθμίσεων - Παρακαλώ, ελέγξτε τα αρχεία .xml + Χρήση προεπιλεγμένων ρυθμίσεων + Παρακαλώ ελέγξτε τα αρχεία .XML Βρέθηκαν %i αντικείμενα Αποτελέσματα αναζήτησης Δεν βρέθηκαν αποτελέσματα @@ -262,7 +262,7 @@ Ήχος Αναζήτηση για υπότιτλους Δημιουργία - Απαλοιφή + Εκκαθάριση Καθυστέρηση ήχου Σελιδοδείκτες - Δέκτης ικανός για αναπαραγωγή AAC @@ -272,7 +272,7 @@ Καθυστέρηση Γλώσσα Ενεργό/ή - Μη-διαστρωματωμένο + Non-interleaved (0=αυτόματα) Εκκαθάριση βάσης δεδομένων @@ -303,7 +303,7 @@ Αναλογική Οπτική/Coax Διάφοροι καλλιτέχνες - Έναρξη DVD + Έναρξη δίσκου Ταινίες Προσαρμογή δειγματοληψίας Ηθοποιοί @@ -314,13 +314,13 @@ Αμυδρό φως Μαύρη οθόνη Ίχνη πλέγματος - Αναμονή ενεργοποίησης προφύλαξης οθόνης + Αναμονή για προφύλαξη οθόνης Λειτουργία προφύλαξης οθόνης Λειτουργία χρονοδιακόπτη τερματισμού Όλα τα άλμπουμ Πρόσφατα άλμπουμ Προφύλαξη οθόνης - Παρουσίαση + Παρουσίαση διαφανειών και των υποφακέλων Ποσοστό εξασθένισης της προφύλαξης οθόνης Ταξ.: Αρχείο - Δέκτης με ικανότητα αναπαραγωγής Dolby Digital (AC3) @@ -331,8 +331,8 @@ Τίτλος Καταιγίδες Διάσπαρτα - Επί το πλείστον - Αίθριος + Κυρίως + Ηλιοφάνεια Νέφη Χιόνι Βροχή @@ -344,7 +344,7 @@ Σποραδικά Άνεμος Δυνατός - Νεφελώδης + Ήπιος Αίθριος Νεφοσκεπής τις πρώτες πρωινές ώρες @@ -354,7 +354,7 @@ Μεσ. Μεγ. Ομίχλη - Καταχνιά + Ξηρά αχλή Επιλογή τοποθεσίας Ανανέωση χρόνου Μονάδα θερμοκρασίας @@ -368,14 +368,14 @@ Υγρασία Προεπιλεγμένα - Πρόσβαση στο Weather.com - Πληροφορίες καιρού: - Αδυναμία λήξης δεδομένων καιρού + Πρόσβαση στην υπηρεσία καιρού + Ανάκτηση καιρού για: + Αδυναμία λήψης δεδομένων καιρού Χειροκίνητα Καμιά κριτική για το άλμπουμ Λήψη μικρογραφίας... Μη διαθέσιμος πόρος - Προβολή: Εικόνες + Προβολή: Μεγ. Εικονίδια Ελαχ. Μεγ. HDMI @@ -386,7 +386,7 @@ Δεν βρέθηκαν πληροφορίες για το άλμπουμ Δεν βρέθηκαν πληροφορίες για το CD Δίσκος - Εισαγωγή ορθού CD/DVD + Εισάγετε το σωστό CD/DVD Παρακαλώ, εισάγετε τον ακόλουθο δίσκο: Ταξ.: DVD# Δεν υπάρχει ελεύθερη λανθάνουσα μνήμη @@ -400,7 +400,7 @@ Σκληρός δίσκος UDF Τοπικό δίκτυο - Internet + Διαδίκτυο Βίντεο Ήχος DVD @@ -422,9 +422,9 @@ Οπίσθιος φωτισμός Φωτεινότητα Αντίθεση - Συντελεστής γάμα + Συντελεστής γάμμα Τύπος - Μετακίνηση της μπάρας για την αλλαγή της θέσης των απεικονίσεων οθόνης (OSD) + Μετακινήστε τη μπάρα για αλλαγή της θέσης των απεικονίσεων οθόνης (OSD) Θέση απεικονίσεων οθόνης (OSD) Συντελεστές Τσιπάκι @@ -440,10 +440,10 @@ Διαγραφή άλμπουμ Επανάληψη - Επανάληψη του ιδίου - Επανάληψη φακέλων + Επανάληψη του ίδιου + Επανάληψη φακέλου Αυτόματη αναπαραγωγή επόμενου κομματιού - - Χρήση Μ. εικονιδίων + - Χρήση Μεγ. εικονιδίων Μεγέθυνση υποτίτλων Ρυθμίσεις για προχωρημένους! Εύρος στάθμης γενικού ήχου @@ -470,7 +470,7 @@ Εκκίνηση Εκκίνηση σε... - Συλλογές + Συνθέσεις Απομάκρυνση πηγής Εναλλαγή πολυμέσων Επιλογή λίστας αναπαραγωγής @@ -478,7 +478,7 @@ Προσθήκη στη λίστα αναπαραγωγής Χειροκίνητη προσθήκη στη συλλογή Εισάγετε τίτλο - Σφάλμα: Διπλός τίτλος + Σφάλμα: Διπλότυπος τίτλος Επιλέξτε είδος Νέο είδος Χειροκίνητη προσθήκη @@ -487,24 +487,24 @@ Λίστα Εικονίδια Μεγάλη λίστα - Εικόνες + Μεγ. Εικονίδια Ευρεία Πολύ ευρεία - Εικόνες άλμπουμ - Εικόνες DVD + Εικον. άλμπουμ + Εικον. DVD DVD Πληροφορίες Συσκευή εξόδου ήχου Συσκευή εξόδου διέλευσης - Δεν υπάρχει βιογραφία γι΄ αυτόν τον καλλιτέχνη + Δεν υπάρχει βιογραφία γι' αυτόν τον καλλιτέχνη Υποβιβασμός πολυκάναλου ήχου σε στερεοφωνικό - Κατάταξη: %s + Ταξ.: %s Όνομα Ημερομηνία Μέγεθος Κομμάτι - Ώρα + Χρόνος Τίτλος Καλλιτέχνης Άλμπουμ @@ -514,21 +514,21 @@ Έτος Αξιολόγηση Τύπος - Χρησιμότητα - Άλμπουμ καλλιτέχνη + Χρήση + Καλλιτέχνης Άλμπουμ Αναπαράχθηκε Τελευταία αναπαραγωγή Σχόλια - Ημ/νία προσάρτησης + Ημ/νία προσθήκης Προεπιλεγμένη - Εταιρεία (studio) + Στούντιο Διαδρομή Χώρα Σε εξέλιξη Αριθμός αναπαραγωγών Σειρά ταξινόμησης - Κριτήρια ταξινόμησης + Μέθοδος ταξινόμησης Λειτουργία Προβολής Απομνημόνευση προβολών διαφορετικών φακέλων Αύξουσα @@ -541,30 +541,30 @@ Όχι Ένα Όλα - Ναι + Όχι Επανάληψη: Όχι Επανάληψη: Μία φορά Επανάληψη: Όλων - Εγγραφή CD ήχου + Αντιγραφή CD ήχου Μεσαία Κανονική Ακραία - Σταθερός ρυθμός - Εγγραφή... + Σταθερό bitrate + Αντιγραφή... Προς: - Αδυναμία εγγραφής CD ή κομματιού - Δεν ορίσθηκε διαδρομή εξαγωγής CDDA. - Εγγραφή κομματιού + Αδυναμία αντιγραφής CD ή κομματιού + Δεν ορίσθηκε διαδρομή αντιγραφής CDDA. + Αντιγραφή κομματιού Εισαγωγή αριθμού Bits/Sample Συχνότητα δειγματοληψίας - CDs ήχου + CD ήχου Κωδικοποιητής Ποιότητα - Ρυθμός + Bitrate Συμπερίληψη αριθμού κομματιού Όλα τα τραγούδια Λειτουργία προβολής @@ -608,17 +608,17 @@ Εκκαθάριση συλλογής Απομάκρυνση παλαιών τραγουδιών από τη συλλογή - Η διαδρομή έχει σαρωθεί προηγούμενος + Η διαδρομή έχει σαρωθεί παλαιότερα Δίκτυο - Διακομιστής - Χρήση ενός διαμεσολαβητή HTTP για πρόσβαση στο internet + Χρήση διαμεσολαβητή HTTP για πρόσβαση στο Διαδίκτυο Πρωτόκολλο Internet (IP) - Προσδιορίσατε λάθος θύρα. Η τιμή κυμαίνεται μεταξύ 1 και 65535. + Ορίστηκε λάθος θύρα. Η τιμή πρέπει να είναι μεταξύ 1 και 65535. Διαμεσολαβητής HTTP - - Εκχώρηση + - Ανάθεση Αυτόματη (DHCP) Χειροκίνητη (Στατική) @@ -627,9 +627,9 @@ - Προεπιλεγμένη πύλη - Διακομιστής DNS Αποθήκευση & επανεκκίνηση - Προσδιορίστηκε εσφαλμένη διεύθυνση. Η τιμή πρέπει να έχει τη μορφή AAA.BBB.CCC.DDD + Ορίστηκε λάθος διεύθυνση. Πρέπει να έχει τη μορφή AAA.BBB.CCC.DDD με τιμές μεταξύ 0 και 255. - Οι αλλαγές δεν αποθηκεύτηκαν. Συνέχιση χωρίς αποθήκευση; + Οι αλλαγές δεν αποθηκεύτηκαν. Συνέχεια χωρίς αποθήκευση; Διακομιστής Ιστού Διακομιστής FTP @@ -637,7 +637,7 @@ Αποθήκευση & εφαρμογή - Κωδικός πρόσβασης - Χωρίς κωδικό πρόσβασης + Χωρίς κωδικό - Κωδικοποίηση χαρακτήρων - Στυλ - Χρώμα @@ -648,9 +648,9 @@ Λευκό Κίτρινο Αρχεία - Δεν υπάρχει πληροφορία γι΄ αυτή την προβολή - Απενεργοποιήστε την λειτουργία συλλογής - Σφάλμα κατά την φόρτωση της εικόνας + Καμία πληροφορία για αυτήν την προβολή + Απενεργοποιήστε τη λειτουργία συλλογής + Σφάλμα κατά τη φόρτωση της εικόνας Επεξεργασία διαδρομής Kατοπτρική εικόνα Είστε σίγουρος; @@ -665,7 +665,7 @@ Κίτρινο Λευκό Μπλε - Φωτεινό πράσινο + Έντονο πράσινο Κιτρινοπράσινο Κυανό Ανοικτό γκρι @@ -677,7 +677,7 @@ Έξοδος ήχου Αναζήτηση Φάκελος παρουσίασης διαφανειών - Διασύνδεση + Διασύνδεση δικτύου - Όνομα ασύρματου δικτύου (ESSID) - Κωδικός πρόσβασης ασύρματου δικτύου - Ασφάλεια ασύρματου δικτύου @@ -686,33 +686,33 @@ WEP WPA WPA2 - Εφαρμογή των ρυθμίσεων διασύνδεσης δικτύου. Παρακαλώ, περιμένετε. - Επιτυχής εκκίνηση της διασύνδεσης δικτύου. - Δεν ήταν επιτυχής η εκκίνηση της διασύνδεσης δικτύου. + Εφαρμογή των ρυθμίσεων διασύνδεσης δικτύου. Παρακαλώ περιμένετε. + Επιτυχής επανεκκίνηση της διασύνδεσης δικτύου. + Δεν ήταν επιτυχής η εκκίνηση της διασύνδεσης δικτύου. Απενεργοποίηση Διασύνδεσης Η Διασύνδεση δικτύου απενεργοποιήθηκε επιτυχώς. Όνομα ασύρματου δικτύου (ESSID) - Έγκριση σε προγράμματα απομακρυσμένου ελέγχου να ελέγξουν το XBMC + Έγκριση σε προγράμματα του συστήματος να ελέγχουν το XBMC Θύρα - Εύρος θύρας - Έγκριση σε προγράμματα άλλων υπολογιστών να ελέγξουν το XBMC + Εύρος θυρών + Έγκριση σε προγράμματα άλλων συστημάτων να ελέγχουν το XBMC Αρχική καθυστέρηση (ms) Συνεχής καθυστέρηση (ms) Μέγιστος αριθμός πελατών - Πρόσβαση στο internet + Πρόσβαση στο Διαδίκτυο - Εισαγωγή μη έγκυρου εύρους τιμών θύρας - Το έγκυρο εύρος τιμών θύρας είναι 1-65535 - Το έγκυρο εύρος τιμών θύρας είναι 1024-65535 + Εισαγωγή μη έγκυρης τιμής θύρας + Το έγκυρο εύρος θυρών είναι 1-65535 + Το έγκυρο εύρος θυρών είναι 1024-65535 Προσθήκη Μουσικής... Προσθήκη Βίντεο... - Προεπισκόπηση Αδυναμία σύνδεσης - Το ΧΒMC είναι ανίκανο να συνδεθεί στο δίκτυο. - Αυτό μπορεί να συμβαίνει διότι το δίκτυο δεν είναι συνδεμένο. - Θέλετε οπωσδήποτε να το προσθέσετε; + Το XBMC δεν μπόρεσε να συνδεθεί στο δίκτυο. + Αυτό μπορεί να συνέβη διότι το δίκτυο δεν είναι συνδεδεμένο. + Θέλετε παρ' όλα αυτά να το προσθέσετε; Διεύθυνση IP Προσθήκη τοποθεσίας δικτύου @@ -724,13 +724,13 @@ Θύρα Όνομα χρήστη Αναζήτηση δικτυακού διακομιστή - Εισαγωγή της δικτυακής διεύθυνσης για τον διακομιστή - Εισαγωγή της διαδρομής στον διακομιστή + Εισαγωγή της δικτυακής διεύθυνσης για το διακομιστή + Εισαγωγή της διαδρομής στο διακομιστή Εισαγωγή του αριθμού θύρας Εισαγωγή του ονόματος χρήστη Προσθήκη πηγής %s Εισαγωγή διαδρομών ή αναζήτηση τοποθεσιών πολυμέσων. - Εισαγωγή ετικέτας για την πηγή πολυμέσων. + Εισαγωγή ονόματος για την πηγή πολυμέσων. Αναζήτηση νέου κοινόχρηστου πόρου Αναζήτηση Δεν ήταν δυνατόν να ανακτηθούν οι πληροφορίες καταλόγου. @@ -742,16 +742,16 @@ Αναζήτηση φακέλου εικόνων Προσθήκη τοποθεσίας δικτύου... Αναζήτηση αρχείου - Yπομενού + Υπομενού Ενεργοποίηση πλήκτρων υπομενού Αγαπημένα - Πρόσθετα βίντεο - Πρόσθετα μουσικής - Πρόσθετα εικόνας + Πρόσθετα Βίντεο + Πρόσθετα Μουσικής + Πρόσθετα Εικόνας Φόρτωση φακέλου Ανακτήθηκαν %i αντικείμενα - Ανακτήθηκαν %i από %i αντικείμενα - Πρόσθετες εφαρμογές + Ανακτήθηκαν %i από τα %i αντικείμενα + Πρόσθετες Εφαρμογές Ορισμός μικρογραφίας plugin Ρυθμίσεις πρόσθετου Σημεία πρόσβασης @@ -766,13 +766,13 @@ Προεπιλεγμένο όνομα χρήστη Προεπιλεγμένος κωδικός πρόσβασης - WINS διακομιστής + Διακομιστής WINS Προσάρτηση κοινόχρηστων SMB Απομάκρυνση Μουσική Βίντεο - Φωτογραφίες + Εικόνες Αρχεία Μουσική & βίντεο Μουσική & εικόνες @@ -798,12 +798,12 @@ Αυτόματος εντοπισμός συστήματος Ψευδώνυμο - Να απαιτείται επιβεβαίωση για να συνδεθεί + Επιβεβαίωση σύνδεσης Αποστολή ονόματος και κωδικού πρόσβασης χρήστη (FTP) - Διάστημα μεταλλικού θορύβου - Να συνδεθείτε στο σύστημα που εντοπίστηκε; + Χρονικό διάστημα ping + Επιθυμείτε να συνδεθείτε στο σύστημα που εντοπίστηκε; - Αναγγελία αυτών των υπηρεσιών σε άλλα συστήματα διαμέσου του Zeroconf + Αναγγελία αυτών των υπηρεσιών σε άλλα συστήματα μέσω του Zeroconf Έγκριση στο XBMC να λαμβάνει περιεχόμενο AirPlay Όνομα συσκευής - Χρήση προστασίας με κωδικό @@ -811,7 +811,7 @@ Ειδική συσκευή ήχου Ειδική συσκευή διέλευσης - Πυκνό + Μετακινούμενο και Παγωνιά Το βράδυ @@ -826,7 +826,7 @@ Πάγος Κρύσταλλοι Άπνοια - και + με θυελλώδης ασθενής βροχή Καταιγίδα @@ -835,14 +835,14 @@ Κόκκοι Καταιγίδες (με κεραυνούς) Μπόρες (με κεραυνούς) - Μέση + Ήπια Πολύ υψηλή Θυελλώδης - Ομίχλη + Υγρά αχλή - Σε κατάσταση ύπνωσης κατά την αναμονή + Απενεργοποίηση οθόνης κατά την αναμονή Διάρκεια @@ -854,7 +854,7 @@ Αρχική τοποθεσία Εφαρμογές - Φωτογραφίες + Εικόνες Διαχείριση αρχείων Ρυθμίσεις Μουσική @@ -862,9 +862,9 @@ Πληροφορίες συστήματος Ρυθμίσεις - Γενικά Ρυθμίσεις - Οθόνη - Ρυθμίσεις - Αισθητικά - Βαθμονόμηση γραφικού περιβάλλοντος (GUI) + Ρυθμίσεις - Εμφάνιση - Βαθμονόμηση γραφικού περιβάλλοντος (GUI) Ρυθμίσεις - Βίντεο - Βαθμονόμηση Οθόνης - Ρυθμίσεις - Φωτογραφίες + Ρυθμίσεις - Εικόνες Ρυθμίσεις - Εφαρμογές Ρυθμίσεις - Καιρός Ρυθμίσεις - Μουσική @@ -884,7 +884,7 @@ Παράθυρο διαδικασίας Αναζήτηση για υπότιτλους... - Προσωρινή αποθήκευση υπότιτλων... + Προσωρινή αποθήκευση υποτίτλων... τερματισμός αποθήκευση Άνοιγμα ροής @@ -892,26 +892,26 @@ Μουσική/Λίστα αναπαραγωγής Μουσική/Αρχεία Μουσική/Συλλογή - Επεξεργαστής λίστας αναπαραγωγής + Επεξεργασία λίστας αναπαραγωγής 100 κορυφαία τραγούδια 100 κορυφαία άλμπουμ Εφαρμογές Ρυθμίσεις Πρόγνωση καιρού Δικτυακό παιχνίδι - Καταλήξεις + Επεκτάσεις Πληροφορίες συστήματος Μουσική - Συλλογή - Μουσική - Εκτελείται τώρα + Τώρα Εκτελείται - Μουσική - Βίντεο - Εκτελείται τώρα - Πληροφορίες + Τώρα Εκτελείται - Βίντεο + Πληροφορίες άλμπουμ Πληροφορίες ταινίας Παράθυρο επιλογής Μουσική/Πληροφορίες - Παράθυρο OK + Παράθυρο 'Επιλογή' Βίντεο/Πληροφορίες Scripts/Πληροφορίες Βίντεο πλήρους οθόνης @@ -923,7 +923,7 @@ Επιστροφή στα βίντεο Εκκίνηση από την αρχή - Επανεκκίνηση από %s + Συνέχεια από %s 0 1 @@ -936,28 +936,28 @@ 8 9 c - Εντάξει + Επιλογή * - Κλειδωμένος! Εισαγωγή κωδικού... + Κλειδώθηκε! Εισαγωγή κωδικού... Εισαγωγή κωδικού πρόσβασης Εισαγωγή κεντρικού κωδικού Εισάγετε κωδικό ξεκλειδώματος ή πιέστε C για ακύρωση - Εισάγετε συνδυασμό πλήκτρων και - πιέστε Εντάξει, ή Επιστροφή για ακύρωση - Τοποθέτηση κλειδώματος + Εισάγετε συνδυασμό πλήκτρων (combo) και + πιέστε 'Επιλογή', ή 'Επιστροφή' για ακύρωση + Ορισμός κλειδώματος Ξεκλείδωμα Επανατοποθέτηση κλειδώματος Απομάκρυνση κλειδώματος Αριθμητικός κωδικός πρόσβασης - Συνδυασμός πλήκτρων του μοχλού + Συνδυασμός πλήκτρων (combo) του μοχλού Κωδικός πρόσβασης πλήρους κειμένου Εισαγωγή νέου κωδικού πρόσβασης Επανεισαγωγή νέου κωδικού πρόσβασης - Λάθος κωδικός πρόσβασης. + Λάθος κωδικός πρόσβασης, δοκιμές έμειναν Ο κωδικός πρόσβασης δεν ταιριάζει. - Δεν επιτράπηκε η πρόσβαση + Δεν επιτρέπεται η πρόσβαση Οι δοκιμές εισαγωγής κωδικού πρόσβασης εξαντλήθηκαν. Το σύστημα τώρα θα απενεργοποιηθεί. Το αντικείμενο κλειδώθηκε @@ -968,15 +968,15 @@ Κεντρικό κλείδωμα Απενεργοποίηση συστήματος όταν εξαντληθούν οι προσπάθειες εισαγωγής Ο κεντρικός κωδικός δεν είναι έγκυρος - Παρακαλώ, εισάγετε έναν έγκυρο κεντρικό κωδικό + Παρακαλώ εισάγετε έναν έγκυρο κεντρικό κωδικό Ρυθμίσεις & διαχείριση αρχείων Ορισμός ως προεπιλογή για όλες τις ταινίες Διαγράφει όλες τις προηγούμενες αποθηκευμένες τιμές Χρονικό διάστημα προβολής κάθε εικόνας Εφέ προσαρμογής αναλογιών σήματος (pan & zoom) - Κανονικό ρολόι - Ψηφιακό ρολόι + Ρολόι 12 ωρών + Ρολόι 24 ωρών Μέρα/Μήνας Μήνας/Μέρα @@ -1002,16 +1002,16 @@ Λειτουργία τερματισμού Έξοδος Αδρανοποίηση - Ύπνωση + Αναστολή Έξοδος Επανεκκίνηση Συστήματος Ελαχιστοποίηση Ενέργεια πλήκτρου λειτουργίας Απενεργοποίηση συστήματος - Είναι ενεργή άλλη συνεδρία (ίσως μέσω ssh); - Προσάρτηση αναιρούμενου δίσκου - Επισφαλής αφαίρεση συσκευής + Είναι ενεργή άλλη συνεδρία, ίσως μέσω ssh; + Προσαρτήθηκε αφαιρούμενος δίσκος + Μη ασφαλής αφαίρεση συσκευής Η συσκευή αφαιρέθηκε επιτυχώς Συνδέθηκε χειριστήριο Αποσυνδέθηκε χειριστήριο @@ -1034,25 +1034,25 @@ Ενεργό για περιεχόμενο SD Πάντα ενεργό - Μέθοδος ανακλιμακοθέτησης - Δικυβική + Μέθοδος Upscaling + Bicubic Lanczos Sinc VDPAU - VDPAU HQ ανακλιμακοθέτηση - VDPAU Μετατροπή στάθμης χρώματος + VDPAU HQ Upscaling επίπεδο + VDPAU Μετατροπή χρώματος επιπέδου στούντιο - Κενό σε άλλες απεικονίσεις + Κενό σε άλλες οθόνες Ανενεργή - Κενές απεικονίσεις + Κενές οθόνες Έχουν ανιχνευτεί ενεργές συνδέσεις! - Εάν συνεχίσετε, δεν θα είναι δυνατός πλέον ο έλεγχος του XBMC. - Να διακοπεί η λειτουργία του Απομακρυσμένου διακομιστή; + Αν συνεχίσετε, μπορεί να χάσετε τον έλεγχο του XBMC. + Να διακοπεί η λειτουργία του απομακρυσμένου διακομιστή; - Αλλαγή κατάστασης συσκευής (Apple Remote); - Εάν χρησιμοποιείτε τώρα τη συσκευή (Apple Remote) για να - ελέγξετε το XBMC, η αλλαγή της ρύθμισης αυτής θα επηρεάσει + Αλλαγή λειτουργίας συσκευής Apple Remote; + Εάν χρησιμοποιείτε τώρα τη συσκευή Apple Remote για να + ελέγχετε το XBMC, η αλλαγή αυτής της ρύθμισης θα επηρεάσει την ικανότητα ελέγχου του. Θέλετε να συνεχίσετε; Μάσκα Υποδικτύου @@ -1063,8 +1063,8 @@ Ποτέ Αμέσως Μετά από %i δευτ. - Ημερομηνία εγκατάστασης - Πλήθος περιστροφών σε ισχύ + Ημερομηνία εγκατάστασης: + Πλήθος περιστροφών σε ισχύ: Προφίλ Διαγραφή προφίλ '%s'; @@ -1077,20 +1077,20 @@ Διάρκεια κουδουνισμού (σε λεπτά) Εκκίνηση ξυπνητηριού σε %im Συναγερμός! - Ακυρώθηκε %im%is απέμειναν - %2.0fm - %2.0fs + Ακυρώθηκε με %im%is να απομένουν + %2.0fm + %2.0fs - Αναζήτηση υποτίτλων στα RARs + Αναζήτηση υποτίτλων σε RAR Αναζήτηση για υπότιτλο... Μετακίνηση αντικειμένου Μετακίνηση αντικειμένου εδώ Ακύρωση μετακίνησης - Υλικό - Ταχύτητα CPU + Υλικό: + Χρήση CPU: - Συνδέθηκε, αλλά η διεύθυνση DNS δεν είναι διαθέσιμη. + Συνδέθηκε, αλλά δεν υπάρχει διαθέσιμη DNS. Σκληρός δίσκος DVD-ROM Μέσα αποθήκευσης @@ -1099,28 +1099,28 @@ Βίντεο Υλικό - Λειτουργικό σύστημα - Ταχύτητα CPU + Λειτουργικό σύστημα: + Ταχύτητα CPU: Κωδικοποιητής βίντεο: - Ανάλυση οθόνης + Ανάλυση οθόνης: - Καλώδιο A/V + Καλώδιο A/V: - Περιοχή DVD - Internet + Περιοχή DVD: + Διαδίκτυο: Συνδέθηκε Δε συνδέθηκε. Ελέγξτε τις ρυθμίσεις δικτύου. - Θερμοκρασία στόχος + Επιθυμητή θερμοκρασία Ταχύτητα ανεμιστήρα Αυτόματος έλεγχος θερμοκρασίας - Προτεραιότητα στην ταχύτητα του ανεμιστήρα + Παράκαμψη ταχύτητας ανεμιστήρα - Γραμματοσειρές Ενεργοποίηση αμφίδρομης κατεύθυνσης - Εμφάνιση ροών τίτλων ειδήσεων (RSS) - Εμφάνιση περιεχομένων φακέλου - Πρότυπο ονομασίας κομματιού + Εμφάνιση ροής τίτλων ειδήσεων (RSS) + Εμφάνιση περιεχομένων αρχικού φακέλου + Πρότυπο ονομασίας κομματιών Επιθυμείτε επανεκκίνηση του συστήματος και όχι μόνο του XBMC; Εφέ μεγέθυνσης @@ -1128,23 +1128,23 @@ Ελαχιστοποίηση μαύρης μπάρας Επανεκκίνηση Βαθμιαία εξασθένιση μεταξύ των τραγουδιών - Επαναδημιουργία μικρογραφίας - Επαναλαμβανόμενη μικρογραφία - Προβολή παρουσίασης - Επαναλαμβανόμενη παρουσίαση + Επαναδημιουργία μικρογραφιών + Μικρογραφίες και σε υποφακέλους + Παρουσίαση διαφανειών + Παρουσίαση διαφανειών και των υποφακέλων Τυχαία διάταξη Στερεοφωνικά Αριστερό μόνο - Δεξιό μόνο + Δεξί μόνο Ενεργοποίηση υποστήριξης karaoke - Διαφάνεια στο υπόβαθρό - Διαφάνεια σε πρώτο πλάνο + Διαφάνεια υποβάθρου + Διαφάνεια προσκήνιου A/V καθυστέρηση Karaoke %s δεν βρέθηκε Σφάλμα κατά το άνοιγμα %s Αδυναμία φόρτωσης %s - Σφάλμα: Έλλειψη μνήμης. + Σφάλμα: Έλλειψη μνήμης Μετακίνηση πάνω Μετακίνηση κάτω Επεξεργασία ετικέτας @@ -1156,19 +1156,19 @@ Πορτοκαλί Κόκκινο Κύκλος - Σβησμένη η λυχνία κατά την αναπαραγωγή + Απενεργοποίηση λυχνίας (LED) κατά την αναπαραγωγή Πληροφορίες ταινίας Κομμάτι σε αναμονή - Αναζήτηση IMDb... + Αναζήτηση στο IMDb... Έρευνα για νέο περιεχόμενο Τώρα εκτελείται... Πληροφορίες άλμπουμ Ανίχνευση αντικειμένου στη συλλογή Διακοπή αναζήτησης Μέθοδος απόδοσης - Χαμηλής ποιότητας (Pixel Shader) + Χαμηλής ποιότητας σκίαση pixel Επικαλύψεις υλικού - Υψηλής ποιότητας (Pixel Shader) + Υψηλής ποιότητας σκίαση pixel Αναπαραγωγή αντικειμένου Ορισμός μικρογραφίας καλλιτέχνη Αυτόματη δημιουργία μικρογραφιών @@ -1179,15 +1179,15 @@ Προεπιλεγμένη κατάσταση προβολής Προεπιλεγμένη φωτεινότητα Προεπιλεγμένη αντίθεση - Προεπιλεγμένος συντελεστής γάμα + Προεπιλεγμένος συντελεστής γάμμα Συνέχιση βίντεο Μάσκα φωνής - Θύρα 1 Μάσκα φωνής - Θύρα 2 Μάσκα φωνής - Θύρα 3 Μάσκα φωνής - Θύρα 4 - Αναζήτηση βασισμένη στην χρήση χρόνου + Αναζήτηση βάσει χρόνου Πρότυπο ονομασίας κομματιού (δεξιά πλευρά) - Προκαθορισμένα + Προκαθορισμένο Δεν υπάρχουν διαθέσιμα προκαθορισμένα γι' αυτή την οπτικοποίηση Δεν υπάρχουν διαθέσιμες ρυθμίσεις γι' αυτή την οπτικοποίηση Εξαγωγή/Εισαγωγή @@ -1198,70 +1198,70 @@ Ρυθμίσεις ήχου και υποτίτλων Ενεργοποίηση υποτίτλων Συντομεύσεις - Αγνόησε το άρθρο "The" κατά την ταξινόμηση - Βαθμιαία εξασθένιση μεταξύ των τραγουδιών του ίδιου άλμπουμ + Αγνόησε τα άρθρα κατά την ταξινόμηση (π.χ. το "The") + Βαθμιαία εξασθένιση μεταξύ τραγουδιών του ίδιου άλμπουμ Αναζήτηση για %s Εμφάνιση της θέσης του κομματιού Απαλοιφή προεπιλογών Συνέχεια - Μικρογραφία + Λήψη μικρογραφίας Πληροφορίες εικόνας %s προκαθορισμένα (Αξιολόγηση IMDb) 250 κορυφαία - Συντονισμός στο Last.FM + Συντονισμός στο Last.fm Ελάχιστη ταχύτητα ανεμιστήρα Αναπαραγωγή από εδώ Λήψη - Ενσωμάτωση καλλιτεχνών που εμφανίζονται μόνο στις συνθέσεις + Συμπερίληψη καλλιτεχνών που εμφανίζονται μόνο σε συνθέσεις Μέθοδος απόδοσης Αυτόματη ανίχνευση - Στοιχειώδης (ARB) - Εξειδικευμένη (GLSL) + Στοιχειώδεις σκιαστές (ARB) + Προηγμένοι σκιαστές (GLSL) Λογισμικό Ασφαλής κατάργηση VDPAU - Έναρξη παρουσίασης διαφανειών εδώ - Απομνημόνευση αυτής της διαδρομής - Χρήση των προσωρινά αποθηκευμένων αντικειμένων - Αποδοχή επιτάχυνσης υλικού (VDPAU) - Αποδοχή επιτάχυνσης υλικού (VAAPI) - Αποδοχή επιτάχυνσης υλικού (DXVA2) - Αποδοχή επιτάχυνσης υλικού (CrystalHD) - Αποδοχή επιτάχυνσης υλικού (VDADecoder) - Αποδοχή επιτάχυνσης υλικού (OpenMax) - Σκιάσεις εικονοστοιχείου + Παρουσίαση διαφανειών από εδώ + Απομνημόνευση για αυτή τη διαδρομή + Χρήση αντικειμένων προσωρινής μνήμης pixel + Έγκριση επιτάχυνσης υλικού (VDPAU) + Έγκριση επιτάχυνσης υλικού (VAAPI) + Έγκριση επιτάχυνσης υλικού (DXVA2) + Έγκριση επιτάχυνσης υλικού (CrystalHD) + Έγκριση επιτάχυνσης υλικού (VDADecoder) + Έγκριση επιτάχυνσης υλικού (OpenMax) + Σκιάσεις Pixel Έγκριση επιτάχυνσης υλικού (VideoToolbox) Μέθοδος συγχρονισμού A/V Χρονισμός ήχου Χρονισµός βίντεο (εις βάρος του ήχου) - Χρονισμός βίντεο (εν νέου δειγματοληψία ήχου) + Χρονισμός βίντεο (εκ νέου δειγματοληψία ήχου) Μέγιστο ποσοστό επανάληψης δειγματοληψίας (%) Ποιότητα επανάληψης δειγματοληψίας Χαμηλή (γρήγορη) Μεσαία Υψηλή Πραγματικά υψηλή (αργή!) - Συγχρονισμός αναπαραγωγής ήχου κατά τη προβολή + Συγχρονισμός αναπαραγωγής ήχου με οθόνη - Παύση κατά τη διάρκεια ανανέωσης του ρυθμού αλλαγής + Παύση κατά την αλλαγή του ρυθμού ανανέωσης Ανενεργό %.1f Δευτερόλεπτο %.1f Δευτερόλεπτα Apple Remote - Έγκριση έναρξης του XBMC μέσου απομακρυσμένου ελέγχου - Ακολουθία χρόνου καθυστέρησης + Έγκριση έναρξης του XBMC μέσω του χειριστηρίου + Χρόνος καθυστέρησης ακολουθίας Ανενεργή Τυπική Τηλεχειριστήριο γενικής χρήσης - Τηλεχειριστήριο γενικής χρήσης (Harmony) + Τηλεχειριστήριο Multi (Harmony) - Σφάλμα συσκευής (Apple Remote) - Αδυναμία υποστήριξης συσκευής (Apple Remote). + Σφάλμα συσκευής Apple Remote + Αδυναμία υποστήριξης συσκευής Apple Remote. Στοίβαγμα Σκόρπισμα @@ -1272,13 +1272,13 @@ Αποτυχία λήψης αρχείου λίστας αναπαραγωγής Κατάλογος παιχνιδιών - Αυτόματη εναλλαγή με βάση τις μικρογραφίες + Αυτόματη εναλλαγή σε μικρογραφίες βάσει Ενεργοποίηση αυτόματης εναλλαγής στην προβολή μικρογραφιών - Χρήση μεγάλων εικονιδίων - - Εναλλαγή βάση + - Εναλλαγή βάσει - Ποσοστό Καθόλου αρχεία και τουλάχιστον μία μικρογραφία - Τουλάχιστον ένα αρχείο και μια μικρογραφία + Τουλάχιστον ένα αρχείο και μία μικρογραφία Ποσοστό μικρογραφιών Επιλογές προβολής Αλλαγή κωδικού 1ης περιοχής @@ -1286,22 +1286,22 @@ Αλλαγή κωδικού 3ης περιοχής Συλλογή Χωρίς τηλεόραση - Εισαγωγή της κοντινότερης μεγάλης πόλης ή ταχυδρομικού κωδικού (US) + Εισαγωγή της κοντινότερης μεγάλης πόλης Συνολική λανθάνουσα μνήμη - Σκληρός δίσκος - Λανθάνουσα μνήμη βίντεο - DVDRom + Λανθάνουσα μνήμη βίντεο - DVD-ROM - Τοπικό δίκτυο - - Internet - Λανθάνουσα μνήμη ήχου - DVDRom + - Διαδίκτυο + Λανθάνουσα μνήμη ήχου - DVD-ROM - Τοπικό δίκτυο - - Internet - Λανθάνουσα μνήμη DVD - DVDRom + - Διαδίκτυο + Λανθάνουσα μνήμη DVD - DVD-ROM - Τοπικό δίκτυο Υπηρεσίες Οι ρυθμίσεις του δικτύου άλλαξαν Το XBMC πρέπει να επανεκκινηθεί για να αλλάξουν οι ρυθμίσεις δικτύου. Να γίνει επανεκκίνηση; - Σύνδεση Internet με περιορισμένο εύρος + Σύνδεση Διαδικτύου με περιορισμένη ταχύτητα - Τερματισμός κατά την αναπαραγωγή %i λεπτ. @@ -1311,27 +1311,27 @@ %i kbps %i kb %i.0 dB - Διαμόρφωση Ώρας - Διαμόρφωση Ημ/νίας + Μορφή Ώρας + Μορφή Ημ/νίας Φίλτρα γραφικού περιβάλλοντος (GUI) Σάρωση στο παρασκήνιο Διακοπή σάρωσης - Δεν είναι εφικτό κατά τη σάρωση πληροφοριών αρχείων + Δεν είναι εφικτό κατά τη σάρωση πληροφοριών πολυμέσων Εφέ Film Grain Έρευνα στους κοινόχρηστους πόρους για μικρογραφίες - Άγνωστος τύπος λανθάνουσας μνήμης - Internet + Άγνωστος τύπος λανθάνουσας μνήμης - Διαδίκτυο Αυτόματο/η Εισάγετε όνομα χρήστη για - Ημερομηνία & Ώρα - Ορισμός ημερομηνίας + Ημερομηνία & ώρα + Ορισμός ημ/νίας Ορισμός ώρας - Εισάγετε την ώρα σε ψηφιακή μορφή - Εισάγετε την ημ/νία στο ΗΗ/MM/ΕΤΟΣ + Εισάγετε την ώρα σε 24ωρη μορφή (ΩΩ:ΛΛ) + Εισάγετε την ημ/νία σε μορφή ΗΗ/MM/ΕΤΟΣ Εισάγετε την διεύθυνση ΙP Εφαρμογή αυτών των ρυθμίσεων τώρα; Εφαρμογή ρυθμίσεων τώρα - Επιτρεπτή η μετονομασία και η διαγραφή + Επιτρεπτή η μετονομασία και η διαγραφή αρχείων Ορισμός ζώνης ώρας Ενεργοποίηση θερινής ώρας @@ -1344,10 +1344,10 @@ Εμφάνιση πληροφοριών εικόνας (EXIF) Χρήση του μεγιστοποιημένου παραθύρου αντί της πλήρους οθόνης Επιλεγμένα τραγούδια στη λίστα αναμονής - Αυτόματη αναπαραγωγή CDs ήχου + Αυτόματη αναπαραγωγή CD ήχου Αναπαραγωγή - DVDs - Αυτόματη αναπαραγωγή DVDs βίντεο + DVD + Αυτόματη αναπαραγωγή DVD Χρήση γραμματοσειράς στους υπότιτλους Διεθνοποίηση Κωδικοποίηση χαρακτήρων @@ -1372,94 +1372,94 @@ Aποθήκευση... Ήχοι πλοήγησης - Προεπιλεγμένο κέλυφος + Προεπιλογή κελύφους - Θέμα Προεπιλεγμένο Θέμα - Last.FM - Αποστολή τραγουδιών στο Last.FM - Όνομα χρήστη Last.FM - Κωδικός πρόσβασης Last.FM + Last.fm + Αποστολή τραγουδιών στο Last.fm + Όνομα χρήστη Last.fm + Κωδικός πρόσβασης Last.fm Αδύνατη η χειραψία: σε αδράνεια... - Παρακαλώ, αναβαθμίστε το XBMC - Απέτυχε η εξακρίβωση. Ελέγξτε το όνομα χρήστη και τον κωδικό πρόσβασης + Παρακαλώ αναβαθμίστε το XBMC + Απέτυχε η εξακρίβωση: Ελέγξτε το όνομα χρήστη και τον κωδικό πρόσβασης Συνδεμένο Αποσυνδεμένο - Αποστολή διαστήματος %i + Διάστημα αποστολής %i %i τραγούδια στη λανθάνουσα μνήμη Αποστολή... Αποστολή σε %i δευτ. - Δουλεύει χρησιμοποιώντας... + Άνοιγμα με... Χρήση συγχρονισμού Smoothed A/V Απόκρυψη ονομάτων αρχείων στην προβολή μικρογραφιών - Εκτελείτε σε Party Mode - Υποβολή τραγουδιών στο Libre.fm - Όνομα χρήστη (Libre.fm) - Κωδικός πρόσβασης (Libre.fm) + Εκτέλεση σε Party Mode + Αποστολή τραγουδιών στο Libre.fm + Όνομα χρήστη Libre.fm + Κωδικός πρόσβασης Libre.fm Libre.fm - Υποβολή αιτήματος τραγουδιού + Υποβολή τραγουδιού Αποστολή Last.fm radio στο Last.fm - Σύνδεση με Last.FM... + Σύνδεση με Last.fm... Επιλογή σταθμού... Αναζήτηση παρόμοιων καλλιτεχνών... Αναζήτηση παρόμοιων ετικετών... Το προφίλ σας (%name%) - Γενικές κορυφαίες ετικέτες + Γενικά κορυφαίες ετικέτες Κορυφαίοι καλλιτέχνες για την ετικέτα %name% Κορυφαία άλμπουμ για την ετικέτα %name% Κορυφαία κομμάτια για την ετικέτα %name% - Ακρόαση της ετικέτας %name% στο Last.FM radio + Ακρόαση της ετικέτας %name% στο Last.fm radio Παρόμοιοι καλλιτέχνες όπως ο %name% - %name% κορυφαία άλμπουμ - %name% κορυφαία κομμάτια - %name% κορυφαίες ετικέτες + Κορυφαία άλμπουμ %name% + Κορυφαία κομμάτια %name% + Κορυφαίες ετικέτες %name% Οι μεγαλύτεροι θαυμαστές του %name% - Ακρόαση θαυμαστών του %name% στο Last.FM radio - Ακρόαση παρόμοιων καλλιτεχνών με τον %name% στο Last.FM radio + Ακρόαση θαυμαστών του %name% στο Last.fm radio + Ακρόαση καλλιτεχνών παρόμοιων με τον %name% στο Last.fm radio Οι καλύτεροι καλλιτέχνες του χρήστη %name% Τα καλύτερα άλμπουμ του χρήστη %name% Τα καλύτερα κομμάτια του χρήστη %name% Φίλοι του χρήστη %name% Γείτονες του χρήστη %name% - Εβδομαδιαίο chart καλλιτέχνη του %name% - Εβδομαδιαίο chart άλμπουμ του %name% - Εβδομαδιαίο chart κομματιού του %name% - Ακρόαση των γειτόνων του %name% στο Last.FM radio - Ακρόαση των προσωπικών του %name% στο Last.FM radio - Ακρόαση των %name%'s mix Last.fm radio - Ανάκτηση λίστας από Last.FM... - Αδύνατη η ανάκτηση λίστας από Last.FM... - Εισάγετε ένα όνομα καλλιτέχνη - Εισάγετε μία ετικέτα για να βρείτε τα παρόμοια + Εβδομαδιαίο chart του καλλιτέχνη %name% + Εβδομαδιαίο chart του άλμπουμ %name% + Εβδομαδιαίο chart του κομματιού %name% + Ακρόαση του Last.fm radio των γειτόνων του %name% + Ακρόαση του προσωπικού Last.fm radio του %name% + Ακρόαση της μίξης Last.fm radio του %name% + Ανάκτηση λίστας από Last.fm... + Αδύνατη η ανάκτηση λίστας από Last.fm... + Εισάγετε ένα όνομα καλλιτέχνη για να βρείτε παρόμοια + Εισάγετε μία ετικέτα για να βρείτε παρόμοιες Κομμάτια που ακούστηκαν πρόσφατα από τον %name% - Ακρόαση των προτιμήσεων του %name% στο Last.FM radio + Ακρόαση των προτιμήσεων του %name% στο Last.fm radio Κορυφαίες ετικέτες για τον χρήστη %name% - Να προστεθεί το παρόν κομμάτι στα αγαπημένα σας; + Να προστεθεί το παρόν κομμάτι στα αγαπημένα σας; Να αποκλειστεί το παρόν κομμάτι; Προσθήκη στα αγαπημένα σας κομμάτια: '%s'. - Δεν προστέθηκε το '%s' στα Αγαπημένα σας. + Δεν μπορεί να προστεθεί το '%s' στα αγαπημένα σας. Αποκλεισμένα: '%s'. - Να μην αποκλειστεί '%s'. + Δεν μπορεί να αποκλειστεί το '%s'. Πρόσφατα αγαπημένα κομμάτια από %name% - Πρόσφατες αναγγελίες από %name% - Αφαιρέθηκε από τα αγαπημένα σας - Αποδεκτό - Να αφαιρεθεί το παρόν κομμάτι από τα αγαπημένα σας; - Να μην αποκλειστεί το παρόν κομμάτι; - - H διαδρομή δεν βρέθηκε - Απέτυχε η σύνδεση με τον διακομιστή δικτύου + Πρόσφατα αποκλεισμένα κομμάτια από %name% + Αφαίρεση από τα αγαπημένα σας + Άρση αποκλεισμού + Να αφαιρεθεί το παρόν κομμάτι από τα αγαπημένα σας; + Να αρθεί ο αποκλεισμός για αυτό το κομμάτι; + + Η διαδρομή δε βρέθηκε + Απέτυχε η σύνδεση με το διακομιστή δικτύου Δεν βρέθηκαν διακομιστές - Δεν βρέθηκαν ομάδες εργασίας + Δεν βρέθηκε η ομάδα εργασίας Άνοιγμα πηγής multi-path Διαδρομή: Γενικά - Έρευνα στο Internet + Έρευνα στο Διαδίκτυο Αναπαραγωγή Αναπαραγωγή πολυμέσων από το δίσκο @@ -1472,27 +1472,27 @@ Εισάγετε όνομα φακέλου Εισάγετε κατάλογο Διαθέσιμες επιλογές: %A, %T, %N, %B, %D, %G, %Y, %F, %S - Εισαγωγή συμβολοσειράς αναζήτησης + Εισαγωγή κειμένου αναζήτησης Καμία Αυτόματη επιλογή Απόπλεξη - Επιλεκτική - Επιλεκτική (αντιστροφή) - Μέθοδος περιπλεγμένου χειρισμού + Bob + Bob (αντιστροφή) + Ακύρωση... Εισάγετε το όνομα του καλλιτέχνη Η αναπαραγωγή απέτυχε - Αποτυχία αναπαραγωγής ενός ή περισσότερων αντικείμενων. + Αποτυχία αναπαραγωγής ενός ή περισσότερων αντικειμένων. Εισαγωγή τιμής - Για περισσότερες λεπτομέρειες ελέγξτε το αρχείο συμβάντων - Το Party Mode ως μέθοδος απορρίφθηκε. - Δεν υπάρχουν τραγούδια στη συλλογή που να ταιριάζουν. + Για λεπτομέρειες ελέγξτε το αρχείο καταγραφής. + Το Party Mode απορρίφθηκε. + Δεν υπάρχουν παρόμοια τραγούδια στη συλλογή. Δεν είναι δυνατός ο συγχρονισμός με τη βάση δεδομένων. Απέτυχε το άνοιγμα της βάσης δεδομένων. Απέτυχε η λήψη τραγουδιών από τη βάση δεδομένων. - Λίστα αναπαραγωγής σε Party Μode + Λίστα αναπαραγωγής σε Party Mode Απόπλεξη (κατά το ήμισυ) - Απόπλεξη βίντεο + Απόπλεξη βίντεο (Deinterlace) Μέθοδος απόπλεξης Ανενεργή Αυτόματη @@ -1515,14 +1515,14 @@ Μέθοδος προσαρμογής ανάλυσης βίντεο Εγγύτερη προσέγγιση - Διγραμμική - Δικυβική + Bilinear + Bicubic Lanczos2 Lanczos3 Sinc8 - Δικυβική (με λογισμικό) - Lanczos (με λογισμικό) - Sinc (με λογισμικό) + Bicubic (λογισμικό) + Lanczos (λογισμικό) + Sinc (λογισμικό) Χρονική Χρονική/Χωρική (VDPAU) Μείωση θορύβου @@ -1549,7 +1549,7 @@ Χρήση εξωτερικού αναπαραγωγέα DVD Εξωτερικός αναπαραγωγέας DVD Φάκελος trainers - Φάκελος στιγμιότυπου + Φάκελος στιγμιότυπων Φάκελος λίστας αναπαραγωγής Εγγραφές @@ -1569,63 +1569,63 @@ Διένεξη - Σάρωση καινούργιων + Σάρωση νέων Σάρωση όλων Περιοχή - Συνοπτικές - Κλείδωμα της μουσικής - Κλείδωμα των βίντεο - Κλείδωμα των φωτογραφιών - Κλείδωμα εφαρμογών και scripts windows + Συνοπτικά + Κλείδωμα παραθύρου μουσικής + Κλείδωμα παραθύρου βίντεο + Κλείδωμα παραθύρου εικόνων + Κλείδωμα παραθύρου εφαρμογών & script Κλείδωμα της διαχείρισης αρχείων Κλείδωμα των ρυθμίσεων Νέα έναρξη Είσοδος στη γενική διαχείριση Έξοδος από τη γενική διαχείριση Δημιουργία προφίλ '%s'; - Έναρξη με καινούργιες ρυθμίσεις + Έναρξη με νέες ρυθμίσεις Η καλύτερη δυνατή Αυτόματη εναλλαγή μεταξύ 16:9 και 4:3 Μεταχείριση στοιβαγμένων αρχείων σαν ένα Προσοχή - Αριστερή γενική διαχείριση - Καταχωρημένη γενική διαχείριση + Αποχώρηση από τη γεν. διαχείριση + Εισαγωγή στη γεν. διαχείριση Μικρογραφία Allmusic.com Απομάκρυνση μικρογραφίας - Προσθέστε προφίλ... - Ερώτημα για όλα τα άλμπουμ + Προσθήκη προφίλ... + Εύρεση πληροφοριών για όλα τα άλμπουμ Πληροφορίες πολυμέσων Ξεχωριστές - Κοινόχρηστα με προεπιλεγμένα - Κοινόχρηστα με προεπιλεγμένα (ανάγνωση μόνο) - Αντιγραφή προεπιλεγμένων + Κοινόχρηστα με προεπιλογές + Κοινόχρηστα με προεπιλογές (ανάγνωση μόνο) + Αντιγραφή προεπιλογών Εικόνα προφίλ - Επιλογές κλειδώματος + Προτιμήσεις κλειδώματος Επεξεργασία προφίλ Κλείδωμα προφίλ Αδύνατη η δημιουργία φακέλου - Φάκελος προφίλ + Κατάλογος προφίλ Έναρξη με νέες πηγές πολυμέσων Σιγουρευτείτε ότι ο επιλεγμένος φάκελος μπορεί να εγγραφεί - και ότι το όνομα του είναι έγκυρο - Αξιολόγηση MPAA + και ότι το νέο όνομα είναι έγκυρο + Αξιολόγ. MPAA Εισαγωγή κωδικού κεντρικού κλειδώματος Αίτημα για κωδικό κεντρικού κλειδώματος στην εκκίνηση Ρυθμίσεις κελύφους - δεν έχει οριστεί σύνδεση - - Ενεργοποίηση εφέ κίνησης κελύφους - Ανενεργές οι Ροές Τίτλων Ειδήσεων κατά την ακρόαση τραγουδιών + Ενεργοποίηση εφέ κίνησης + Απενεργοποίηση της Ροής Τίτλων Ειδήσεων (RSS) κατά την ακρόαση μουσικής Ενεργοποίηση πλήκτρων συντόμευσης Εμφάνιση των εφαρμογών στο κεντρικό μενού Εμφάνιση πληροφοριών για τη μουσική Εμφάνιση πληροφοριών για τον καιρό Εμφάνιση πληροφοριών για το σύστημα - Εμφάνιση διαθέσιμου χώρου στους C: E: F: - Εμφάνιση διαθέσιμου χώρου στους E: F: G: + Εμφάνιση διαθέσιμου χώρου στα C: E: F: + Εμφάνιση διαθέσιμου χώρου στα E: F: G: Πληροφορίες καιρού Ελεύθερος χώρος Εισάγετε όνομα κοινόχρηστου πόρου @@ -1636,47 +1636,47 @@ Εισάγετε κωδικό κλειδώματος προφίλ Οθόνη σύνδεσης Λήψη πληροφοριών άλμπουμ - Λαμβάνει πληροφορίες για το άλμπουμ - Αδυναμία εγγραφής του CD ή του κομματιού κατά την αναπαραγωγή δίσκου - Κεντρικό κλείδωμα και επιλογές - Εισαγωγή κωδικού για την ενεργοποίηση της γενικής διαχείρισης - ή αντιγραφή του κωδικού όπως αυτός έχει προκαθοριστεί; + Λαμβάνονται πληροφορίες για το άλμπουμ + Αδυναμία αντιγραφής του CD ή του κομματιού κατά την αναπαραγωγή του CD + Κωδικός κεντρικού κλειδώματος και επιλογές + Ο κωδικός κεντρικού κλειδώματος να ενεργοποιεί πάντα τη γεν. διαχείριση + ή να αντιγράφεται ο προκαθορισμένος κωδικός; Αποθήκευση αλλαγών στο προφίλ; Βρέθηκαν παλιές ρυθμίσεις. Θέλετε να τις χρησιμοποιήσετε; Βρέθηκαν παλιές πηγές πολυμέσων. - Χωρισμένο (κλειδωμένο) + Ξεχωριστές (κλειδωμένο) Root - Μεγέθυνση Ρυθμίσεις UPnP Αυτόματη έναρξη πελάτη UPnP Τελευταία σύνδεση: %s - Ποτέ δεν συνδέθηκε + Ποτέ δε συνδέθηκε Προφίλ %i / %i - Όνομα χρήστη / Επιλέξτε ένα προφίλ + Σύνδεση χρήστη / Επιλέξτε ένα προφίλ Χρήση κλειδώματος στην οθόνη σύνδεσης Λάθος κωδικός κλειδώματος. - Απαιτεί να ενεργοποιήσετε το κεντρικό κλείδωμα - Θέλετε να το ρυθμίσετε τώρα; + Απαιτείται ορισμός του κεντρικού κλειδώματος. + Θέλετε να το ορίσετε τώρα; Φόρτωση πληροφοριών εφαρμογής Party on! Αληθές - Αναμιγνύοντας τα ποτά - Γεμίζοντας τα ποτήρια + Αναμιγνύονται τα ποτά + Γεμίζουν τα ποτήρια Συνδεμένος σαν Αποσύνδεση - Πήγαινε στο root - Ύφανση - Ύφανση (αντιστροφή) - Συνδυασμός + Μετάβαση σε root + Weave + Weave (αντιστροφή) + Blend Επανεκκίνηση βίντεο Επεξεργασία τοποθεσίας δικτύου Απομάκρυνση τοποθεσίας δικτύου - Θέλετε να σαρώσετε τον φάκελο; + Θέλετε να σαρώσετε το φάκελο; Μονάδα μνήμης Προσάρτηση μονάδας μνήμης Αδύνατη η προσάρτηση μονάδας μνήμης - Στη θύρα %i ,υποδοχή %i + Στη θύρα %i, υποδοχή %i Κλείδωμα προφύλαξης οθόνης Ορισμός σε Όνομα χρήστη @@ -1691,7 +1691,7 @@ Ακύρωση χρονοδιακόπτη τερματισμού Κλείδωμα ρυθμίσεων για %s Αναζήτηση... - Συνολικές πληροφορίες + Συνοπτικές πληροφορίες Πληροφορίες αποθηκευτικού χώρου Πληροφορίες σκληρού δίσκου Πληροφορίες DVD-ROM @@ -1701,7 +1701,7 @@ Συνολικά Χρησιμοποιημένα από τα - Δεν υποστηρίζει κλείδωμα + Δεν υποστηρίζεται κλείδωμα Ξεκλείδωτος Κλειδωμένος Παγωμένος @@ -1711,7 +1711,7 @@ Δίκτυο Windows (SMB) Διακομιστής XBMSP Διακομιστής FTP - Μοίρασμα μουσικής iTunes (DAAP) + Διαμοίραση μουσικής iTunes (DAAP) Διακομιστής UPnP Εμφάνιση πληροφοριών για το βίντεο Τέλος @@ -1721,27 +1721,27 @@ Διαγραφή Κενό Επαναφόρτωση κελύφους - Περιστροφή εικόνων που χρησιμοποιούν τις πληροφορίες EXIF + Περιστροφή εικόνων που χρησιμοποιούν πληροφορίες EXIF Χρήση στυλ αφισών για τις τηλεοπτικές σειρές Απασχολημένο - Ενεργοποίηση αυτόματης κύλισης στην επισκόπηση πλοκής & κριτικής + Ενεργοποίηση αυτόματης κύλισης για πλοκή & κριτική Προσαρμογή Ενεργοποίηση καταγραφής σφαλμάτων (debug log) Λήψη πρόσθετων πληροφοριών κατά τις ενημερώσεις συλλογής Προκαθορισμένη υπηρεσία πληροφοριών άλμπουμ Προκαθορισμένη υπηρεσία πληροφοριών καλλιτέχνη - Αλλαγή καταγραφέα + Αλλαγή scraper Εξαγωγή μουσικής συλλογής Εισαγωγή μουσικής συλλογής Δεν βρέθηκε ο καλλιτέχνης! - Αποτυχία λήψης πληροφοριών για τον καλλιτέχνη + Αποτυχία λήψης πληροφοριών καλλιτέχνη Party on! (βίντεο) - Αναμιγνύοντας τα ποτά (βίντεο) - Γεμίζοντας τα ποτήρια (βίντεο) + Αναμιγνύονται τα ποτά (βίντεο) + Γεμίζουν τα ποτήρια (βίντεο) Διακομιστής WebDAV (HTTP) Διακομιστής WebDAV (HTTPS) Πρώτη σύνδεση, επεξεργαστείτε το προφίλ σας @@ -1759,15 +1759,15 @@ Ροή τίτλων ειδήσεων (RSS) Δευτερεύον DNS - DHCP διακομιστή: + Διακομιστής DHCP: Δημιουργία νέου φακέλου - Σκίαση LCD κατά την αναπαραγωγή + Αμαύρωση LCD κατά την αναπαραγωγή Άγνωστο ή πάνω στην μητρική (προστατεύεται) - Σκίαση LCD σε παύση + Αμαύρωση LCD στην παύση Βίντεο - Συλλογή - Ταξ. κατά: ID + Ταξ.: ID Αναπαραγωγή κομματιού... Επαναφορά βαθμονόμησης @@ -1780,18 +1780,18 @@ Χρήση φακέλων ή ονομάτων αρχείων στις αναζητήσεις; Ορισμός περιεχομένου Φάκελος - Έλεγχος περιεχομένου κατ' επανάληψη; + Έλεγχος περιεχομένου και των υποφακέλων; Ξεκλείδωμα πηγών Ηθοποιός Ταινία Σκηνοθεσία - Θέλετε να απομακρύνετε όλα τα αντικείμενα που βρίσκονται - σ΄ αυτή την διαδρομή από τη συλλογή του XBMC; + Θέλετε να απομακρύνετε όλα τα αντικείμενα + αυτής της διαδρομής από τη συλλογή του XBMC; Ταινίες Τηλεοπτικές σειρές Αυτός ο φάκελος περιέχει Εκτέλεση αυτόματης σάρωσης - Σάρωση κατ' επανάληψη + Σάρωση και των υποφακέλων ως Σκηνοθέτες Δεν βρέθηκαν αρχεία βίντεο σε αυτή τη διαδρομή! @@ -1824,13 +1824,13 @@ Πρωτότυπος τίτλος Ανανέωση πληροφοριών τηλεοπτικής σειράς Ανανέωση πληροφοριών για όλα τα επεισόδια; - Ο επιλεγμένος φάκελος περιέχει μία ενιαία τηλεοπτική σειρά + Ο επιλεγμένος φάκελος περιέχει μόνο μία τηλεοπτική σειρά Εξαίρεση του επιλεγμένου φακέλου από τυχόν ελέγχους Ιδιαίτερα στοιχεία - Αυτόματη απόσπαση μικρογραφιών κύκλου - Ο Επιλεγμένος φάκελος περιέχει ένα ενιαίο βίντεο - Σύνδεσμος στην τηλεοπτική σειρά - Αφαίρεση συνδέσμου από την τηλεοπτική σειρά + Αυτόματη λήψη μικρογραφιών κύκλων + Ο επιλεγμένος φάκελος περιέχει μόνο ένα βίντεο + Σύνδεσμος σε τηλεοπτική σειρά + Αφαίρεση συνδέσμου από τηλεοπτική σειρά Πρόσφατα εισαχθείσες ταινίες Πρόσφατα εισαχθέντα επεισόδια Στούντιο @@ -1839,25 +1839,25 @@ Μουσικό βίντεο Αφαίρεση μουσικού βίντεο από τη συλλογή Πληροφορίες μουσικού βίντεο - Λαμβάνονται πληροφορίες για το μουσικό βίντεο - Συρραμμένα + Φόρτωση πληροφοριών για το μουσικό βίντεο + Ανάμικτα Άλμπουμ καλλιτέχνη Άλμπουμ Αναπαραγωγή τραγουδιού Μουσικά βίντεο από άλμπουμ Μουσικά βίντεο ανά καλλιτέχνη Αναπαραγωγή μουσικού βίντεο - Λήψη μικρογραφιών ηθοποιού κατά τη προσθήκη στη συλλογή + Λήψη μικρογραφιών ηθοποιού κατά την προσθήκη στη συλλογή Ορισμός μικρογραφίας ηθοποιού Αφαίρεση σελιδοδείκτη επεισοδίου Ορισμός σελιδοδείκτη επεισοδίου - Ρυθμίσεις καταγραφέα + Ρυθμίσεις scraper Λήψη πληροφοριών για το μουσικό βίντεο Λήψη πληροφοριών για την τηλεοπτική σειρά Διαφημιστικό - Ισοπέδωση - Ισοπέδωση τηλεοπτικών σειρών + Ενιαία λίστα (Flatten) + Ενιαία λίστα επεισοδίων σειράς (Flatten) Λήψη Fanart Προβολή Fanart στις συλλογές βίντεο και μουσικής Έλεγχος για νέα περιεχόμενα @@ -1871,7 +1871,7 @@ Πάντα Έχει διαφημιστικό Ψευδές - Παρουσίαση Fanart + Παρουσίαση διαφανειών Fanart Εξαγωγή σε ένα αρχείο ή σε πολλαπλά αρχεία ανά εγγραφή; Ένα αρχείο @@ -1881,9 +1881,9 @@ Εξαίρεση διαδρομής από τις ενημερώσεις συλλογής Εξαγωγή μικρογραφιών και πληροφοριών Ομάδες Ταινιών - Ορισμός θέσης μικρογραφίας ταινίας - Εξαγωγή μικρογραφιών καλλιτέχνη; - Επιλεγμένο fanart + Ορισμός μικρογραφίας ομάδας + Εξαγωγή μικρογραφιών ηθοποιού; + Επιλογή fanart Τοπικό fanart Χωρίς fanart Τρέχον fanart @@ -1893,7 +1893,7 @@ για όλα τα στοιχεία αυτής της διαδρομής; Fanart Βρέθηκαν τοπικά αποθηκευμένες πληροφορίες. - Να αγνοηθούν και να ανανεωθούν από το internet; + Να αγνοηθούν και να ανανεωθούν από το διαδίκτυο; Αδυναμία λήψης πληροφοριών Αδυναμία σύνδεσης με τον απομακρυσμένο διακομιστή Επιθυμείτε να συνεχίσετε την αναζήτηση; @@ -1919,7 +1919,7 @@ Προσθήκη κοινόχρηστου πολυμέσου... - Διαμοιρασμός κοινόχρηστων συλλογών μουσικής και βίντεο διαμέσου UPnP + Διαμοιρασμός συλλογών μουσικής και βίντεο μέσω UPnP Επεξεργασία κοινόχρηστων πολυμέσων Απομάκρυνση κοινόχρηστων πολυμέσων @@ -1927,15 +1927,15 @@ Ταινία & εναλλακτικός φάκελος υποτίτλων Παράκαμψη γραμματοσειρών υποτίτλων ASS/SSA - Ενεργοποίηση ποντικιού και υποστήριξης Οθόνης Αφής - Ενεργοποίηση ήχων πλοήγησης κατά την εκτέλεση πολυμέσων + Ενεργοποίηση ποντικιού και υποστήριξης οθόνης αφής + Ενεργοποίηση ήχων πλοήγησης κατά την αναπαραγωγή Μικρογραφία Περιοχή αναπαραγωγέα DVD Έξοδος βίντεο Αναλογία οθόνης Κανονική Letterbox - Ευρεία προβολή + Ευρεία οθόνη Ενεργοποίηση 480p Ενεργοποίηση 720p Ενεργοποίηση 1080i @@ -1947,15 +1947,15 @@ Διαχείριση στάθμης θορύβου Θορυβώδες Αθόρυβο - Ενεργοποίηση προσαρμοσμένου υπόβαθρου + Ενεργοποίηση προσαρμοσμένου υποβάθρου Διαχείριση παροχής ενέργειας Υψηλή τροφοδοσία Χαμηλή τροφοδοσία Υψηλή αναμονή Χαμηλή αναμονή - Αδυναμία δημιουργίας προσωρινών αρχείων μεγαλύτερων των 4 gb + Αδυναμία δημιουργίας προσωρινών αρχείων μεγαλύτερων από 4GB Κεφάλαιο - Υψηλή ποιότητα (Pixel Shader V2) + Υψηλή ποιότητα (Σκίαση pixel v2) Ενεργοποίηση λίστας αναπαραγωγής κατά την εκκίνηση Ενεργοποίηση εφέ παλινδρομικής κίνησης περιέχει @@ -1970,36 +1970,36 @@ πριν στο τελευταίο όχι στο τελευταίο - Καταγραφείς - Προεπιλεγμένος καταγραφέας ταινίας - Προεπιλεγμένος καταγραφέας τηλεοπτικής σειράς - Προεπιλεγμένος καταγραφέας μουσικού βίντεο - Ενεργοποίηση επαναφοράς (βάση της γλώσσας του καταγραφέα) + Scraper + Προεπιλεγμένο scraper ταινιών + Προεπιλεγμένο scraper τηλεοπτικών σειρών + Προεπιλεγμένο scraper μουσικών βίντεο + Ενεργοποίηση εναλλακτικής βάσει της γλώσσας του scraper - Ρυθμίσεις Πολύγλωσσο - Δεν υπάρχει διαθέσιμος καταγραφέας - Τιμές για αντιστοίχιση - Όροι έξυπνης λίστας αναπαραγωγής - Κριτήρια αντιστοίχισης αντικειμένων - Νέοι κανόνες... - Αντικείμενα με πολλές αντιστοιχίες - με όλους τους κανόνες - με έναν ή περισσότερους κανόνες + Δεν υπάρχει διαθέσιμο scraper + Τιμή για αντιστοίχιση + Κανόνας έξυπνης λίστας αναπαραγωγής + Αντιστοίχιση αντικειμένων όταν + Νέος κανόνας... + Τα αντικείμενα πρέπει να πληρούν + όλους τους κανόνες + έναν ή περισσότερους κανόνες Αριθμητικό όριο Χωρίς περιορισμό - Συσχετιζόμενο στοιχείο + Σειρά κατά αύξουσα φθίνουσα Επεξεργασία έξυπνης λίστας αναπαραγωγής Όνομα λίστας αναπαραγωγής - Εύρεση αντιστοιχίας αντικειμένων + Εύρεση αντικειμένων για τα οποία Επεξεργασία %i αντικείμενα Νέα έξυπνη λίστα αναπαραγωγής... %c Δίσκος - Επεξεργασία όρων Party Mode + Επεξεργασία κανόνων Party Mode Αρχικός φάκελος - Πλήθος θεαμάτων + Πλήθος προβληθέντων Τίτλος επεισοδίου Ανάλυση βίντεο Κανάλια ήχου @@ -2009,13 +2009,13 @@ Γλώσσα υποτίτλων Το τηλεχειριστήριο στέλνει εντολές πληκτρολογίου - Επεξεργασία - Απαιτείται σύνδεση στο Internet. - Λήψη περισσότερων... + Απαιτείται σύνδεση στο Διαδίκτυο. + Λήψη Περισσότερων... Σύστημα αρχείων root Λανθάνουσα μνήμη πλήρης Η λανθάνουσα μνήμη γέμισε πριν φθάσει το απαιτούμενο μέγεθος για συνεχόμενη αναπαραγωγή - Θέση υπότιτλου + Θέση υποτίτλου Σταθερή Κάτω πλευρά του βίντεο Κάτω από το βίντεο @@ -2026,13 +2026,13 @@ Διαδρομή αρχείου Μέγεθος αρχείου Ημερομηνία αρχείου - Ευρετήριο διαφάνειας + Θέση διαφάνειας Ανάλυση Σχόλιο - Απόδοση + Έγχρωμη/Ασπρόμαυρη Επεξεργασία JPEG - Ημερομηνία λήψης + Ημερομηνία/Ώρα Περιγραφή Κατασκευαστής κάμερας Μοντέλο κάμερας @@ -2052,8 +2052,8 @@ Ευαισθησία ISO Ψηφιακή μεγέθυνση Πλάτος CCD - GPS γεωγραφικό πλάτος - GPS γεωγραφικό μήκος + GPS γεωγρ. πλάτος + GPS γεωγρ. μήκος GPS υψόμετρο Προσανατολισμός @@ -2062,7 +2062,7 @@ Λεζάντα Δημιουργός Επικεφαλίδα - Εξειδικευμένες πληροφορίες + Ειδικές πληροφορίες Κατηγορία Προέλευση Τίτλος @@ -2071,17 +2071,17 @@ Σημειώσεις πνευματικής ιδιοκτησίας Όνομα αντικειμένου Πόλη - Επαρχεία + Πολιτεία Χώρα Νομοθετικές πληροφορίες Ημερομηνία δημιουργίας Πνευματικά δικαιώματα Κωδικός χώρας Υπηρεσία πληροφόρησης - Έγκριση στους ελεγκτές UPnP να ελέγχουν το XBMC - Απόπειρα αποφυγής οδηγιών πριν από το μενού DVD + Έγκριση ελέγχου του XBMC μέσω UPnP + Απόπειρα αποφυγής οδηγιών πριν το μενού DVD Αποθηκευμένη μουσική - Ερώτημα για όλους τους καλλιτέχνες + Εύρεση πληροφοριών για όλους τους καλλιτέχνες Λήψη πληροφοριών για το άλμπουμ Λήψη πληροφοριών για τον καλλιτέχνη Βιογραφικό @@ -2090,11 +2090,11 @@ Επιλογή καλλιτέxνη Πληροφορίες καλλιτέχνη Όργανα - Γέννηση + Γεννήθηκε Δημιουργία Θεματολόγιο - Διάλυση - Θάνατος + Διαλύθηκε + Πέθανε Έτη ενεργής σταδιοδρομίας Ετικέτα Γέννηση/Δημιουργία @@ -2116,14 +2116,14 @@ Θερμοκρασία CPU: Συνολική μνήμη Δεδομένα προφίλ - Χρήση 'Αμυδρού φωτός' κατά την παύση της αναπαραγωγής βίντεο + Χρήση 'Αμυδρού φωτός' κατά την παύση αναπαραγωγής βίντεο Όλες οι εγγραφές Aνά τίτλο Ανά ομάδα Δικτυακά κανάλια Εγγραφές ανά τίτλο Οδηγός - Επιτρεπόμενο σφάλμα στην αναλογία οθόνης για να ελαχιστοποιηθούν οι μαύρες μπάρες + Σφάλμα αναλογίας οθόνης για μείωση μαύρων μπαρών Εμφάνιση αρχείων βίντεο στις λίστες Κατασκευαστής DirectX: Έκδοση Direct3D: @@ -2159,9 +2159,9 @@ Ενεργός εξωτερικός αναπαραγωγέας - Πιέστε το 'Εντάξει' για να τερματίσετε τον αναπαραγωγέα + Πιέστε 'Επιλογή' για να τερματίσετε την αναπαραγωγή - Πιέστε το 'Εντάξει' όταν η αναπαραγωγή ολοκληρωθεί + Πιέστε 'Επιλογή' όταν η αναπαραγωγή ολοκληρωθεί Πρόσθετο @@ -2203,10 +2203,10 @@ Εγκατάσταση από αρχείο zip Λήψη %i%% Διαθέσιμες ενημερώσεις - Δεν πληρούνται οι Εξαρτήσεις - Το Πρόσθετο δεν έχει τη σωστή δομή - %s χρησιμοποιείται από τα εγκατεστημένα Πρόσθετα - Αδυναμία απεγκατάστασης αυτού του Πρόσθετου + Δεν πληρούνται οι εξαρτήσεις + Το πρόσθετο δεν έχει τη σωστή δομή + Το %s χρησιμοποιείται από τα εγκατεστημένα πρόσθετα + Αδυναμία απεγκατάστασης αυτού του πρόσθετου Επαναφορά Διαθέσιμα πρόσθετα @@ -2232,7 +2232,7 @@ Δεν ήταν δυνατή η σύνδεση Απαιτείται επανεκκίνηση Απενεργοποίηση - Απαιτείται Πρόσθετο + Απαιτείται πρόσθετο Νέα προσπάθεια επανασύνδεσης; Επανεκκινήσεις πρόσθετου Κλείδωμα διαχειριστή πρόσθετων @@ -2243,12 +2243,12 @@ Επιθυμείτε να απενεργοποιηθεί από το σύστημά σας; Κατεστραμμένο Επιθυμείτε να εφαρμοστεί αυτό το κέλυφος; - Για να χρησιμοποιήσετε αυτή τη λειτουργία πρέπει να κατεβάσετε ένα Πρόσθετο: - Επιθυμείτε να κατεβάσετε αυτό το Πρόσθετο; + Για να χρησιμοποιήσετε αυτή τη λειτουργία πρέπει να κατεβάσετε ένα πρόσθετο: + Επιθυμείτε να κατεβάσετε αυτό το πρόσθετο; Ειδοποιήσεις - Λειτουργία συλλογής + Λειτουργία Συλλογής Διάταξη πληκτρολογίου QWERTY Σε λειτουργία η διέλευση ήχου @@ -2259,8 +2259,8 @@ Ποιότητα διαφημιστικού Ροή πολυμέσων Λήψη - Λήψη και εκτέλεση - Λήψη και αποθήκευση + Λήψη & εκτέλεση + Λήψη & αποθήκευση Σήμερα Αύριο Αποθήκευση @@ -2271,33 +2271,33 @@ Εκτεταμένος Ορισμός αναπαραγωγέα DVD αντί του κανονικού Επιβεβαίωση λήψης πριν την αναπαραγωγή του βίντεο - Clips - Επανεκκίνηση plugin για την ενεργοποίηση του - Σήμερα το βράδυ - Αύριο το βράδυ + Clip + Επανεκκίνηση plugin για την ενεργοποίησή του + Απόψε + Αύριο βράδυ Kατάσταση καιρού - Βροχόπτωση + Υετός Βροχή Υγρασία Αίσθηση Παρατηρούμενη - Εκφυγή από το κανονικό + Παρέκκλιση από το κανονικό Ανατολή ηλίου Δύση ηλίου Λεπτομέρειες - Εξέλιξη - Ροή εξώφυλλων + Πρόγνωση + Ροή εξωφύλλων Μετάφραση κειμένου Κατηγορία λίστας χαρτών %s - Τριήμερη - Χάρτες καιρού + 36ωρο + Χάρτες Ωριαία Σαββατοκύριακο %sη ημέρα Προειδοποίηση Προειδοποιήσεις Επιλογή - Πρόγνωση + Έλεγχος Ρύθμιση Κύκλοι Εκτέλεση @@ -2319,9 +2319,9 @@ Σημειώσεις έκδοσης Αλλαγές έκδοσης Για να εκτελεστεί η έκδοση %s απαιτείται - η %s αναθεωρημένη έκδοση του XBMC ή και νεώτερη. - Παρακαλώ, αναβαθμίστε άμεσα το XBMC. - Δεν βρέθηκαν δεδομένα! + η %s αναθεωρημένη έκδοση του XBMC ή νεώτερη. + Παρακαλώ αναβαθμίστε το XBMC. + Δε βρέθηκαν δεδομένα! Επόμενη σελίδα Αγαπητό Απεχθές @@ -2330,7 +2330,7 @@ Ενεργοποίηση προσαρμοσμένου πλήκτρου script Αποτυχία εκκίνησης - Διακομιστής web + Διακομιστής ιστού Διακομιστής Συμβάντων Απομακρυσμένος Διακομιστής Επικοινωνίας @@ -2361,11 +2361,11 @@ Αδυναμία εύρεσης προηγούμενου αντικειμένου για αναπαραγωγή Αποτυχία εκκίνησης του zeroconf - Είναι εγκατεστημένη η Υπηρεσία Bonjour της Apple; Δείτε το αρχείο καταγραφής για περισσότερες πληροφορίες. + Είναι εγκατεστημένη η υπηρεσία Bonjour της Apple; Δείτε το αρχείο καταγραφής για περισσότερες πληροφορίες. Απόδοση Βίντεο - Αποτυχία αρχικοποίησης φίλτρων/scalers βίντεο, επαναφορά σε διγραμμική προσαρμογή ανάλυσης - Αποτυχία αρχικοποίησης της συσκευής ήχου + Αποτυχία χρήσης φίλτρων/scalers βίντεο, επαναφορά σε bilinear προσαρμογή ανάλυσης + Αποτυχία έναρξης της συσκευής ήχου Ελέγξτε τις ρυθμίσεις ήχου Περιφερειακά @@ -2374,9 +2374,9 @@ Γενικός προσαρμογέας δικτύου Γενικός δίσκος Δεν υπάρχουν διαθέσιμες ρυθμίσεις για αυτό το περιφερειακό. - Η νέα συσκευή έχει ρυθμιστεί - Η συσκευή έχει αφαιρεθεί - Το Keymap να χρησιμοποιηθεί για τη συγκεκριμένη συσκευή + Η νέα συσκευή ρυθμίστηκε + Η συσκευή αφαιρέθηκε + Keymap για χρήση με αυτή τη συσκευή Ενεργοποιημένο Keymap Τοποθεσία @@ -2389,19 +2389,19 @@ Pulse-Eight Nyxboard Μετάβαση στο πληκτρολόγιο εντολών Ενεργοποίηση διακόπτη εντολών - Πιέστε το "user" ως πλήκτρο εντολών + Πιέστε το "user" πλήκτρο εντολών Ενεργοποίηση διακόπτη εντολών Αδυναμία εκκίνησης του προσαρμογέα Ενεργοποίηση της τηλεόρασης κατά την εκκίνηση του XBMC - Απενεργοποίηση συσκευών κατά τη διακοπή λειτουργίας του XBMC + Απενεργοποίηση συσκευών κατά τον τερματισμό του XBMC Συσκευές σε κατάσταση αναμονής κατά την προφύλαξη οθόνης - Δεν ήταν δυνατή η ανίχνευση της θύρας CEC. Ρυθμίστε την χειροκίνητα. - Δεν ήταν δυνατή η ανίχνευση του προσαρμογέα CEC. - Μη υποστηριζόμενη έκδοση διεπαφής libcec. %d είναι μεγαλύτερη από την έκδοση που το XBMC υποστηρίζει (%d) - Βάλτε αυτόν τον υπολογιστή σε κατάσταση αναμονής όταν η τηλεόραση είναι απενεργοποιημένη + Δεν εντοπίστηκε η θύρα CEC. Ρυθμίστε την χειροκίνητα. + Δεν εντοπίστηκε ο προσαρμογέας CEC. + Μη υποστηριζόμενη έκδοση libCEC. Η %d είναι μεγαλύτερη από την έκδοση που το XBMC υποστηρίζει (%d) + Ο υπολογιστής σε κατάσταση αναμονής όταν κλείσει η τηλεόραση Αριθμός θύρας HDMI Συνδεδεμένη - O προσαρμογέας εντοπίσθηκε, αλλά η libcec δεν είναι διαθέσιμη + O προσαρμογέας εντοπίσθηκε, αλλά η libCEC δεν είναι διαθέσιμη Χρήση των ρυθμίσεων γλώσσας της τηλεόρασης diff --git a/language/Japanese/strings.xml b/language/Japanese/strings.xml index 46e3282..d3126e0 100644 --- a/language/Japanese/strings.xml +++ b/language/Japanese/strings.xml @@ -1,10 +1,9 @@  - - - + + + - プログラム ピクチャ @@ -15,7 +14,8 @@ XBMC SVN ファイルマネージャー 天気予報 - xbmc media center + XBMC メディアセンター + 月曜日 火曜日 水曜日 @@ -23,6 +23,7 @@ 金曜日 土曜日 日曜日 + 1月 2月 3月 @@ -35,9 +36,49 @@ 10月 11月 12月 + + + + + + + + + + 1月 + 2月 + 3月 + 4月 + 5月 + 6月 + 7月 + 8月 + 9月 + 10月 + 11月 + 12月 + + + 北北東 + 北東 + 東北東 + + 東南東 + 南東 + 南南東 + + 南南西 + 南西 + 西南西 + 西 + 西北西 + 北西 + 北北西 + 不定 + 表示: 自動 - 表示: 自動(大) - 表示: アイコン(小) + 表示: 自動 (大) + 表示: アイコン (小) 表示: リスト スキャン 並べ替え: 名前 @@ -50,17 +91,19 @@ サムネイル(複数)作成 ショートカット 一時停止 + 更新失敗 + インストール失敗 コピー 移動 削除 名前の変更 - 新しいフォルダー + 新規フォルダー コピーの確認 移動の確認 削除の確認 - コピーしますか? - 移動しますか? - 削除しますか? + コピーしますか? + 移動しますか? + 削除しますか? ステータス オブジェクト 一般 @@ -84,8 +127,8 @@ タイプ: 固定 DHCP - MACアドレス - IPアドレス + MAC アドレス + IP アドレス リンク: 半二重 全二重 @@ -97,92 +140,110 @@ リンクしていません 空き 利用不可 - トレーは開いています + トレーが開いています 読み込み中... ディスク無し ディスク有り スキン - 映像方式・サイズ - - + + 画面解像度 + ビデオに合わせてリフレッシュレートを調整 + 発売日 - トーン + アスペクト比 4:3 のビデオの再生 + + ムード スタイル + 長さ アルバムの選択 トラック - 批評 + レビュー 更新 アルバムの検索 OK - アルバムが見つかりません! + アルバムが見つかりません! すべて選択 - メディア情報のスキャン + メディア情報スキャン中 保存 シャッフル - 削除 + クリア スキャン 検索中... - ビデオの選択: - ビデオの詳細を読込中... + 情報が見付かりません! + ムービーの選択: + %s の情報を問い合わせ中 + ムービーの詳細を読込中... + Web インターフェイス + 公開時コピー - 概要 - 投票結果 + あらすじ + + 評価 出演者 ストーリー 再生 次へ 前へ - UI設定 - 画面の補正 + UI の設定... + 画面補正... ソフト化 拡大 ピクセル比 - DVDドライブ + DVD ドライブ ディスクを入れて下さい リモート共有 ネットワークに接続されていません - 中止 + キャンセル 表示時間 - テストパターン + 表示位置の上下微調整 + テストパターン... + オーディオ CD トラック名を freedb.org で検索 プレイリストのランダム再生 HDD停止までの時間(分) ビデオフィルター 無し ポイントフィルタ - バイリニア補間(シャープ) - 異方性フィルタリング(ノーマル) - クインカンクス(ソフト) - ガウスキュービック(ベリ-ソフト) - 縮小フィルタリング - 拡大フィルタリング - 終了時 プレイリストを消去 + バイリニア補間(シャープ) + 異方性フィルタリング(ノーマル) + クインカンクス(ソフト) + ガウスキュービック(ベリーソフト) + 縮小フィルタリング + 拡大フィルタリング + 終了時にプレイリストを消去 + 表示モード + フルスクリーン #%d + ウィンドウ化 + リフレッシュレート + フルスクリーン + Sizing: (%i,%i)->(%i,%i) (Zoom x%2.2f) AR:%2.2f:1 (Pixels: %2.2f:1) (VShift: %2.2f) + スクリプト 言語 - 音楽 + ミュージック 視覚エフェクト ディレクトリの選択 - すべてのスピーカーへ出力 + ステレオ音声を全スピーカーから出力 チャンネル数 - - DTSレシーバーを有効化 + - DTS 対応レシーバー CDDB - CDDB情報をフリーサーバーから検索 + CDDB 情報取得中 エラー タグを読み込む 開始 SHOUTcast お待ち下さい... スクリプト出力 - Webサーバーを有効化 + HTTP 経由での XBMC の制御を有効に 録音 - 録音の停止 - 並べ替え: トラック + 録音停止 + 並べ替え: トラック番号 並べ替え: 時間 - 並べ替え: タイトル - 並べ替え: アーティスト - 並べ替え: アルバム - トップ100 + 並べ替え: タイトル名 + 並べ替え: アーティスト名 + 並べ替え: アルバム名 + トップ 100 左側上部枠の補正 右側下部枠の補正 字幕の位置 @@ -192,30 +253,37 @@ 正方形になるように調整して下さい 設定が読み込めません 設定の初期化 - .xmlファイルをチェックして下さい - %iアイテムを発見しました + .xml ファイルをチェックして下さい + %i 個見つかりました 検索結果 見つかりませんでした + 字幕 フォント - サイズ: + ダイナミックレンジの圧縮 ビデオ オーディオ - 字幕を参照する + 字幕を参照 ブックマークの作成 ブックマークの削除 音声オフセット - Bookmarks + ブックマーク + - AAC 対応レシーバー + - MP1 対応レシーバー + - MP2 対応レシーバー + - MP3 対応レシーバー 遅延 言語 有効 非インターリーブ + (0=自動) - データベースを更新します + データベースを更新中 準備中... データベースエラー 曲の検索中... - データベースを更新しました + データベースの更新が完了しました 曲の更新中... 曲を更新できません アーティストの更新中... @@ -232,18 +300,19 @@ データベースの圧縮中... データベースを圧縮できません ライブラリを消去しますか? - データベースの更新 + ライブラリの消去... 実行 フレームレートの調整 オーディオ出力 アナログ - デジタル - 色々なアーティスト - Discの再生 - 映画 + デジタル(光/同軸) + VA/オムニバス + ディスクの再生 + ムービー フレームレートの調整 俳優 公開年 + ダウンミックス時に音量ブースト プログラム OFF @@ -251,14 +320,14 @@ マトリックス スクリーンセーバー起動時間 スクリーンセーバーモード - シャットダウンまでの時間 + シャットダウンタイマー すべてのアルバム 最近追加されたアルバム スクリーンセーバー - R.スライドショー - スクリーンセーバーのフェードレベル(%) - 並べ替え: ファイル - - AC3レシーバーを有効化 + ランダムスライドショー + スクリーンセーバーの暗さ(%) + 並べ替え: ファイル名 + - Dolby Digital (AC3) 対応レシーバー 並べ替え: 名前 並べ替え: 公開年 並べ替え: 評価 @@ -301,7 +370,7 @@ 結露点 湿度 - Defaults + デフォルト 天気予報サービスに接続中 天気を取得中: 天気を取得できません @@ -310,18 +379,24 @@ サムネイルの取得中... 利用できません 表示: アイコン(大) + 最低気温 + 最高気温 + HDMI + アルバム情報の削除 - CDDB情報の削除 + CDDB 情報の削除 選択 アルバム情報が見つかりません - CDDB情報が見つかりません + CDDB 情報が見つかりません ディスク - 正しいCD/DVDを入れて下さい - 次のCD/DVDを挿入して下さい + 正しい CD/DVD を入れて下さい + 次の CD/DVD を挿入して下さい: 並べ替え: DVD# キャッシュしない - ライブラリから映画を削除 - Really remove '%s'? + ライブラリからムービーを削除 + 本当に '%s' を削除しますか? + %s の風 %i %s + リムーバブルディスク ファイルを開く キャッシュ @@ -352,31 +427,32 @@ コントラスト ガンマ タイプ - OSD位置の調節 - OSDの位置 + OSD 位置の調節 + OSD の位置 クレジット MODチップ - OFF - 音楽のみ - 音楽 & ビデオ + オフ + ミュージックのみ + ミュージック & ビデオ プレイリストをロードできません OSD - スキン&言語 + スキン & 言語 外観 - オーディオ設定 - XBMCについて + オーディオ設定 + XBMC について + アルバムの削除 リピート 個別リピート フォルダーごとのリピート 次のアイテムを自動再生 - - アイコン大の使用 + - アイコン(大)の使用 字幕の大きさ - 高度な設定 (エキスパート専用) + 高度な設定 (エキスパート専用!) 全体の音量(dB) - ビデオをGUIの解像度に合わせる + ビデオを GUI の解像度に合わせる 設定 - 拡張子を隠す + 拡張子を表示する 並べ替え: タイプ オンラインサービスに接続できません アルバム情報の取得に失敗しました @@ -389,12 +465,14 @@ 視覚エフェクトを有効化 ビデオモードを切り替えを有効化 起動画面 - メニュー画面 + ホーム画面 手動設定 ジャンル + 最近再生されたアルバム 実行 Launch in... + コンピレーション このソースを削除 メディア切り替え @@ -403,25 +481,26 @@ プレイリストに追加 手動でライブラリに追加 タイトルを入力 - Error: Duplicate title + エラー: タイトルが重複しています ジャンルを選択 - New Genre - Manual Addition - Enter Genre + 新規ジャンル + 手動で追加 + ジャンル名を入力 表示: %s - List + リスト アイコン - Big List - Big Icons - Wide - Big Wide - Album Icons - DVD Icons + リスト(大) + アイコン(大) + ワイド + 超ワイド + アルバムアイコン + DVD アイコン DVD - Media Info + メディア情報 オーディオ出力デバイス - Passthrough Output Device - No biography for this artist + パススルー出力デバイス + このアーティストのバイオグラフィーがありません + 並べ替え: %s 名前 日付 @@ -436,26 +515,28 @@ ファイル 公開年 評価 - Type - Usage - Album Artist + タイプ + 回数 + アルバムアーティスト 再生回数 最後に再生した日 - Comment + コメント 追加日 - Default + でフォルト スタジオ パス 処理中 + 再生回数 + 並べ替え方向 並べ替え方法 表示モード - Remember views for different folders + 他のフォルダでもこのビューを使用 昇順 降順 プレイリストを編集 フィルター - Cancel Party Mode + パーティーモードをキャンセル パーティーモード ランダム オフ @@ -465,18 +546,23 @@ リピート: オフ リピート: 1項目 リピート: すべて - CD録音 - ミディアム(低音質) - スタンダード(中音質) - エクストリーム(高音質) + + オーディオ CD の読み込み + ミディアム (低音質) + スタンダード (中音質) + エクストリーム (高音質) 固定ビットレート リッピング中... + 保存先: - CD or Trackを録音できません - CDDARipパスが設定されていません - Rip Audio Track - Enter number - CDリッピング + CD または楽曲を読み込めませんでした + CDDARip パスが設定されていません + オーディオトラックを読み込む + 番号を入力 + ビットレート/サンプルレート + サンプリング周波数 + + オーディオ CD エンコーダー 品質 ビットレート @@ -494,11 +580,11 @@ モード トラックレベル使用 アルバムレベル使用 - プリアンプレベル - 平均化したファイルを基準 - プリアンプレベル - 平均化ファイルを基準にしない - 平均化したファイルのクリッピングを避ける - クロップ ブラック バー - 大きなファイルを解凍する必要があります。続けますか? + プリアンプレベル - 平均化したファイルを基準 + プリアンプレベル - 平均化ファイルを基準にしない + 平均化したファイルのクリッピングを避ける + 黒帯部分をトリミングする + 大きなファイルを解凍する必要があります。続けますか? ライブラリから削除 ビデオライブラリをエクスポート ビデオライブラリをインポート @@ -507,42 +593,52 @@ ライブラリを参照する 製作年 ライブラリを更新 - Show Debug Info - Browse for Executable - プレイリストを参照する - フォルダーを参照する + デバッグ情報を表示 + 実行ファイルを参照 + プレイリストを参照 + フォルダーを参照 楽曲情報 - Volume Amplification - Choose Export Folder + ノンリニアズーム + + ボリューム増幅 + エクスポートフォルダの選択 このファイルは存在しません。 - ライブラリから削除しますか? + ライブラリから削除しますか? スクリプトを参照する + 圧縮レベル + ライブラリの整理 ライブラリから古い曲を削除します このパスは以前にスキャンしました ネットワーク - - HTTPプロキシ ホスト - HTTPプロキシを使用 - インターネット プロトコル(IP) - 無効なポートです。1から65535の間で設定して下さい - HTTPプロキシ - 接続方式 + - サーバ + + HTTP プロキシを使用 + + インターネット プロトコル (IP) + 無効なポートです。1から65535の間で設定して下さい。 + HTTP プロキシ + + - 接続方式 自動 (DHCP) 手動 (固定) + - IPアドレス - ネットマスク - デフォルト ゲートウェイ - DNSサーバー 設定の保存 & 再起動 - 無効なアドレスです。AAA.BBB.CCC.DDDの様に記述して下さい - 0から255の間から選んで下さい - 変更は保存されません 本当によろしいですか? - Webサーバー - FTPサーバー + 無効なアドレスです。AAA.BBB.CCC.DDD のように記述してください。 + 0 から 255 の間から選んで下さい + 変更は保存されません 本当によろしいですか? + Web サーバー + FTP サーバー + - ポート + 設定の保存 - パスワード - No Pass + パスワードなし - 文字コード - スタイル: - カラー: @@ -555,15 +651,17 @@ ファイル スキャン情報はありませんでした ライブラリモードを終了して下さい - イメージロードできません + イメージの読み込みに失敗 パスの編集 Mirror Image - よろしいですか? - Removing Source + よろしいですか? + ソースの削除 + プログラムリンクの追加 プログラムパスの編集 プログラム名の編集 パスの階層の編集 + 表示: リスト(大) 黄色 白色 @@ -573,106 +671,138 @@ 青緑色 Reserved Reserved + + エラー %i: 利用不可 オーディオハードウェア シーク中 スライドショーフォルダー ネットワークインターフェース - -ワイヤレスネットワーク名(SSID) + - ワイヤレスネットワーク名(ESSID) + - ワイヤレスパスワード + - ワイヤレスセキュリティ ネットワークインターフェース設定を保存して適用 ネットワークインターフェース設定を適用しています。お待ち下さい。 - システム上のプログラムによるXBMCの制御を許可 + システム上のプログラムによる XBMC の制御を許可 ポート - ポートレンジ - 別のシステム上のプログラムによるXBMCの制御を許可 + ポート番号の範囲 + 別のシステム上のプログラムによる XBMC の制御を許可 Initial Repeat Delay (ms) Continuous Repeat Delay (ms) Maximum Number of Clients インターネット接続 + 誤ったポート番号が入力されました + ポート番号は 1-65535 の間から選んで下さい + ポート番号は 1024-65535 の間から選んで下さい + + ミュージックを追加... + ビデオを追加... - プレビュー 接続できません - XBMC was unable to connect to the network location. - This could be due to the network not being connected. - Would you like to add it anyway? - IP Address + XBMC はこのネットワーク上の場所に接続できませんでした。 + ネットワークに繋がっていない可能性があります。 + それでも追加しますか? + + IP アドレス ネットワーク上の場所を追加 - Protocol - Server Address - Server Name - Remote Path - Shared Folder + プロトコル + サーバのアドレス + サーバ名 + リモートパス + 共有フォルダ ポート ユーザー名 - ネットワークサーバを参照する - Enter the network address of the server - Enter the path on the server - Enter the port number - Enter the username - Add %s Source - メディアロケーションのパスを入力するか、参照してください。 - メディアソースの名前を入力してください。 - Browse for new share + ネットワークサーバを参照 + サーバのネットワークアドレスを入力 + サーバ上のパスを入力 + ポート番号を入力 + ユーザ名を入力 + %s ソースの追加 + メディアのパスを参照するか入力してください。 + ソースの名前を入力してください。 + 新しい共有の参照 参照 - Could not retrieve directory information. - ソース追加 + フォルダ情報の取得に失敗 + ソースを追加 ソースを編集 - Edit %s Source - Enter the new label - イメージを参照する - イメージフォルダーを参照する + %s ソースを編集 + 新しいラベルを入力 + イメージを参照 + イメージフォルダを参照 ネットワーク上の場所を追加... - ファイルを参照する - Submenu - Enable Submenu Buttons + ファイルを参照 + サブメニュー + サブメニューボタンを有効にする お気に入り ビデオ アドオン ミュージック アドオン ピクチャ アドオン - Loading directory - Retrieved %i items - Retrieved %i of %i items + フォルダの読み込み中 + %i アイテムを取得 + %i アイテム (全 %i アイテム中) を取得 プログラム アドオン プラグインサムネイル指定 アドオン設定 + アクセスポイント + その他... + - ユーザ名 + スクリプト設定 シングル + Web のアドレスを入力 + SMB シェア SMB ワークグループ SMB ユーザー名 - SMB パスワード - SMB WINSサーバー - Mount SMB Shares + SMB パスワード + + WINSサーバー + SMB 共有のマウント + 削除 ミュージック ビデオ ピクチャ ファイル - ミュージック & ビデオ - ミュージック & ピクチャー - ミュージック & ファイル - ビデオ & ピクチャー - ビデオ & ファイル - ピクチャー & ファイル - ミュージック & ビデオ & ピクチャー - ミュージック & ビデオ & ピクチャー & ファイル + ミュージック & ビデオ + ミュージック & ピクチャー + ミュージック & ファイル + ビデオ & ピクチャー + ビデオ & ファイル + ピクチャー & ファイル + ミュージック & ビデオ & ピクチャー + ミュージック & ビデオ & ピクチャー & ファイル 無効 - ファイル & ミュージック & ビデオ - ファイル & ピクチャー & ミュージック - ファイル & ピクチャー & ビデオ - ミュージック & プログラム - ビデオ & プログラム - ピクチャー & プログラム - ミュージック & ビデオ & ピクチャー & プログラム - プログラム & ビデオ & ミュージック - プログラム & ピクチャー & ミュージック - プログラム & ピクチャー & ビデオ + ファイル & ミュージック & ビデオ + ファイル & ピクチャー & ミュージック + ファイル & ピクチャー & ビデオ + ミュージック & プログラム + ビデオ & プログラム + ピクチャー & プログラム + ミュージック & ビデオ & ピクチャー & プログラム + プログラム & ビデオ & ミュージック + プログラム & ピクチャー & ミュージック + プログラム & ピクチャー & ビデオ + 自動検出 - system 自動検出 + システムにより自動検出 ニックネーム - Ask to Connect - FTPユーザー・パスワードを送る - PINGをかける間隔 - Would you like to connect to the Autodetected system? + + 接続を確認する + FTP ユーザー・パスワードを送る + PING をかける間隔 + 自動検出されたシステムに接続しますか? + + Zeroconf + 本サービスを Zeroconf 経由でアナウンスする + XBMC の AirPlay コンテンツ受信を許可する + デバイス名 + - パスワード保護を使う + AirPlay + + カスタムオーディオデバイス + カスタムパススルーデバイス + 漂う and 凍った @@ -690,23 +820,41 @@ おだやか with windy - drizzle - T-Storm - Drizzle - Foggy + 小雨 + 雷雨 + 小雨 + + Grains + 雷・暴風 + 雷・大雨 + Moderate + Very High + Windy + Mist + + + + システムが右の時間以上アイドル状態が続くと画面をスリープ + + 上映時間 - LCD Type + + スクリプトが失敗! : %s + 新しいバージョンが必要です - ログを参照 + + LCD/VFDを有効にする + ホーム プログラム ピクチャー - ファイル + ファイルマネージャー 設定 ミュージック ビデオ システム情報 設定 - 一般 設定 - 画面 - 設定 - 外観 - GUI設定 + 設定 - 外観 - GUI 設定 設定 - 画面 - スクリーン設定 設定 - ピクチャー 設定 - プログラム @@ -714,23 +862,29 @@ 設定 - ミュージック 設定 - システム 設定 - ビデオ - 設定 - ネットワーク + 設定 - ネットワーク 設定 - 外観 スクリプト Webブラウザ + ビデオ ビデオ/プレイリスト + ログイン画面 設定 - プロファイル + アドオンブラウザー + はい/いいえ ダイアログ 進行ダイアログ - 字幕を検索しています... - Caching subtitles... - terminating + + 字幕を検索中... + 字幕をキャッシュ中... + 終了中 バッファ中 - Opening stream + ストリームを開いていいます + ミュージック/プレイリスト ミュージック/ファイルリスト ミュージック/ライブラリ - Playlist Editor + プレイリストエディター Top 100 曲 Top 100 アルバム プログラム @@ -739,24 +893,30 @@ ネットワーク・ゲーム エクステンション システム情報 + ミュージック - ライブラリ - ミュージック - 再生中 - ビデオ - 再生中 + ミュージック - 現在再生中 + + ビデオ - 現在再生中 アルバム情報 ムービー情報 + ダイアログの選択 ミュージック/情報 - ダイアログOK + ダイアログ OK ビデオ/情報 スクリプト/情報 フルスクリーンビデオ オーディオ視覚エフェクト + ファイルスタッキング ダイアログ - Rebuild index... - Return to Music Window - Return to Videos Window + インデクスの再構築... + ミュージックのウィンドウに戻る + ビデオのウィンドウに戻る + 最初から再生 %s から再開 + 0 1 2 @@ -770,13 +930,13 @@ c ok * - フォルダーロック + ロック中!コードを入力してください パスワード入力 マスターコード入力 アンロックコード入力 C を押すとキャンセル ボタンパスワードを入力し - Startを押してください。Backでキャンセル + Start を押してください。Back でキャンセル セット ロック アンロック リセット ロック @@ -790,56 +950,87 @@ リトライ 停止 パスワードが合いません アクセスが否定されます - パスワードリトライの限界を超えました - Systemを停止します + パスワードリトライ回数の限界を超えました + システムを停止します アイテム ロック シェアロックが復活します ロック変更 Source Lock - パスワードが未記入です 再び試みてください + パスワードが未記入です 再び試みてください マスターロック - Shutdown system if Master Lock retries exceeded + パスワードリトライ回数の限界を超えたらシステムをシャットダウンする マスターコードが有効ではありません - 正しいマスター コードを入力して下さい - Settings & Filemanager - Set as default for all Movies - This will reset any previously saved values + 正しいマスターコードを入力して下さい + 設定 & ファイルマネージャー + 全ビデオ再生のデフォルト値に設定 + 過去の設定値はリセットされます 一枚の表示時間 パン/ズームエフェクトの使用 - 12 hour clock - 24 hour clock - Day/Month - Month/Day + + 12時間時計 + 24時間時計 + 日/月 + 月/日 + システム稼動時間 時間 合計稼働時間 + バッテリーレベル + 天気予報 + スクリーンセーバー フルスクリーンOSD + システム - HDDの停止 + HDD の停止 ビデオのみ - - 遅延 - - 最小ファイル再生時間 + - 停止までの遅延時間 + - この時間より長い再生は遅延時間後に停止 シャットダウン - Default Shutdown mode - Quit - Hibernate - Suspend - Exit + + シャットダウン機能 + 終了 + ハイバネート + サスペンド + 終了 再起動 最小化 - リムーバブルHDDをマウントしました + 電源ボタンを押した際の動作 + システム終了・電源を切る + + 別のセッションが動作中です(ssh 経由かも?) + リムーバブル HDD をマウントしました 安全でないデバイスの取り外し デバイスが正しく外されました + ジョイスティックが接続されました + ジョイスティックが外されました + + バッテリ残量が少なくなっています + フリッカーフィルタ - Vertical Blank Sync - Disabled - Enabled During Video Playback - Always Enabled - この解像度を保持しますか? + ドライバに任せる (再起動が必要) + Vertical Blank の同期方法 + 無効 + ビデオ再生中のみ有効 + 常に有効 + この解像度を保持しますか? + + 高品質アップコンバート + 無効 + SD 画質のコンテンツにのみ有効 + 常に有効 + + アップコンバートの方式 + Bicubic + Lanczos + Sinc + VDPAU + VDPAU HQ Upscaling level + VDPAU Studio level color conversion + Active Connections Detected! If you proceed, you might not be able to control XBMC any longer. Are you sure you to stop the Event Server? @@ -847,75 +1038,74 @@ If you are currently using the Apple Remote to control XBMC, changing this setting might affect your ability to continue controlling it. Do you want to proceed? - HDD Key: - HDD Temp: - DVD Model: - DVD Firmware: - HDD Model: - HDD Serial: - HDD Firmware: - HDD Password: - HDD Lock State: サブネットマスク デフォルトゲートウェイ - プライマリDNS - Initialize failed - GamePad - Keyboard - Mouse - Head/MicroPhone - MemoryStick - IR-Remote - Controller Port + プライマリ DNS + 初期化に失敗 + Never Immediately After %i secs HDD Install Date: HDD Power Cycle Count: + プロファイル - プロフィール '%s'を削除しますか? - 最後にロードしたプロフィール: + プロファイル '%s' を削除しますか? + + 最後にロードしたプロファイル: 不明 上書き + アラーム クロック アラーム クロック 間隔 (分) - %im 分後にアラーム開始 + %i 分後にアラームが作動します アラーム! - %im%is でキャンセル + 残り%i分%i秒でキャンセルされました + %2.0f分 + %2.0f秒 + RARファイル内から字幕を探す 字幕を参照する... - Move Item - Move Item Here - Cancel Move - Hardware: - CPU Usage: - Hard Disk + アイテムの移動 + アイテムをここに移動 + 移動のキャンセル + + ハードウェア: + CPU 使用率: + + 接続しましたが、DNS がありません。 + ハードディスク DVD-ROM ストレージ - Default + デフォルト ネットワーク ビデオ ハードウェア + オペレーティング システム: - CPU速度: + CPU 速度: + ビデオエンコーダー: 画面解像度: - A/V Cable: - DVD 地域: + + A/V ケーブル: + + DVD リージョン(地域): インターネット: 接続済み 接続されていません。ネットワーク設定を確認してください。 - - 目標温度 - - ファンスピード + + 目標温度 + ファンスピード 自動温度コントロール - ファンスピード コントロール + ファンスピード制御 - フォント - Flipping双方向ストリングスを有効化 - RSSフィードを有効化 - 親フォルダーの項目を隠す + Flipping 双方向ストリングスを有効化 + RSS フィードを有効化 + 親フォルダーの項目を表示する トラック命名テンプレート - Systemをリブートしますか? - XBMCをリスタートしますか? + システムを再起動しますか? + XBMC の再起動ではありません ズーム エフェクト フロート エフェクト ブラックバー 縮小 @@ -929,29 +1119,30 @@ ステレオ 左のみ 右のみ - CD+G再生有効化 + CD+G 再生有効化 バックグラウンド透明 フォアグラウンド透明 A/V 遅延 カラオケ %s が見つかりません - オープン エラー %s - ロードできません %s + %s を開く際にエラー + %がロードできません エラー: メモリー不足 上へ 下へ ラベル編集 - 規定値作成 + デフォルトに設定 削除ボタン + 現状 サイクル - 再生でLEDのON/OFFをする + 再生でLED の ON/OFF をする 映画情報 キュー項目 - IMDbを検索... + IMDb を検索... 新しいコンテンツをスキャン プレイ中... アルバム情報 @@ -965,20 +1156,21 @@ アーティストサムネイル指定 サムネイルを自動で作成 音声有効化 + デバイス有効化 ボリューム デフォルト 表示モード デフォルト 輝度 デフォルト コントラスト デフォルト ガンマ - 停止履歴から再生 + 最後に停止した位置からビデオを再生 Voice Mask - Port 1 Voice Mask - Port 2 Voice Mask - Port 3 Voice Mask - Port 4 タイムベースシーク使用 トラック名 詳細情報 表示 - Preset + プリセット プリセットが有効な視覚エフェクトではありません 設定が有効な視覚エフェクトではありません イジェクト/ロード @@ -989,41 +1181,71 @@ オーディオ・字幕 設定 字幕有効化 ショートカット - 冠詞(theなど)を並べ替え対象から外す + 冠詞 (the など) を無視して並べ替えを行う アルバム内クロスフェード - %sを参照する + %s を参照 Show track position デフォルトをクリア - Resume + 再開 サムネイルを取得 画像情報 - %s Presets - (IMDb User Rating) + %s プリセット + (IMDb ユーザによる評価) Top 250 - Tune in on Last.FM - Minimum fanspeed - Downloading + Tune in on Last.fm + 最低ファン速度 + ダウンロード中 コンピレーションのみに登場するアーティストを含める + レンダリング方法 + 自動検出 + ベーシック (ARB) + アドバンスト (GLSL) + ソフトウェア + 安全に削除 + VDPAU + ここからスライドショーを開始 + このパス用に記憶 + ピクセルバッファーオブジェクトを使用 ハードウェア アクセラレータを許可 (VDPAU) ハードウェア アクセラレータを許可 (VAAPI) ハードウェア アクセラレータを許可 (DXVA2) ハードウェア アクセラレータを許可 (CrystalHD) ハードウェア アクセラレータを許可 (VDADecoder) ハードウェア アクセラレータを許可 (OpenMax) + ピクセル シェーダー + ハードウェア アクセラレータを許可 (VideoToolbox) + + A/V 同期方法 + オーディオクロック + ビデオクロック (オーディオ側をあわせる) + ビデオクロック (オーディオを再サンプリングする) + 最大再サンプリング量 (%) + 再サンプリング品質 + 低 (高速) + + + 最高 (遅い!) + ディスプレイ同期周波数に合わせて再生 + Apple Remote - Sequence Delay Time - Disabled - Standard - Universal Remote - Apple Remote Error - Apple Remote support could be enabled. + + リモコンからの XBMC の起動を許可 + Sequence delay time + + 無効 + 標準 + 汎用リモコン + Apple Remote エラー + Apple Remote サポートを有効にできません。 + スタック スタック解除 - プレイリストを取得中... + プレイリストファイルの取得中... ストリームリストを取得中... ストリームリストを解析中... - ストリームリストを取得できません - プレイリストを取得できません + ストリームリストの取得に失敗 + プレイリストファイルの取得に失敗 + ゲームディレクトリ サムネイル表示の自動切換 サムネイル表示の自動切換を有効化 @@ -1037,57 +1259,68 @@ エリアコード 3 ライブラリ No TV - 最も近くの大都市名゙を入力 - ビデオ/オーディオ/DVD キャッシュ - HDD - ビデオ キャッシュ - DVDRom - - ローカルネットワーク + 最も近くの大都市名を入力 + ビデオ/オーディオ/DVD キャッシュ - HDD + ビデオ キャッシュ - DVD-ROM + - LAN - インターネット - オーディオ キャッシュ - DVDRom - オーディオ キャッシュ - Local Network - オーディオ キャッシュ - Internet - DVD キャッシュ - DVDRom - DVD キャッシュ - Local Network + オーディオ キャッシュ - DVD-ROM + オーディオ キャッシュ - LAN + オーディオ キャッシュ - インターネット + DVD キャッシュ - DVD-ROM + DVD キャッシュ - LAN サーバー + ネットワーク設定が変更されました - 設定を反映する為に再始動が必要です - ネットワーク設定 今再始動しますか? + ネットワーク設定の変更を反映するには + 再起動が必要です。 今すぐ再始動しますか? + インターネット接続の帯域制限 + - プレー中でもシャットダウン %i 分 %i 秒 - %i ms + %i ミリ秒 %i %% %i kbps %i kb %i.0 dB - Time Format - Date Format - GUIフィルター + 時刻のフォーマット + 日付のフォーマット + GUI フィルター + バックグラウンドスキャンの使用 スキャン停止 メディア情報スキャン中は不可能 フィルム粒子エフェクト - Look for thumbs on remote shares - 不明なキャッシュ - Internet + リモート共有上でサムネールを使う + 不明なキャッシュ - インターネット 自動 ユーザー名入力 日付 & 時間 - 日付 設定 - 時間 設定 + 日付の設定 + 時刻の設定 24時間表示 時:分 で入力 日付 日/月/年 で入力 - IPアドレス入力 + IP アドレスを入力 この設定を適用しますか? 設定適用 ファイル名変更・削除 許可 - タイムゾーン + + タイムゾーン設定 サマータイム有効化 お気に入りに追加 お気に入りから削除 - スキンカラー + - スキンカラー + タイムゾーン(国) タイムゾーン ファイルリスト - EXIF情報を表示 + EXIF 情報を表示 + フルスクリーンウィンドウの使用 (「フルスクリーン」ではなく) + 選択した曲をキューに入れる + オーディオ CD を自動的に再生する 再生 + DVD + DVD を自動的に再生する 字幕に使用するフォント インターナショナル 文字セット @@ -1095,28 +1328,34 @@ セキュリティ 入力デバイス 省電力 - Remove - Games + + 削除 + ゲーム + 追加 - Password + + パスワード + ライブラリ データベース * すべてのアルバム * すべてのアーティスト * すべての曲 * すべてのジャンル + バッファリング... ナビゲーションサウンド スキン デフォルト - スキンテーマ - Default Theme - Last.FM - Submit songs to Last.FM - Last.FMユーザー名 - Last.FMパスワード + - テーマ + デフォルトテーマ + + Last.fm + Last.fm に曲を送信する + Last.fm ユーザ名 + Last.fm パスワード 操作不可: 停止中... - XBMCを更新してください - Bad authorisation: Check username and password + XBMC を更新してください + 認証に失敗: ユーザー名とパスワードを確認してください 接続しました 接続できません 送信間隔 %i @@ -1125,21 +1364,77 @@ 送信 %i 秒 ...を使用して再生 Use Smoothed A/V Synchronisation - Hide File Names in Thumbs View - Play in Party Mode - Libre.fmユーザー名 - Libre.fmパスワード + サムネールビューではファイル名を隠す + パーティーモードで再生 + Libre.fm ユーザー名 + Libre.fm パスワード + Libre.fm 楽曲送信 + + Last.fm ラジオを Last.fm に送信 + Last.fm に接続中... + ラジオ局を選択中... + 類似アーティストを検索... + 類似タグを検索... + あなたのプロフィール (%name%) + 人気のタグ + タグ %name% で人気のアーティスト + タグ %name% で人気のアルバム + タグ %name% で人気のトラック + タグ %name% の Last.fm ラジオを聴く + %name% の類似アーティスト + %name% のトップアルバム + %name% のトップトラック + %name% のトップタグ + %name% のトップファン + %name% のファンの Last.fm ラジオを聴く + %name% の類似アーティストの Last.fm ラジオを聴く + ユーザー %name% のベストアーティスト + ユーザー %name% のベストアルバム + ユーザー %name% のベストトラック + ユーザー %name% の友だち + ユーザー %name% のご近所さん + %name% の週刊アーティストチャート + %name% の週刊アルバムチャート + %name% の週刊トラックチャート + %name% のご近所さんの Last.fm ラジオを聴く + %name% の Last.fm ラジオを聴く + %name% の mix Last.fm ラジオを聴く + Last.fm からリストを取得中... + Last.fm からリスト取得に失敗... アーティスト名を入力し関連アイテム検索 タグ名を入力し類似アイテム検索 - パスが見つかりません or 無効です + %name% が最近聴いたトラック + %name% おすすめの Last.fm ラジオ + ユーザー %name% のトップタグ + + 現在再生中のトラックを Love トラックに追加しますか? + 現在再生中のトラックを Last.fm ライブラリから削除しますか? + Love トラックに追加: '%s' + '%s' を Love トラックに追加できませんでした。 + Last.fm ライブラリから削除: '%s'. + '%s' を Last.fm ライブラリから削除できませんでした。 + %name% が最近 Love トラックにした曲 + %name% が最近 Last.fm ライブラリから削除した曲 + Love トラックから削除 + ライブラリに戻す + このトラックを Love トラックから削除しますか? + このトラックをライブラリに戻しますか? + + パスが見つからないか、パスが無効です サーバーに接続できません サーバーが見つかりません ワークグループが見つかりません + + Opening multi-path source + パス: + 一般 + インターネット検索 プレイヤー - Play media from disc + ディスクからメディア再生 + 新しいタイトルを入力 動画名を入力 プロファイル名を入力 @@ -1148,68 +1443,236 @@ 新しいファイル名を入力 フォルダー名を入力 ディレクトリを入力 - 使用可能オプション: %A, %T, %N, %B, %D, %G, %Y, %F + 使用可能オプション: %A, %T, %N, %B, %D, %G, %Y, %F 検索文字列を入力 - None + なし 自動選択 インターレース解除 - ODDフィールド表示 - EVENフィールド表示 - インターレース処理 + ODD フィールド表示 + EVEN フィールド表示 + キャンセル中... アーティスト名を入力 プレイバックに失敗しました - 1つ以上のアイテムの再生に失敗しました + 1つ以上のアイテムの再生に失敗しました。 + 値を入力 + 詳しくはログファイルを参照して下さい。 + パーティーモードを終了しました。 + ライブラリには一致する曲はありませんでした。 + データベースを初期化できませんでした。 + データベースを開けませんでした。 + データベースから曲を取得できませんでした。 + パーティモードプレイリスト + インターレース解除 (Half) + ビデオのインターレース解除 + インターレース解除方法 + オフ + 自動 + オン + すべてのビデオ 未視聴 視聴済み 視聴済みにする 未視聴にする タイトルを編集 - 外部DVDプレイヤを使用 - 外部DVDプレイヤ指定 + + 処理が中断されました + コピーに失敗 + 1つ以上のファイルのコピーに失敗しました + 移動に失敗 + 1つ以上のファイルの移動に失敗しました + 削除に失敗 + 1つ以上のファイルの削除に失敗しました + + ビデオのリサイズ方式 + ニアレストネイバー + バイリニア + バイキュービック + Lanczos2 + Lanczos3 + Sinc8 + バイキュービック (ソフトウェア) + Lanczos (software) + Sinc (software) + Temporal + Temporal/Spatial + (VDPAU) ノイズリダクション + (VDPAU) シャープネス + 逆テレシネ (30fps => 24fps) + Lanczos3 最適化 + 自動 + Temporal (Half) + Temporal/Spatial (Half) + DXVA + DXVA Bob + DXVA Best + Spline36 + Spline36 optimized + Software Blend + + 後処理 + + ディスプレイスリープタイムアウト + + チャンネル切り替え + + + 保存されたミュージックのフォルダー + 外部 DVD プレーヤーを使用 + 外部 DVD プレーヤーの指定 スクリーンショットフォルダー設定 - プレイリストフォルダー設定 + + プレイリストフォルダー + 録音 + スクリーンショット + XBMC を使用 + ミュージックプレイリスト ビデオプレイリスト + ゲームを起動しますか? 並べ替え: プレイリスト サーバ上のサムネイル 現在のサムネイル ローカルサムネイル サムネイルなし サムネイルを選択 - - + + + + コンフリクト + 新規スキャン + 全てスキャン 地域 + + + 概要 + ミュージックウィンドウをロック + ビデオウィンドウをロック + ピクチャーウィンドウをロック + プログラム & スクリプトウィンドウをロック + ファイルマネージャーをロック + ロックの設定 + フレッシュ起動 + マスターモードに入る + マスターモードから抜ける + プロファイル '%s' を作成しますか? + 全設定を初期化して起動する + Best available + 16x9 と 4x3 を自動切り替え + Treat stacked files as single file + 注意 + マスターモードから抜けました + マスターモードに入りました + Allmusic.com サムネール + + サムネールの削除 + プロファイルの追加... + 全アルバムの情報を取得 + メディア情報 + Separate + Shares with default + Shares with default (read only) + Copy default + プロファイル画像 + プロファイルをロック + プロファイルの編集 + プロファイルのロック + フォルダの作成に失敗 + プロファイルフォルダー + メディアソース設定を初期化して起動する + 選択したフォルダーが書き込み可能であること、 + 新規フォルダ名が有効であることを確認してください。 MAPP評価 + マスターロックコードの入力 + 起動時にマスターロックコードを入力させる スキン設定 - 未設定 - - アニメーション表示有効化 - 音楽再生中はRSSを停止 - ショートカットボタン有効化 - スキンを拡大・縮小 + アニメーション表示を有効にする + 音楽再生中は RSS を停止 + ショートカットボタンを有効にする + メインメニューに「プログラム」を表示 + ミュージック情報を表示 + 天気予報情報を表示 + システム情報を表示 + Show available disc space C: E: F: + Show available disc space E: F: G: + 天気予報情報 + Drive space free + Enter the name of an existing share + Lock code + プロファイルの読み込み + プロファイル名 + メディアソース + プロファイルのロックコードを入力 + ログイン画面 + アルバム情報の取得中 + アルバムの情報を取得中 + CD 再生中に CD やトラックの読み込みはできません + マスターロックコードと設定 + Entering master lock code always enables master mode + それともデフォルト値からコピーしますか? + プロファイルに変更内容を保存しますか? + 古い設定が見つかりました。 + その古い設定を使いますか? + 古いメディアソースが見つかりました。 + Separate (locked) + Root + - スキンの拡大・縮小 + - Zoom + UPnP 設定 + UPnP クライアントの自動起動 + 最終ログイン: %s + ログイン履歴なし + プロファイル %i / %i + ユーザーログイン / プロファイルを選択 + ログインが面でロックを使用 + ロックコードが不正です。 + マスターロックの設定が必要です。 + いまここで設定しますか? + プログラム情報の読み込み中 パーティー開始! + True + Mixing drinks + Filling glasses + ログイン済: + ログオフ 一番上の階層へ + Weave + Weave (inverted) Blend + ビデオを再起動 ネットワーク上の場所を編集 ネットワーク上の場所を削除 - シャットダウンタイマ + フォルダをスキャンしますか? + メモリユニット + メモリユニットがマウントされました + メモリユニットをマウントできませんでした + ポート %i, スロット %i + スクリーンセーバーをロック + Set + ユーザー名 + パスワードを設定: + シャットダウンタイマー シャットダウンまでの時間 (単位:分) - タイマスタート, %i分後にシャットダウン + タイマースタート, %i分後にシャットダウン 30分後にシャットダウン 1時間後にシャットダウン 2時間後にシャットダウン - シャットダウンタイマを設定 - シャットダウンタイマをキャンセル + シャットダウンタイマーを設定 + シャットダウンタイマーをキャンセル + %s の設定をロック 参照... 概要情報 ストレージ情報 + ハードディスク情報 + DVD-ROM 情報 ネットワーク情報 ビデオ情報 ハードウェア情報 - Total - Used + 合計 + 使用済 of Locking Not Supported Not Locked @@ -1219,63 +1682,98 @@ Week Line Windowsネットワーク (SMB) - XBMSP Server - FTP Server - iTunes music share (DAAP) - UPnP Server - Show Video Info - Done + XBMSP サーバー + FTP サーバー + iTunes ミュージック共有 (DAAP) + UPnP サーバー + ビデオ情報を表示 + 完了 Shift Caps Lock - Symbols + 記号 Backspace Space スキンを再ロード - EXIF情報による画像の向き補正 + EXIF 情報による画像の向き補正 Use Poster View Styles for TV Shows お待ち下さい... - あらすじと批評で自動スクロールを有効化 - Custom - Enable debug logging + UPnP + + あらすじとレビューで自動スクロールを有効化 + カスタム + デバッグログ出力を有効にする + 更新時に追加情報をダウンロードする + アルバム情報取得用デフォルトサービス + アーティスト情報取得用デフォルトサービス スクレーパーを変更 ミュージックライブラリをエクスポート ミュージックライブラリをインポート + アーティストが見つかりませんでした! アーティスト情報の取得に失敗しました + + + パーティー開始! (ビデオ) - - - - - - - セカンダリDNS - DHCPサーバ: + Mixing drinks (videos) + Filling glasses (videos) + WebDAV サーバー (HTTP) + WebDAV サーバー (HTTPS) + 初回ログイン、プロファイルを編集して下さい + HTS Tvheadend クライアント + VDR Streamdev クライアント + MythTV クライアント + ネットワークファイルシステム (NFS) + セキュアシェル (SSH/SFTP) + Apple ファイル共有プロトコル (AFP) + + Web サーバーディレクトリ (HTTP) + Web サーバーディレクトリ (HTTPS) + フォルダに書き込みできません: + スキップして続けますか? + RSS フィード + + セカンダリ DNS + DHCP サーバ: + 新規フォルダー作成 + 再生中は LCD を暗くする + 不明、またはオンボード (protected) + 一時停止中に LCD を暗くする + ビデオ - ライブラリ + 並べ替え: ID + + Play part... + 設定のリセット + %s の設定値をリセットしてすべて + デフォルト値に戻します。 + Browse for destination + Movies are in separate folders that match the movie title + フォルダ名も検索対象にする ファイル - Use file or folder names in lookups? + ファイル名・フォルダ名を検索対象にしますか? コンテンツを設定 フォルダー - Look for content recursively? - Unlock Sources - Actor - Movie + コンテンツを再帰的に探索しますか? + ソースのロック解除 + 俳優 + 映画 監督 Do you want to remove all items within 映画 テレビ番組 このディレクトリが含むのは - Run Automated Scan + 自動スキャンを実行 再帰的スキャン as 監督 - No video files found in this path! + このパスにはビデオファイルがありませんでした! votes テレビ番組情報 エピソード情報 テレビ番組の詳細をロード中 - Fetching Episode Guide - Loading Info For Episodes In Directory + エピソードガイド取得中 + ディレクトリ内のエピソード情報を読み込み中 テレビ番組を選択: テレビ番組名を入力 シーズン %i @@ -1285,24 +1783,24 @@ エピソードをライブラリから削除 テレビ番組をライブラリから削除 テレビ番組 - Episode Plot + エピソードのあらすじ * 全シーズン 視聴済みを除外 Prod Code 未視聴アイテムのあらすじを表示する - * Hidden to prevent spoilers * + * あらすじ非表示 * シーズンサムネイル指定 - Season Image + シーズンイメージ シーズン 映画情報を取得中 Unassign Content テレビ番組情報を更新 すべてのエピソード情報を更新しますか? 選択したフォルダーにはテレビ番組1種類のみ含まれる - Exclude selected folder from scans - Specials + 選択したフォルダーをスキャン対象から除外する + スペシャル シーズンサムネイルの自動取得 - Selected folder contains a single Video + 選択したフォルダにはビデオが1つだけあります テレビ番組とリンクを設定 テレビ番組とのリンクを解除 最近追加された映画 @@ -1315,74 +1813,106 @@ 音楽ビデオ情報 音楽ビデオ情報を取得中 Mixed - Go To Albums by Artist - Go To Album - Play Song - Go To Music Videos from Album - Go To Music Videos by Artist - Play Music Video + アーティスト別アルバムへ + アルバムへ + 曲を再生 + アルバムのミュージックビデオへ + アーティストのミュージックビデオへ + ミュージックビデオを再生 ライブラリ追加時に俳優のサムネイルを取得する 俳優のサムネイルを指定 - Remove Episode Bookmark - Set Episode Bookmark + + エピソードブックマークを削除 + エピソードブックマークを設定 スクレーパー設定 音楽ビデオ情報を取得中 テレビ番組情報を取得中 予告 フラット化 テレビ番組のフラット化 - Fanartを取得 - ビデオ及び音楽ライブラリでFanartを表示する + Fanart を取得 + ビデオ及び音楽ライブラリで Fanart を表示する 新しいコンテンツをスキャン中 初回放映 脚本家 Clean File and Folder Names - Never + Replace file names with library titles + + しない 1シーズンのみの場合 常に - Has Trailer + 予告編あり False - Fanart Slideshow + Fanart スライドショー Export to a single file or separate files per entry? Single file Separate Export thumbs and fanart? - Overwrite old files? + 古いファイルを上書きしますか? ライブラリの更新から除外 - Fanartを選択 + Fanart を選択 + ローカル Fanart + Fanart なし + 現在の Fanart + リモート Fanart + コンテンツを変更 + Do you want to refresh info for all + items within this path? + Fanart + Locally stored information found. + Ignore and refresh from internet? 情報を取得できませんでした + Unable to connect to remote server + Would you like to continue scanning? + Countries + episode + episodes + Listener + Listeners + Set movieset fanart + Movie set + Group movies in sets + + + 隠しファイル/フォルダーを表示 - TuxBox Client + + TuxBox クライアント WARNING: Target TuxBox device is in Recording-Mode! The Stream will be Stopped! Zap to Channel: %s Failed! Are you sure to start the stream? Connecting to: %s TuxBox Device - Add Media Share... - UPnPサーバ有効化 - Edit Media Share - Remove Media Share + + + メディア共有を追加... + ビデオ/ミュージックライブラリを UPnP 経由で共有 + + メディア共有を編集 + メディア共有を削除 字幕フォルダー設定 Movie & Alternate Subtitle Directory - マウス有効化 + Override ASS/SSA subtitles fonts + + マウス・タッチスクリーンの有効化 再生時もナビゲーションサウンドを有効化 - Thumbnail - Forced DVD Player Region + サムネール + DVD Player リージョンの強制指定 ビデオ出力 アスペクト比 - Normal - Letterbox - Widescreen - 480p有効化 - 720p有効化 - 1080i有効化 - Enter Name of New Playlist + ノーマル + レターボックス + ワイドスクリーン + 480p 有効化 + 720p 有効化 + 1080i 有効化 + 新規プレイリスト名を入力 ソース追加ボタンを無効 スクロールバー表示 視聴済み除外ボタンをビデオライブラリに追加 - Open + 開く Acoustic Management Level Fast Quiet @@ -1392,11 +1922,11 @@ Low Power High Standby Low Standby - Unable to cache files bigger than 4 gb - Chapter + 4GB 以上のファイルはキャッシュできません + チャプター High Quality Pixel Shader V2 起動時後プレイリストを再生 - Tweenアニメーション有効化 + Tween アニメーション有効化 contains does not contain is @@ -1423,64 +1953,84 @@ one or more of the rules Limit to No Limit - Order by - ascending - descending - Edit Smart Playlist - Name of the playlist + 並べ替え + 昇順 + 降順 + スマートプレイリストの編集 + プレイリスト名 Find items where - Edit - %i items - New Smart Playlist... - %c Drive - Edit Party Mode Rules - Watched count - Episode Title - File Name - File Path - File Size - File Date/Time + 編集 + %i アイテム + 新規スマートプレイリスト... + %c ドライブ + パーティモードルールの編集 + 試聴回数 + エピソードタイトル + ビデオの解像度 + オーディオチャンネル + ビデオコーデック + オーディオコーデック + 音声言語 + 字幕言語 + リモコンによるキーボード入力 + - 編集 + インターネット接続が必要です。 + Get More... + Root filesystem + Cache full + Cache filled before reaching required amount for continous playback + + 字幕の場所 + Fixed + Bottom of video + Below video + Top of video + Above video + ファイル名 + ファイルのパス + ファイルサイズ + ファイルの日付 Slide Index - Resolution - Comment - Colour/bw - Jpeg Process - Date/Time - Description - Camera Make - Camera Model - Exif Comment - Firmware - Aperture - Focal Length - Focus Distance - Exposure - Exposure Time - Exposure Bias - Exposure Mode - Flash Used - Whitebalance - Light Source - Metering Mode + 解像度 + コメント + カラー/白黒 + JPEG 処理 + 日時 + 説明 + カメラのメーカー + カメラのモデル名 + EXIF コメント + ファームウェア + 絞り + 焦点距離 + ピント位置 + 露出 + 露出時間 + 露出バイアス + 露出モード + フラッシュの有無 + ホワイトバランス + 光源 + 測光方式 ISO - Digital Zoom - CCD Width - GPS Latitude - GPS Longitude - GPS Altitude - Orientation - Supplemental Categories - Keywords - Caption - Author - Headline + ディジタルズーム + CCD の横幅 + GPS 緯度 + GPS 経度 + GPS 高度 + 写真の向き + 追加カテゴリ + キーワード + キャプション + 作者 + ヘッドライン Special Instructions - Category + カテゴリー Byline Byline Title - Credit - Source - Copyright Notice + クレジット + ソース + 著作権情報 Object Name City State @@ -1490,59 +2040,340 @@ Copyright Flag Country Code Reference Service - Enable UPnP Renderer - Attempt to skip introduction before DVD Menu - Ripped Audio CDs - Query Info For All Artists + UPnP 経由でのXBMC の操作を許可 + DVD メニューより前のイントロ部分をスキップ (可能な場合) + Saved music + 全アーティストの情報を検索 アルバム情報を取得中 アーティスト情報を取得中 - Biography - Discography - Searching Artist - Select Artist + バイオグラフィー + ディスコグラフィー + アーティストの検索 + アーティストを選択 アーティスト情報 + 楽器 + 生まれ + 結成 + テーマ + 解散 + 死去 + アクティブな期間 + レーベル + 生誕/結成 + + + 開始時にライブラリを更新 ライブラリの更新状況を表示しない - DNSサフィックス + + %2.3fs Delayed by: %2.3fs Ahead by: %2.3fs 字幕オフセット - OpenGLベンダー: - OpenGLレンダラー: - OpenGLバージョン: - GPU温度: - CPU温度: + OpenGL ベンダー: + OpenGL レンダラー: + OpenGL バージョン: + GPU 温度: + CPU 温度: 合計メモリー - Profile Data + プロファイルデータ + ビデオ再生中に一時停止したら画面を暗くする + 全録音 + タイトル順 + グループ順 + ライブチャンネル + タイトル順録音 + ガイド + Allowed error in aspect ratio to minimize black bars + Show video files in listings + DirectX ベンダー: + Direct3D バージョン: + + + フォント + - サイズ + - 色 + - 文字セット + カラオケタイトルをエクスポート (HTML) + カラオケタイトルをエクスポート (CSV) + カラオケタイトルのインポート... + Show song selector automatically + カラオケタイトルのエクスポート... + Enter song number + 白/緑 + 白/赤 + 白/青 + 黒/白 + デフォルトの動作 + 選択 + 情報を表示 さらに... + 全て再生 + + Teletext not available + Activate Teletext + Part %i + Buffering %i bytes + Stopping + Running + + + External Player Active + Click OK to terminate the player + + Click OK when playback has ended + アドオン アドオン アドオン設定 アドオン情報 + + メディアソース + ムービー情報 スクリーンセーバー + スクリプト + 視覚エフェクト アドオン レポジトリ + 字幕 + 歌詞 + TV 情報 + ミュージックビデオ情報 + アルバム情報 + アーティスト情報 + サービス + + 設定 + 無効 + 有効 アドオン無効 - 設定できないアドオン + 天気 + Weather.com (標準) + このアドオンは設定できません + 設定の読み込みに失敗 すべてのアドオン アドオン取得 + アップデートの確認 + 強制的にリフレッシュ + 変更履歴 + アンインストール + インストール 無効なアドオン - zipファイルからインストール + (現在の設定をクリア) + zip ファイルからインストール ダウンロード中 %i%% - 有効なアドオン - このアドオンを有効化しますか? - このアドオンを無効化しますか? - アドオンのアップデートが可能! + 利用可能なアップデート + 依存関係が満たされません + アドオンが正しい構造になっていません + %s は以下のインストール済のアドオンに使われています + このアドオンはアンインストールできません + ロールバック + + 利用可能なアドオン + バージョン: + 注意書き + ライセンス: + 変更履歴 + このアドオンを有効にしますか? + このアドオンを無効にしますか? + アドオンのアップデートがあります! 有効なアドオン 自動更新 - アドオン有効 - アドオン更新 - アドオンのダウンロードをキャンセル? + アドオンが有効になりました + アドオンが更新されました + アドオンのダウンロードをキャンセルしますか? 現在ダウンロード中のアドオン + アップデート可能 + アップデート + + アドオンを読み込めませんでした。 + 原因不明のエラーが発生しました。 + 設定が必要 + 接続不可 + 再起動が必要 + 無効化 + 必要なアドオン + 最接続しますか? + アドオンの再起動 + アドオンマネージャをロック + + (現在) + (ブラックリスト) + Add-on has been marked as broken in repository. + このシステム上で無効にしますか? + Broken + このスキンに切り替えますか? + この機能を使うには以下のアドオンのダウンロードが必要です: + このアドオンをダウンロードしますか? 通知 + + ライブラリモード QWERTYキーボード パススルーオーディオ使用中 + + + + + + 予告編の品質 + ストリーム + ダウンロード + ダウンロードして再生 + ダウンロードして保存 + 今日 + 明日 + Saving + Copying + ダウンロードフォルダの指定 + Search duration + Short + Long + 通常のプレーヤーの代わりに DVD プレーヤーを使用 + ビデオ再生前にダウンロードするか確認する + クリップ + プラグインを再起動して有効にする + 今夜 + 明日の夜 + Condition + 降雨量 + 降雨量 + Humid + Feels + Observed + Departure from normal + Sunrise + 日没 + Details + Outlook + カバーフロー + テキストを翻訳 + Map list %s category + 36 Hour + マップ + 時間ごと + 週末 + %s日 + アラート + アラート + 選択する: + チェック: + 設定する: シーズン + 使用: + 観る: + 聴く: + 見る: + 設定する: + Power メニュー + 再生する: + オプション + エディター + About your + 星の評価 + バックグラウンド + バックグラウンド + カスタムバックグラウンド + カスタムバックグラウンド + README をみる + Changelog をみる + このバージョンの %s は + XBMC リビジョン %s またはより新しい版が必要です。 + XBMC をアップデートしてください。 + データが見つかりません! + 次のページ + Love + Hate + This file is stacked, select the part you want to play from. + スクリプトのパス + カスタムスクリプト用ボタンを有効にする + + 起動に失敗しました: + Web サーバー + イベントサーバー + リモートコミュニケーションサーバー + + 新規コネクションを検出 + + + + + スピーカー設定 + 2.0 + 2.1 + 3.0 + 3.1 + 4.0 + 4.1 + 5.0 + 5.1 + 7.0 + 7.1 + + + 次のアイテムがありません + 一つ前のアイテムがありません + + Zeroconf 起動に失敗 + Apple の Bonjour サービスはインストールされていますか? 詳しくはログを参照して下さい。 + + ビデオレンダリング + ビデオフィルタ/リサイズの初期化に失敗しました。代わりにバイリニアスケーリングを行います。 + オーディオデバイスの初期化に失敗 + オーディオ設定を見直してください + + 周辺機器 + + 汎用 HID デバイス + 汎用ネットワークアダプタ + 汎用ディスク + この周辺機器用の設定はありません。 + 新しいデバイスが設定されました + デバイスが取り外されました + このデバイスで使うキーマップ + キーマップ有効 + このデバイスではカスタムキーマップを使わないで下さい + + Location + Class + Name + Vendor + Product ID + + Pulse-Eight CEC アダプタ + Pulse-Eight Nyxboard リモコン + Switch to keyboard side command + Switch to remote side command + Press "user" button command + Enable switch side commands + アダプタをオープンできませんでした + XBMC 起動時に電源を入れるデバイス + XBMC 終了時に電源を切るデバイス + スクリーンセーバー動作中にデバイスをスタンバイモードにする + + CEC ポートが検出できませんでした。手動で設定してください。 + + CEC アダプタの初期化に失敗しました。設定を見直してください。 + この libCEC インターフェースバージョンは未サポートです。%d は、XBMC がサポートするバージョン %d より大きいバージョン番号です。 + TV の電源が落とされたら PC をスタンバイモードにする + HDMI ポート番号 + 接続完了 + アダプタはありますが libCEC がありません + TV の言語設定を使ってください + HDMI デバイスに接続しました + 起動時に XBMC をアクティブソースにする + 物理アドレス (HDMI ポートを上書き) + COM ポート (不要であれば空欄に) + 設定が変更されました + 設定変更に失敗しました。設定内容を確認してください。 + XBMC 終了時に'非アクティブソース'コマンドを送信 diff --git a/language/Polish/strings.xml b/language/Polish/strings.xml index ac07e8e..21ecd37 100644 --- a/language/Polish/strings.xml +++ b/language/Polish/strings.xml @@ -1369,7 +1369,241 @@ Lanczos3 (zoptymalizowany) Auto Wyświetlaj odliczanie czasu uśpienia - Wybierz kanał + + + Przełącz na kanał + Osobne wyrazy wyszukiwania za pomocą AND, OR lub NOT. + lub wyrażenia użyć w celu znalezienia dokładnego dopasowania, jak "Czarnoksiężnik z krainy Oz ". + Znajdź podobny program + Importowanie EPG od klientów + PVR informacje o strumieniu + Urządzenie odbiorcze + Aktualizacja statusu urządzenia + Jakość sygnału + SNR + BER + UNC + PVR Backend + Niekodowanych + Fixed + Kodowanie + PVR Backend %i - %s + Nagrania TV + Domyślny folder dla miniatur PVR + Kanały + TV + Radio + Ukryte + Kanały TV + Kanały Radiowe + Nadchodzące nagrania + Dodaj timer... + Brak wyników wyszukiwania + Brak wpisów EPG + Kanał + Teraz + Następny + Linia czasu + Informacje + Już rozpoczął nagrywanie na tym kanale + Ten kanał nie może być odtwarzany. Sprawdź dziennik(log) + To nagranie nie może być odtworzone. Sprawdź dziennik(log). . + Pokaż jakość sygnału + Nie jest obsługiwany przez PVR backend. + Czy na pewno chcesz ukryć ten kanał? + Timer + Czy na pewno chcesz zmienić nazwę tego nagrania + Czy na pewno chcesz zmienić nazwę tego timer-a? + Nagrywanie + Proszę sprawdzić konfigurację lub dziennik(log) + Żaden klient PVR nie urchomił sie. Poczekaj na start klientów PVR lub sprawdz dziennik(log). + Nowy kanał + Informacje o programie + Zarządzanie Grupami + Pokaż kanał + Pokaż widoczne kanały + Pokaż ukryte kanały + Przenieść kanał do: + Informacje o nagrywaniu + Ukryj kanał + Brak dostępnych informacji + Nowy timer + Edytuj timer + Timer aktywny + Zatrzymaj nagrywanie + Usuń timer + Dodaj timer + Sortuj według: Kanał + Idź do początku + Idź do końca + Domyślnie okno EPG + Ładowanie nagrań od klientów + To wydarzenie jest już zarejestrowane. + Nie można skasować tego nagrania. Sprawdź dziennik(log) + EPG + EPG skanowanie timeout + EPG skanuj co: + Nie przechowywać w bazie danych EPG + Opóźnienie przełączania kanałów + Active: + Nazwa: + Folder: + Radio: + Kanał: + Day: + Rozpoczęcie: + Koniec: + Priorytet: + Lifetime (dni): + Dzień pierwszy: + Brak kanału %u + Pn-__-__-__-__-__-__ + __-Wt-__-__-__-__-__ + __-__-Śr-__-__-__-__ + __-__-__-Czw-__-__-__ + __-__-__-__-Pt-__-__ + __-__-__-__-__-Sob-__ + __-__-__-__-__-__-Niedz + Pn-Wt-Śr-Czw-Pt-__-__ + Pn-Wt-Śr-Czw-Pt-Sob-__ + Pn-Wt-Śr-Czw-Pt-Sob-Niedz + __-__-__-__-__-Sob-Niedz + Wprowadź nazwę nagrania + Uwaga + Timer obecny + Czy na pewno chcesz usunąć ten kanał, w tym wszystkie timer-y na tym kanale?? + Ten kanał jest obecnie używany do oglądania. + Proszę przełączyć na inny kanał. + Przeszukaj brakujące IKONY + Wprowadź nazwę folderu do zapisu + Rozmiar: + Następny timer + w + Nagrania nie zsynchronizowane. Sprawdź dziennik(log). + Nie można zapisać timer-a. Sprawdź dziennik(log). + Wystąpił nieoczekiwany błąd. Spróbuj ponownie później lub sprawdzić dziennik(log) + Błąd PVR backend. Sprawdź dziennik(log). + Timer-y nie zsynchronizowane. Sprawdź dziennik(log). + Dalej + Wersja + Adres + Rozmiar dysku + Wyszukiwanie kanałów + Nie można użyć funkcji PVR podczas wyszukiwania. + Na którym serwerze chcesz szukać? + Numer klienta + Unikać powtórzeń + Timer jest w czasie nagrywania. Czy na pewno chcesz usunąć ten timer? + Tylko kanały FTA + Ignoruj obecne timer-y + Ignoruj obecne nagrywania + Czas rozpoczęcia + Czas zakończenia + Data rozpoczęcia + Data zakończenia + Minimalny czas trwania + Maksymalny czas + Dołącz nieznane gatunki + Szukany ciąg + Dołącz opis + Case sensitive + Kanał niedostępny + Brak zdefiniowanych grup + Prosze utowrzyć najpierw grupe + Nazwa nowej grupy + Group + Przewodnik szukania + Zarządzanie Grupą + Brak zdefiniowanych grup + Zgrupowane + Grupy + PVR backend nie obsługuje tego działania. Sprawdź dziennik(log). + Kanał + Pn + Wt + Śr + Czw + Pt + Sob + Niedz + z + Następne nagranie + Aktualne nagranie + z + do + Na + Nagrywanie aktywne + Nagrania + Nie można rozpocząć nagrywanie. Sprawdź dziennik(log) + Przełącz + PVR informacje + Skanuj w poszukiwaniu brakujących IKON + Przełączaj kanał bez naciskania OK + Ukryj okno informacyjne o video + Timeout przy uruchamianiu odtwarzania + Uruchom zminimalizowany + Czas nagrywania w locie + Domyślny priorytet nagrywania + Domyślny lifetime nagrywania + Margines na początku nagrywania + Margines na końcu nagrywania + Odtwarzanie + Pokaż informacje o kanale przy przełączaniu kanałów + Automatyczne ukrywanie informacji o kanale + TV + Menu/OSD + Dni do wyświetlenia w EPG + Czas trwania informacji o kanale + Zresetowania bazy danych PVR + Wszystkie dane w bazie danych PVR są usuwane + zresetowania bazy danych EPG + Dane EPG są usuwane + Zacznij od ostatniego oglądanego kanału + Zminimalizowane + Usługi PVR + Brak podłączonych backend-ów PVR obsługujących skanowanie kanałów + wyszukiwanie kanałów nie można uruchomić. Sprawdź dziennik(log) + Kontynuować? + Działania klienta + PVR client specific actions + Nagrywanie rozpoczęło się o: %s + Zakończeniu nagrywania o: %s + Manager kanałów + EPG źródło: + Nazwa kanału: + Ikona kanału: + Edytuj kanał + Nowy kanał + Zarządzanie Grupą + Aktywuj EPG: + Grupa: + Wprowadź nazwe nowego kanału + XBMC wirtualny backend + Klient + Usuń kanał + Ta lista zawiera zmiany + Wybierz backend + Wprowadź prawidłowy adres URL dla nowego kanału + PVR backend nie wspiera timer-ów. + Wszystkie kanały radiowe + Wszystkie kanały TV + Widoczne + Niezgrupowane kanały + Kanały w + Zsychronizuj grupy kanałów z backend-em + EPG + Wtyczka PVR nie może zostać uruchomiona. Sprawdź ustawienia lub uzyskać więcej informacji z dziennik(log) + Nagrywanie zostało przerwane + nagrywanie zaplanowane + Rozpoczęło się nagrywanie + Nagrywanie zakończone + Nagrywanie usunięte + Zamykaj OSD kanału po przełączniu + Zapobieganie aktualizacji EPG podczas odtwarzania strumienia TV + Zawsze używaj kolejność kanałów z backend-u/ów + Wyczyść wyniki wyszukiwania + Wyświetl powiadomienie aktualizacji timer-a + Katalog zapisywanej muzyki Użyj zewnętrznego odtwarzacza DVD Zewnętrzny odtwarzacz DVD @@ -2092,6 +2326,17 @@ Serwer zdalnej komunikacji Wykryto nowe połączenie System głośników + 2.0 + 2.1 + 3.0 + 3.1 + 4.0 + 4.1 + 5.0 + 5.1 + 7.0 + 7.1 + Nie mogę znaleźć następnej pozycji do odtworzenia Nie mogę znaleźć poprzedniej pozycji do odtworzenia Błąd podczas startu zeroconf @@ -2127,4 +2372,4 @@ Połączono Znaleziono adapter, ale brak biblioteki libcec Użyj ustawienia języka z TV - \ No newline at end of file + diff --git a/language/Russian/langinfo.xml b/language/Russian/langinfo.xml index 326cb34..19bed3b 100644 --- a/language/Russian/langinfo.xml +++ b/language/Russian/langinfo.xml @@ -1,4 +1,4 @@ - + utf-8 @@ -18,4 +18,24 @@ mps + + The + A + An + Der + Die + Das + Le + La + Les + Un + Une + Des + Il + Lo + La + Gli + Uno + Una + \ No newline at end of file diff --git a/language/Russian/strings.xml b/language/Russian/strings.xml index 85d2985..f5d6557 100644 --- a/language/Russian/strings.xml +++ b/language/Russian/strings.xml @@ -1,6 +1,5 @@ - Программы Фотографии @@ -54,7 +53,7 @@ окт. нояб. дек. - + С ССВ СВ @@ -876,9 +875,15 @@ Скрипты Веб-браузер + Видео + Видео/плейлист + Экран входа + Настройки - Профили + Браузер дополнений + Диалог "Да/Нет" Диалог выполнения @@ -935,6 +940,9 @@ 8 9 c + Ok + * + Ок * Заблокировано. Введите код… @@ -1019,7 +1027,7 @@ Фильтр мерцания По выбору драйвера (требуется перезапуск) - + Вертикальная синхронизация Отключена Только при просмотре видео @@ -1067,11 +1075,11 @@ Профили Удалить профиль "%s"? - + Последний загруженный профиль: Неизвестно Перезаписать - + Таймер напоминаний Период таймера напоминаний (в мин.) Запущен; сработает через %i мин. @@ -1172,7 +1180,7 @@ Выбрать эскиз исполнителя Создавать эскизы Включить микрофон - + Включить устройство Громкость Основной режим просмотра @@ -1496,7 +1504,7 @@ Выкл. Авто Вкл. - + Все видео Не просмотрено Просмотрено @@ -1537,12 +1545,427 @@ Spline36 Оптимизир. Spline36 Blend (программный) - + Постобработка Переход дисплея в спящий режим через + + %i MiByte + %i часов + %i дней + + Переключиться на канал + Разделяйте различные слова для поиска, используя AND, OR и/или NOT. + Или используйте фразы для полнотекстового поиска, например: "Аццкий Сотона". + Найти похожую программу + Загрузить EPG из клиентов + Информация о потоке PVR + Принимающее устройство + Статус приема + Качество сигнала + SNR + BER + UNC + Backend + Free To Air + Фиксированно + Раскодирование + Сервер %i - %s + Записи ТВ + Основная папка для миниатюр ТВ каналов + Каналы + ТВ + Радио + Скрытые + ТВ каналы + Каналы радио + Будущие записи + Добавить таймер... + Нет результатов + Нет информации ТВ Гида + ТВ Гид + Текущее + Следующее + Шкала времени + Информация + Запись учже начата + Канал не может быть проигран + Запись не может быть проиграна + Показать качество сигнала + Сейчас не поддерживается! + Подтвердить скрытие канала + Таймер + Переименовать запись? + Переименовать таймер? + Запись + Пожалуйста проверьте настройки Backend + Нет доступных PVR клиентов + Новый канал + Информация о программе + Управление группами + Показать канал + Показать обычные каналы + Показать скрытые каналы + Переместить в: + Информация о записи + Спрятать канал + Информация недоступна! + Новый таймер + Правка таймера + Вкл/Выкл таймер + Остановить запись + Удалить таймер + Новый таймер + Сортировка: Каналы + В начало + В конец + Основная программа гида + Загрузить информацию о записи из клиента + Таймер уже установлен на это время + Нельзя удалить запись! + ТВ-Гид + Тайм-аут сканирования ТВ-Гида + Тайм-аут обновления ТВ-Гида + Игнорировать базу ТВ Гида PVR-сервера + Тайм-аут запуска канала + Активный: + Имя: + Директория: + Радио: + Канал: + День: + Начало: + Конец: + Приоритет: + Время жизни (дн): + Первый день: + Незнакомый канал %u + Пн-__-__-__-__-__-__ + __-Вт-__-__-__-__-__ + __-__-Ср-__-__-__-__ + __-__-__-Чт-__-__-__ + __-__-__-__-Пт-__-__ + __-__-__-__-__-Сб-__ + __-__-__-__-__-__-Вс + Пн-Вт-Ср-Чт-Пт-__-__ + Пн-Вт-Ср-Чт-Пт-Сб-__ + Пн-Вт-Ср-Чт-Пт-Сб-Вс + __-__-__-__-__-Сб-Вс + Введите имя записи + Внимание + Текущий таймер + Удалить канал и таймер? + Канал просматривается + Пожалуйста переключите канал! + Поиск пропавших миниатюр + Введите директорию для записей + Размер: + След. таймер в + в + Запись не синхронна! + Нельзя сохранить таймер! + Пробовать снова... + Ошибка сервера! + Таймеры не синхронны! + Далее + Версия + Адрес + Размер + Поиск каналов + Невозможно выполнить во время поиска каналов! + На каком сервере хотите искать? + Номер клиента + Избежать повторов + Таймер еще записывает - удалить? + Free-To-Air only + Игнорировать текущие таймеры + Игнорировать текущие записи + Время старта + Время останова + Дата старта + Дата останова + Мин. длительность + Макс. длительность + Включать неизвестные жанры + Строка поиска + Включать описание + Учесть регистр + Канал недоступен + Группы неопределены + Пожалуйста создайте первую + Имя новой группы + Все каналы + Группы + Гид по поиску + Управление группами + Без групп + В группе + Группы + Несовместимый PVR-Server! + Канал + Пн + Вт + Ср + Чт + Пт + Сб + Вс + с + Следующая запись + Текущая запись + с + до + В + Идет запись + Записи + Нельзя начать запись + Переключить + Информация PVR + Поиск потерянных ярлыков + Переключение канала без нажатия OK + Спрятать информационный блок о длине видео + Тайм-аут сканирования кааналов + Запустить минимизированным + Время для мгновенной записи + Приоритет по-умолчанию + Время жизни по-умолчанию + Интервал записи до времени старта + Интервал записи после окончания + Повтор + Показывать информацию при переключении канала + Timeout requested channel info + ТВ + Меню / OSD + Количество отображаемыемых в ТВ Гиде дней + Время задержки для ТВ Гида + Время показа информации о канале + Очистить базу данных ТВ + Вся информация из базы удалена + Удалить данные ТВ-Гида и получить новые + EPG стерто + Показать последний просматриваемый канал при старте + Мини + PVR service + Сканирование каналов не поддерживается сервером + Сканирование каналов не может быть запущено + Продолжить? + Действия клиента + Специальные действия клиента PVR + Запись начата в: %s + Запись закончена в: %s + Управление каналами + Источник EPG: + Имя канала: + Ярлык канала: + Редактировать + Новый канал + Управление группами + Активировать EPG: + Группа: + Введите имя канала + Виртуальный канал XBMC + Клиент + Удалить канал + Список изменений + Выберите клиент канала + Введите верный URL! + PVR-Server не поддерживает таймеры! + + Другой/Неизвестен + Фильм/Драма + Детектив/Триллер + Приключения/Вестерн/Война + Наука/Фэнтези/Ужасы + Комедия + Мелодрамма/Быт + Романтика + Классика/Религия/История/Драма + Для взрослых/Драма + + + + + + + + Новости/События + Новости/Погода + Новости + Документалистика + Дискуссии/Интервью/Дебаты + + + + + + + + + + + + Шоу/Игровое шоу + Игровое шоу/Состязания + Различные шоу + Говорильня + + + + + + + + + + + + + Спорт + События + Спортивные события + Футболл + Теннис/Сквош + Командный спорт + Атлетика + Мотоспорт + Водный спорт + Зимний спорт + Equestrian + Боевые искуства + + + + + Детские/Юношеские программы + Для дошкольников + Развлекательные программы с 6 до 14 лет + Развлекательные программы с 11 до 16 лет + Информационный/Обучающий + Мультфильмы/Куклы + + + + + + + + + + + Музыка/Балет/Танцы + Рок/Попса + Классическая музыка + Народная музыка + Опера + Балет + + + + + + + + + + + Искуство/Культура + Перформанс + Прикладное искуство + Религия + Популярное искуство + Литература + Фильм/Кино + Экспериментальное видео + Широковещательный + New Media + Искуство/Культура + Мода + + + + + Политика/Экономика + Журналы/Сообщения/Документалистика + Экономика/Социальна ясфера + Жизнь замечательных людей + + + + + + + + + + + + + Обучение/Наука + Природа/Животные/Окружающая среда + Технологии/Естественные науки + Медицина/Физиология/Психология + Заграница/Путешествие + Социум/Спиритические науки + Образование + Языки + + + + + + + + + Отдых/Хобби + Туризм/Путешествия + Сделай сам + Инженерия + Фитнес и здоровье + Кулинария + Advertisement/Shopping + Gardening + + + + + + + + + Спец. характеристики + В оригинале + Черно-белое + Неизданное + Прямой эфир + + + + + + + + + + + + Драма + Детектив/Триллер + Приключения/Вестерн/Война + Наука/Фэнтези/Ужасы + Комедия + Мыло/Мелодрамма/Фольклор + Романтика + История/Религия + Для взрослых + + + + + + + Папка сохраненной музыки Использовать внешний проигрыватель DVD @@ -1773,7 +2196,7 @@ Это сбросит калибровочные значения для %s до значений по умолчанию Укажите назначение - + Файлы в отдельных папках с названием фильма Использовать имена папок для поиска Файл Использовать имена файлов или папок для поиска? @@ -1863,7 +2286,7 @@ Премьера Сценарий - Показывать метаданные в представлении файлов + Показывать названия из медиатеки вместо имен файлов Никогда Если один сезон @@ -1925,7 +2348,7 @@ Папка субтитров Папка для фильмов и альтернативных субтитров Игнорировать шрифты субтитров ASS/SSA - + Включить мышь и сенсорный экран Звуки интерфейса во время проигрывания Эскизы @@ -2013,7 +2436,7 @@ Корневая ФС Кэш заполнен Объем кэша недостаточен для непрерывного проигрывания - + Расположение субтитров Фиксированное Снизу видео @@ -2329,7 +2752,7 @@ Веб-сервер Сервер событий Сервер удаленного доступа - + Обнаружено новое подключение @@ -2355,10 +2778,10 @@ Не удается найти следующий файл Не удается найти предыдущий файл - + Не удалось запустить zeroconf Проверьте, установлена ли служба Apple Bonjour. См. журнал. - + Обработчик видео Не удалось активировать фильтры видео. Используется масштабирование bilinear. Не удалось активировать аудиоустройство @@ -2380,7 +2803,7 @@ Название Производитель ID продукта - + Адаптер Pulse-Eight CEC Pulse-Eight Nyxboard Включить дополнительные команды клавиатуры diff --git a/language/Slovak/strings.xml b/language/Slovak/strings.xml index 64f3e4e..becb3a0 100644 --- a/language/Slovak/strings.xml +++ b/language/Slovak/strings.xml @@ -1,1600 +1,1376 @@ - + - + Programy Obrázky Hudba - Video - + Videá TV program Nastavenia + XBMC SVN Správca súborov Počasie xbmc media center Pondelok - Utorok Streda Štvrtok Piatok Sobota Nedeľa - Január Február Marec Apríl Máj Jún - Júl August September Október November December - Po Ut St Št Pi So - Ne Jan Feb Mar Apr Máj - Jún Júl Aug Sep Okt Nov - Dec S SSV SV VSV V - VJV JV JJV J JJZ JZ - ZJZ Z ZSZ SZ SSZ premenlivé - Zobrazenie: Auto Zobrazenie: Auto veľké Zobrazenie: Ikony Zobrazenie: Zoznam Prezrieť Usporiadať: Názov - Usporiadať: Dátum Usporiadať: Veľkosť Nie Áno Prezentácia Vytvoriť náhľady - Vytvoriť náhľady Skratky PAUZA Akualizácia sa nepodarila Inštalácia sa nepodarila Kopírovať - Presunúť Vymazať Premenovať Nový priečinok Potvrdenie kopírovania Potvrdenie presunutia - Potvrdenie vymazania Kopírovať tieto súbory? Presunúť tieto súbory? Vymazať tieto súbory? - Stav - Objekty - + Priebeh + Objekt(ov) Všeobecné Prezentácia Systémové informácie Obrazovka - Album - Interprét - - Skladba - Štýl/Žáner - Playlist-y + Albumy + Interpréti + Skladby + Žánre + Playlisty Hľadať SYSTÉMOVÉ INFORMÁCIE Teploty: - CPU: GPU: Čas: - Aktuálny stav: + Aktuálne: Build: Sieť: - Typ: Statická DHCP MAC IP - Prepojenie: - + Stav: Polovičný duplex Plný duplex - Úložisko - Jednotka - Voľných + Kapacita + Disk + Voľné miesto Video - Voľná pamäť Žiadne prepojenie Voľné - Nedostupný + Nedostupné Vysunúť disk Čítam - - Žiaden disk - Disk dostupný + Žiadny disk + Disk vložený Vzhľad Rozlíšenie - Prispôsobiť obnovovaciu frekvenciu obrazovky k videu - Dátum vydania: - - Zobrazenie 4:3 videa + Prispôsobovať obnovovaciu frekvenciu obrazovky podľa videa + Dátum vydania + Zobrazovať 4:3 videa Charakter: Štýly Skladba Dĺžka - Výber albumu - - Stopy + Vyberte albumu + Skladby Recenzia Obnoviť Vyhľadávanie albumu OK Albumy nenájdené! - Vybrať všetko Získavanie informácií o médiu Uložiť Náhodné Vyčistiť Prehľadať - Vyhľadávam... - Bez informácií! - Výber filmu: + Informácie nenájdené! + Vyberte film: Zisťujem informácie o %s Načítanie detailov o filme Webové rozhranie - - Obsah - Popis + Stručné info + Obsah filmu Hlasov - Herci + Obsadenie Obsah Prehrať - - Ďalší - Predchádzajúci - Kalibrácia rozhrania... - Kalibrácia videa... + Násl. + Pred. + Kalibrácia používateľského rozhrania... + Kalibrácia obrazu... Zmäkčenie - Veľkosť priblíženia - + Priblíženie Pomer strán DVD disk Prosím vložte disk Vzdialené zdieľanie Sieť nie je pripojená Zrušiť - Rýchlosť - Vertikálny posun + Vertikálne posunutie Testovací obraz... - Vyhľadať audio CD na freedb - Nahodný playlist pri otvorení - Zastaviť disk - + Vyhľadávať názvy skladieb z CD na freedb.org + Náhodne prehrávať skladby po načítaní playlist-u + Uspávať disk Video filtre Žiadne Bodový Lineárny Anizotropický Quincunx - Gaussovsko kubický Zmenšenie Zväčšenie - Vymazať playlist pri ukončení - Vybrať zobrazenie + Odstrániť playlist po skončení prehrávania + Možnosti zobrazenia Celá obrazovka #%d - - Okno + V Okne Obnovovacia frekvencia Celá obrazovka - Kalibrácia: (%i,%i)->(%i,%i) (Zoom x%2.2f) AR:%2.2f:1 (Pixels: %2.2f:1) (VShift: %2.2f) + Zmena veľkosti: (%i,%i)->(%i,%i) (Priblíženie x%2.2f) AR:%2.2f:1 (Pixelov: %2.2f:1) (VShift: %2.2f) Skripty Jazyk - Hudba - Vizualizácie - Nastaviť cieľový adresár + Vizualizácia + Vyberte cieľový priečinok Stereo výstup do všetkých reproduktorov Počet kanálov - DTS kompatibilný receiver - CDDB - Dotazujem freedb pre CDDB info + Získavnie informácií o CD Chyba Povoliť čítanie tagov Otváranie Shoutcast - - Čakanie na štart... + Prebieha príprava spustenia... Výstup skript Povoliť ovládanie XBMC cez HTTP - Nahrávanie - Stop Náhr. - Usporiadať: Stopa - - Usporiadať: Čas - Usporiadať: Názov - Usporiadať: Interprét - Usporiadať: Album + Nahrávať + Ukončiť nahrávanie + Zoradiť podľa: Stopy + Zoradiť podľa: Času + Zoradiť podľa: Názvu + Zoradiť podľa: Interpréta + Zoradiť podľa: Albumu Naj 100 - Vrchná ľavá kompenzácia presnímania - - Spodná pravá kompenzácia presnímania + Nastavenie ľavého horného okraja + Nastavenie pravého spodného okraja Pozícia titulkov - Úprava Pixel Ratia - Posunom šipiek zmeníte veľkosť presnímania - Posuňte čiaru pre zmenu pozície titulkov - Zmeňte pravouholník nech je štvorec - - Nie je možné otvoriť nastavenia + Nastavenie pomeru strán + Šípkami nastavíte okraj + Posunutím čiari zmeníte pozíciu titulkov + Upravte obdĺžnik tak, aby vznikol perfektný štvorec + Nepodarilo sa otvoriť nastavenia Použitie predvolených nastavení Prosím skontrolujte .xml súbory nájdených %i položiek Výsledky hľadania Žiadny výsledok - Titulky Písmo - Veľkosť Kompresia dynamického rozsahu - Obraz + Video Zvuk - - Vybrať titulky + Vyberte titulky Vytvoriť záložku Vymazať záložku - Oneskorenie zvuku + Posunutie zvuku Záložky - AAC kompatibilný receiver - - MP1 kompatibilný receiver - MP2 kompatibilný receiver - MP3 kompatibilný receiver Oneskorenie Jazyk Aktivované - - Neprekladaný + Neprekladané video (0=auto) Čistenie databázy Pripravujem... Chyba databázy Vyhľadávam skladby... - Vyčistenie databázy úspešné Čistenie skladieb... Chyba pri čistení skladieb Čistenie interprétov... Chyba pri čistení interprétov Čistenie žánrov... - Chyba pri čistení žánrov Čistenie ciest... Chyba pri čistení ciest Čistenie albumov... Chyba pri čistení albumov Zapisujem zmeny... - Chyba pri zapisovaní zmien Toto môže chvíľku trvať... Komprimujem databázu... Chyba pri komprimácii databázy - Chcete vyčistiť knižnicu? - Čistenie knižnice... - - Štart + Naozaj chcete vyčistiť knižnicu? + Vyčistiť knižnicu... + Spustiť Konverzia snímkovania Audio výstup Analógový Digitálny Rôzny interpréti - CD/DVD Filmy Prispôsobenie snímkovania Herec Rok Zvyšovať hlasitosť pri downmixe - Programy - Vypnúť + Vypnuté Zahmliť Čierna Matrix Trails - Čas nečinnosti pre šetrič obrazovky - + Čas nečinnosti potrebný pre aktiváciu šetriča obrazovky Šetrič obrazovky - Čas nečinnosti pre vypnutie + Čas nečinnosti potrebný pre vypnutie systému Všetky albumy - Nedávno pridané albumy + Naposledy pridané albumy Šetrič obrazovky - Ceľková prezentácia - + Rekurzívna prezentácia Hladina blednutia šetriča obrazovky Usporiadať: Súbor - Dolby Digital (AC3) kompatibilný reciever - Usporiadať: Názov - Usporiadať: Rok - Usporiadať: Hodnotenie - + Zoradiť podľa: Názvu + Zoradiť podľa: Roku + Zoradiť podľa: Hodnotenia IMDb Názov - búrka + búrky čiastočne prevažne slnečno - - zamračene + zamračené sneženie dážď - slabý - dop. - pop. - + slabý(é) + AM + PM prehánky občas - premenlivé + miestami veterno silný pekne - jasno oblačno ranné prehánky - veterno + snehové prehánky min. - stred max. hmla mrholenie - Vyberte miesto - Obnoviť po - + Vyberte mesto + Obnovovať po Jednotky teploty Jednotky rýchlosti Počasie Teplota - Ovzdušie + Zobrazenie UV Index - Vietor Rosný bod Vlhkosť Predvolené Pristupujem k weather.com - Čítam počasie pre: - - Nie je možné načítať dáta pre počasie + Získavam počasie pre: + nepodarilo sa načítať dáta o počasí Manuálne Pre tento album nie je žiadna recenzia Sťahujem náhľad... - Nie je prístupné + Nedostupné Zobrazenie: Veľké ikony - - Povoliť knižnicu - Vysoké + Noc + Deň HDMI Odstrániť informácie o albume - Odstrániť CDDB info + Odstrániť CD info Vybrať - - Neboli nájdené informácie pre album. - Nebolo nájdené CDDB informácie. + Informácie pre album neboli nájdené. + CD informácie neboli nájdené Disk - Vložte správne CD/DVD - Prosím vložte ďalšie CD/DVD - Usporiadať: DVD# - + Vložte CD/DVD + Prosím vložte disk s označením: + Zoradiť podľa: DVD# Žiadna medzipamäť Odstrániť film z knižnice - Naozaj odstrániť '%s'? - Z %s rychlosti %i %s - Externý disk + Naozaj chcete odstrániť '%s'? + %s %i %s + Vymeniteľný disk Otváranie súboru - Medzipamäť Harddisk UDF - LAN + Lokálna sieť Internet Video - Audio DVD - Automatické spustenie + Automaticky prehrávať médiá LCD - Povolené + Aktívne Stĺpcov - - Adresa riadku 1 - Adresa riadku 2 - Adresa riadku 3 - Adresa riadku 4 + Adresa 1 riadku + Adresa 2 riadku + Adresa 3 riadku + Adresa 4 riadku Riadky - Mód - + režim Prepnúť zobrazenie Titulky Zvuková stopa [aktívny] Titulky Podsvietenie - Jas Kontrast Gamma Typ - OSD pozíciu zmeníte posunom čiary + Pozíciu OSD zmeníte posunom čiary Pozícia OSD - Autori Modčip Vypnúť Iba hudba Hudba a Video Nedá sa otvoriť playlist - OSD Vzhľad a jazyk Prostredie Nastavenia zvuk O XBMC Odstrániť album - Opakovať Opakovať jeden Opakovať priečinok - Automaticky prehrať ďalšiu skladbu - - Použiť veľké ikony + Automaticky prehrávať ďalšiu skladbu + - Používať veľké ikony Velkosť vobsubs - Pokročilé nastavenia (iba expert!) Celková hlasitosť - Prepočítavať videa do rozlíšenia GUI + Prepočítavať videa do GUI rozlíšenia Kalibrácia - Schovať prípony médií - Usporiadať: Typ - + Zobrazovať prípony médií + Zoradiť podľa: Typu Nedá sa pripojiť k www.allmusic.com Sťahovanie informácií o albume zlyhalo - Hľadanie názvov albumov... + Hľadanie názvu albumov... Otvoriť Pracujem Prázdny - - Načítanie informácií o médiu zo súborov... - Usporiadať: Použitie - Povoliť vizualizácie - Povoliť zmenu video módu + Prebieha načítanie informácií zo súborov... + Zoradiť podľa: Použitia + Zobrazovať vizualizácie + Povoliť zmenu video režimu Úvodné okno - Domáce okno - + Domovská stránka Manuálne nastavenia Žáner - Nedávno prehrávané albumy + Naposledy prehrávané albumy Spustiť Spustiť... Kompilácie - Odstrániť zdroj - Zmena média - Vybrať playlist + Prejsť do inej sekcie + Vyberte playlist Nový playlist... Pridať do playlist-u Manuálne pridať do knižnice - - Napíšte názov + Zadajte názov Chyba: Duplicitný názov - Vybrať žáner + Vyberte žáner Nový žáner Manuálne pridanie Vložiť žáner - Zobrazenie: %s Zoznam Ikony - Veľký zoznam - Veľké ikony - Široký - - Veľmi široký - Ikony albumov - Ikony DVD + Zoznam II + Ikony II + Stĺpce + Stĺpce II + Náhľady albumov + Náhľady DVD DVD - Info o médiu + Informácie o médiu Zariadenie pre výstup zvuku - Zariadenie pre prestup zvuku Životopis pre tohoto interpréta nie je dostupný Prevádzať viackanálový zvuk na stereo - Usporiadať: %s + Zoradiť: %s Názov Dátum - Veľkosť Stopa Čas Názov Interprét Album - Playlist ID Súbor Rok Hodnotenie Typ - Použitie Autor albumu - Počet prehraní - Poslednéhé prehranie + Počet prehratí + Naposledy prehrané Komentár Dátum pridania - Predvolené Štúdio - Cesta + Umiestnenie Krajina Práve prebieha - Krát hrané - + Počet prehratí Smer usporiadania Spôsob usporiadania - Mód zobrazenia + režim zobrazenia Pamätať si zobrazenie pre každý priečinok Stúpajúci Klesajúci - Upraviť playlist Filter - Zrušiť párty mód - Párty mód - Náhodne + Zrušiť párty režim + Párty režim + Náhodné Vypnuté - Jeden Všetky Vypnuté Opakovať: Vypnuté - Opakovať: Jedno + Opakovať: 1 Opakovať: Všetko - - Stiahnuť audio CD + Skopírovať CD Stredná Štandardná Extrémna Konštantný datový tok Sťahujem... - Do: - Nie je možné stiahnuť CD alebo stopu + Nepodarilo sa skopírovať CD alebo stopu CDDA cesta nie je nastavená. - Stiahnuť audio stopu + Skopírovať audio stopu Zadaj číslo Bitov/Vzorka - Vzorkovacia frekvencia - CD sťahovanie + Audio CD Enkodér Kvalita Datový tok Zahrnúť číslo stopy - Všetky skladby od - Režim obrazu + Režim zobrazenia Normálne Zväčšiť Natiahnuť 4:3 - Natiahnuť 14:9 - + Široké priblíženie Natiahnuť 16:9 - Pôvodná veľkosť - Vlastný - Úprava zosilnenia - Spôsob úpravy zosilnenia - Používať úroveň stopy - - Používať úroveň albumu - Úroveň predzosilenia - Súbory s úpravou zosilnenia - Úroveň predzosilenia - Súbory bez úpravy zosilnenia - Zakázať odrezanie pri súboroch s úpravou zosilnenia - Orezať čierne okraje + Originálna veľkosť + Vlastné + ReplayGain / stará sa o minimálny rozdiel hlasitosti v rôznych skladbách + ReplayGain úprava hlasitosti + Použiť úroveň stopy + Použiť úroveň albumu + Úroveň - ReplayGain súbory + Úroveň - Súbory bez ReplayGain + Zabrániť predimenzovaniu pri súboroch s ReplayGain + Orezávať čierne okraje Treba rozbaliť veľký súbor. Pokračovať? - Odstrániť z knižnice - Export video knižnice - Import video knižnice + Exportovať video knižnicu + Importovať video knižnicu Prebieha import Prebieha export - Vybrať knižnicu - - Rok - Aktualizácia knižnice - Zobraziť ladiace informácie - Vybrať spúšťací súbor - Vybrať playlist - Vybrať priečinok - + Vyberte knižnicu + Roky + Aktualizovať knižnicu + Zobrazovať ladiace informácie + Vyberte spúšťací súbor + Vyberte playlist + Vyberte priečinok Informácie o skladbe Nelineárne roztiahnutie Zosilnenie hlasitosti Vyberte priečinok pre export Súbor už nieje dostupný. - Želáte si ho odstrániť z knižnice? - + Prajete si ho odstrániť z knižnice? Vyberte Skript Úroveň kompresie Vyčistiť knižnicu Odstraňujem staré skladby z knižnice - Táto cesta bola už skenovaná + Táto cesta bola už prehľadaná Sieť - - Server Použiť HTTP proxy server pre prístup na internet Internet protokol (IP) Nesprávny port. Hodnota musí byť medzi 1 a 65535. HTTP Proxy - Priradenie - + - Priradenie Automatický (DHCP) Manuálne (Statický) - IP Adresa - Sieťová maska - Predvolená brána - DNS server - Uložiť a reštartovať Nesprávna adresa. Hodnota musí byť AAA.BBB.CCC.DDD s číslami v rozsahu 0 a 255. Zmeny neboli uložené. Pokračovať bez uloženia? Web server FTP server - - Port Uložiť a použiť - Heslo Žiadne heslo - Písmo - Štýl - - Farba Obyčajné Tučné Kurzíva Tučné kurzíva Biele - Žlté Súbory - Žiadna zoskenovaná informácia pre toto zobrazenie - Prepnúť do súborového zobrazenia + Pre toto zobrazenie neodpovedajú žiadne položky + Vypnite prosím režim knižnice Chyba pri načítaní obrázku Upraviť cestu - Otočiť Ste si istý? - Odstraňovanie zdroju + Odstránenie zdroju Pridať zástupcu programu Upraviť cestu programu Upraviť názov programu - - Upraviť hĺbku pre cestu - Zobrazenie: Veľké ikony + Upraviť hĺbku cesty + Zobrazenie: Veľký zoznam Žltá Biela Modrá Svetlozelená - Žltozelená Ružová - Rezervované - Rezervované + Svetlošedá + Šedá Chyba %i: zdieľanie nie je prístupné - Audio zariadenie - - Vyhľadávam - Priečinok prezentácie + Audio výstup + Prebieha hľadanie + Priečinok s prezentáciami Sieťové rozhranie - Názov bezdrôtovej siete (ESSID) - Heslo bezdrôtovej siete - Bezpečnost bezdrôtovej siete - Uložiť a použiť nastavenie siete Bez šifrovania WEP WPA WPA2 Prebieha použitie zmien nastavenia siete. Počkajte prosím. - Reštart sieťového rozhrania bol úspešný. Štart sieťového rozhrania bol neúspešný. Rozhranie zakázané Sieťové rozhranie bolo zakázané. Názov bezdrôtovej siete (ESSID) Povoliť ovládanie XBMC aplikáciami na tomto systéme - Port Rozsah portov - Povoliť ovládanie XBMC aplikáciami z iného systému - Oneskorenie odozvy pre prvý stisk (ms) - Oneskorenie odozvy pre dlhý stisk (ms) + Povoliť ovládanie XBMC aplikáciami z iného systému + Úvodné oneskorenie opakovania (ms) + Následujúce oneskorenie opakovania (ms) Maximálny počet klientov - Internetový prístup Bolo zadané nesprávne číslo portu Povolený rozsah portu je 1-65535 Povolený rozsah portu je 1024-65535 - Pridať Hudbu... - Pridať Videá... - - Ukážka šetriča obrazovky + Pridať hudbu... + Pridať videá... + - Náhľad Nedá sa pripojiť - XBMC sa nemohol pripojiť na sieťové miesto. + XBMC sa nemohol pripojiť na sieťové umiestnenie. Toto môže byť kvôli nedostupnosti siete. Radi by ste to aj tak pridali? IP adresa - - Pridať sieťové miesto + Pridať sieťové umiestnenie Protokol Adresa servera Názov servera Vzdialená cesta Zdieľaný priečinok - Port - Meno - Vybrať sieťový server - Napíšte sieťovú adresu servera - Napíšte cestu na serveri - Napíšte číslo portu - - Napíšte meno - Pridať %s zdroj - Vložte cestu, alebo vyberte lokalitu média. - Napíšte názov pre tento média zdroj. - Vybrať nové zdieľanie - Vybrať - - Nie je možné načítať informácie priečinku. + Užívateľské meno + Vyberte sieťový server + Zadajte sieťovú adresu servera + Zadajte cestu na server + Zadajte číslo portu + Zadajte užívateľské meno + Pridajte cestu pre: %s + Zadajte cestu, alebo vyberte umiestnenie médií. + Zadajte názov pre tento zdroj médií. + Vyberte umiestnenie + Prechádzať + Nepodarilo sa načítať informácie priečinku. Pridať zdroj Upraviť zdroj Upraviť %s zdroj - Napíšte nový názov - Vybrať obrázok - - Vybrať priečinok s obrázkami - Pridať sieťové miesto... - Vybrať súbor + Zadajte nový názov + Vyberte obrázok + Vyberte priečinok s obrázkami + Pridať sieťové umiestnenie... + Vyberte súbor Podmenu - Povoliť tlačítka podmenu + Aktivovať tlačítka podmenu Obľúbené - - Doplnky - Video - Doplnky - Hudba - Doplnky - Obrázky + -Video (doplnky) + -Hudba (doplnky) + -Obrázky (doplnky) Prebieha načítanie priečinku Načítaných %i položiek Načítaných %i z %i položiek - - Doplnky - Programy + -Programy (doplnky) Nastavenie náhľadu doplnku Nastavenie doplnku Prístupové body (AP) Ostatné ... - Užívateľské meno - Nastavenia skriptu Single Zadajte webovú adresu SMB klient Pracovná skupina Predvolené meno - Predvolené heslo WINS server Pripojiť SMB zdieľané priečinky Odstrániť Hudba Video - Obrázky Súbory - Hudba a Video - Hudba a Obrázky - Hudba a Súbory - Video a Obrázky - - Video a Súbory - Obrázky a Súbory - Hudba a Video a Obrázky - Hudba a Video a Obrázky a Súbory - Zakázané - Súbory a Hudba a Video - - Súbory a Obrázky a Hudba - Súbory a Obrázky a Video - Hudba a Programy - Video a Programy - Obrázky a Programy - Hudba a Video a Obrázky a Programy - - Programy a Video a Hudba - Programy a Obrázky a Hudba - Programy a Obrázky a Video + Hudba & Video + Hudba & Obrázky + Hudba & Súbory + Video & Obrázky + Video & Súbory + Obrázky & Súbory + Hudba & Video & Obrázky + Hudba & Video & Obrázky & Súbory + Vypnuté + Súbory & Hudba & Video + Súbory & Obrázky & Hudba + Súbory & Obrázky & Video + Hudba & Programy + Video & Programy + Obrázky & Programy + Hudba & Video & Obrázky & Programy + Programy & Video & Hudba + Programy & Obrázky & Hudba + Programy & Obrázky & Video Autodetekcia Autodetekcia systému Prezývka - Opýtať sa na pripojenie Poslať FTP meno a heslo Ping interval - Chcete sa pripojiť na autodetekovaný system? + Chcete sa pripojiť na autodetekovaný systém? Oznamovať tieto služby ďalším počítačom cez Zeroconf Povoliť XBMC príjem AirPlay obsahu Názov zariadenia - Použiť ochranu heslom Vlastné zariadenie pre výstup audia - Vlastné zariadenie pre passthrough zvuku ustupujúci a mrznúci neskôr ojedinele - prehánky búrky slnečno zatiahnuté v blízkom - okolí ľadové krištáliky bezvetrie s veterno - mrholenie silná búrka mrholenie zahmlené - Krupy - Búrky - - Búrky s prehánkami + krupy + búrky + búrky s prehánkami Stredné Velmi vysoké Veterno Hmla - Aktivovať úsporný režim pri nečinnosti - + Aktivovať úsporný režim obrazovky pri nečinnosti Dĺžka Chyba skriptu! : %s Je vyžadovaná novšia verzia - Viac informácií v logu - Typ LCD + Aktivovať LCD/VFD Domov Programy - Obrázky Správca súborov Nastavenie Hudba Video Systémové informácie - Nastavenia - Hlavné Nastavenia - Obrazovky Nastavenia - Zobrazenie - Kalibrácia GUI Nastavenia - Video - Kalibrácia obrazovky Nastavenia - Obrázky Nastavenia - Programy - Nastavenia - Počasie Nastavenia - Hudba Nastavenia - Systém Nastavenia - Videá Nastavenia - Sieť Nastavenia - Zobrazenie - Skripty Webový prehliadač + Videá Videá/Playlist + Úvodná obrazovka Nastavenia - Profily + Doplnok-prehliadač Áno/Nie dialog Dialóg spracovania - Prebieha vyhľadávanie titulkov... Prebieha načítavanie titulkov... prerušenie načítanie do medzipamäte Otváranie streamu Hudba/Playlist - Hudba/Súbory Hudba/Knižnica Playlist editor Naj 100 skladieb - Naj 100 Albumov + Naj 100 albumov Programy - Konfigurácia Predpoveď počasia Hranie po sieti Rozšírenia Systémové informácie Hudba - Knižnica - - Teraz hrá - Hudba - Teraz hrá - Video + Práve hrá - Hudba + Práve hrá - Video Informácie o albume Informácie o filme Výberový dialóg Hudba/Info - Dialóg OK Video/Info Skripty/Info Video na celú obrazovku - Audio vizualizácie - Dialóg pre súbory dokopy - + Vizualizácie hudby + Dialóg pri spojovaní súborov Prerábam index... - Vrátiť sa do hudby - Vrátiť sa do videa - Štart od začiatku - Pokračovať od poslednej pozície + Vrátiť sa do sekcie 'Hudba' + Vrátiť sa do sekcie 'Videá' + Začať od začiatku + Pokračovať od %s 0 - 1 2 3 4 5 6 - 7 8 9 c - ok + Ok * - - Zamknuté! Vložte kód... + Zamknuté! Vložte heslo... Zadajte heslo - Zadajte hlavný kód - Zadajte odomykací kód + Zadajte hlavné heslo + Zadajte heslo pre odomknutie alebo stlačte C pre zrušenie Vložte kombináciu tlačidiel a - - stlačte Start alebo Back pre zrušenie + stlačte OK, alebo Späť pre zrušenie Nastaviť zámok Odomknúť Resetnúť zámok Odstrániť zámok Číselné Heslo - - Kombinácie tlačidiel na Gamepad-e + Kombinácia tlačidiel na Gamepad-e Textové Heslo - Napíšte nové heslo - Znovu napíšte nové heslo + Zadajte nové heslo + Znovu zadajte nové heslo Nesprávne heslo, - možností ostáva - - Napísané heslá nie sú totožné. + možnosí ostáva + Zadané heslá nie sú totožné. Vstup Nepovolený Limit pre opakovanie bol prekročený. Systém sa teraz vypne. Položka zamknutá Reaktivovať zámok - Zmeniť zámok - Zdieľať zámok - Heslo bolo prázdne. Skúste znova. + Uzamknúť zdroj + Žiadne heslo, skúste znova. Hlavný zámok Vypnúť systém ak boli prekročené pokusy na hlavný zámok Hlavný kľúč nie je správny! - Prosím vložte správny hlavný kľúč! - Nastavenia a Správca súborov + Nastavenia & Správca súborov Nastaviť ako predvolené pre všetky filmy Toto vymaže všetky uložené hodnoty - Čas zobrazenia obrázku - Použiť efekty priblíženia a posunutia obrázku - + Doba zobrazenia každého obrázku + Používať efekty priblíženia a posunutia obrázku 12 hodinový formát 24 hodinový formát Deň/Mesiac Mesiac/Deň - Systém žije - Minúty - + Doba používania + Minút Hodiny Dni - Celkovo žije + Celková doba používania Stav batérie Počasie Šetrič obrazovky - OSD na celú obrazovku Systém Okamžitý HD Spindown - Len Video + Iba Video - Oneskorenie - Minimálna dĺžka súboru - Vypnúť Predvolený spôsob vypnutia Ukončiť Dlhodobý spánok Úsporný režim Ukončiť - Reštartovať Minimalizovať Funkcia tlačítka pre vypnutie Vypnúť systém Existuje nejaké aktívne pripojenie, (napr. cez SSH) ? - Pripojený vymeniteľný pevný disk - - Nebezpečne odobrať zariadenie + Vymeniteľný pevný disk pripojený + Nebezpečné vybratie zariadenia Zariadenie bolo úspšne odobrané Joystick bol pripojený Joystick bol odpojený Nízka úroveň batérie Blikací filter - - Nastavené ovladačom (vyžaduje reštart) + Nastavené ovládačom (vyžaduje reštart) Vertikálna synchronizácia obrazovky (V-Sync) Zakázané Povolené počas prehrávania videa Vždy povolené Test rozlíšenia - Uložiť rozlíšenie? Chcete ponechať toto rozlíšenie? - Vysoko kvalitný softwarový prepočet + Vysoko kvalitný prepočet (upscaling) Zakázané - Povolené pre SD videa + Povolené pre SD obsah Vždy povolené - - Metóda prepočtu + Spôsob prepočtu Bicubic Lanczos Sinc VDPAU VDPAU HQ prepočet (upscaling) - VDPAU farebná konverzia - Studio level Stmavovať ostatné obrazovky Zakázané - Vypni obrazovku + Povolené Zistené aktívne spojenie! Ak budete pokračovať, môžeťe stratiť ovládanie XBMC - natrvalo. Určiťe chcete zastaviť event server? - Zmeniť mód diaľkového ovládania Apple? + Zmeniť režim diaľkového ovládania Apple? Ak práve používate diaľkové ovládanie Apple na ovládanie - XBMC, zmenou nastavenia možete ovplyvniť vašu + XBMC, zmenou nastavenia možete ovplyvniť Vašu schopnosť ovládať ho. Chcete pokračovať? - Maska siete: - + Maska podsiete Brána Primárny DNS Inicializácia zlyhala Nikdy Ihneď Po %i sekundách - Dátum inštalácie disku: - Počet zapnutí disku + Počet zapnutí disku: Profily Vymazať profil '%s'? Posledný otvorený profil: Neznámy - Prepísať Budík - Budíkový interval (v minútach) - Načasovaný, budík o %im + Interval budíku (v minútach) + Budík nastavený, budenie o %im Budík! Zrušené (zostávalo %im%is) - %2.0fm %2.0fs Hľadať titulky v RARoch Hľadať titulky... Presunúť položku Presunúť položku sem - Zrušiť presunutie Hardware: - Záťaž CPU: + Zaťaženie CPU: Pripojený, ale DNS je nedostupný Hard Disk DVD-ROM - - Úložisko + Voľné miesto Predvolené Sieť Video - Hardware - Operačný systém - + CPU a RAM + Operačný systém: Rýchlosť CPU: Video enkodér: Rozlíšenie obrazovky: A/V Kábel: DVD Región: Internet: - Pripojený Nie je Pripojený. Skontrolujte sieťové nastavenia. Cieľová teplota Otáčky ventilátora Automatické regulovanie teploty Nastavenie otáčok ventilátora - - Písmo vzhľadu - Povoliť preklápanie obojsmerných reťazcov - Povoliť RSS spravodajstvo - Schovať rodičovský priečinok - Šablóna názvu stopy + - Písmo + Aktivovať opačné titulky (arabčina, hebrejčina, ...) + Aktivovať RSS spravodajstvo + Zobrazovať položku pre návrat do nadradeného priečinku + Šablona názvu stopy Naozaj chcete reštartovať systém - - alebo len XBMC? + alebo iba XBMC? Efekt zväčšenia Efekt splynutia Redukcia čiernych okrajov Reštart - Prelínanie - + Prelínanie zvuku medzi skladbami Aktualizovať náhľady - Náhľady rekurzívne + Rekurzívne náhľady Prezentácia - Prezentácia rekurzívna - Náhodne + Rekurzívna prezentácia + Náhodné poradie Stereo - - Len ľavý - Len pravý - Povoliť podporu karaoke + Iba ľavý + Iba pravý + Aktivovať podporu karaoke Priehľadnosť pozadia Priehľadnosť popredia A/V oneskorenie - Karaoke %s nebolo nájdené Chyba pri otváraní %s - Nie je možné otvoriť %s + Nepodarilo sa otvoriť %s Chyba: nedostatok pamäte Premiestniť hore - Premiestniť dole Upraviť názov - Spraviť predvolené + Nastaviť ako predvolené Odstrániť tlačidlo Nechať tak ako je Zelená - Oranžová Červená Cyklovať Vypnúť LED pri prehrávaní - Informácie o filme - Položka do zásoby - + Detailné informácie + Pridať do fronty Hľadať v IMDb... Hľadať nový obsah - Teraz hrá... + Práve hrá... Informácie o albume - Skenovať položku do knižnice - Zastaviť skenovanie - + Pridať do knižnice + Zastaviť vyhľadávanie Vykresľovacia metóda Nízkokvalitný Pixel Shader Hardvérové prekrývanie Vysokokvalitný Pixel Shader Prehrať položku Nastaviť náhľad pre interpréta - - Vytvoriť náhľady + Automaticky vytvárať náhľady Povoliť hlas Povoliť zariadenie Hlasitosť - Predvolený zobrazovací mód + Predvolený zobrazovací režim Predvolený jas - Predvolený kontrast Predvolená gamma - Pokračovať + Pokračovať v prehrávaní videa Maska hlasu - port 1 Maska hlasu - port 2 Maska hlasu - port 3 - Maska hlasu - port 4 - Použiť vyhľadávanie na základe času - Šablóna názvu stopy - vpravo + Pretáčať video na základe časového intervalu + Šablona názvu stopy - vpravo Predvoľby Pre túto vizualizáciu nie sú k dispozícii žiadne predvoľby Pre túto vizualizáciu nie sú k dispozícii žiadne nastavenia - Vysunúť/Zasunúť - Použiť vizualizácie pri prehrávaní hudby + Zobrazovať vizualizáciu počas prehrávania hudby Vypočítať veľkosť Počítanie veľkosti priečinka Nastavenia videa - Nastavenie hudby a titulkov - - Povoliť titulky + Nastavenie zvuku a titulkov + Zobrazovať titulky Záložky - Ignorovať "The" pri usporiadaní - Stišovať stopy - Vybrať pre %s - Zobraziť pozíciu stopy - - Vymazať predvolené + Ignorovať 'The' pri usporiadaní + Plynulé prelínanie skladieb na albume + Hľadať %s + Zobrazovať pozíciu stopy + Zrušiť ako predvolené Pokračovať Náhľady Informácie o obrázku %s predvolieb (Hodnotenie užívateľov IMDb) - Naj 250 Naladiť na Last.FM Minimálna rýchlosť ventilátora - Pustiť odtiaľto + Prehrať odtiaľto Sťahujem - Schovať interprétov bez kompilácii - + Zobrazovať aj tých interprétov, ktorí sú iba na kompiláciach Vykresľovacia metóda Zistiť automaticky Jednoduchý shader (ARB) Pokročilý shader (GLSL) Softvér Bezpečne odobrať - VDPAU - Začať slideshow tu + Začať prezentáciu tu Zapamätať pre túto cestu Použiť objekty vyrovnávacej pamäte pixelu Aktivovať hardwarovú akceleráciu (VAAPI) - Povoliť hardwarovú akceleráciu (VAAPI) - - Povoliť hardwarovú akceleráciu (DXVA2) - Povoliť hardwarovú akceleráciu (CrystalHD) - Povoliť hardwarovú akceleráciu (VDADecoder) - Povoliť hardwarovú akceleráciu (OpenMax) + Aktivovať hardwarovú akceleráciu (VAAPI) + Aktivovať hardwarovú akceleráciu (DXVA2) + Aktivovať hardwarovú akceleráciu (CrystalHD) + Aktivovať hardwarovú akceleráciu (VDADecoder) + Aktivovať hardwarovú akceleráciu (OpenMax) Pixel Shadery - Povoliť hardwarovú akceleráciu (Video Toolbox) - + Aktivovať hardwarovú akceleráciu (Video Toolbox) Spôsob synchronizácie A/V - podľa audia - podľa videa (vynechať/duplikovať audio) - podľa videa (prispôsobiť rýchlosť audia) + Podľa audia + Podľa videa (vynechať/duplikovať audio) + Podľa videa (prispôsobiť rýchlosť audia) Maximálna zmena rýchlosti (%) Kvalita zmeny rýchlosti - Nízka (rýchla) Stredná Vysoká Veľmi vysoká (pomalé!) Synchronizovať prehrávanie videa k obrazovke Pozastaviť prehrávanie pri zmene obnovovacej frekvencie - Vypnuté %.1f Sekunda %.1f Sekúnd Diaľkové ovládanie Apple - Vždy spustené + Povoliť spustenie XBMC diaľkovým ovládaním Čas oneskorenia sekvencie - Zakázaný Štandardný Univerzálne diaľkové ovládanie Multifunkčné diaľkové ovládanie (Harmony) - Ovládač pre ovládanie Apple je nainštalovaný. - Podporu pre ovládanie Apple nie je možné povoliť. - - Spolu - Samostatne + Diaľkové ovládanie Apple Chyba + Podpora diaľkového ovládania Apple by mohla byť zapnutá. + Zlučovať + Nezlučovať Sťahujem playlist súbor... Sťahujem zoznam streamov... Parsujem zoznam streamov... Sťahovanie zoznamu streamov zlyhalo - Sťahovanie súboru playlist-u zlyhalo Priečinok s hrami - Autoprepínanie pre náhľady založené na - Povoliť autoprepínanie na náhľady - - Používať veľké ikony - - Prepínanie založené na - - - Percentá + Prepínať na režim náhľadov + Automaticky prepínať náhľady + - ak sú veľké ikony + - podľa pravidla + - podľa percent Žiadne súbory a najmenej jeden náhľad Aspoň jeden súbor a jeden náhľad Podiel náhľadov Zobrazenie Zmeniť kód oblasti 1 - Zmeniť kód oblasti 2 Zmeniť kód oblasti 3 Knižnica Žiadna TV - Napíšte najbližšie veľké mesto + Zadajte najbližšie veľké mesto Medzipamäť - Video/Audio/DVD - HDD - Medzipamäť - Video - DVDRom - Lokálna sieť - Internet Medzipamäť - Audio - DVDRom - Lokálna sieť - Internet - Medzipamäť - DVD - DVDRom - Lokálna sieť Servery Sieťové nastavenia boli zmenené XBMC vyžaduje reštart pre zmenu sieťových nastavení. Reštartovať? - Limitovať rýchlosť internetového pripojenia - - Vypínanie počas prehrávania + - Vypnúť pri hraní %i min %i sek %i ms %i %% - %i kbps %i kb %i.0 dB Formát Času Formát Dátumu GUI Filtre - - Používať skenovanie na pozadí - Zastaviť skenovanie - Nie je možne zoskenovať informácie pre médiá + Použiť vyhľadávanie na pozadí + Zastaviť vyhľadávanie + Nie je možné vykonať, počas hľadania informácií o médiu Krupicový efekt na film - Hľadať náhľady na vzdialených zložkách + Hľadať náhľady na sieťových jednotkách Medzipamäť - Ostatné - Internet - Automatický - Napíšte meno pre + Zadajte užívateľské meno pre Dátum a čas Nastaviť Dátum Nastaviť Čas - Napíšte čas v 24 hodinovom formáte HH:MM - - Napíšte dátum v DD/MM/YYYY formáte - Napíšte IP adresu + Zadajte čas v 24 hodinovom formáte HH:MM + Zadajte dátum v DD/MM/YYYY formáte + Zadajte IP adresu Použiť tieto nastavenia teraz? - Teraz použiť zmeny + Použiť zmeny teraz Povoliť premenovanie a mazanie súborov Nastaviť časové pásmo - Automaticky upraviť hodiny na letný čas Pridať medzi obľúbené Odstrániť z obľúbených - Farby vzhľadu - Časové pásmo - krajiny + - Farby + Časové pásmo krajiny Časové pásmo - - Zoznam súborov - Zobraziť EXIF informácie o obrázku + Možnosti súborov + Zobrazovať informácie o obrázku (EXIF) Uprednostniť režim okna celej obrazovky pred skutočnou celou obrazovkou Pridávať skladby do fronty pri ich výbere - Automaticky prehrať Audio CD + Automaticky prehrávať Audio CD Prehrávanie - DVD - Automaticky prehrať DVD + Automaticky prehrávať DVD Font pre textové titulky Oblasť a jazyk Znaková sada Ladenie / Debug - Bezpečnosť Vstupné zariadenia Napájanie Odstrániť Hry Pridať - Heslo Knižnica Databáza * Všetky albumy * Všetci interpréti * Všetky skladby - * Všetky žánre Buferujem... Zvuky navigácie - Predvolený vzhľad - Téma vzhľadu + Predvolené + - Téma Predvolená téma - Last.FM Last.FM - Odosielať informácie o skladbách - Last.FM meno - Last.FM heslo + Last.FM - Užívateľské meno + Last.FM - Heslo Nedá sa nadviazať spojenie: spím... Prosím aktualizujte XBMC - Zlá autorizácia: Skontrolujte meno a heslo Pripojený Odpojený Interval pre posielanie %i Načítaných %i skladieb Posielam... - Pošlem za %i sekund Prehrať použitím... Používať hladkú A/V synchornizáciu - Schovať názvy súborov v náhľadoch - Prehrať v párty móde + Skryť názvy súborov v náhľadoch + Prehrať v párty režime Libre.fm - Odosielať informácie o skladbách - Libre.fm - Užívateľské meno Libre.fm - Heslo Libre.fm - Online služby - Last.FM - Odosielať informácie o rádiách + Služby + Last.fm - Odosielať informácie o rádiách Spájam sa s Last.FM... - Nastavujem stanicu... Hľadať podobných interprétov... - Hľadať podobné značky... + Hľadať podobné slová... Váš profil (%name%) - Najpoužívanejšie značky - Najlepší interpréti pre značku %name% - - Najlepšie albumy pre značku %name% - Najlepšie piesne pre značku %name% - Počúvať značku %name% na Last.FM radiu + Najpoužívanejšie slová + Najlepší interpréti pre slovo %name% + Najlepšie albumy pre slovo %name% + Najlepšie skladby pre slovo %name% + Počúvať slovo %name% na Last.FM radiu Podobní interpréti ako %name% - Najlepšie %name% albumy - Najlepšie %name% piesne - - Najpoužívanejšie %name% tagy + Najlepšie albumy %name% + Najlepšie skladby %name% + Najpoužívanejšie slová %name% Najväčší fanúškovia %name% Počúvať %name% fanúškov Last.FM radiu Počúvať %name% podobných interprétov na Last.FM radiu Najlepší interpréti pre užívateľa %name% Najlepšie albumy pre užívateľa %name% - - Najlepšie piesne pre užívateľa %name% + Najlepšie skladby pre užívateľa %name% Kamaráti užívateľa %name% Susedia užívateľa %name% Týždenné rebríčky interprétov pre %name% Týždenné rebríčky albumov pre %name% - Týždenné rebríčky piesní pre %name% - + Týždenné rebríčky skladieb pre %name% Počúvať %name% susedov Last.FM radiu Počúvať %name% osobný Last.FM radiu - Počúvať %name% obľúbene piesne Last.FM radiu + Počúvať %name% obľúbene skladby Last.FM radiu Sťahujem zoznam z Last.FM... - Nie je možné stiahnuť zoznam z Last.FM... - Napíšte meno interpréta pre hľadanie podobných - - Napíšte značku pre hľadanie podobných - Piesne nedávno počúvané užívateľom %name% - Počúvať %name% odporúčania Last.FM radio + Nepodarilo sa stiahnuť zoznam z Last.FM... + Zadajte meno interpréta pre hľadanie podobných + Zadajte slovo pre hľadanie podobných + Naposledy počúvané skladby užívateľom %name% + Počúvať %name% odporúčania Last.FM Obľúbené tagy užívateľa %name% - Chcete pridať túto skladbu k vaším obľúbeným? + Chcete pridať túto skladbu k Vaším obľúbeným? Chcete zakázať túto skladbu? - - Skladba pridaná k vaším obľúbeným: '%s'. - Skladbu '%s' sa nepodarilo pridať k vaším obľúbeným. + Skladba pridaná k Vaším obľúbeným: '%s'. + Skladbu '%s' sa nepodarilo pridať k Vaším obľúbeným. Zakázané: '%s'. Nepodarilo sa zakázať '%s'. Ostatné obľúbené skladby užívateľa %name% Ostatné zakázané skladby užívateľa %name% - - Odstrániť z obľúbených skladieb? + Odstrániť z obľúbených skladieb Povoliť zakázanú - Chcete odstrániť túto skladbu z vašich obľúbených? + Chcete odstrániť túto skladbu z Vašich obľúbených? Chcete opäť povoliť túto zakázanú skladbu? - Cesta nenájdená alebo nesprávna - Nie je možné spojenie zo sieťovým serverom - + Cesta nenájdená + Nepodarilo sa spojenie zo sieťovým serverom Servery neboli nájdené Skupina nebola nájdená - Otváranie multi-cestového zdroja - Cesta: - Všeobecné - Hľadanie CDDB - + Otváranie priečinku s viacerými cestami + Umiestnenie: + Hlavné + Vyhľadávanie na internete Prehrávač - Prehrať médiá z disku + Prehrávať médiá z disku (CD/DVD/BluRay) Zadajte nový názov - Napíšte názov filmu - Napíšte názov profilu - Napíšte názov albumu - - Napíšte názov playlist-u - Napíšte názov súboru - Napíšte názov priečinka - Vložte adresár + Zadajte názov filmu + Zadajte názov profilu + Zadajte názov albumu + Zadajte názov playlist-u + Zadajte názov súboru + Zadajte názov priečinka + Prejdite do priečinka Dostupné možnosti: %A, %T, %N, %B, %D, %G, %Y, %F, %S - Napíšte hľadaný výraz - + Zadajte hľadaný výraz Žiadne - Auto Výber + Automaticky Deinterlácia Bob Bob (Opačný) - Prekladaný materiál /Interlaced Handling - Prerušujem... - Napíšte meno interpréta - Prehrávanie playlist-u zrušené - Príliš veľa nasledujúcich položiek zlyhalo + Zadajte meno interpréta + Prehrávanie zlyhalo + Prehrávanie jednej, alebo viacerých položiek zlyhalo Zadajte hodnotu Skontrolujte Log súbor pre viac informácií. - - Párty mód prerušený. - Žiadne skladby neboli nájdené v knižnici. + Párty režim prerušený. + V knižnici nie sú žiadne odpovedajúce skladby. Nedá sa inicializovať databáza. - Nedá sa otvoriť databáza. - Nedajú sa načítať skladby z databázy. - Párty mód playlist - + Databáza sa nedá otvoriť. + Skladby sa nedajú načítať z databázy. + Párty režim playlist De-interlácia (Polovičná) Deinterlácia videa Spôsob deinterlácie @@ -1606,35 +1382,30 @@ Videné Označiť ako videné Označiť ako nevidené - Upraviť titul Operácia bola prerušená Kopírovanie zlyhalo Zlyhalo kopírovanie najmenej jedného súboru Presunutie zlyhalo Zlyhal presun najmenej jedného súboru - Mazanie zlyhalo Zlyhalo zmazanie najmenej jedného súboru Spôsob úpravy videa - Nearest Neighbour - Bilinear - Bicubic - + Najbližší sused + Bilineárny + Bikubický Lanczos2 Lanczos3 Sinc8 - Bicubic (software) + Bikubický (software) Lanczos (software) Sinc (software) - Dočasný Dočasný/Spatial (VDPAU) Redukcia šumu (VDPAU) Ostrosť Inverzný Telecine Lanczos3 optimalizovaný - Automaticky Dočasný (Polovičný) Dočasný/Spatial (polovičný) @@ -1643,747 +1414,647 @@ DXVA Best Spline36 Spline36 optimalizovaná + Software Blend Post-processing - Zobraziť odpočet do uspania - + Zobraziť čas do vypnutia Prepnúť na kanál - Priečinok pre sťahovanie CDDA - Použiť externý prehrávač + Priečinok pre ukladanie hudby + Použiť externý DVD prehrávač Externý DVD prehrávač Priečinok s trainermi - Priečinok screenshotov - + Priečinok pre ukladanie obrázkov (screenshotov) Priečinok playlist-ov Nahrávky Screenshoty Použiť XBMC Hudobné playlist-y Video playlist-y - Chcete spustiť túto hru? - Usporiadať: Playlist - IMDb náhľad - Súčasný náhľad + Zoradiť podľa: Playlistu + Internetový náhľad + Aktuálny náhľad Lokálny náhľad - Žiaden náhľad - + Bez náhľadu Zvoliť náhľad Konflikt - Skenovať nové - Skenovať všetko + Prehľadať nové + Prehľadať všetko Región - Sumár - Zamknúť hudbu - Zamknúť video - Zamknúť obrázky - Zamknúť programy, uloženia a skripty + Zamknúť sekciu Hudba + Zamknúť sekciu Video + Zamknúť sekciu Obrázky + Zamknúť Programy & skripty Zamknúť správcu súborov - Zamknúť nastavenia Načisto naštartovať - Vstúpiť do admin módu - Opustiť admin mód + Vstúpiť do hlavného režimu + Opustiť hlavný režim Vytvoriť profil '%s' ? - Štartovať s prázdnymi nastaveniami - - Najlepšie možné - Autoprepínanie medzi 16x9 a 4x3 + Spustiť s čistými nastaveniami + Najlepšie dostupné + Automaticky prepínať 16:9 a 4:3 režimy Považovať zlúčené súbory za jeden súbor Výstraha - Admin mód deaktivovaný - Admin mód aktivovaný - + Hlavný režim deaktivovaný + Hlavný režim aktivovaný Allmusic.com náhľad Odstrániť náhľad Pridať profil... - Stiahnuť informácie pre všetky albumy - Informácie o médiu + Získať informácie pre všetky albumy + Informácie o médiách Oddelený - Zdieľať s predvoleným Zdieľať s predvoleným (len čítanie) Kopírovať predvolené Obrázok profilu Nastavenia zámku Upraviť profil - Zamknutie profilu - Priečinok nie je možné vytvoriť - Adresár profilov + Priečinok sa nepodarilo vytvoriť + Priečinok profilu Štartovať s čistými zdrojmi médií Ubezpečte sa, že zvolený priečinok je zapisovateľný - a nový názov priečinku je korektný - - MPAA Hodnotenie: - Napíšte hlavný kód - Pýtať sa na hlavný kód pri štarte + a nový názov priečinku je správny + Prístupnosť + Zadajte hlavné heslo + Pýtať sa na hlavné heslo pri štarte Nastavenie vzhľadu - žiadny link - - Povoliť animácie - - Zakázať RSS počas hudby - Povoliť záložkové tlačítka - Zobraziť XLink Kai informácie - Zobraziť informácie o hudbe - Zobraziť informácie o počasí - Zobraziť systémové informácie - - Zobraziť voľné miesto na C: E: F: - Zobraziť voľné miesto na E: F: G: - Predpoveď počasia + Zobrazovať animácie + Zakázať RSS počas prehrávania hudby + Aktivovať záložky + Zobrazovať programy v hlavnom menu + Zobrazovať informácie o hudbe + Zobrazovať informácie o počasí + Zobrazovať systémové informácie + Zobrazovať voľné miesto na C: E: F: + Zobrazovať voľné miesto na E: F: G: + Informácie o počasí Voľné miesto - Napíšte názov existujúceho zdieľania - Kód - - Otvoriť profil + Zadajte názov existujúceho zdieľania + Uzamykacie heslo + Načítať profil Názov profilu Zdroje médií - Napíšte kód pre uzamknutie profilu - Prihlásenie - Získavam informácie o albume - - Získavam informácie pre albume - Nie je možné stiahnuť CD alebo stopu počas prehrávania CD - Hlavný kód a nastavenia - Vloženie hlavného kódu vždy povolí admin mód + Zadajte heslo pre uzamknutie profilu + Úvodná obrazovka + Získavanie informácií o albume + Ukladanie informácií o albume + CD, alebo stopu nie je možné uložiť počas prehrávania CD + Hlavné heslo a nastavenia + Vložením hlavného hesla vždy aktivovať hlavný režim alebo kopírovať z predvoleného? Uložiť zmeny do profilu? - Staré nastavenia nájdené. Chcete ich použiť? Staré zdroje médií nájdené. Oddelený (zamknuté) - Hlavný - Zväčšenie vzhľadu - - UPnP Klient - Autoštart + Hlavný priečinok + - Zväčšenie + UPnP nastavenia + Autoštart UPnP klienta Posledné prihlásenie: %s Nikdy neprihlásený Profil %i / %i Prihlásenie / Výber profilu - - Použiť zámok na prihlasovacej obrazovke - Nesprávny kód. - Toto vyžaduje aby bol nastavený admin zámok. - Chcete to nastaviť teraz? + Aktivovať zámok na úvodnej obrazovke + Nesprávne uzamykacie heslo. + Vyžaduje sa nastavenie hlavného zámku. + Chcete ho nastaviť teraz? Načítanie informácie o programe - Párty sa začína! - - Pravda + Párty sa začala! + Pravdivé Miešam nápoje Plním poháre Prihlásený ako Odhlásiť - Prejsť do hlavného - - Vlna - Vlna (naopak) + Prejsť do hl. priečinku + Weave + Weave (naopak) Miešať Reštartovať video - Upraviť sieťové miesto - Odstrániť sieťové miesto - - Chcete skenovať priečinok? - Pamäťová karta - Pamäťová karta nainštalovaná - Nie je možné nainštalovať pamäťovú kartu + Upraviť sieťové umiestnenie + Odstrániť sieťové umiestnenie + Chcete prehľadať priečinok? + Pamäťová jednotka + Pamäťová jednotka nainštalovaná + Nepodarilo sa nainštalovať pamäťovú jednotku V porte %i, slote %i Zamknúť šetrič obrazovky - Nastaviť - Meno - Napíšte heslo pre - Časovač vypnutia + Užívateľské meno + Zadajte heslo pre + Automatické vypnutie Vypnúť za (v minútach) - Naštartované, vypnutie za %im - + Vypnutie je nastavené. Vypnutie za %im Vypnutie za 30 minút Vypnutie za 60 minút Vypnutie za 120 minút - Vlastný časovač vypnutia + Časovač vypnutia Zrušiť časovač vypnutia Zamknúť nastavenia pre %s - - Vybrať... + Prechádzať... Informácie základné - Informácie o úložisku + Informácie o hdd Informácie o harddisku Informácie o DVD-ROM Informácie o sieti - Informácie o videu - Informácie o hardware - Celkom: %s MB, použitých: %s MB, voľných: %s MB - Celkom HDD používaných: %u%% voľných: %u%% - %s: %s MB of %s MB voľných + Informácie o CPU a RAM + Celkom + Použité + z Zamknutie nie je podporované - - Odomknutý + Nezamknutý Zamknutý Zamrznutý - Vyžaduje reset + Vyžaduje reštart Týždeň Linka - - Windows sieť (SMB) + Sieť Windows (SMB) XBMSP server FTP server - iTunes zdieľanie hudby (DAAP) + iTunes zdieľanie (DAAP) UPnP Server - Zobraziť informácie o videu - - V poriadku + Zobrazovať informácie o videu + Hotovo Shift Caps Lock Symboly - Backspace - Space - + Vymazať + Medzera Obnoviť vzhľad - Otočiť podľa EXIF informácií - Detekovanie hardwarových hodnôt + Otáčať obrázky podľa EXIF informácií + Použiť zobrazenie 'Plagáty' pre TV seriály Prosím čakajte - Povoliť automatické rolovanie obsahu a recenzie + Aktivovať automatické skrolovanie obsahu & recenzie Vlastné - - Povoliť ladenie / debug log - Získať informácie o albume, keď sa pridáva do knižnice - Získať informácie o interprétovy, keď sa pridáva do knižnice - Predvolený sťahovač pre hudbu - Zmeniť Sťahovač - Export knižnice hudby - - Import knižnice hudby + Začať ukladať informácie / debug log + Sťahovať dodatočné informácie počas aktualizácie + Predvolená služba pre získavanie informácií o albume + Predvolená služba pre získavanie informácií o interprétovy + Zmeniť sťahovač + Exportovať hudbonú knižnicu + Importovať hudbonú knižnicu Interprét nenájdený! Sťahovanie informácií o interprétovy zlyhalo - Párty zahájená! (videa) + Párty sa začala! (videa) Miešam nápoje (videa) - Nalievam poháre (videa) - + Plním poháre (videa) WebDAV server (HTTP) WebDAV server (HTTPS) Prvé prihlásenie, editujte svoj profil HTS Tvheadend klient VDR Streamdev klient MythTV klient - Sieťový Systém Súborov (NFS) Secure Shell (SSH/SFTP) Protokol súboru Apple (AFP) - Web server zložka (HTTP) - Web server zložka (HTTPS) - Nie je možné zapísať do priečinka: - Želáte si preskočiť a prejsť ďalej? - + Web server priečinok (HTTP) + Web server priečinok (HTTPS) + Nepodarilo sa zapísať do priečinka: + Prajete si preskočiť a prejsť ďalej? RSS Spravodajstvo - Sekundárne DNS + Sekundárny DNS DHCP Server: Vytvoriť nový priečinok Stmaviť LCD pri prehrávaní - Neznámy alebo na Doske (chránený) - - Stmaviť LCD pri pauze + Neznáme alebo obsiahnuté (chránené) + Stmaviť LCD pri pozastavení Video - Knižnica - Usporiadať: ID + Zoradiť podľa: ID Hrať časť... - Časť %i / %i + Vyčistenie kalibrácie Tímto zmažete uložené hodnoty kalibrácie pre %s - na predvolené hodnoty. - Vybrať cieľ + Vybrať umiestnenie + Filmy sú v jednotlivých priečinkoch, ktoré zodpovedajú názvu filmu Vyhľadávať podľa názvu priečinku Súbor Chcete vyhľadávať podľa názvu súboru alebo priečinku? - Nastaviť obsah - + Pridať obsah Priečinok Vyhľadávať v podpriečinkoch? Odomknúť zdroje Herec Film - Režisér - + Réžia Chcete odstrániť všetky položky v - tejto ceste z knižnice? + tejto ceste z knižnice XBMC? Filmy Seriály Tento priečinok obsahuje - Spustiť automatické prehľadanie - + Spustiť automatické prehľadávanie Vyhľadávať v podpriečinkoch ako - Režisér + Réžia Na tejto ceste nebol nájdený žiadny video súbor! hlasov Informácie o seriáli - Informácie o epizóde Načítanie detailov o seriáli Získavanie informácií o epizódach Načítanie informácií o epizódach v priečinku Vyberte seriál: Zadajte názov seriálu - Sezóna %i Epizóda Epizódy Načítanie detailov o epizóde Odstrániť epizódu z knižnice Odstrániť seriál z knižnice - Seriál Obsah epizódy * Všetky sezóny - Schovať sledované + Skryť videné Kód produkcie - Zobraziť obsah pre nevidené videá - + Zobrazovať obsah pre nevidené videá * nezobrazené pre spoilery * Priradiť náhľad k sezóne Obrázok sezóny Sezóna Sťahovanie informácií o filme Odobrať obsah - Pôvodný názov - Obnoviť informácie o seriáli - Obnoviť informácie pre všetky epizódy? + Aktualizovať informácie o seriáli + Aktualizovať informácie pre všetky epizódy? Priečinok obsahuje jeden seriál Vylúčiť priečinok z prehľadávania - Špeciál - + Špeciálne Automaticky sťiahnúť náhľad k sezónam Priečinok obsahuje jedno video - Spojiť so seriálom - Odstrániť spojenie so seriálom + Priradiť k TV seriálu + Odstrániť z TV seriálu Naposledy pridané filmy Naposledy pridané epizódy - - Štúdio + Štúdiá Videoklipy Naposledy pridané videoklipy Videoklip Odstrániť videoklip z knižnice Informácie o videoklipe - Načítanie informácií o videoklipe Zmiešané Prejsť na albumy podľa interpréta Prejsť na album Prehrať skladbu Prejsť na videoklipy z albumu - Prejsť na videoklipy od interpréta Prehrať videoklip - Automaticky stiahnuť náhľady hercov + Sťahovať náhľady hercov počas pridávania do knižnice Nastaviť náhľad hercov Odstrániť záložku epizódy Nastaviť záložku epizódy - Nastavenie Sťahovača Sťahujem informácie o videoklipe Sťahujem informácie o seriáli Ukážka - Jednoduchý mód - Zobraziť TV seriály zjednodušene - + Zúžený režim + Zobrazovať TV seriály v zúženom režime FanArt-y - Zobraziť FanArt vo video knižnici + Zobrazovať FanArt v knižnici videí a hudby Hľadá sa nový obsah Premiéra - Autor - - - Zobraziť metadata v súboroch + Napísal + + + Nahradiť názvy súborov s názvami knižníc Nikdy Iba ak jedna sezóna Vždy Má ukážku - Nie - + Nepravdivé Fanart prezentácia Exportovať všetko do jedného súboru alebo - každú položku do samostatného súboru? + každú položku oddelene do samostatného súboru? 1 súbor Oddelene Exportovať náhľady a FanArt? - Prepísať staré súbory? - Nezahrňovať položky v tomto umiestnení pri aktualizácii knižnice + Vynechať položky v tomto umiestnení pri aktualizácii knižnice Získavať náhľady a informácie o videu zo súboru Sady Priradiť náhľad sade filmov Exportovať náhľady hercov? - Vyberte FanArt Lokálny FanArt - Žiadny FanArt + Bez FanArt-u Aktuálny FanArt Internetový FanArt Zmeniť obsah - - Prajete si aktualizovať informácie pre + Aktualizovať informácie pre všetky položky v tomto umiestnení? FanArt Lokálne uložené informácie nájdené. Ignorovať a aktualizovať z internetu? - Nie je možné stiahnuť informácie - + Nepodarilo sa stiahnuť informácie Server je pravdepodobne nedostupný Chcete pokračovať v aktualizácii? Krajina epizóda epizódy Poslucháč - Poslucháči - Nastaviť fanart setu filmov - Set filmov - Zobraziť skryté súbory a priečinky + Nastaviť fanart kolekcii filmov + Kolekcia filmov + Zoskupovať filmy do kolekcií + Zobrazovať skryté súbory a priečinky TuxBox klient - POZOR: CieľovéTuxBox zariadenie je v nahrávacom móde! + POZOR: Cieľové TuxBox zariadenie je v nahrávacom režime! Stream bude zastavený! - Prepnutie na kanál: %s zlyhalo! Chcete spustiť stream? - Pripájam k: %s + Prebieha pripojenie k: %s TuxBox zariadenie Pridať zdieľané médiá... Zdielať video a hudobné knižnice pomocou UPnP - Upraviť zdieľanie média Odstrániť zdieľanie média Priečinok s titulkami Film a alternatívny priečinok s titulkami - Povoliť myš + Prepisovať ASS/SSA písmo titulkov + Aktivovať ovládanie myšou a podporu dotykových displejov Hrať zvuky navigácie počas prehrávania média - - Náhľad + Náhľady Vnútiť prehrávaču DVD región - Video zariadenie - Video vzhľad + Video výstup + Video aspekt Normálny Letterbox - Širokouhlý - Povoliť 480p - Povoliť 720p - Povoliť 1080i + Aktivovať 480p + Aktivovať 720p + Aktivovať 1080i Zadaj názov nového playlist-u - Zobraziť tlačítko "Pridať zdroj" v zozname súborov - - Povoliť rolovacie pruhy - Vytvoriť filtrovanie podľa sledovania vo video knižnici + Zobrazovať položku 'Pridať zdroj' v sekciách + Aktivovať Scrollbar + Aktivovať filter videných videí v knižnici Otvoriť - Úroveň akustickej správy + Správa akustickej úrovne Rýchly Tichý - - Povoliť vlastné pozadie - Úroveň správy napájania - Veľa energie - Málo energie - Veľká pohotovosť - Malá pohotovosť - + Aktivovať vlastné pozadie + Správa napájania + Vysoký výkon / Vyššia spotreba + Nízky výkon / Nízka spotreba + Spánok / Vyššia spotreba + Spánok / Nízka spotreba Súbory väčšie ako 4GB sa nedajú načítať do vyrovnávacej pamäte Kapitola Vysoko kvalitý Pixel Shader V2 - Povoliť playlist pri štarte - Použi trasúce animácie - obsahje - + Načítať playlist pri štarte + Použiť 'trasúce' animácie + obsahuje neobsahuje je nie je - začína s - končí s + začína na + končí na viac ako - menej ako - potom - predtým - nakoniec - vôbec nie + násl. + pred. + je posledný + nie je posledný Sťahovače - Predvolený sťahovač pre filmy Predvolený sťahovač pre TV seriály Predvolený sťahovač pre klipy - Povoliť odpoveď na základe jazyka sťahovača - - Nastavenia + Aktivovať odpoveď na základe jazyka sťahovača + - Nastavenie Viacjazyčný - Žiadne sťahovače nie sú k dispozícii - Nájst hodnotu + Nájsť hodnotu Pravidlá inteligentného playlist-u - Zhodné položky kde + Položky, kde Nové pravidlo... Položky sa musia zhodovať - - všetky pravidlá - jedno alebo viac pravidiel - S limitom + vo všetkých pravidlách + v minimálne jednom pravidle + Limit Bez limitu Usporiadať podľa - stúpajúci - - klesajúci + vzostupne + zostupne Upraviť inteligentný playlist Názov playlist-u - Hľadaj položky kde + Nájsť položky, kde Upraviť %i položiek - Nový inteligentný playlist... %c disk - Upraviť párty mód pravidlá - Domáci priečinok - Počet sledovaní + Upraviť pravidlá párty režimu + Domovský priečinok + Počet zhliadnutí Názov epizódy - Rozlíšenie videa Počet audio kanálov Kodek videa Koded audia - Jayzk audia + Jazyk audia Jazyk titulkov - - Diaľkový ovládač emuluje stlačenia klávesnice + Emulovať klávesnicu diaľkovým ovládaním - Upraviť - Je vyžadované internetové pripojenie. - Získať Viac... - Koreňový adresár súborového systému - + Vyžadované internetové pripojenie. + Získať viac... + Hlavný priečinok súborového systému + Medzipamäť plná + Medzipamäť plná pred dosiahnutím potrebného množstva pre nepretržité prehrávanie Umiestnenie titulkov - Fixné + Pevné V spodnej časti videa Pod videom V hornej časti videa Nad videom - Názov súboru - - Cesta k súboru + Umiestnenie súboru Veľkosť súboru Dátum/čas súboru Číslo stránky Rozlíšenie - Poznámka - - Farba/čb - Jpeg spracovanie + Komentár + Farba/Č&B + JPEG spracovanie Dátum/čas Popis Značka fotoaparátu Typ fotoaparátu - - Poznámka exif + EXIF poznámka Firmware Clona Ohnisková vzdialenosť - Vzdialenosť ohniska + Zaostrenie Expozícia - Čas expozície - Úprava expozície + Expozícia / bias Spôsob expozície Použitý blesk Vyváženie bielej Zdroj svetla - - Režim merania + Metering režim ISO Digitálne priblíženie CCD šírka GPS šírka GPS dĺžka - GPS výška Orientácia Doplnkové kategórie Kľučové slová Titul Autor - - Titulok + Nadpis Špeciálne inštrukcie Kategória Podtitul - Podtitul titulu + Názov podtitulu Hodnotenie - Zdroj Upozornenie o autorských právach Názov objektu Mesto Štát Krajina - - Oficiálny text distribútora + Pôvodná Tx Referencia Dátum vytvorenia Označenie autorských práv Kód krajiny Referenčná služba Povoliť ovládanie XBMC cez UPnP - Pokus o preskočenie úvodu pred DVD menu - Skopírované audio CD - Vyhľadať informácie o všetkých interprétoch + Uložená hudba + Akualizovať informácie všetkých interprétov Sťahujem informácie o albume Sťahujem informácie o interprétovy Životopis - Diskografia Hľadanie interpréta - Výber interpréta - Informácie interpréta + Vyberte interpréta + Informácie o interprétovy Nástroje - Narodený - - Založený - Žánre - Rozpadnutý - Zomrel + Dátum narodenia + Dátum založenia + Zameranie + Dátum rozpadu + Dátum smrti Aktívne roky - Názov - - Narodený/Založený + Label + Dátum Narodenia/Založenia Aktualizovať knižnicu pri štarte - Vždy aktualizovať knižnicu na pozadí - - DNS prípona + Aktualizovať knižnicu na pozadí / Skryť proces aktualizácie + - DNS suffix %2.3fs Oneskorené o %2.3fs - Vpredu o %2.3fs - Oneskorenie titulkov - OpenGL výrobca: - OpenGL karta: + Posunutie titulkov + OpenGL vendor: + OpenGL renderer: OpenGL verzia: - Teplota GPU - - Teplota CPU + Teplota GPU: + Teplota CPU: Celková Pamäť Údaje profilu - Povoliť stlmenie obrazovky počas pauzy videa + Aktivovať stlmenie obrazovky počas pozastaveného videa Všetky nahrávky Podľa názvu - Podľa skupiny Živé kanály Nahrávky podľa názvu Návod Odchylka pomeru strán k minimalizácii čiernych okrajov - Zobraziť videá v zozname súborov - - DirectX výrobca: + Zobrazovať videá v zozname súborov + DirectX: Direct3D verzia: Font - Veľkosť - Farba - Znaková sada - - Exportovať do HTML - Exportovať do CSV + Exportovať karaoke tituly do HTML + Exportovať karaoke tituly do CSV Importovať karaoke tituly... - Automaticky zobraziť dialóg pre výber skladby + Automaticky zobrazovať okno výberu skladby Exportovať karaoke tituly... - Vyber číslo skladby - + Zadajte číslo skladby biela/zelená biela/červená biela/modrá čierna/biela - Predvolené akcie pri výbere položky - Zobraziť ponuku - + Predvolená akcia pri výbere položky + Vybrať Zobraziť informácie Viac... Prehrať všetko Teletext nie je k dispozícii Povoliť teletext Časť %i - Prebieha načítanie %i bajtov Prebieheha ukončovanie Prebieha spustenie - Externý Prehrávač Je Aktívny + Externý Prehrávač Aktívny Kliknite OK pre zatvorenie prehrávača Kliknite OK po ukončení prehrávania - Doplnok Doplnky Nastavenia doplnku - Informácie doplnku + Informácie o doplnku Zdroje médií Informácie o filme - Šetrič obrazovky Skript Vizualizácia Repozitár doplnkov Titulky Texty skladieb - - Informácie o TV seriáli + Informácie o TV Informácie o klipe Informácie o albume Informácie o interprétovy Služby - Nastavenie - + Nastaviť Deaktivovať Aktivovať Doplnok je deaktivovaný Počasie Weather.com (štandardný) - Tento doplnok nejde konfigurovať - + Tento doplnok sa nedá nastaviť Chyba pri načítaní konfigurácie nastavenia - Všetky Doplnky - Získať Doplnky + Všetky doplnky + Získať doplnky Skontrolovať aktualizácie Vynútiť obnovu Zmeny - Odinštalovať - Nainštalovať + Inštalovať Deaktivované Doplnky (Vyčistiť aktuálne nastavenia) Inštalovať doplnky zo zip archívu Stiahnuté %i%% - Dostupné aktualizácie Závislosti sa nestretli Doplnok nemá správnu štruktúru %s je použitá následovným nainštalovaným doplnkom Tento doplnok sa nedá odinštalovať - Návrat - + Obnoviť zmeny Dostupné doplnky Verzia: Upozornenie Licencia: Zmeny - Želáte si aktivovať tento doplnok? - - Želáte si deaktivovať tento doplnok? - Je k dispozícii aktualizácia doplnku! + Prajete si aktivovať tento doplnok? + Prajete si deaktivovať tento doplnok? + Aktualizácia doplnku je k dispozícii! Aktivované Doplnky Auto. aktualizácie Doplnok bol aktivovaný Doplnok bol aktualizovaný - Naozaj chcete zrušiť sťahovanie doplnku? Momentálne sťahované doplnky Aktualizácia k dispozícii Aktualizovať Načítanie doplnku sa nepodarilo. Objavila sa neznáma chyba. - Vyžadovaná zmena nastavení Nedá sa pripojiť Je vyžadovaný reštart @@ -2391,130 +2062,151 @@ Potrebný doplnok Pokúsiť sa o opätovné pripojenie? Doplnok sa reštartuje - - Uzamknutie správcu doplnkov + Zamknúť správcu doplnkov (aktuálny) (na čiernej listine) Doplnok bol v repozitáry označený ako nefunkčný. Chcete ho deaktivovať? Nefunkčný - - Želáte si použiť tento skin? - Pre použite tejto funkcie potrebujete stiahnuť Doplnok: - Želáte si stiahnuť tento doplnok? + Prajete si použiť tento vzhľad? + Pre používanie tejto funkcie je potrebné stiahnuť doplnok: + Prajete si stiahnuť tento doplnok? Notifikácie - Knižničný mód + Režim knižnice QWERTY klávesnica - Audio je preposielané receiveru - Kvalita traileru - + Preposielané audio + Kvalita ukážky Streamovať Stiahnuť Stiahnuť a prehrať Stiahnuť a uložiť Dnes Zajtra - Prebieha ukladanie Prebieha kopírovanie - Nastaviť adresár pre sťahovanie - Doba vyhladávania + Nastaviť priečinok pre sťahovanie + Doba vyhľadávania Krátky Dlhý - - Použiť DVD prehrávač namiesto bežného prehrávača + Používať DVD prehrávač namiesto bežného prehrávača Pred prehrávaním videa sa spýtať na jeho stiahnutie Klipy Pre aktiváciu reštartujte doplnok Dnes večer Zajtra večer - Stav Zrážky Zrážky Vlhkosť - zdá sa ako + Zdá sa ako Pozorované - Odchylka od normálu Východ slnka Západ slnka Detaily - Outlook + Výhľad Coverflow - Preložiť text Namapovať zoznam %s kategórie 36 Hodín Mapy Hodinu Víkend - %s deň Upozornenie Upozornenia Vyberte Vašu Zkontrolovať Nastaviť - Sezóny Použiť - Sledovať + Pozerať Počúvať Prezerať - Konfigurovať - + Nastaviť Vypnutie Menu Prehrať Nastavenia Editor O. . . - Hodnotenie Pozadie Pozadia Vlastné pozadie Vlastné pozadia Zobraziť Readme - Zobraziť Históriu zmien - Pre spustenie tejto verzie %s je vyžadovaná + Pre spustenie tejto verzie %s je potrebná XBMC revízia %s alebo vyššia. Prosím aktualizujte XBMC. Žiadne dáta neboly nájdené! Ďalšia strana - Milovať Nenávidieť - Tento súbor sa skladá z viac častí. Vyberte tu, od ktorej chcete spustit prehrávanie. - Cesta ku skriptu + Tento súbor sa skladá z viacero častí. Vyberte tú, od ktorej chcete spustiť prehrávanie. + Umiestnenie skriptu Povoliť vlastné tlačítko skriptu Nepodarilo sa začať - Webserver - Server Udalostí + Server udalostí Vzdialený komunikačný server + Zistené nové pripojenie Lame Vorbis Wav - DXVA2 VAAPI Flac - Nastavenie Reproduktorov + Nastavenie reproduktorov 2.0 2.1 - 3.0 3.1 4.0 4.1 5.0 5.1 - 7.0 7.1 - Nie je možné nájsť ďalšiu položku pre prehratie - Nie je možné nájsť predošlú položku pre prehratie - + Nepodarilo sa nájsť ďalšiu položku + Nepodarilo sa nájsť predošlú položku + Spustenie zeroconf zlyhalo + Je Apple Bonjour služba nainštalovaná? Pozri log pre viac informácií. + Vykreslovanie videa + Video filtrovanie/škálovanie zlyhalo, použitie bilineárneho škálovania. + Nepodarilo sa inicializovať audio zariadenia + Skontrolujte Vaše audio nastavenia + Periférne zariadenia + HID zariadenie + Sieťová karta + Pevný disk + Pre toto periférne zariadenie nie sú žiadne nastavenia dostupné. + Nové zariadenie nakonfigurované + Zariadenie odstránené + Rozloženie kláves pre toto zariadenie + Rozloženie kláves povolené + Umiestnenie + Trieda + Meno + Výrobca + ID produktu + Pulse-Eight CEC adaptér + Pulse-Eight Nyxboard + Prepnúť na príkazy klávesnice + Prepnúť na príkazy diaľkového ovládania + Stlačte tlačidlo príkazu 'užívateľ' (USER) + Aktivovať prepnutie strán príkazov + Adaptér sa nedá otvoriť + Zapnúť TV pri spúšťaní XBMC + Vypnúť zariadenia pri ukončení XBMC + Aktivovať pohotovostný režim zariadení pri spustení šetriča obrazovky + Nepodarilo sa zistiť CEC port. Nastavte ho manuálne. + Nepodarilo sa zistiť CEC adaptér. + Nepodporovaná verzia libcec rozhrania. %d je vyššia ako XBMC podporuje (%d) + Aktivovať pohotovstný režim PC pri vypnutí TV + HDMI portu + Pripojené + Adaptér nájdený, libcec nie je dostupný + Použiť nastavenia jazyku TV + \ No newline at end of file diff --git a/language/Slovenian/strings.xml b/language/Slovenian/strings.xml index 8f8d425..b2a1de9 100644 --- a/language/Slovenian/strings.xml +++ b/language/Slovenian/strings.xml @@ -1013,6 +1013,8 @@ Pomanjšaj Ukaz gumba za izklop Izključi sistem + Spodbudi izklop ob nedejavnosti + Omogoči izklop ob nedejavnosti Je druga seja aktivna, ssh? Priključen zunanji trdi disk @@ -1543,12 +1545,459 @@ Spline36 Spline36 optimized Programski Blend + Samodejno - Optimizirano za ION Post-procesiranje Prikaži čas to zamaknjenega izklopa - Preklopi na kanal + %i MBajtov + %i ur + %i dni + + + Preklopi na program + Ločite iskalne besede z AND (in), OR (ali) in/ali NOT (brez). + ali uporabite celotne fraze, kot je "Čarovnik iz Oza". + Poišči podobne oddaje + Uvažam EPG iz odjemalcev + Informacija o pretoku PVR + Naprava zajema + Status naprave + Kakovost signala + SNR + BER + UNC + Hrbtenica PVR + Brezplačno + Fiksno + Enkripcija + Hrbtenica PVR %i - %s + Posnetki TV + Privzeta mapa za sličice PVR + Programi + TV + Radio + Skrito + TV programi + Radio programi + Prihajajoča snemanja + Dodaj časovnik... + Ni rezultatov iskanja + Ni vnosov EPG + Program + Trenutno + Naslednje + Časovni trak + Informacije + Snemanje na tem programu se je že pričelo + Tega programa ni mogoče predvajati. Preverite zapisnik za podrobnosti. + Tega posnetka ni mogoče predvajati. Preverite zapisnik za podrobnosti. + Prikaži kakovost signala + Ni podprto s strani hrbtenice PVR. + Ste prepričani, da želite skriti ta program? + Časovnik + Ste prepričani, da želite preimenovati ta posnetek? + Ste prepričani, da želite preimenovati ta posnetek? + Snemanje + Preverite svoje nastavitve ali pa poiščite več informacij v zapisniku. + Noben odjemalec PVR še ni bil zagnan. Počakajte na odjemalce PVR ali pa poiščite več informacij v zapisniku. + Nov program + Informacija o oddaji + Upravljanje skupin + Prikaži program + Prikaži vidne programe + Prikaži skrite programe + Premakni program v: + Informacija o posnetku + Skrij program + Informacija ni na voljo + Nov časovnik + Uredi časovnik + Časovnik vključen + Ustavi snemanje + Izbriši časovnik + Dodaj časovnik + Razvrsti: Program + Pojdi na začetek + Pojdi na konec + Privzeto okno EPG + Prenašam posnetke z odjemalcev + Ta oddaja je že bila posneta. + Posnetka ni mogoče izbrisati. Preverite zapisnik za podrobnosti. + EPG + Čas iskanja EPG + Interval posodabljanja EPG + Ne skranjuj EPG v bazi + Zamakni preklop programa + Aktivno: + Ime: + Mapa: + Radio: + Program: + Dan: + Začetek: + Konec: + Prioriteta: + Življenjska doma (dnevi): + Prvi dan: + Neznan program %u + Po-__-__-__-__-__-__ + __-To-__-__-__-__-__ + __-__-Sr-__-__-__-__ + __-__-__-Če-__-__-__ + __-__-__-__-Pe-__-__ + __-__-__-__-__-So-__ + __-__-__-__-__-__-Ne + Po-To-Sr-Če-Pe-__-__ + Po-To-Sr-Če-Pe-So-__ + Po-To-Sr-Če-Pe-So-Ne + __-__-__-__-__-So-Ne + Vnesite ime za to snemanje + Opozorilo + Prisoten časovnik + Ste prepričani, da želite izbrisati ta program, vključno z vsemi njegovimi časovniki? + Ta program se trenutno predvaja. + Preklopite na drug program. + Poišči manjkajoče ikone + Vnesite ime mape za snemanje + Velikost: + Naslednji časovnik + ob + Snemanja niso sinhronizirana. Preverite zapisnik za podrobnosti. + Časovnika ni mogoče shraniti. Preverite zapisnik za podrobnosti. + Zgodila se je nepričakovana napaka. Poskusite znova ali pa poiščite več informacij v zapisniku. + Napaka v hrbtenici PVR. Preverite zapisnik za podrobnosti. + Časovniki niso sinhronizirani. Preverite zapisnik za podrobnosti. + Naslednje + Različica + Naslov + Velikost + Išči programe + PVR funkcij ni mogoče uporabljati med iskanjem. + Na katerem strežniku želite iskati? + Številka odjemalca + Izogni se ponavljanjem + Časovnik se še vedno snema. Ste prepričani, da ga želite izbrisati? + Samo brezplačni programi + Zanemari prisotne časovnike + Zanemari prisotne posnetke + Začetni čas + Končni čas + Začetni datum + Končni datum + Najmanjše trajanje + Največje trajanje + Vključi neznane žanre + Ključne besede + Vključi opis + Občutljivo na velikosti črk + Program ni na voljo + Ni definiranih skupin + Najprej ustvarite skupino + Ime nove skupine + Skupina + Preišči vodič + Upravljanje skupin + Ni definiranih skupin + V skupini + Skupine + Hrbtenica PVR ne podpira tega ukaza. Preverite zapisnik za podrobnosti. + Program + Po + To + Sr + Če + Pe + So + Ne + od + Naslednje snemanje + Trenutno snemam + od + do + Na + Aktivno snemanje + Posnetki + Snemanja ni mogoče pričeti. Preverite zapisnik za podrobnosti. + Preklopi + Informacije o PVR + Poišči manjkajoče ikone + Preklopi programe brez pritiska na OK + Skrij informacijo o videu + Zamik pri začetku predvajanja + Predvajanje prični pomanjšano + Takošnje trajanje snemanja + Privzeta prioriteta snemanja + Privzeta življenjska doba snemanja + Območje na začetku snemanja + Območje na koncu snemanja + Predvajanje + Prikažite informacijo o programu, ko prekljapljate med njimi + Samodejno skrij informacijo o programu + TV + Meni/OSD + Količina prikazanih dni v EPG + Trajanje informacij o programu + Ponastavi bazo PVR + Vsi podatki v bazi PVR bodo izbrisani + Ponastavi bazo EPG + EPG se ponastavlja + Nadaljuj zadnji program ob zagonu + Minimirano + Storitev PVR + Nobena povezana hrbtenica PVR ne podpira iskanja programov. + Iskanja programov ni mogoče pričeti. Preverite zapisnik za podrobnosti. + Nadaljujem? + Ukazi odjemalca + Specifični ukazi odjemalca PVR + Snemanje se je pričelo: %s + Snemanje se je končalo: %s + Upravljalec programov + Vir EPG: + Ime programa: + Ikona programa: + Uredi program + Nov program + Upravljanje skupin + Aktiviran EPG: + Skupina: + Vnesite ime novega programa + Navidezna hrbtenica XBMC + Odjemalec + Izbriši program + Ta seznam vsebuje spremembe + Izberi hrbtenico + Vnesite veljaven URL za nov program + Hrbtenica PVR ne podpira časovnikov. + Vsi radijski progami + Vsi TV programi + Vidno + Programi brez skupine + Programi v + Sinhroniziraj skupine programov s hrbtenico + EPG + Nobenega dodatka PVR ni mogoče vključiti. Preverite svoje nastavitve ali pa poiščite več informacij v zapisniku. + Preklicano snemanje + Nastavljeno snemanje + Pričeto snemanje + Zaključeno snemanje + Izbrisano snemanje + Zapri OSD po preklapljanju programov + Onemogoči posodobitve EPG med predvajanjem + Vedno uporabi vrstni red programov s hrbtenic(e) + Počisti rezultate iskanja + Prikaži obvestila o spremembah časovnikov + Uporabi številke programov s hrbtenice (samo pri enem vključenem dodatku PVR) + Upravljalec PVR se zaganja + uvažanje programov + uvažanje časovnikov + uvažanje posnetkov + zaganjanje niti v ozadju + Noben dodatek PVR ni omogočen + Upravljalec PVR je bil omogočen brez + omogočenih dodatkov. Omogočite vsaj enega + za uporabo funkcionalnosti PVR. + + Čas nedejavnosti hrbtenice + Nastavi ukaz za zbujanje (cmd [timestamp]) + Zbudi se pred snemanjem + Dnevno zbujanje + Čas dnevnega zbujanja (HH:MM:SS) + + Drugo/Neznano + Film/Drama + Detektivka/Triler + Pustolovščina/Vestern/Vojni + Znanstvena fantastika/Fantazija/Grozljivka + Komedija + Nadaljevanka/Melodrama/Folklora + Romanca + Resno/Klasično/Versko/Zgodovinski film/Drama + Film za odrasle/Drama + + + + + + + + Novice/Trenutni dogodki + Novice/Vremenska napoved + Novice + Dokumentarec + Pogovor/Intervju/Debata + + + + + + + + + + + + Šov/Igra + Igra/Kviz/Tekmovanje + Šov + Pogovorna oddaja + + + + + + + + + + + + + Šport + Posebni dogodek + Športna oddaja + Nogomet + Tenis/Squash + Ekipni športi + Atletika + Avtomobilizem + Vodni športi + Zimski športi + Jahanje + Borilne veščine + + + + + Otroška/Mladinska oddaja + Oddaja za predšolsko mladino + Zabavna oddaja od 6 do 14 let + Zabavna oddaja od 10 do 16 let + Informativna/Izobraževalna/Šolska oddaja + Risanka/Lutke + + + + + + + + + + + Glasba/Balet/Ples + Rock/Pop + Resna/Klasična glasba + Narodnozabavna/Tradicionalna glasba + Musical/Opera + Balet + + + + + + + + + + + Umetnost/Kultura + Predstava + Slikarstvo + Verstva + Popularna/Tradicionalna umetnost + Literatura + Film/Kino + Eksperimentalni Film/Video + Oddajanje/Mediji + Novi mediji + Umetnost/Kulturna oddaja + Moda + + + + + Družba/Politika/Ekonomija + Poročilo/Dokumentarec + Ekonomija/Svetovanje + Znane osebe + + + + + + + + + + + + + Izobraževanje/Znanost/Dejstva + Narava/Živali/Okolje + Tehnologija/Naravoslovje + Medicina/Fiziologija/Psihologija + Tuje dežele/Odprave + Družba/Duhovnost + Nadaljnje izobraževanje + Jeziki + + + + + + + + + Sprostitev/Hobi + Turizem/Potovanja + Rokodelstvo + Avto-moto + Kondicija & Zdravje + Kuhanje + Oglaševanje/Nakupovanje + Vrtnarstvo + + + + + + + + + Posebne značilnosti + Prvotni jezik + Črno & Belo + Neobjavljeno + Prenos v živo + + + + + + + + + + + + Drama + Detektivka/Triler + Postolovščina/Vestern/Vojni + Znanstvena fantastika/Fantazika/Grozljivka + Komedija + Nadaljevanka/Melodrama/Folklora + Romanca + Resno/Klasično/Versko/Zgodovinsko + Za odrasle + + + + + + + Mapa za shranjeno glasbo Uporabi zunanji DVD predvajalnik @@ -2188,6 +2637,7 @@ Informacije o albumih Informacije o izvajalcih Storitve + Odjemalci PVR Prilagodi Onemogoči @@ -2223,7 +2673,7 @@ Želite omogočiti ta dodatek? Želite onemogočiti ta dodatek? Na voljo je posodobitev dodatka! - Omogočeni dodatki + Nameščeni dodatki Samodejna posodobitev Dodatek je omogočen Dodatek je posodobljen diff --git a/language/Swedish/strings.xml b/language/Swedish/strings.xml index 1c5e26f..e2bf93d 100644 --- a/language/Swedish/strings.xml +++ b/language/Swedish/strings.xml @@ -1415,6 +1415,440 @@ den här visualiseringen Efterbearbetning Visa insommningstimeout Byt till kanal + Separera sökorden genom att använda AND, OR och/eller NOT. + eller använd en fraser för att hitta en exakt matchning, exempelvis "The wizard of Oz". + Sök liknande program + Importera EPG från klienter + PVR ströminformation + Mottagarenhet + Status för mottagarenhet + Signalkvalitet + SNR + BER + UNC + PVR Backend + Frivisning + Låst + Kryptering + PVR Backend %i - %s + TV inspelningar + Standardmapp för PVR miniatyrer + Kanaler + TV + Radio + Gömda + TV kanaler + Radiokanaler + Kommande inslepningar + Lägg till timer... + Inga sökresultat + Inga EPG poster + Kanal + Nu + Nästa + Tidslinje + Information + Inspelning redan startad på denna kanal + Denna kanal kan inte spelas upp. Se loggen för mer information. + Denna inspelning kan inte spelas upp. Se loggen för mer information. + Visa signalkvalitet + Stödjs inte av PVR backendet + Är du säker att du vill gömma denna kanal? + Timers + Är du säker att du vill döpa om denna inspelning? + Är du säker att du vill döpa om denna timer? + Inspelning + Var god se över din konfiguration eller se loggen för mer information. + Inga PVR klienter har startats. Vänta tills att PVR klienterna har slutfört uppstarten, eller se loggen för mer information. + Ny kanal + Programinformation + Grupphantering + Visa kanal + Visa synliga kanaler + Visa gömda kanaler + Flytta kanal till: + Inspelningsinformation + Dölj kanal + Ingen information tillgänglig + Ny timer + Ändra timer + Timer aktiverad + Stoppa inspelning + Radera timer + Lägg till timer + Sortera efter: Kanal + Gå till början + Gå till slutet + Förvalt EPG fönster + Laddar inspelningar från klienter + Detta event spelas redan in. + Denna inspelning kunde inte raderas. Se loggen för mer information. + EPG + EPG-skanning timeout + Uppdateringsintervall för EPG + Lagra inte EPG i databasen + Fördröjning vid kanalbyte + Aktiv: + Namn: + Mapp: + Radio: + Kanal: + Dag: + Startar: + Slutar: + Prioritet: + Livstid (dagar): + Första dagen: + Okänd kanal %u + Må-__-__-__-__-__-__ + __-Ti-__-__-__-__-__ + __-__-On-__-__-__-__ + __-__-__-To-__-__-__ + __-__-__-__-Fr-__-__ + __-__-__-__-__-Lö-__ + __-__-__-__-__-__-Sö + Må-Ti-On-To-Fr-__-__ + Må-Ti-On-To-Fr-Lö-__ + Må-Ti-On-To-Fr-Lö-Sö + __-__-__-__-__-Lö-Sö + Ange namn för inspelningen + Varning + Timer närvarande + Är du säker att du vill ta bort denna kanal, inklusive kanalens alla timers? + Denna kanal för närvarande för uppspelning. + Var god byt till en annan kanal. + Skanna efter saknade kanalikoner + Ange mappnamn för inspelningen + Storlek: + Nästa timer den + vid + Inspelningarna är inte synkroniserade. Se loggen för mer information. + Kunde inte spara timern. Se loggen för mer information. + Ett oväntat fel inträrrade. Försök igen senare eller se loggen för mer information. + PVR backend fel. Se loggen för mer information. + Timers är inte synkroniserade. Se loggen för mer information. + Nästa + Version + Adress + Diskstorlek + Sök efter kanaler + PVR-funktionaliteten kan inte användas under pågående sökning. + På vilken server vill du söka? + Klientnummer + Unvik upprepningar + Denna inspelning är fortfarande aktiv. Är du säker att du vill ta bort denna timer? + Endast frivisningskanaler + Ignorera nuvarande timers + Ignorera nuvarande inspelningar + Starttid + Sluttid + Startdatum + Slutdatum + Varaktighetsminimum + Varaktighetsmaximum + Inkludera okända genrer + Söksträng + Inkludera beskrivning + Skiftlägeskänslig + Kanal ej tillgänglig + Inga grupper definerade + Var god skapa en grupp först + Den nya gruppens namn + Grupp + Sökguiden + Grupphantering + Inga grupper definerade + Grupperad + Grupper + Detta PVR backend stödjer inte denna handling. Se loggen för mer information. + Kanal + + Ti + On + To + Fr + + + från + Nästa inspelning + Nuvarande inspelning + från + till + Den + Aktiv inspelning + Inspelningar + Kunde inte starta inspelningen. Se loggen för mer information. + Byt till + PVR information + Skanna efter saknade ikoner + Byt kanal utan att trycka OK + Göm videoinformationsfönster + Tidsgräns för uppspelningsförsök + Starta uppspelningar minimerad + Varaktighet vid direktinspelning + Standardprioritet för inspelning + Standardlivstid för inspelning + Marginal vid början av en inspelning + Marginal vid slutet av en inspelning + Uppspelning + Visa kanalinformation vid kanalbyte + Göm kanalinformation automatiskt + TV + Meny/OSD + Antal dagar att visa i EPG + Kanalinformationens varaktighet + Töm PVR-databasen + All data i PVR databasen kommer att raderas + Töm EPG databasen + EPG raderas + Starta senaste kanalen vid uppstart + Minimerad + PVR tjänst + Ingen av dom anslutna PVR backenden stödjer kanalsökning. + Kanalen kunde inte startas. Se loggen för mer information. + Fortsätt? + Klienthandlingar + PVR klients specifika handlingar + Inspelningen startades: %s + Inspelningen slutfördes: %s + Kanalhanterare + EPG källa: + Kanalnamn: + Kanalikon: + Editera kanal + Ny kanal + Grupphantering + Aktivera EPG: + Grupp: + Ange den nya kanalens namn + XBMC virtuell backend + Klient + Ta bort kanal + Denna lista innehåller ändringar + Välj backend + Ange en korrekt URL för den nya kanalen + PVR backendet stödjer inte timers. + Alla radiokanaler + Alla TV kanaler + Synliga + Ogrupperade kanaler + Kanaler i + Synkronisera kanalgrupper med backend(s) + EPG + Inget PVR tillägg kunde aktiveras. Kontrollera dina inställningar eller se loggen för mer information. + Inspelning avbryten + Inspelning schemalagd + Inspelning startad + Inspelning slutförd + Inspelning raderad + Stäng kanalens OSD efter kanalbyte + Förhindra EPG uppdateringar vid aktiv TV strömmning + Använd alltid kanalnumrering från backend(s) + Rensa sökresultaten + Visa informationsfönster vid timeruppdateringar + Använd backends kanalnumrering (fungerar enbart med ett aktiverat PVR tillägg) + PVR hanteraren startar + importerar kanaler + importerar timers + importerar inspelningar + startar bakgrundstrådar + Inget PVR tillägg aktiverad + PVR hanteraren har startats utan något aktiverat PVR tillägg. + Aktivera åtminstånde ett PVR tillägg för att + aktivera PVR funktionaliteten. + Övrigt/Okänt + Film/Drama + Detektiv/Thriller + Äventyr/Västern/Krig + Science Fiction/Fantasi/Skräck + Komedi + Såpa/Melodrama/Folkloristisk + Romans + Allvarsam/Klassisker/Religös/Historisk Film/Drama + Vuxenfilm/Drama + + + + + + + + Nyheter/Aktuella händelser + Nyheter/Väder + Nyhetsmagasin + Dokumentär + Diskussion/Intervju/Debatt + + + + + + + + + + + + Föreställning/Spelföreställning + Game show/Frågesport/Tävling + Varitetsföreställning + Talkshow + + + + + + + + + + + + + Sport + Speciellt evenemang + Sportmagasin + Amerikans fotboll + Tennis/Squash + Lagsport + Gymnastik + Motorsport + Vattensport + Vinterports + Ridsport + Kampsport + + + + + Barnprogram/Ungdomsprogram + Program för förskolebarn + Underhållningsprogram för 6 till 14 år + Underhållningsprogram för 10 till 16 år + Information/Utbildning/Skolprogram + Tecknat/Marionett + + + + + + + + + + + Musik/Ballett/Dans + Rock/Pop + Allvarlig/Klassisk musik + Folk/Traditionell musik + Musikal/Opera + Ballett + + + + + + + + + + + Konst/Kultur + Scenkonst + Finkultur + Religion + Populärkultur/Traditionell konst + Litteratur + Film/Biograf + Experimentell film/Video + Utsändning/Press + New Media + Konst/Kulturmagasin + Mode + + + + + Social/Politisk/Ekonomi + Magasin/Rapporter/Dokumentär + Ekonomi/Social rådgivning + Anmärkningsvära människor + + + + + + + + + + + + + Utbildning/Vetenskap/Fakta + Natur/Djur/Miljö + Teknik/Naturvetenskap + Medicin/Fysiologi/Psykologi + Främmande länder/Expeditioner + Social/Andlig vetenskap + Ytterligare utbildning + Språk + + + + + + + + + Fritid/Hobby + Turism/Resa + Hantverk + Motor + Motion & hälsa + Matlagning + Annonsering/Shopping + Trädgårdsskötsel + + + + + + + + + Speciella egenskaper + Hemspråk + Svartvitt + Opublicerat + Direktsändning + + + + + + + + + + + + Drama + Detektiv/Thriller + Äventyr/Västern/Krig + Science Fiction/Fantasi/Skräck + Komedi + Såpa/Melodrama/Folkloristisk + Romantik + Allvarlig/Klassisk religion/Historia + Vuxen + + + + + + + Mapp för sparad musik Använd extern DVD-spelare Extern DVD-spelare diff --git a/lib/addons/library.xbmc.addon/Makefile.in b/lib/addons/library.xbmc.addon/Makefile.in new file mode 100644 index 0000000..cd8b009 --- /dev/null +++ b/lib/addons/library.xbmc.addon/Makefile.in @@ -0,0 +1,27 @@ +ARCH=@ARCH@ +INCLUDES=-I. -I../../../xbmc/addons/include -I../../../xbmc +DEFINES+= +CXXFLAGS=-fPIC +LIBNAME=libXBMC_addon +OBJS=$(LIBNAME).o + +LIB_SHARED=../../../addons/library.xbmc.addon/$(LIBNAME)-$(ARCH).so + +all: $(LIB_SHARED) + +$(LIB_SHARED): $(OBJS) +ifeq ($(findstring osx,$(ARCH)), osx) + $(CXX) $(LDFLAGS) -Wl,-alias_list,@abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper_mach_alias \ + -bundle -undefined dynamic_lookup -read_only_relocs suppress -o $@ \ + @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o $(OBJS) +else + $(CXX) $(CFLAGS) $(LDFLAGS) -shared -g -o $(LIB_SHARED) $(OBJS) +endif + +CLEAN_FILES = \ + $(LIBNAME).so \ + +DISTCLEAN_FILES= \ + Makefile \ + +include ../../../Makefile.include diff --git a/lib/addons/library.xbmc.addon/libXBMC_addon.cpp b/lib/addons/library.xbmc.addon/libXBMC_addon.cpp new file mode 100644 index 0000000..009618f --- /dev/null +++ b/lib/addons/library.xbmc.addon/libXBMC_addon.cpp @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2005-2010 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 +#include +#include +#include +#include "../../../addons/library.xbmc.addon/libXBMC_addon.h" +#include "../../../xbmc/addons/AddonCallbacks.h" + +#ifdef _WIN32 +#include +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif + + +using namespace std; +using namespace ADDON; + +AddonCB *m_Handle = NULL; +CB_AddOnLib *m_cb = NULL; + +extern "C" +{ + +DLLEXPORT int XBMC_register_me(void *hdl) +{ + if (!hdl) + fprintf(stderr, "libXBMC_addon-ERROR: XBMC_register_me is called with NULL handle !!!\n"); + else + { + m_Handle = (AddonCB*) hdl; + m_cb = m_Handle->AddOnLib_RegisterMe(m_Handle->addonData); + if (!m_cb) + fprintf(stderr, "libXBMC_addon-ERROR: XBMC_register_me can't get callback table from XBMC !!!\n"); + else + return 1; + } + return 0; +} + +DLLEXPORT void XBMC_unregister_me() +{ + if (m_Handle && m_cb) + m_Handle->AddOnLib_UnRegisterMe(m_Handle->addonData, m_cb); +} + +DLLEXPORT void XBMC_log(const addon_log_t loglevel, const char *format, ... ) +{ + if (m_cb == NULL) + return; + + char buffer[16384]; + va_list args; + va_start (args, format); + vsprintf (buffer, format, args); + va_end (args); + m_cb->Log(m_Handle->addonData, loglevel, buffer); +} + +DLLEXPORT bool XBMC_get_setting(const char* settingName, void *settingValue) +{ + if (m_cb == NULL) + return false; + + return m_cb->GetSetting(m_Handle->addonData, settingName, settingValue); +} + +/*DLLEXPORT bool XBMC_update_setting(const char* settingName, void *settingValue) +{ + if (m_cb == NULL) + return false; + + return m_cb->UpdateSetting(m_Handle->addonData, settingName, settingValue); +}*/ + + +DLLEXPORT void XBMC_queue_notification(const queue_msg_t type, const char *format, ... ) +{ + if (m_cb == NULL) + return; + + char buffer[16384]; + va_list args; + va_start (args, format); + vsprintf (buffer, format, args); + va_end (args); + m_cb->QueueNotification(m_Handle->addonData, type, buffer); +} + +DLLEXPORT void XBMC_unknown_to_utf8(string &str) +{ + if (m_cb == NULL) + return; + + string buffer = m_cb->UnknownToUTF8(str.c_str()); + str = buffer; +} + +DLLEXPORT const char* XBMC_get_localized_string(int dwCode) +{ + if (m_cb == NULL) + return ""; + + return m_cb->GetLocalizedString(m_Handle->addonData, dwCode); +} + +DLLEXPORT const char* XBMC_get_dvd_menu_language() +{ + if (m_cb == NULL) + return ""; + + return m_cb->GetDVDMenuLanguage(m_Handle->addonData); +} + +DLLEXPORT const char* XBMC_get_localized_date(time_t time, bool bLongDate, bool bWithShortNames) +{ + if (m_cb == NULL) + return ""; + + return m_cb->GetLocalizedDate(m_Handle->addonData, time, bLongDate, bWithShortNames); +} + +DLLEXPORT const char* XBMC_get_localized_time(time_t time, bool bWithSeconds) +{ + if (m_cb == NULL) + return ""; + + return m_cb->GetLocalizedTime(m_Handle->addonData, time, bWithSeconds); +} + +}; diff --git a/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj b/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj new file mode 100644 index 0000000..e4339a5 --- /dev/null +++ b/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj @@ -0,0 +1,89 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7} + XBMC_VDR + Win32Proj + + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ..\..\..\..\..\addons\library.xbmc.addon\ + Debug\ + ..\..\..\..\..\addons\library.xbmc.addon\ + Release\ + + + + Disabled + ..\..\..\..\..\xbmc\addons\include;..\..\..\..\..\xbmc\addons;..\..\..\..\..\xbmc\cores\dvdplayer\DVDDemuxers;..\..\..\..\..\xbmc;%(AdditionalIncludeDirectories) + _WIN32;_DEBUG;_WINDOWS;VDR_EXPORTS;_WIN32PC;_WINSOCKAPI_;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Sync + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + ..\..\..\..\..\addons\library.xbmc.addon\$(ProjectName).dll + true + + + + + ..\..\..\..\..\xbmc\addons\include;..\..\..\..\..\xbmc\addons;..\..\..\..\..\xbmc\cores\dvdplayer\DVDDemuxers;..\..\..\..\..\xbmc;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;HAS_SDL_OPENGL;HAS_SDL;_USRDLL;XBMC_VDR_EXPORTS;_WIN32PC;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + Sync + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + ..\..\..\..\..\addons\library.xbmc.addon\$(ProjectName).dll + + + + + + + + + + + + \ No newline at end of file diff --git a/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj.filters b/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj.filters new file mode 100644 index 0000000..916673c --- /dev/null +++ b/lib/addons/library.xbmc.addon/project/VS2010Express/libXBMC_addon.vcxproj.filters @@ -0,0 +1,19 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + + + Source Files + + + \ No newline at end of file diff --git a/lib/addons/library.xbmc.gui/Makefile.in b/lib/addons/library.xbmc.gui/Makefile.in new file mode 100644 index 0000000..b5df484 --- /dev/null +++ b/lib/addons/library.xbmc.gui/Makefile.in @@ -0,0 +1,27 @@ +ARCH=@ARCH@ +INCLUDES=-I. -I../../../xbmc/addons/include -I../../../xbmc -I../../../xbmc/cores/dvdplayer/DVDDemuxers +DEFINES+= +CXXFLAGS=-fPIC +LIBNAME=libXBMC_gui +OBJS=$(LIBNAME).o + +LIB_SHARED=../../../addons/library.xbmc.gui/$(LIBNAME)-$(ARCH).so + +all: $(LIB_SHARED) + +$(LIB_SHARED): $(OBJS) +ifeq ($(findstring osx,$(ARCH)), osx) + $(CXX) $(LDFLAGS) -Wl,-alias_list,@abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper_mach_alias \ + -bundle -undefined dynamic_lookup -read_only_relocs suppress -o $@ \ + @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o $(OBJS) +else + $(CXX) $(CFLAGS) $(LDFLAGS) -shared -g -o $(LIB_SHARED) $(OBJS) +endif + +CLEAN_FILES = \ + $(LIB_SHARED) \ + +DISTCLEAN_FILES= \ + Makefile \ + +include ../../../Makefile.include diff --git a/lib/addons/library.xbmc.gui/libXBMC_gui.cpp b/lib/addons/library.xbmc.gui/libXBMC_gui.cpp new file mode 100644 index 0000000..1e74e75 --- /dev/null +++ b/lib/addons/library.xbmc.gui/libXBMC_gui.cpp @@ -0,0 +1,673 @@ +/* + * Copyright (C) 2005-2010 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 +#include +#include +#include +#include "../../../addons/library.xbmc.gui/libXBMC_gui.h" +#include "addons/AddonCallbacks.h" + +#ifdef _WIN32 +#include +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif + +using namespace std; + +AddonCB *m_Handle = NULL; +CB_GUILib *m_cb = NULL; + +extern "C" +{ + +DLLEXPORT int GUI_register_me(void *hdl) +{ + if (!hdl) + fprintf(stderr, "libXBMC_gui-ERROR: GUILib_register_me is called with NULL handle !!!\n"); + else + { + m_Handle = (AddonCB*) hdl; + m_cb = m_Handle->GUILib_RegisterMe(m_Handle->addonData); + if (!m_cb) + fprintf(stderr, "libXBMC_gui-ERROR: GUILib_register_me can't get callback table from XBMC !!!\n"); + else + return 1; + } + return 0; +} + +DLLEXPORT void GUI_unregister_me() +{ + if (m_Handle && m_cb) + m_Handle->GUILib_UnRegisterMe(m_Handle->addonData, m_cb); +} + +DLLEXPORT void GUI_lock() +{ + m_cb->Lock(); +} + +DLLEXPORT void GUI_unlock() +{ + m_cb->Unlock(); +} + +DLLEXPORT int GUI_get_screen_height() +{ + return m_cb->GetScreenHeight(); +} + +DLLEXPORT int GUI_get_screen_width() +{ + return m_cb->GetScreenWidth(); +} + +DLLEXPORT int GUI_get_video_resolution() +{ + return m_cb->GetVideoResolution(); +} + + +// Dialogs +DLLEXPORT int GUI_Dialog_ShowYesNo(const char* heading, const char* line0, const char* line1, const char* line2, int* bCanceled, const char* noLabel, const char* yesLabel) +{ + return m_cb->Dialog_ShowYesNo(heading, line0, line1, line2, bCanceled, noLabel, yesLabel); +} + +DLLEXPORT CAddonGUIWindow* GUI_Window_create(const char *xmlFilename, const char *defaultSkin, bool forceFallback, bool asDialog) +{ + return new CAddonGUIWindow(xmlFilename, defaultSkin, forceFallback, asDialog); +} + +DLLEXPORT void GUI_Window_destroy(CAddonGUIWindow* p) +{ + delete p; +} + +DLLEXPORT bool GUI_Window_OnClick(GUIHANDLE handle, int controlId) +{ + CAddonGUIWindow *window = (CAddonGUIWindow*) handle; + return window->OnClick(controlId); +} + +DLLEXPORT bool GUI_Window_OnFocus(GUIHANDLE handle, int controlId) +{ + CAddonGUIWindow *window = (CAddonGUIWindow*) handle; + return window->OnFocus(controlId); +} + +DLLEXPORT bool GUI_Window_OnInit(GUIHANDLE handle) +{ + CAddonGUIWindow *window = (CAddonGUIWindow*) handle; + return window->OnInit(); +} + +DLLEXPORT bool GUI_Window_OnAction(GUIHANDLE handle, int actionId) +{ + CAddonGUIWindow *window = (CAddonGUIWindow*) handle; + return window->OnAction(actionId); +} + +DLLEXPORT bool GUI_Window_OnContextMenu(GUIHANDLE handle,int controlId,int itemNumber, unsigned int contextButtonId) +{ + CAddonGUIWindow *window = (CAddonGUIWindow*) handle; + return window->OnContextMenu(controlId,itemNumber, contextButtonId); +} + +CAddonGUIWindow::CAddonGUIWindow(const char *xmlFilename, const char *defaultSkin, bool forceFallback, bool asDialog) +{ + CBOnInit = NULL; + CBOnClick = NULL; + CBOnFocus = NULL; + CBOnContextMenu = NULL; + if (m_Handle && m_cb) + { + m_WindowHandle = m_cb->Window_New(m_Handle->addonData, xmlFilename, defaultSkin, forceFallback, asDialog); + if (!m_WindowHandle) + fprintf(stderr, "libXBMC_gui-ERROR: cGUIWindow can't create window class from XBMC !!!\n"); + + m_cb->Window_SetCallbacks(m_Handle->addonData, m_WindowHandle, this, GUI_Window_OnInit, GUI_Window_OnClick, GUI_Window_OnFocus, GUI_Window_OnAction,GUI_Window_OnContextMenu); + } +} + +CAddonGUIWindow::~CAddonGUIWindow() +{ + if (m_Handle && m_cb && m_WindowHandle) + { + m_cb->Window_Delete(m_Handle->addonData, m_WindowHandle); + m_WindowHandle = NULL; + } +} + +bool CAddonGUIWindow::Show() +{ + return m_cb->Window_Show(m_Handle->addonData, m_WindowHandle); +} + +void CAddonGUIWindow::Close() +{ + m_cb->Window_Close(m_Handle->addonData, m_WindowHandle); +} + +void CAddonGUIWindow::DoModal() +{ + m_cb->Window_DoModal(m_Handle->addonData, m_WindowHandle); +} + +bool CAddonGUIWindow::OnInit() +{ + if (!CBOnInit) + return false; + + return CBOnInit(m_cbhdl); +} + +bool CAddonGUIWindow::OnClick(int controlId) +{ + if (!CBOnClick) + return false; + + return CBOnClick(m_cbhdl, controlId); +} + +bool CAddonGUIWindow::OnFocus(int controlId) +{ + if (!CBOnFocus) + return false; + + return CBOnFocus(m_cbhdl, controlId); +} + +bool CAddonGUIWindow::OnAction(int actionId) +{ + if (!CBOnAction) + return false; + + return CBOnAction(m_cbhdl, actionId); +} + +bool CAddonGUIWindow::OnContextMenu(int controlId,int itemNumber, unsigned int contextButtonId) +{ + if (!CBOnContextMenu) + return false; + + return CBOnContextMenu(m_cbhdl, controlId,itemNumber, contextButtonId); +} + +bool CAddonGUIWindow::SetFocusId(int iControlId) +{ + return m_cb->Window_SetFocusId(m_Handle->addonData, m_WindowHandle, iControlId); +} + +int CAddonGUIWindow::GetFocusId() +{ + return m_cb->Window_GetFocusId(m_Handle->addonData, m_WindowHandle); +} + +bool CAddonGUIWindow::SetCoordinateResolution(int res) +{ + return m_cb->Window_SetCoordinateResolution(m_Handle->addonData, m_WindowHandle, res); +} + +void CAddonGUIWindow::SetProperty(const char *key, const char *value) +{ + m_cb->Window_SetProperty(m_Handle->addonData, m_WindowHandle, key, value); +} + +void CAddonGUIWindow::SetPropertyInt(const char *key, int value) +{ + m_cb->Window_SetPropertyInt(m_Handle->addonData, m_WindowHandle, key, value); +} + +void CAddonGUIWindow::SetPropertyBool(const char *key, bool value) +{ + m_cb->Window_SetPropertyBool(m_Handle->addonData, m_WindowHandle, key, value); +} + +void CAddonGUIWindow::SetPropertyDouble(const char *key, double value) +{ + m_cb->Window_SetPropertyDouble(m_Handle->addonData, m_WindowHandle, key, value); +} + +const char *CAddonGUIWindow::GetProperty(const char *key) const +{ + return m_cb->Window_GetProperty(m_Handle->addonData, m_WindowHandle, key); +} + +int CAddonGUIWindow::GetPropertyInt(const char *key) const +{ + return m_cb->Window_GetPropertyInt(m_Handle->addonData, m_WindowHandle, key); +} + +bool CAddonGUIWindow::GetPropertyBool(const char *key) const +{ + return m_cb->Window_GetPropertyBool(m_Handle->addonData, m_WindowHandle, key); +} + +double CAddonGUIWindow::GetPropertyDouble(const char *key) const +{ + return m_cb->Window_GetPropertyDouble(m_Handle->addonData, m_WindowHandle, key); +} + +void CAddonGUIWindow::ClearProperties() +{ + m_cb->Window_ClearProperties(m_Handle->addonData, m_WindowHandle); +} + +int CAddonGUIWindow::GetListSize() +{ + return m_cb->Window_GetListSize(m_Handle->addonData, m_WindowHandle); +} + +void CAddonGUIWindow::ClearList() +{ + m_cb->Window_ClearList(m_Handle->addonData, m_WindowHandle); +} + +GUIHANDLE CAddonGUIWindow::AddStringItem(const char *name, int itemPosition) +{ + return m_cb->Window_AddStringItem(m_Handle->addonData, m_WindowHandle, name, itemPosition); +} + +void CAddonGUIWindow::AddItem(GUIHANDLE item, int itemPosition) +{ + m_cb->Window_AddItem(m_Handle->addonData, m_WindowHandle, item, itemPosition); +} + +void CAddonGUIWindow::AddItem(CAddonListItem *item, int itemPosition) +{ + m_cb->Window_AddItem(m_Handle->addonData, m_WindowHandle, item->m_ListItemHandle, itemPosition); +} + +void CAddonGUIWindow::RemoveItem(int itemPosition) +{ + m_cb->Window_RemoveItem(m_Handle->addonData, m_WindowHandle, itemPosition); +} + +GUIHANDLE CAddonGUIWindow::GetListItem(int listPos) +{ + return m_cb->Window_GetListItem(m_Handle->addonData, m_WindowHandle, listPos); +} + +void CAddonGUIWindow::SetCurrentListPosition(int listPos) +{ + m_cb->Window_SetCurrentListPosition(m_Handle->addonData, m_WindowHandle, listPos); +} + +int CAddonGUIWindow::GetCurrentListPosition() +{ + return m_cb->Window_GetCurrentListPosition(m_Handle->addonData, m_WindowHandle); +} + +void CAddonGUIWindow::SetControlLabel(int controlId, const char *label) +{ + m_cb->Window_SetControlLabel(m_Handle->addonData, m_WindowHandle, controlId, label); +} + +void CAddonGUIWindow::AddContextMenuButton(int controlId,unsigned int contextButtonId,const char* label) +{ + m_cb->Window_AddContextMenuButton(m_Handle->addonData,m_WindowHandle,controlId,contextButtonId,label); +} + +///------------------------------------- +/// cGUISpinControl + +DLLEXPORT CAddonGUISpinControl* GUI_control_get_spin(CAddonGUIWindow *window, int controlId) +{ + return new CAddonGUISpinControl(window, controlId); +} + +DLLEXPORT void GUI_control_release_spin(CAddonGUISpinControl* p) +{ + delete p; +} + +CAddonGUISpinControl::CAddonGUISpinControl(CAddonGUIWindow *window, int controlId) + : m_Window(window) + , m_ControlId(controlId) +{ + m_SpinHandle = m_cb->Window_GetControl_Spin(m_Handle->addonData, m_Window->m_WindowHandle, controlId); +} + +void CAddonGUISpinControl::SetVisible(bool yesNo) +{ + if (m_SpinHandle) + m_cb->Control_Spin_SetVisible(m_Handle->addonData, m_SpinHandle, yesNo); +} + +void CAddonGUISpinControl::SetText(const char *label) +{ + if (m_SpinHandle) + m_cb->Control_Spin_SetText(m_Handle->addonData, m_SpinHandle, label); +} + +void CAddonGUISpinControl::Clear() +{ + if (m_SpinHandle) + m_cb->Control_Spin_Clear(m_Handle->addonData, m_SpinHandle); +} + +void CAddonGUISpinControl::AddLabel(const char *label, int iValue) +{ + if (m_SpinHandle) + m_cb->Control_Spin_AddLabel(m_Handle->addonData, m_SpinHandle, label, iValue); +} + +int CAddonGUISpinControl::GetValue() +{ + if (!m_SpinHandle) + return -1; + + return m_cb->Control_Spin_GetValue(m_Handle->addonData, m_SpinHandle); +} + +void CAddonGUISpinControl::SetValue(int iValue) +{ + if (m_SpinHandle) + m_cb->Control_Spin_SetValue(m_Handle->addonData, m_SpinHandle, iValue); +} +///------------------------------------- +/// cGUIListContainer + +DLLEXPORT CAddonGUIListContainer* GUI_control_get_listcontainer(CAddonGUIWindow *window, int controlId) +{ + return new CAddonGUIListContainer(window, controlId); +} + +DLLEXPORT void GUI_control_release_listcontainer(CAddonGUIListContainer* p) +{ + delete p; +} + +CAddonGUIListContainer::CAddonGUIListContainer(CAddonGUIWindow *window, int controlId) + : m_Window(window) + , m_ControlId(controlId) + ,m_Items(NULL) + ,m_ListHandle(NULL) +{ + m_ListHandle = m_cb->Window_GetControl_ListContainer(m_Handle->addonData, m_Window->m_WindowHandle, controlId,&m_Items); +} + +void CAddonGUIListContainer::SetVisible(bool yesNo) +{ + if (m_ListHandle) + m_cb->Control_ListContainer_SetVisible(m_Handle->addonData, m_ListHandle, yesNo); +} + +void CAddonGUIListContainer::AddItem(CAddonListItem *item) +{ + if (!m_ListHandle || !item) + return; + m_cb->Control_ListContainer_AddItems(m_Handle->addonData,m_ListHandle,m_Items,&(item->m_ListItemHandle),1); +} + +void CAddonGUIListContainer::AddItems(CAddonListItem* items[],int size) +{ + if (!m_ListHandle || !items) + return; + vector vecItems; + for(int i = 0; i < size; i++) + vecItems.push_back(items[i]->m_ListItemHandle); + m_cb->Control_ListContainer_AddItems(m_Handle->addonData,m_ListHandle,m_Items,&vecItems[0],vecItems.size()); +} + + +CAddonListItem* CAddonGUIListContainer::GetItem(int index) +{ + if (!m_ListHandle) + return NULL; + GUIHANDLE item=(GUIHANDLE)m_cb->Control_ListContainer_GetItem(m_Handle->addonData,m_ListHandle,m_Items,index); + return new CAddonListItem(item); +} + +int CAddonGUIListContainer::GetSelected() +{ + if (!m_ListHandle) + return -1; + return m_cb->Control_ListContainer_GetSelected(m_Handle->addonData,m_ListHandle); +} + +void CAddonGUIListContainer::ResetList() +{ + if (!m_ListHandle) + return; + m_cb->Control_ListContainer_Reset(m_Handle->addonData,m_ListHandle,m_Items); +} +/* +class CAddonGUIListContainer +{ +public: + CAddonGUIListContainer(CAddonGUIWindow *window, int controlId); + ~CAddonGUIListContainer() {} + + virtual void SetVisible(bool yesNo); + virtual void AddItems(CAddonListItem *items); + virtual void GetItem(bool yesNo); + +private: + CAddonGUIWindow *m_Window; + int m_ControlId; + GUIHANDLE m_ButtonHandle; +};*/ + +///------------------------------------- +/// cGUIRadioButton + +DLLEXPORT CAddonGUIRadioButton* GUI_control_get_radiobutton(CAddonGUIWindow *window, int controlId) +{ + return new CAddonGUIRadioButton(window, controlId); +} + +DLLEXPORT void GUI_control_release_radiobutton(CAddonGUIRadioButton* p) +{ + delete p; +} + +CAddonGUIRadioButton::CAddonGUIRadioButton(CAddonGUIWindow *window, int controlId) + : m_Window(window) + , m_ControlId(controlId) +{ + m_ButtonHandle = m_cb->Window_GetControl_RadioButton(m_Handle->addonData, m_Window->m_WindowHandle, controlId); +} + +void CAddonGUIRadioButton::SetVisible(bool yesNo) +{ + if (m_ButtonHandle) + m_cb->Control_RadioButton_SetVisible(m_Handle->addonData, m_ButtonHandle, yesNo); +} + +void CAddonGUIRadioButton::SetText(const char *label) +{ + if (m_ButtonHandle) + m_cb->Control_RadioButton_SetText(m_Handle->addonData, m_ButtonHandle, label); +} + +void CAddonGUIRadioButton::SetSelected(bool yesNo) +{ + if (m_ButtonHandle) + m_cb->Control_RadioButton_SetSelected(m_Handle->addonData, m_ButtonHandle, yesNo); +} + +bool CAddonGUIRadioButton::IsSelected() +{ + if (!m_ButtonHandle) + return false; + + return m_cb->Control_RadioButton_IsSelected(m_Handle->addonData, m_ButtonHandle); +} + + +///------------------------------------- +/// cGUIProgressControl + +DLLEXPORT CAddonGUIProgressControl* GUI_control_get_progress(CAddonGUIWindow *window, int controlId) +{ + return new CAddonGUIProgressControl(window, controlId); +} + +DLLEXPORT void GUI_control_release_progress(CAddonGUIProgressControl* p) +{ + delete p; +} + +CAddonGUIProgressControl::CAddonGUIProgressControl(CAddonGUIWindow *window, int controlId) + : m_Window(window) + , m_ControlId(controlId) +{ + m_ProgressHandle = m_cb->Window_GetControl_Progress(m_Handle->addonData, m_Window->m_WindowHandle, controlId); +} + +void CAddonGUIProgressControl::SetPercentage(float fPercent) +{ + if (m_ProgressHandle) + m_cb->Control_Progress_SetPercentage(m_Handle->addonData, m_ProgressHandle, fPercent); +} + +float CAddonGUIProgressControl::GetPercentage() const +{ + if (!m_ProgressHandle) + return 0.0; + + return m_cb->Control_Progress_GetPercentage(m_Handle->addonData, m_ProgressHandle); +} + +void CAddonGUIProgressControl::SetInfo(int iInfo) +{ + if (m_ProgressHandle) + m_cb->Control_Progress_SetInfo(m_Handle->addonData, m_ProgressHandle, iInfo); +} + +int CAddonGUIProgressControl::GetInfo() const +{ + if (!m_ProgressHandle) + return -1; + + return m_cb->Control_Progress_GetInfo(m_Handle->addonData, m_ProgressHandle); +} + +string CAddonGUIProgressControl::GetDescription() const +{ + if (!m_ProgressHandle) + return ""; + + return m_cb->Control_Progress_GetDescription(m_Handle->addonData, m_ProgressHandle); +} + + +///------------------------------------- +/// cListItem + +DLLEXPORT CAddonListItem* GUI_ListItem_create(const char *label, const char *label2, const char *iconImage, const char *thumbnailImage, const char *path) +{ + return new CAddonListItem(label, label2, iconImage, thumbnailImage, path); +} + +DLLEXPORT void GUI_ListItem_destroy(CAddonListItem* p) +{ + delete p; +} + +CAddonListItem::CAddonListItem(const char *label, const char *label2, const char *iconImage, const char *thumbnailImage, const char *path) +{ + m_ListItemHandle = m_cb->ListItem_Create(m_Handle->addonData, label, label2, iconImage, thumbnailImage, path); +} + +CAddonListItem::CAddonListItem(GUIHANDLE ListItemHandle) + : m_ListItemHandle(ListItemHandle) +{ +} + +/*CAddonListItem::~CAddonListItem(void) +{ + //m_ListItemHandle will leak if it has not been assigned to a list (i.e. a smartpointer) +}*/ + +const char *CAddonListItem::GetLabel() +{ + if (!m_ListItemHandle) + return ""; + + return m_cb->ListItem_GetLabel(m_Handle->addonData, m_ListItemHandle); +} + +void CAddonListItem::SetLabel(const char *label) +{ + if (m_ListItemHandle) + m_cb->ListItem_SetLabel(m_Handle->addonData, m_ListItemHandle, label); +} + +const char *CAddonListItem::GetLabel2() +{ + if (!m_ListItemHandle) + return ""; + + return m_cb->ListItem_GetLabel2(m_Handle->addonData, m_ListItemHandle); +} + +void CAddonListItem::SetLabel2(const char *label) +{ + if (m_ListItemHandle) + m_cb->ListItem_SetLabel2(m_Handle->addonData, m_ListItemHandle, label); +} + +void CAddonListItem::SetIconImage(const char *image) +{ + if (m_ListItemHandle) + m_cb->ListItem_SetIconImage(m_Handle->addonData, m_ListItemHandle, image); +} + +void CAddonListItem::SetThumbnailImage(const char *image) +{ + if (m_ListItemHandle) + m_cb->ListItem_SetThumbnailImage(m_Handle->addonData, m_ListItemHandle, image); +} + +void CAddonListItem::SetInfo(const char *Info) +{ + if (m_ListItemHandle) + m_cb->ListItem_SetInfo(m_Handle->addonData, m_ListItemHandle, Info); +} + +void CAddonListItem::SetProperty(const char *key, const char *value) +{ + if (m_ListItemHandle) + m_cb->ListItem_SetProperty(m_Handle->addonData, m_ListItemHandle, key, value); +} + +const char *CAddonListItem::GetProperty(const char *key) const +{ + if (!m_ListItemHandle) + return ""; + + return m_cb->ListItem_GetProperty(m_Handle->addonData, m_ListItemHandle, key); +} + +void CAddonListItem::SetPath(const char *Path) +{ + if (m_ListItemHandle) + m_cb->ListItem_SetPath(m_Handle->addonData, m_ListItemHandle, Path); +} + + +}; diff --git a/lib/addons/library.xbmc.gui/project/VS2010Express/libXBMC_gui.vcxproj b/lib/addons/library.xbmc.gui/project/VS2010Express/libXBMC_gui.vcxproj new file mode 100644 index 0000000..7b886bf --- /dev/null +++ b/lib/addons/library.xbmc.gui/project/VS2010Express/libXBMC_gui.vcxproj @@ -0,0 +1,86 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942} + XBMC_VDR + Win32Proj + + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ..\..\..\..\..\addons\library.xbmc.gui\ + Debug\ + ..\..\..\..\..\addons\library.xbmc.gui\ + Release\ + + + + Disabled + ..\..\..\..\..\xbmc;..\..\..\..\..\xbmc\addons\include;..\..\..\..\..\xbmc\cores\dvdplayer\DVDDemuxers;%(AdditionalIncludeDirectories) + _WIN32;_DEBUG;_WINDOWS;VDR_EXPORTS;_WIN32PC;_WINSOCKAPI_;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + true + Sync + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + ..\..\..\..\..\addons\library.xbmc.gui\$(ProjectName).dll + true + + + + + ..\..\..\..\..\xbmc;..\..\..\..\..\xbmc\addons\include;..\..\..\..\..\xbmc\cores\dvdplayer\DVDDemuxers;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;HAS_SDL_OPENGL;HAS_SDL;_USRDLL;XBMC_VDR_EXPORTS;_WIN32PC;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + Sync + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + ../../../../../addons/library.xbmc.gui/$(ProjectName).dll + + + + + + + + + \ No newline at end of file diff --git a/lib/addons/library.xbmc.gui/project/VS2010Express/libXBMC_gui.vcxproj.filters b/lib/addons/library.xbmc.gui/project/VS2010Express/libXBMC_gui.vcxproj.filters new file mode 100644 index 0000000..7ccd231 --- /dev/null +++ b/lib/addons/library.xbmc.gui/project/VS2010Express/libXBMC_gui.vcxproj.filters @@ -0,0 +1,14 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + + + Source Files + + + \ No newline at end of file diff --git a/lib/addons/library.xbmc.pvr/Makefile.in b/lib/addons/library.xbmc.pvr/Makefile.in new file mode 100644 index 0000000..1edf411 --- /dev/null +++ b/lib/addons/library.xbmc.pvr/Makefile.in @@ -0,0 +1,27 @@ +ARCH=@ARCH@ +INCLUDES=-I. -I../../../xbmc/addons/include -I../../../xbmc -I../../../xbmc/cores/dvdplayer/DVDDemuxers +DEFINES+= +CXXFLAGS=-fPIC +LIBNAME=libXBMC_pvr +OBJS=$(LIBNAME).o + +LIB_SHARED=../../../addons/library.xbmc.pvr/$(LIBNAME)-$(ARCH).so + +all: $(LIB_SHARED) + +$(LIB_SHARED): $(OBJS) +ifeq ($(findstring osx,$(ARCH)), osx) + $(CXX) $(LDFLAGS) -Wl,-alias_list,@abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper_mach_alias \ + -bundle -undefined dynamic_lookup -read_only_relocs suppress -o $@ \ + @abs_top_srcdir@/xbmc/cores/DllLoader/exports/wrapper.o $(OBJS) +else + $(CXX) $(CFLAGS) $(LDFLAGS) -shared -g -o $(LIB_SHARED) $(OBJS) +endif + +CLEAN_FILES = \ + $(LIB_SHARED) \ + +DISTCLEAN_FILES= \ + Makefile \ + +include ../../../Makefile.include diff --git a/lib/addons/library.xbmc.pvr/libXBMC_pvr.cpp b/lib/addons/library.xbmc.pvr/libXBMC_pvr.cpp new file mode 100644 index 0000000..585abde --- /dev/null +++ b/lib/addons/library.xbmc.pvr/libXBMC_pvr.cpp @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2005-2010 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 + * + */ + +#define USE_DEMUX // enable including of the demuxer packet structure + +#include +#include +#include +#include +#include "../../../addons/library.xbmc.pvr/libXBMC_pvr.h" +#include "addons/AddonCallbacks.h" +#include "cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h" + +#ifdef _WIN32 +#include +#define DLLEXPORT __declspec(dllexport) +#else +#define DLLEXPORT +#endif + +using namespace std; + +AddonCB *m_Handle = NULL; +CB_PVRLib *m_cb = NULL; + +extern "C" +{ + +DLLEXPORT int PVR_register_me(void *hdl) +{ + if (!hdl) + fprintf(stderr, "libXBMC_pvr-ERROR: PVRLib_register_me is called with NULL handle !!!\n"); + else + { + m_Handle = (AddonCB*) hdl; + m_cb = m_Handle->PVRLib_RegisterMe(m_Handle->addonData); + if (!m_cb) + fprintf(stderr, "libXBMC_pvr-ERROR: PVRLib_register_me can't get callback table from XBMC !!!\n"); + else + return 1; + } + return 0; +} + +DLLEXPORT void PVR_unregister_me() +{ + if (m_Handle && m_cb) + m_Handle->PVRLib_UnRegisterMe(m_Handle->addonData, m_cb); +} + +DLLEXPORT void PVR_transfer_epg_entry(const PVR_HANDLE handle, const EPG_TAG *epgentry) +{ + if (m_cb == NULL) + return; + + m_cb->TransferEpgEntry(m_Handle->addonData, handle, epgentry); +} + +DLLEXPORT void PVR_transfer_channel_entry(const PVR_HANDLE handle, const PVR_CHANNEL *chan) +{ + if (m_cb == NULL) + return; + + m_cb->TransferChannelEntry(m_Handle->addonData, handle, chan); +} + +DLLEXPORT void PVR_transfer_timer_entry(const PVR_HANDLE handle, const PVR_TIMER *timer) +{ + if (m_cb == NULL) + return; + + m_cb->TransferTimerEntry(m_Handle->addonData, handle, timer); +} + +DLLEXPORT void PVR_transfer_recording_entry(const PVR_HANDLE handle, const PVR_RECORDING *recording) +{ + if (m_cb == NULL) + return; + + m_cb->TransferRecordingEntry(m_Handle->addonData, handle, recording); +} + +DLLEXPORT void PVR_add_menu_hook(PVR_MENUHOOK *hook) +{ + if (m_cb == NULL) + return; + + m_cb->AddMenuHook(m_Handle->addonData, hook); +} + +DLLEXPORT void PVR_recording(const char *Name, const char *FileName, bool On) +{ + if (m_cb == NULL) + return; + + m_cb->Recording(m_Handle->addonData, Name, FileName, On); +} + +DLLEXPORT void PVR_trigger_channel_update() +{ + if (m_cb == NULL) + return; + + m_cb->TriggerChannelUpdate(m_Handle->addonData); +} + +DLLEXPORT void PVR_trigger_channel_groups_update() +{ + if (m_cb == NULL) + return; + + m_cb->TriggerChannelGroupsUpdate(m_Handle->addonData); +} + +DLLEXPORT void PVR_trigger_timer_update() +{ + if (m_cb == NULL) + return; + + m_cb->TriggerTimerUpdate(m_Handle->addonData); +} + +DLLEXPORT void PVR_trigger_recording_update() +{ + if (m_cb == NULL) + return; + + m_cb->TriggerRecordingUpdate(m_Handle->addonData); +} + +DLLEXPORT void PVR_free_demux_packet(DemuxPacket* pPacket) +{ + if (m_cb == NULL) + return; + + m_cb->FreeDemuxPacket(m_Handle->addonData, pPacket); +} + +DLLEXPORT DemuxPacket* PVR_allocate_demux_packet(int iDataSize) +{ + if (m_cb == NULL) + return NULL; + + return m_cb->AllocateDemuxPacket(m_Handle->addonData, iDataSize); +} + +DLLEXPORT void PVR_transfer_channel_group(const PVR_HANDLE handle, const PVR_CHANNEL_GROUP *group) +{ + if (m_cb == NULL) + return; + + m_cb->TransferChannelGroup(m_Handle->addonData, handle, group); +} + +DLLEXPORT void PVR_transfer_channel_group_member(const PVR_HANDLE handle, const PVR_CHANNEL_GROUP_MEMBER *member) +{ + if (m_cb == NULL) + return; + + m_cb->TransferChannelGroupMember(m_Handle->addonData, handle, member); +} + +}; diff --git a/lib/addons/library.xbmc.pvr/project/VS2010Express/libXBMC_pvr.vcxproj b/lib/addons/library.xbmc.pvr/project/VS2010Express/libXBMC_pvr.vcxproj new file mode 100644 index 0000000..0d9986a --- /dev/null +++ b/lib/addons/library.xbmc.pvr/project/VS2010Express/libXBMC_pvr.vcxproj @@ -0,0 +1,86 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + + {6D8C91F8-992F-4C83-9DE3-485D64EF8420} + XBMC_VDR + Win32Proj + + + + DynamicLibrary + MultiByte + + + DynamicLibrary + MultiByte + + + + + + + + + + + + + + + <_ProjectFileVersion>10.0.30319.1 + ..\..\..\..\..\addons\library.xbmc.pvr\ + Debug\ + ..\..\..\..\..\addons\library.xbmc.pvr\ + Release\ + + + + Disabled + ..\..\..\..\..\xbmc;..\..\..\..\..\xbmc\addons\include;..\..\..\..\..\xbmc\cores\dvdplayer\DVDDemuxers;%(AdditionalIncludeDirectories) + _WIN32;_DEBUG;_WINDOWS;VDR_EXPORTS;_WIN32PC;_WINSOCKAPI_;%(PreprocessorDefinitions) + true + Sync + EnableFastChecks + MultiThreadedDebugDLL + + + Level3 + ProgramDatabase + + + ..\..\..\..\..\addons\library.xbmc.pvr\$(ProjectName).dll + true + + + + + ..\..\..\..\..\xbmc;..\..\..\..\..\xbmc\addons\include;..\..\..\..\..\xbmc\cores\dvdplayer\DVDDemuxers;%(AdditionalIncludeDirectories) + WIN32;NDEBUG;_WINDOWS;HAS_SDL_OPENGL;HAS_SDL;_USRDLL;XBMC_VDR_EXPORTS;_WIN32PC;%(PreprocessorDefinitions) + Sync + MultiThreadedDLL + + + Level3 + ProgramDatabase + + + ..\..\..\..\..\addons\library.xbmc.pvr\$(ProjectName).dll + + + + + + + + + \ No newline at end of file diff --git a/lib/addons/library.xbmc.pvr/project/VS2010Express/libXBMC_pvr.vcxproj.filters b/lib/addons/library.xbmc.pvr/project/VS2010Express/libXBMC_pvr.vcxproj.filters new file mode 100644 index 0000000..db93c59 --- /dev/null +++ b/lib/addons/library.xbmc.pvr/project/VS2010Express/libXBMC_pvr.vcxproj.filters @@ -0,0 +1,18 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hpp;hxx;hm;inl;inc;xsd + + + + + Source Files + + + \ No newline at end of file diff --git a/lib/cmyth/Win32/libcmyth.def b/lib/cmyth/Win32/libcmyth.def index 7ea4356..4562442 100644 --- a/lib/cmyth/Win32/libcmyth.def +++ b/lib/cmyth/Win32/libcmyth.def @@ -45,6 +45,11 @@ EXPORTS cmyth_file_request_block cmyth_file_seek cmyth_freespace_create + cmyth_inputlist_create + cmyth_input_destroy + cmyth_input_create + cmyth_rcv_free_inputlist + cmyth_get_free_inputlist cmyth_keyframe_create cmyth_keyframe_fill cmyth_keyframe_string @@ -98,6 +103,7 @@ EXPORTS cmyth_chanlist_get_count cmyth_channel_chanid cmyth_channel_channum + cmyth_channel_channumstr cmyth_channel_name cmyth_channel_icon cmyth_channel_visible @@ -117,6 +123,8 @@ EXPORTS cmyth_proginfo_category cmyth_proginfo_seriesid cmyth_proginfo_programid + cmyth_proginfo_recordid + cmyth_proginfo_priority cmyth_proginfo_stars cmyth_proginfo_playgroup cmyth_proginfo_originalairdate @@ -215,4 +223,66 @@ EXPORTS cmyth_ringbuf_read cmyth_file_read cmyth_livetv_read - cmyth_get_cutlist \ No newline at end of file + cmyth_get_cutlist + cmyth_mysql_update_timer + cmyth_mysql_delete_timer + cmyth_mysql_add_timer + cmyth_mysql_get_timers + cmyth_mysql_is_radio + cmyth_livetv_chain_duration + cmyth_timer_recordid + cmyth_timer_chanid + cmyth_timer_starttime + cmyth_timer_endtime + cmyth_timer_title + cmyth_timer_description + cmyth_timer_type + cmyth_timer_category + cmyth_timer_subtitle + cmyth_timer_priority + cmyth_timer_startoffset + cmyth_timer_endoffset + cmyth_timer_searchtype + cmyth_timer_inactive + cmyth_timer_callsign + cmyth_timer_dup_method + cmyth_timer_dup_in + cmyth_timer_rec_group + cmyth_timer_store_group + cmyth_timer_play_group + cmyth_timer_autotranscode + cmyth_timer_userjobs + cmyth_timer_autocommflag + cmyth_timer_autoexpire + cmyth_timer_maxepisodes + cmyth_timer_maxnewest + cmyth_timerlist_get_item + cmyth_timerlist_get_count + cmyth_mysql_get_channelgroups + cmyth_mysql_get_channelids_in_group + cmyth_channel_sourceid + cmyth_channel_multiplex + cmyth_mysql_get_recorder_list + cmyth_mysql_get_prog_finder_time_title_chan + cmyth_conn_set_setting + cmyth_conn_get_backend_hostname + cmyth_conn_get_client_hostname + cmyth_conn_get_setting + cmyth_timer_transcoder + cmyth_mysql_get_storagegroups + cmyth_mysql_get_playgroups + cmyth_mysql_get_recprofiles + cmyth_mysql_get_cardtype + cmyth_channel_callsign + cmyth_get_watched_status_mysql + cmyth_set_watched_status_mysql + cmyth_file_position + cmyth_update_file_length + cmyth_storagegroup_filelist + cmyth_storagegroup_filelist_get_item + cmyth_storagegroup_filelist_count + cmyth_storagegroup_get_filelist + cmyth_storagegroup_file_get_filename + cmyth_storagegroup_file_get_lastmodified + cmyth_storagegroup_file_get_size + diff --git a/lib/cmyth/Win32/libcmyth.vcproj b/lib/cmyth/Win32/libcmyth.vcproj index 55cf9af..ddca3fb 100644 --- a/lib/cmyth/Win32/libcmyth.vcproj +++ b/lib/cmyth/Win32/libcmyth.vcproj @@ -216,6 +216,10 @@ > + + diff --git a/lib/cmyth/Win32/libcmyth.vcxproj b/lib/cmyth/Win32/libcmyth.vcxproj index a698d8a..17d7c57 100644 --- a/lib/cmyth/Win32/libcmyth.vcxproj +++ b/lib/cmyth/Win32/libcmyth.vcxproj @@ -54,7 +54,7 @@ Disabled ..;../include;include;../librefmem;../libcmyth;%(AdditionalIncludeDirectories) - WIN32;DEBUG;_LIB;inline=__inline; _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;DEBUG;_LIB;inline=__inline;_CRT_SECURE_NO_WARNINGS;_USE_32BIT_TIME_T;%(PreprocessorDefinitions) true EnableFastChecks MultiThreadedDebugDLL @@ -75,6 +75,7 @@ $(Configuration)\vs2010\$(TargetName).lib + true @@ -94,7 +95,7 @@ ..;../include;include;../librefmem;../libcmyth;%(AdditionalIncludeDirectories) - WIN32;NDEBUG;_LIB;inline=__inline; _CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions) + WIN32;NDEBUG;_LIB;inline=__inline;_CRT_SECURE_NO_WARNINGS;_USE_32BIT_TIME_T;%(PreprocessorDefinitions) MultiThreadedDLL @@ -113,6 +114,7 @@ $(Configuration)\vs2010\$(TargetName).lib + true @@ -137,6 +139,7 @@ + diff --git a/lib/cmyth/Win32/libcmyth.vcxproj.filters b/lib/cmyth/Win32/libcmyth.vcxproj.filters index 0032e92..96b7eb2 100644 --- a/lib/cmyth/Win32/libcmyth.vcxproj.filters +++ b/lib/cmyth/Win32/libcmyth.vcxproj.filters @@ -31,6 +31,9 @@ Source Files + + Source Files + Source Files diff --git a/lib/cmyth/include/cmyth/cmyth.h b/lib/cmyth/include/cmyth/cmyth.h index 52f2f68..51ea428 100644 --- a/lib/cmyth/include/cmyth/cmyth.h +++ b/lib/cmyth/include/cmyth/cmyth.h @@ -154,6 +154,23 @@ typedef struct cmyth_chanlist *cmyth_chanlist_t; struct cmyth_tvguide_progs; typedef struct cmyth_tvguide_progs *cmyth_tvguide_progs_t; +/* fetzerch: Added to support querying of free inputs (is tunable on) */ +struct cmyth_input { + char *inputname; + unsigned long sourceid; + unsigned long inputid; + unsigned long cardid; + unsigned long multiplexid; + unsigned long livetvorder; /* new in V71 */ +}; +typedef struct cmyth_input *cmyth_input_t; + +struct cmyth_inputlist { + cmyth_input_t *input_list; + long input_count; +}; +typedef struct cmyth_inputlist *cmyth_inputlist_t; + /* * ----------------------------------------------------------------- * Debug Output Control @@ -255,7 +272,7 @@ extern cmyth_file_t cmyth_conn_connect_file(cmyth_proginfo_t prog, * \return file handle */ extern cmyth_file_t cmyth_conn_connect_path(char* path, cmyth_conn_t control, - unsigned buflen, int tcp_rcvbuf); + unsigned buflen, int tcp_rcvbuf,char* sgToGetFrom); /** * Create a ring buffer connection to a recorder. @@ -349,6 +366,30 @@ extern int cmyth_conn_get_protocol_version(cmyth_conn_t conn); extern char * cmyth_conn_get_setting(cmyth_conn_t conn, const char* hostname, const char* setting); +/** + * Set a MythTV setting for a hostname + * \param conn connection handle + * \param hostname hostname to apply the setting to + * \param setting the setting name to set + * \param value the value of the setting + * \retval <0 for failure + */ +extern int cmyth_conn_set_setting(cmyth_conn_t conn, + const char* hostname, const char* setting, const char* value); + +/** + * Get the backend hostname used in the settings database + * \param conn connection handle + * \retval ref counted string with backend hostname + */ +extern char* cmyth_conn_get_backend_hostname(cmyth_conn_t conn); + +/** + * Get the client hostname used when creating the backend connection + * \param conn connection handle + * \retval ref counted string with client hostname + */ +extern char* cmyth_conn_get_client_hostname(cmyth_conn_t conn); /* * ----------------------------------------------------------------- * Event Operations @@ -524,6 +565,8 @@ extern cmyth_livetv_chain_t cmyth_livetv_chain_create(char * chainid); extern cmyth_file_t cmyth_livetv_get_cur_file(cmyth_recorder_t rec); +extern long long cmyth_livetv_chain_duration(cmyth_recorder_t rec); + extern int cmyth_livetv_chain_switch(cmyth_recorder_t rec, int dir); extern int cmyth_livetv_chain_switch_last(cmyth_recorder_t rec); @@ -573,6 +616,9 @@ extern int cmyth_database_set_user(cmyth_database_t db, char *user); extern int cmyth_database_set_pass(cmyth_database_t db, char *pass); extern int cmyth_database_set_name(cmyth_database_t db, char *name); +extern int cmyth_get_watched_status_mysql(cmyth_database_t db, int recordid); +extern int cmyth_set_watched_status_mysql(cmyth_database_t db, int recordid, int watchedStat); + /* * ----------------------------------------------------------------- * Ring Buffer Operations @@ -749,6 +795,20 @@ extern char *cmyth_proginfo_subtitle(cmyth_proginfo_t prog); extern char *cmyth_proginfo_description(cmyth_proginfo_t prog); /** + * Retrieve the season of a program. + * \param prog proginfo handle + * \return season + */ +extern unsigned short cmyth_proginfo_season(cmyth_proginfo_t prog); + +/** + * Retrieve the episode of a program. + * \param prog proginfo handle + * \return episode + */ +extern unsigned short cmyth_proginfo_episode(cmyth_proginfo_t prog); + +/** * Retrieve the category of a program. * \param prog proginfo handle * \return null-terminated string @@ -805,6 +865,27 @@ extern char *cmyth_proginfo_seriesid(cmyth_proginfo_t prog); extern char *cmyth_proginfo_programid(cmyth_proginfo_t prog); /** + * Retrieve the inetref of a program. + * \param prog proginfo handle + * \return null-terminated string + */ +extern char *cmyth_proginfo_inetref(cmyth_proginfo_t prog); + +/** + * Retrieve the record ID of the matching record rule + * \param prog proginfo handle + * \return unsigned long + */ +extern unsigned long cmyth_proginfo_recordid(cmyth_proginfo_t prog); + +/** + * Retrieve the priority of a program + * \param prog proginfo handle + * \return long + */ +extern long cmyth_proginfo_priority(cmyth_proginfo_t prog); + +/** * Retrieve the critics rating (number of stars) of a program. * \param prog proginfo handle * \return null-terminated string @@ -962,6 +1043,10 @@ extern unsigned long long cmyth_file_start(cmyth_file_t file); extern unsigned long long cmyth_file_length(cmyth_file_t file); +extern unsigned long long cmyth_file_position(cmyth_file_t file); + +extern int cmyth_update_file_length(cmyth_file_t file, unsigned long long newLength); + extern int cmyth_file_get_block(cmyth_file_t file, char *buf, unsigned long len); @@ -988,6 +1073,10 @@ extern long cmyth_channel_chanid(cmyth_channel_t channel); extern long cmyth_channel_channum(cmyth_channel_t channel); +extern char * cmyth_channel_channumstr(cmyth_channel_t channel); + +extern char * cmyth_channel_callsign(cmyth_channel_t channel); + extern char * cmyth_channel_name(cmyth_channel_t channel); extern char * cmyth_channel_icon(cmyth_channel_t channel); @@ -1023,6 +1112,17 @@ extern cmyth_commbreaklist_t cmyth_get_cutlist(cmyth_conn_t conn, cmyth_proginfo extern int cmyth_rcv_commbreaklist(cmyth_conn_t conn, int *err, cmyth_commbreaklist_t breaklist, int count); /* + * ------- + * Card Input Operations + * ------- + */ +extern cmyth_inputlist_t cmyth_inputlist_create(void); +extern cmyth_input_t cmyth_input_create(void); +extern cmyth_inputlist_t cmyth_get_free_inputlist(cmyth_recorder_t rec); +extern int cmyth_rcv_free_inputlist(cmyth_conn_t conn, int *err, cmyth_inputlist_t inputlist, int count); + + +/* * mysql info */ @@ -1076,4 +1176,107 @@ extern int cmyth_get_delete_list(cmyth_conn_t, char *, cmyth_proglist_t); extern int cmyth_mythtv_remove_previos_recorded(cmyth_database_t db,char *query); extern cmyth_chanlist_t cmyth_mysql_get_chanlist(cmyth_database_t db); + +/*tsp*/ +extern int cmyth_mysql_is_radio(cmyth_database_t db, int chanid); + +/* timers */ +struct cmyth_timer; +typedef struct cmyth_timer* cmyth_timer_t; + +struct cmyth_timerlist; +typedef struct cmyth_timerlist* cmyth_timerlist_t; + +extern int cmyth_timer_recordid(cmyth_timer_t timer); +extern int cmyth_timer_chanid(cmyth_timer_t timer); +extern time_t cmyth_timer_starttime(cmyth_timer_t timer); +extern time_t cmyth_timer_endtime(cmyth_timer_t timer); +extern char* cmyth_timer_title(cmyth_timer_t timer); +extern char* cmyth_timer_description(cmyth_timer_t timer); +extern int cmyth_timer_type(cmyth_timer_t timer); +extern char* cmyth_timer_category(cmyth_timer_t timer); +extern char* cmyth_timer_subtitle(cmyth_timer_t timer); +extern int cmyth_timer_priority(cmyth_timer_t timer); +extern int cmyth_timer_startoffset(cmyth_timer_t timer); +extern int cmyth_timer_endoffset(cmyth_timer_t timer); +extern int cmyth_timer_searchtype(cmyth_timer_t timer); +extern int cmyth_timer_inactive(cmyth_timer_t timer); +extern char* cmyth_timer_callsign(cmyth_timer_t timer); +extern int cmyth_timer_dup_method(cmyth_timer_t timer); +extern int cmyth_timer_dup_in(cmyth_timer_t timer); +extern char* cmyth_timer_rec_group(cmyth_timer_t timer); +extern char* cmyth_timer_store_group(cmyth_timer_t timer); +extern char* cmyth_timer_play_group(cmyth_timer_t timer); +extern int cmyth_timer_autotranscode(cmyth_timer_t timer); +extern int cmyth_timer_userjobs(cmyth_timer_t timer); +extern int cmyth_timer_autocommflag(cmyth_timer_t timer); +extern int cmyth_timer_autoexpire(cmyth_timer_t timer); +extern int cmyth_timer_maxepisodes(cmyth_timer_t timer); +extern int cmyth_timer_maxnewest(cmyth_timer_t timer); +extern int cmyth_timer_transcoder(cmyth_timer_t timer); + + +extern cmyth_timer_t cmyth_timerlist_get_item(cmyth_timerlist_t pl, int index); +extern int cmyth_timerlist_get_count(cmyth_timerlist_t pl); + +extern cmyth_timerlist_t cmyth_mysql_get_timers(cmyth_database_t db); + + +extern int cmyth_mysql_add_timer(cmyth_database_t db, int chanid,char* callsign,char* description, time_t starttime, time_t endtime,char* title,char* category,int type,char* subtitle,int priority,int startoffset,int endoffset,int searchtype,int inactive, + int dup_method, int dup_in, char* rec_group, char* store_group, char* play_group, int autotranscode, int userjobs, int autocommflag, int autoexpire, int maxepisodes, int maxnewest, int transcoder); +extern int cmyth_mysql_delete_timer(cmyth_database_t db, int recordid); +extern int cmyth_mysql_update_timer(cmyth_database_t db, int recordid, int chanid,char* callsign,char* description, time_t starttime, time_t endtime,char* title,char* category, int type,char* subtitle,int priority,int startoffset,int endoffset,int searchtype,int inactive, + int dup_method, int dup_in, char* rec_group, char* store_group, char* play_group, int autotranscode, int userjobs, int autocommflag, int autoexpire, int maxepisodes, int maxnewest, int transcoder); + +typedef struct cmyth_channelgroups { + char channelgroup[65]; + unsigned int ID; +} cmyth_channelgroups_t; + +extern int cmyth_mysql_get_channelgroups(cmyth_database_t db,cmyth_channelgroups_t** changroups); +extern int cmyth_mysql_get_channelids_in_group(cmyth_database_t db,unsigned int groupid,int** chanids); + +extern int cmyth_channel_sourceid(cmyth_channel_t channel); +extern int cmyth_channel_multiplex(cmyth_channel_t channel); + +typedef struct cmyth_rec { + int recid; + int sourceid; +} cmyth_rec_t; + +extern int cmyth_mysql_get_recorder_list(cmyth_database_t db,cmyth_rec_t** reclist); + +extern int cmyth_mysql_get_prog_finder_time_title_chan(cmyth_database_t db,cmyth_program_t *prog, char* title,time_t starttime,int chanid); + +extern int cmyth_mysql_get_storagegroups(cmyth_database_t db, char** *profiles); +extern int cmyth_mysql_get_playgroups(cmyth_database_t db, char** *profiles); + +typedef struct cmyth_recprofile{ +int id; +char name[128]; +char cardtype[32]; +} cmyth_recprofile_t; + +extern int cmyth_mysql_get_recprofiles(cmyth_database_t db, cmyth_recprofile_t** profiles); + +extern char* cmyth_mysql_get_cardtype(cmyth_database_t db, int chanid); + +/* Get a storage group file list */ +extern int cmyth_storagegroup_filelist(cmyth_conn_t control, char** *sgFilelist, char* sg2List, char* mythostname); + +struct cmyth_storagegroup_filelist; +typedef struct cmyth_storagegroup_filelist* cmyth_storagegroup_filelist_t; + +struct cmyth_storagegroup_file; +typedef struct cmyth_storagegroup_file* cmyth_storagegroup_file_t; + +extern cmyth_storagegroup_file_t cmyth_storagegroup_filelist_get_item(cmyth_storagegroup_filelist_t fl, int index); +extern int cmyth_storagegroup_filelist_count(cmyth_storagegroup_filelist_t fl); + +extern cmyth_storagegroup_filelist_t cmyth_storagegroup_get_filelist(cmyth_conn_t control,char* storagegroup, char* hostname); + +extern char* cmyth_storagegroup_file_get_filename(cmyth_storagegroup_file_t file); +extern unsigned long cmyth_storagegroup_file_get_lastmodified(cmyth_storagegroup_file_t file); +extern unsigned long long cmyth_storagegroup_file_get_size(cmyth_storagegroup_file_t file); + #endif /* __CMYTH_H */ diff --git a/lib/cmyth/include/refmem/atomic.h b/lib/cmyth/include/refmem/atomic.h index 71d9a6e..9aba22e 100644 --- a/lib/cmyth/include/refmem/atomic.h +++ b/lib/cmyth/include/refmem/atomic.h @@ -74,7 +74,7 @@ __mvp_atomic_decrement(mvp_atomic_t *valp) "lock xaddl %0, (%1);" " dec %0;" : "=r" (__val) - : "r" (valp), "0" (0x1) + : "r" (valp), "0" (-0x1) : "cc", "memory" ); #elif defined __i386__ diff --git a/lib/cmyth/libcmyth/Makefile b/lib/cmyth/libcmyth/Makefile index 9b37fbf..a83e872 100644 --- a/lib/cmyth/libcmyth/Makefile +++ b/lib/cmyth/libcmyth/Makefile @@ -1,6 +1,6 @@ INCLUDES=-I. -I../include -SRCS=bookmark.c commbreak.c connection.c event.c file.c freespace.c keyframe.c livetv.c mysql_query.c mythtv_mysql.c posmap.c proginfo.c proglist.c rec_num.c recorder.c ringbuf.c socket.c timestamp.c debug.c utf8tolatin1.c +SRCS=bookmark.c commbreak.c connection.c event.c file.c freespace.c input.c keyframe.c livetv.c mysql_query.c mythtv_mysql.c posmap.c proginfo.c proglist.c rec_num.c recorder.c ringbuf.c socket.c timestamp.c debug.c utf8tolatin1.c LIB=libcmyth.a diff --git a/lib/cmyth/libcmyth/bookmark.c b/lib/cmyth/libcmyth/bookmark.c index af7580f..4681c21 100644 --- a/lib/cmyth/libcmyth/bookmark.c +++ b/lib/cmyth/libcmyth/bookmark.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include @@ -59,7 +60,7 @@ long long cmyth_get_bookmark(cmyth_conn_t conn, cmyth_proginfo_t prog) } if ((r=cmyth_rcv_long_long(conn, &err, &ll, count)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, - "%s: cmyth_rcv_longlong() failed (%d)\n", + "%s: cmyth_rcv_long_long() failed (%d)\n", __FUNCTION__, r); ret = err; goto out; @@ -74,7 +75,7 @@ long long cmyth_get_bookmark(cmyth_conn_t conn, cmyth_proginfo_t prog) int cmyth_set_bookmark(cmyth_conn_t conn, cmyth_proginfo_t prog, long long bookmark) { char *buf; - unsigned int len = CMYTH_TIMESTAMP_LEN + CMYTH_LONGLONG_LEN + 18; + unsigned int len = CMYTH_TIMESTAMP_LEN + CMYTH_LONGLONG_LEN * 2 + 18; char resultstr[3]; int r,err; int ret; @@ -85,8 +86,18 @@ int cmyth_set_bookmark(cmyth_conn_t conn, cmyth_proginfo_t prog, long long bookm if (!buf) { return -ENOMEM; } - sprintf(buf,"%s %ld %s %lld %lld","SET_BOOKMARK",prog->proginfo_chanId, - start_ts_dt, bookmark >> 32,(bookmark & 0xffffffff)); + if (conn->conn_version >= 66) { + /* + * Since protocol 66 mythbackend expects a single 64 bit integer rather than two 32 bit + * hi and lo integers. + */ + sprintf(buf, "SET_BOOKMARK %ld %s %"PRIu64, prog->proginfo_chanId, + start_ts_dt, (int64_t)bookmark); + } + else { + sprintf(buf, "SET_BOOKMARK %ld %s %d %d", prog->proginfo_chanId, + start_ts_dt, (int32_t)(bookmark >> 32), (int32_t)(bookmark & 0xffffffff)); + } pthread_mutex_lock(&mutex); if ((err = cmyth_send_message(conn,buf)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, diff --git a/lib/cmyth/libcmyth/cmyth_local.h b/lib/cmyth/libcmyth/cmyth_local.h index 40bed11..f6e4352 100644 --- a/lib/cmyth/libcmyth/cmyth_local.h +++ b/lib/cmyth/libcmyth/cmyth_local.h @@ -39,12 +39,16 @@ #ifdef _MSC_VER #pragma warning(disable:4267) -#define pthread_mutex_lock(a) -#define pthread_mutex_unlock(a) -#define PTHREAD_MUTEX_INITIALIZER NULL; -typedef void* pthread_mutex_t; +//#define pthread_mutex_lock(a) +//#define pthread_mutex_unlock(a) +#define pthread_mutex_lock(a) EnterCriticalSection(a) +#define pthread_mutex_unlock(a) LeaveCriticalSection(a) +//#define PTHREAD_MUTEX_INITIALIZER NULL; +#define PTHREAD_MUTEX_INITIALIZER InitializeCriticalSection(&mutex); +//typedef void* pthread_mutex_t; +typedef CRITICAL_SECTION pthread_mutex_t; extern pthread_mutex_t mutex; -#define mutex __cmyth_mutex +//#define mutex __cmyth_mutex #define SHUT_RDWR SD_BOTH typedef SOCKET cmyth_socket_t; typedef int socklen_t; @@ -135,6 +139,9 @@ struct cmyth_channel { char *name; char *icon; int visible; + /* tsp - added sourceID and multiplex */ + int sourceid; + int multiplex; }; struct cmyth_chanlist { @@ -142,6 +149,49 @@ struct cmyth_chanlist { int chanlist_count; }; + +/* tsp: Added timer */ + +struct cmyth_timer { + int recordid; + int chanid; + time_t starttime; + time_t endtime; + char* title; + char* description; + int type; + char* category; + char* subtitle; + int priority; + int startoffset; + int endoffset; + int searchtype; + int inactive; + char* callsign; + + int dup_method; + int dup_in; + char* rec_group; + char* store_group; + char* play_group; + int autotranscode; + int userjobs; + int autocommflag; + int autoexpire; + int maxepisodes; + int maxnewest; + int transcoder; + /* + char* profile; + int prefinput; + */ + }; + +struct cmyth_timerlist { + cmyth_timer_t *timerlist_list; + int timerlist_count; +}; + /* Sergio: Added to support the tvguide functionality */ struct cmyth_tvguide_progs { cmyth_program_t * progs; @@ -163,6 +213,25 @@ struct cmyth_recorder { }; /** + * MythTV proglist + */ + +struct cmyth_storagegroup_filelist { + cmyth_storagegroup_file_t *storagegroup_filelist_list; + int storagegroup_filelist_count; +}; + + +struct cmyth_storagegroup_file { + char* filename; + char* storagegroup; + char* hostname; + unsigned long modified; + unsigned long size; +}; + + +/** * MythTV file connection */ struct cmyth_file { @@ -177,6 +246,8 @@ struct cmyth_file { cmyth_conn_t file_control; /**< master backend connection */ }; +long long cmyth_file_seek_unlocked(cmyth_file_t file, long long offset, int whence); + struct cmyth_ringbuf { cmyth_conn_t conn_data; long file_id; @@ -224,6 +295,8 @@ struct cmyth_proginfo { char *proginfo_title; char *proginfo_subtitle; char *proginfo_description; + unsigned short proginfo_season; /* new in V67 */ + unsigned short proginfo_episode; /* new in V67 */ char *proginfo_category; long proginfo_chanId; char *proginfo_chanstr; @@ -258,6 +331,7 @@ struct cmyth_proginfo { char *proginfo_chan_output_filters; /* new in V8 */ char *proginfo_seriesid; /* new in V8 */ char *proginfo_programid; /* new in V12 */ + char *proginfo_inetref; /* new in V67 */ cmyth_timestamp_t proginfo_lastmodified; /* new in V12 */ char *proginfo_stars; /* new in V12 */ cmyth_timestamp_t proginfo_originalairdate; /* new in V12 */ diff --git a/lib/cmyth/libcmyth/connection.c b/lib/cmyth/libcmyth/connection.c index 9d5fb0d..4b9e27d 100644 --- a/lib/cmyth/libcmyth/connection.c +++ b/lib/cmyth/libcmyth/connection.c @@ -44,9 +44,32 @@ #include static char * cmyth_conn_get_setting_unlocked(cmyth_conn_t conn, const char* hostname, const char* setting); +static int cmyth_conn_set_setting_unlocked(cmyth_conn_t conn, const char* hostname, const char* setting, const char* value); +#ifdef _MSC_VER +CRITICAL_SECTION mutex; -pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +BOOL APIENTRY DllMain(HANDLE hModule, + DWORD ul_reason_for_call, + LPVOID lpReserved) +{ + switch( ul_reason_for_call ) { + case DLL_PROCESS_ATTACH: + InitializeCriticalSection(&mutex); + break; + /*case DLL_THREAD_ATTACH: + ... + case DLL_THREAD_DETACH: + ...*/ + case DLL_PROCESS_DETACH: + DeleteCriticalSection(&mutex); + break; + } + return TRUE; +} +#else +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; +#endif typedef struct { int version; char token[9]; // 8 characters + the terminating NULL character @@ -56,6 +79,15 @@ static myth_protomap_t protomap[] = { {62, "78B5631E"}, {63, "3875641D"}, {64, "8675309J"}, + {65, "D2BB94C2"}, + {66, "0C0FFEE0"}, + {67, "0G0G0G0"}, + {68, "90094EAD"}, + {69, "63835135"}, + {70, "53153836"}, + {71, "05e82186"}, + {72, "D78EFD6F"}, + {73, "D7FE8D6F"}, {0, 0} }; @@ -527,7 +559,7 @@ cmyth_conn_connect_file(cmyth_proginfo_t prog, cmyth_conn_t control, int err = 0; int count = 0; int r; - int ann_size = sizeof("ANN FileTransfer []:[][]:[]"); + int ann_size = sizeof("ANN FileTransfer 0[]:[][]:[]"); cmyth_file_t ret = NULL; if (!prog) { @@ -553,7 +585,7 @@ cmyth_conn_connect_file(cmyth_proginfo_t prog, cmyth_conn_t control, cmyth_dbg(CMYTH_DBG_PROTO, "%s: connecting data connection\n", __FUNCTION__); if (control->conn_version >= 17) { - myth_host = cmyth_conn_get_setting_unlocked(control, prog->proginfo_host, + myth_host = cmyth_conn_get_setting_unlocked(control, prog->proginfo_hostname, "BackendServerIP"); } if (!myth_host) { @@ -575,6 +607,12 @@ cmyth_conn_connect_file(cmyth_proginfo_t prog, cmyth_conn_t control, myth_host, prog->proginfo_port, buflen); goto shut; } + /* + * Explicitly set the conn version to the control version as cmyth_connect() doesn't and some of + * the cmyth_rcv_* functions expect it to be the same as the protocol version used by mythbackend. + */ + conn->conn_version = control->conn_version; + ann_size += strlen(prog->proginfo_pathname) + strlen(my_hostname); announcement = malloc(ann_size); if (!announcement) { @@ -584,7 +622,7 @@ cmyth_conn_connect_file(cmyth_proginfo_t prog, cmyth_conn_t control, goto shut; } if (control->conn_version >= 44) { - sprintf(announcement, "ANN FileTransfer %s[]:[]%s[]:[]", + sprintf(announcement, "ANN FileTransfer %s 0[]:[]%s[]:[]", // write = false my_hostname, prog->proginfo_pathname); } else { @@ -631,7 +669,7 @@ cmyth_conn_connect_file(cmyth_proginfo_t prog, cmyth_conn_t control, r = cmyth_rcv_u_long_long(conn, &err, &ret->file_length, count); if (err) { cmyth_dbg(CMYTH_DBG_ERROR, - "%s: (length) cmyth_rcv_longlong() failed (%d)\n", + "%s: (length) cmyth_rcv_u_long_long() failed (%d)\n", __FUNCTION__, err); goto shut; } @@ -674,7 +712,7 @@ cmyth_conn_connect_file(cmyth_proginfo_t prog, cmyth_conn_t control, */ cmyth_file_t cmyth_conn_connect_path(char* path, cmyth_conn_t control, - unsigned buflen, int tcp_rcvbuf) + unsigned buflen, int tcp_rcvbuf, char* sgToGetFrom) { cmyth_conn_t conn = NULL; char *announcement = NULL; @@ -683,7 +721,7 @@ cmyth_conn_connect_path(char* path, cmyth_conn_t control, int err = 0; int count = 0; int r, port; - int ann_size = sizeof("ANN FileTransfer []:[][]:[]"); + int ann_size = sizeof("ANN FileTransfer 0[]:[][]:[]"); struct sockaddr_in addr; socklen_t addr_size = sizeof(addr); cmyth_file_t ret = NULL; @@ -716,18 +754,29 @@ cmyth_conn_connect_path(char* path, cmyth_conn_t control, __FUNCTION__, host, port, buflen); goto shut; } - ann_size += strlen(path) + strlen(my_hostname); - announcement = malloc(ann_size); - if (!announcement) { + /* + * Explicitly set the conn version to the control version as cmyth_connect() doesn't and some of + * the cmyth_rcv_* functions expect it to be the same as the protocol version used by mythbackend. + */ + conn->conn_version = control->conn_version; + + ann_size += strlen(path) + strlen(my_hostname) + strlen(sgToGetFrom) + 6; + announcement = malloc(ann_size); if (!announcement) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: malloc(%d) failed for announcement\n", __FUNCTION__, ann_size); goto shut; } - if (control->conn_version >= 44) { - sprintf(announcement, "ANN FileTransfer %s[]:[]%s[]:[]", + if (control->conn_version >= 44) { /*TSP: from version 44 according to the source code*/ + if (strlen(sgToGetFrom) > 1) { + sprintf(announcement, "ANN FileTransfer %s 0 0 0[]:[]%s[]:[]%s", + my_hostname, path, sgToGetFrom); + } + else { + sprintf(announcement, "ANN FileTransfer %s 0[]:[]%s[]:[]", // write = false my_hostname, path); - } + } + } else { sprintf(announcement, "ANN FileTransfer %s[]:[]%s", my_hostname, path); @@ -771,7 +820,7 @@ cmyth_conn_connect_path(char* path, cmyth_conn_t control, r = cmyth_rcv_u_long_long(conn, &err, &ret->file_length, count); if (err) { cmyth_dbg(CMYTH_DBG_ERROR, - "%s: (length) cmyth_rcv_longlong() failed (%d)\n", + "%s: (length) cmyth_rcv_u_long_long() failed (%d)\n", __FUNCTION__, err); goto shut; } @@ -1287,6 +1336,8 @@ cmyth_conn_get_protocol_version(cmyth_conn_t conn) } + + int cmyth_conn_get_free_recorder_count(cmyth_conn_t conn) { @@ -1347,6 +1398,93 @@ cmyth_conn_get_setting(cmyth_conn_t conn, const char* hostname, const char* sett return result; } +int cmyth_conn_set_setting(cmyth_conn_t conn, + const char* hostname, const char* setting, const char* value) +{ + int result = -1; + + pthread_mutex_lock(&mutex); + result = cmyth_conn_set_setting_unlocked(conn, hostname, setting, value); + pthread_mutex_unlock(&mutex); + + return result; +} + +char * +cmyth_conn_get_backend_hostname(cmyth_conn_t conn) +{ + int count, err; + char* result = NULL; + + pthread_mutex_lock(&mutex); + if(conn->conn_version < 17) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: protocol version doesn't support QUERY_HOSTNAME\n", + __FUNCTION__); + return NULL; + } + + if (!conn) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", + __FUNCTION__); + return NULL; + } + + if ((err = cmyth_send_message(conn, "QUERY_HOSTNAME")) < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_send_message() failed (%d)\n", + __FUNCTION__, err); + goto err; + } + + if ((count=cmyth_rcv_length(conn)) < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_length() failed (%d)\n", + __FUNCTION__, count); + goto err; + } + + result = ref_alloc(count+1); + count -= cmyth_rcv_string(conn, &err, + result, count, count); + if (err < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_string() failed (%d)\n", + __FUNCTION__, err); + goto err; + } + + while(count > 0 && !err) { + char buffer[100]; + count -= cmyth_rcv_string(conn, &err, buffer, sizeof(buffer)-1, count); + buffer[sizeof(buffer)-1] = 0; + cmyth_dbg(CMYTH_DBG_ERROR, "%s: odd left over data %s\n", __FUNCTION__, buffer); + } + pthread_mutex_unlock(&mutex); + + if(!strcmp("-1",result)) { + cmyth_dbg(CMYTH_DBG_PROTO, + "%s: Failed to retrieve backend hostname.\n", + __FUNCTION__); + return NULL; + } + return result; +err: + pthread_mutex_unlock(&mutex); + if(result) + ref_release(result); + + return NULL; +} + +char * +cmyth_conn_get_client_hostname(cmyth_conn_t conn) +{ + char* result=NULL; + result = ref_strdup(my_hostname); + return result; +} + + static char * cmyth_conn_get_setting_unlocked(cmyth_conn_t conn, const char* hostname, const char* setting) { @@ -1398,6 +1536,12 @@ cmyth_conn_get_setting_unlocked(cmyth_conn_t conn, const char* hostname, const c cmyth_dbg(CMYTH_DBG_ERROR, "%s: odd left over data %s\n", __FUNCTION__, buffer); } + if(!strcmp("-1",result)) { + cmyth_dbg(CMYTH_DBG_PROTO, + "%s: Setting: %s or hostname: %s not found.\n", + __FUNCTION__, setting,hostname); + return NULL; + } return result; err: if(result) @@ -1406,3 +1550,37 @@ err: return NULL; } +static int cmyth_conn_set_setting_unlocked(cmyth_conn_t conn, + const char* hostname, const char* setting, const char* value) +{ + char msg[1024]; + int err = 0; + + if(conn->conn_version < 17) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: protocol version doesn't support SET_SETTING\n", + __FUNCTION__); + return -1; + } + + if (!conn) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", + __FUNCTION__); + return -2; + } + + snprintf(msg, sizeof(msg), "SET_SETTING %s %s %s", hostname, setting, value); + if ((err = cmyth_send_message(conn, msg)) < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_send_message() failed (%d)\n", + __FUNCTION__, err); + return -3; + } + + if (cmyth_rcv_okay(conn, "OK") < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_okay() failed\n", + __FUNCTION__); + return -4; + } + + return 1; +} diff --git a/lib/cmyth/libcmyth/event.c b/lib/cmyth/libcmyth/event.c index f340ac6..f45682f 100644 --- a/lib/cmyth/libcmyth/event.c +++ b/lib/cmyth/libcmyth/event.c @@ -88,16 +88,27 @@ cmyth_event_get(cmyth_conn_t conn, char * data, int len) event = CMYTH_EVENT_LIVETV_CHAIN_UPDATE; strncpy(data, tmp + 20, len); } else if (strncmp(tmp, "SIGNAL", 6) == 0) { + int dstlen=len; event = CMYTH_EVENT_SIGNAL; + /*Get Recorder ID */ + strncat(data,"cardid ",7); + strncat(data,tmp+7,consumed-12); + strncat(data,";",2); /* get slock, signal, seen_pat, matching_pat */ - while (count > 0) { - /* get signalmonitorvalue name */ + while (count > 0) { + + /* get signalmonitorvalue name */ consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; - + /*strncat(data,tmp,dstlen-2); + strncat(data,"=",2); + dstlen -= consumed;*/ /* get signalmonitorvalue status */ consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; + strncat(data,tmp,dstlen-2); + strncat(data,";",2); + dstlen -= consumed; } } else if (strncmp(tmp, "ASK_RECORDING", 13) == 0) { event = CMYTH_EVENT_ASK_RECORDING; @@ -164,8 +175,8 @@ cmyth_event_select(cmyth_conn_t conn, struct timeval *timeout) int ret; cmyth_socket_t fd; - cmyth_dbg(CMYTH_DBG_DEBUG, "%s [%s:%d]: (trace) {\n", __FUNCTION__, - __FILE__, __LINE__); + /*cmyth_dbg(CMYTH_DBG_DEBUG, "%s [%s:%d]: (trace) {\n", __FUNCTION__, + __FILE__, __LINE__);*/ if (conn == NULL) return -EINVAL; @@ -177,8 +188,8 @@ cmyth_event_select(cmyth_conn_t conn, struct timeval *timeout) ret = select((int)fd+1, &fds, NULL, NULL, timeout); - cmyth_dbg(CMYTH_DBG_DEBUG, "%s [%s:%d]: (trace) }\n", - __FUNCTION__, __FILE__, __LINE__); + /*cmyth_dbg(CMYTH_DBG_DEBUG, "%s [%s:%d]: (trace) }\n", + __FUNCTION__, __FILE__, __LINE__);*/ return ret; } diff --git a/lib/cmyth/libcmyth/file.c b/lib/cmyth/libcmyth/file.c index 74408ed..32c8876 100644 --- a/lib/cmyth/libcmyth/file.c +++ b/lib/cmyth/libcmyth/file.c @@ -20,6 +20,7 @@ #include #include #include +#include #ifndef _MSC_VER #include #endif @@ -254,6 +255,56 @@ cmyth_file_length(cmyth_file_t file) } /* + * cmyth_update_file_length(cmyth_file_t file, unsigned long long newLength) + * + * Scope: PUBLIC + * + * Description + * + * Updates a files length, with a value returned from a UPDATE_FILE_SIZE event + * + * Return Value: + * + * Sucess: a int value >= 0 + * + * Failure: a int containing -errno + */ +int +cmyth_update_file_length(cmyth_file_t file, unsigned long long newLength) +{ + if (!file) { + return -EINVAL; + } + file->file_length = newLength; + return 0; +} + +/* + * cmyth_file_position(cmyth_file_t p) + * + * Scope: PUBLIC + * + * Description + * + * Obtain the position in the data of a file. + * + * Return Value: + * + * Sucess: a long long value >= 0 + * + * Failure: a long long containing -errno + */ +unsigned long long +cmyth_file_position(cmyth_file_t file) +{ + if (!file) { + return -EINVAL; + } + return file->file_pos; +} + + +/* * cmyth_file_get_block(cmyth_file_t file, char *buf, unsigned long len) * * Scope: PUBLIC @@ -449,6 +500,105 @@ cmyth_file_seek(cmyth_file_t file, long long offset, int whence) pthread_mutex_lock(&mutex); + if (file->file_control->conn_version >= 66) { + /* + * Since protocol 66 mythbackend expects to receive a single 64 bit integer rather than + * two 32 bit hi and lo integers. + */ + snprintf(msg, sizeof(msg), + "QUERY_FILETRANSFER %ld[]:[]SEEK[]:[]%"PRIu64"[]:[]%d[]:[]%"PRIu64, + file->file_id, + (int64_t)offset, + whence, + (int64_t)file->file_pos); + } + else { + snprintf(msg, sizeof(msg), + "QUERY_FILETRANSFER %ld[]:[]SEEK[]:[]%d[]:[]%d[]:[]%d[]:[]%d[]:[]%d", + file->file_id, + (int32_t)(offset >> 32), + (int32_t)(offset & 0xffffffff), + whence, + (int32_t)(file->file_pos >> 32), + (int32_t)(file->file_pos & 0xffffffff)); + } + + if ((err = cmyth_send_message(file->file_control, msg)) < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_send_message() failed (%d)\n", + __FUNCTION__, err); + ret = err; + goto out; + } + + if ((count=cmyth_rcv_length(file->file_control)) < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_length() failed (%d)\n", + __FUNCTION__, count); + ret = count; + goto out; + } + if ((r=cmyth_rcv_long_long(file->file_control, &err, &c, count)) < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_long_long() failed (%d)\n", + __FUNCTION__, r); + ret = err; + goto out; + } + + switch (whence) { + case SEEK_SET: + file->file_pos = offset; + break; + case SEEK_CUR: + file->file_pos += offset; + break; + case SEEK_END: + file->file_pos = file->file_length - offset; + break; + } + + file->file_req = file->file_pos; + if(file->file_pos > file->file_length) + file->file_length = file->file_pos; + + ret = file->file_pos; + + out: + pthread_mutex_unlock(&mutex); + + return ret; +} + +long long +cmyth_file_seek_unlocked(cmyth_file_t file, long long offset, int whence) +{ + char msg[128]; + int err; + int count; + long long c; + long r; + long long ret; + + if (file == NULL) + return -EINVAL; + + if ((offset == 0) && (whence == SEEK_CUR)) + return file->file_pos; + + if ((offset == file->file_pos) && (whence == SEEK_SET)) + return file->file_pos; + + while(file->file_pos < file->file_req) { + c = file->file_req - file->file_pos; + if(c > sizeof(msg)) + c = sizeof(msg); + + if (cmyth_file_get_block(file, msg, (unsigned long)c) < 0) + return -1; + } + + snprintf(msg, sizeof(msg), "QUERY_FILETRANSFER %ld[]:[]SEEK[]:[]%d[]:[]%d[]:[]%d[]:[]%d[]:[]%d", file->file_id, @@ -500,11 +650,9 @@ cmyth_file_seek(cmyth_file_t file, long long offset, int whence) ret = file->file_pos; out: - pthread_mutex_unlock(&mutex); return ret; } - /* * cmyth_file_read(cmyth_recorder_t rec, char *buf, unsigned long len) * diff --git a/lib/cmyth/libcmyth/input.c b/lib/cmyth/libcmyth/input.c new file mode 100644 index 0000000..b9bda31 --- /dev/null +++ b/lib/cmyth/libcmyth/input.c @@ -0,0 +1,235 @@ +/* + * Copyright (C) 2012, Christian Fetzer + * http://www.mvpmc.org/ + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + */ + +#include +#include +#include +#include +#include + +static void +cmyth_inputlist_destroy(cmyth_inputlist_t il) +{ + int i; + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__); + if (!il) { + return; + } + for (i = 0; i < il->input_count; ++i) { + if (il->input_list[i]) { + ref_release(il->input_list[i]); + } + il->input_list[i] = NULL; + } + if (il->input_list) { + free(il->input_list); + } +} + +cmyth_inputlist_t +cmyth_inputlist_create(void) +{ + cmyth_inputlist_t ret; + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__); + ret = ref_alloc(sizeof(*ret)); + if (!ret) { + return(NULL); + } + ref_set_destroy(ret, (ref_destroy_t)cmyth_inputlist_destroy); + + ret->input_list = NULL; + ret->input_count = 0; + return ret; +} + +void +cmyth_input_destroy(cmyth_input_t i) +{ + cmyth_dbg(CMYTH_DBG_DEBUG, "%s {\n", __FUNCTION__); + if (!i) { + cmyth_dbg(CMYTH_DBG_DEBUG, "%s }!a\n", __FUNCTION__); + return; + } + cmyth_dbg(CMYTH_DBG_DEBUG, "%s }\n", __FUNCTION__); + + if (i->inputname) { + ref_release(i->inputname); + } +} + +cmyth_input_t +cmyth_input_create(void) +{ + cmyth_input_t ret = ref_alloc(sizeof(*ret)); + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s {\n", __FUNCTION__); + if (!ret) { + cmyth_dbg(CMYTH_DBG_DEBUG, "%s }!\n", __FUNCTION__); + return NULL; + } + ref_set_destroy(ret, (ref_destroy_t)cmyth_input_destroy); + + ret->inputname = NULL; + ret->sourceid = 0; + ret->inputid = 0; + ret->cardid = 0; + ret->multiplexid = 0; + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s }\n", __FUNCTION__); + return ret; +} + +cmyth_inputlist_t +cmyth_get_free_inputlist(cmyth_recorder_t rec) +{ + unsigned int len = CMYTH_LONGLONG_LEN + 36; + int err; + int count; + char *buf; + int r; + + cmyth_inputlist_t inputlist = cmyth_inputlist_create(); + + buf = alloca(len); + if (!buf) { + return inputlist; + } + + sprintf(buf,"QUERY_RECORDER %d[]:[]GET_FREE_INPUTS", rec->rec_id); + pthread_mutex_lock(&mutex); + if ((err = cmyth_send_message(rec->rec_conn, buf)) < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_send_message() failed (%d)\n", + __FUNCTION__, err); + goto out; + } + + count = cmyth_rcv_length(rec->rec_conn); + if (count < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_length() failed (%d)\n", + __FUNCTION__, count); + goto out; + } + + if ((r = cmyth_rcv_free_inputlist(rec->rec_conn, &err, inputlist, count)) < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_string() failed (%d)\n", + __FUNCTION__, r); + goto out; + } + + out: + pthread_mutex_unlock(&mutex); + return inputlist; +} + +int cmyth_rcv_free_inputlist(cmyth_conn_t conn, int *err, + cmyth_inputlist_t inputlist, int count) +{ + int consumed; + int total = 0; + char *failed = NULL; + cmyth_input_t input; + char inputname[100]; + unsigned long sourceid; + unsigned long inputid; + unsigned long cardid; + unsigned long multiplexid; + unsigned long livetvorder; + + if (count <= 0) { + *err = EINVAL; + return 0; + } + + while (count) { + consumed = cmyth_rcv_string(conn, err, inputname, sizeof(inputname)-1, count); + inputname[sizeof(inputname)-1] = 0; + count -= consumed; + total += consumed; + if (*err) { + failed = "cmyth_rcv_string"; + goto fail; + } + + consumed = cmyth_rcv_ulong(conn, err, &sourceid, count); + count -= consumed; + total += consumed; + if (*err) { + failed = "cmyth_rcv_ulong"; + goto fail; + } + + consumed = cmyth_rcv_ulong(conn, err, &inputid, count); + count -= consumed; + total += consumed; + if (*err) { + failed = "cmyth_rcv_ulong"; + goto fail; + } + + consumed = cmyth_rcv_ulong(conn, err, &cardid, count); + count -= consumed; + total += consumed; + if (*err) { + failed = "cmyth_rcv_ulong"; + goto fail; + } + + consumed = cmyth_rcv_ulong(conn, err, &multiplexid, count); + count -= consumed; + total += consumed; + if (*err) { + failed = "cmyth_rcv_ulong"; + goto fail; + } + + if (conn->conn_version >= 71) { + consumed = cmyth_rcv_ulong(conn, err, &livetvorder, count); + count -= consumed; + total += consumed; + if (*err) { + failed = "cmyth_rcv_ulong"; + goto fail; + } + } + + input = cmyth_input_create(); + input->inputname = ref_strdup(inputname); + input->sourceid = sourceid; + input->inputid = inputid; + input->cardid = cardid; + input->multiplexid = multiplexid; + input->livetvorder = livetvorder; + + inputlist->input_list = realloc(inputlist->input_list, + (++inputlist->input_count) * sizeof(cmyth_input_t)); + inputlist->input_list[inputlist->input_count - 1] = input; + } + + return total; + + fail: + cmyth_dbg(CMYTH_DBG_ERROR, "%s: %s() failed (%d)\n", + __FUNCTION__, failed, *err); + return total; +} diff --git a/lib/cmyth/libcmyth/livetv.c b/lib/cmyth/libcmyth/livetv.c index 96e50a2..2cb67a2 100644 --- a/lib/cmyth/libcmyth/livetv.c +++ b/lib/cmyth/libcmyth/livetv.c @@ -805,6 +805,34 @@ int cmyth_livetv_chain_read(cmyth_recorder_t rec, char *buf, unsigned long len) } /* + * cmyth_livetv_chain_duration(cmyth_recorder_t file) + * + * Scope: PUBLIC + * + * Description + * + * Get current chain duration + * + * Return Value: + * + * Sucess: chain duration + * + * Failure: an int containing -errno + */ + +long long +cmyth_livetv_chain_duration(cmyth_recorder_t rec) +{ + int cur, ct; + long long ret=0; + ct = rec->rec_livetv_chain->chain_ct; + for (cur = 0; cur < ct; cur++) { + ret += rec->rec_livetv_chain->chain_files[cur]->file_length; + } + return ret; +} + +/* * cmyth_livetv_chain_seek(cmyth_recorder_t file, long long offset, int whence) * * Scope: PUBLIC @@ -869,6 +897,11 @@ cmyth_livetv_chain_seek(cmyth_recorder_t rec, long long offset, int whence) } return offset; } + else + { + cur = rec->rec_livetv_chain->chain_current; + fp = rec->rec_livetv_chain->chain_files[cur]; + } offset += fp->file_req; @@ -893,7 +926,7 @@ cmyth_livetv_chain_seek(cmyth_recorder_t rec, long long offset, int whence) pthread_mutex_lock(&mutex); - ret = cmyth_file_seek(fp, offset, whence); + ret = cmyth_file_seek_unlocked(fp, offset, whence); PRINTF("** SSDEBUG: new pos %lld after seek command\n", ret); @@ -1047,6 +1080,13 @@ cmyth_spawn_live_tv(cmyth_recorder_t rec, unsigned buflen, int tcp_rcvbuf, goto err; } + for(i=0; i<20; i++) { + if(cmyth_recorder_is_recording(rec) != 1) + sleep(1); + else + break; + } + if ((rtrn = cmyth_livetv_chain_setup(rec, tcp_rcvbuf, prog_update_callback)) == NULL) { *err = "Failed to setup livetv."; diff --git a/lib/cmyth/libcmyth/mysql_query.c b/lib/cmyth/libcmyth/mysql_query.c index 6370e13..7cb7d4e 100644 --- a/lib/cmyth/libcmyth/mysql_query.c +++ b/lib/cmyth/libcmyth/mysql_query.c @@ -368,3 +368,4 @@ cmyth_mysql_query(cmyth_mysql_query_t * query) } return 0; } + diff --git a/lib/cmyth/libcmyth/mythtv_mysql.c b/lib/cmyth/libcmyth/mythtv_mysql.c index 3ff23fa..c593b43 100644 --- a/lib/cmyth/libcmyth/mythtv_mysql.c +++ b/lib/cmyth/libcmyth/mythtv_mysql.c @@ -57,12 +57,21 @@ cmyth_database_close(cmyth_database_t db) } } +static void +cmyth_database_destroy(cmyth_database_t db) +{ + cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__); + cmyth_database_close(db); +} + cmyth_database_t cmyth_database_init(char *host, char *db_name, char *user, char *pass) { cmyth_database_t rtrn = ref_alloc(sizeof(*rtrn)); cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__); + ref_set_destroy(rtrn, (ref_destroy_t)cmyth_database_destroy); + if (rtrn != NULL) { rtrn->db_host = ref_strdup(host); rtrn->db_user = ref_strdup(user); @@ -277,6 +286,72 @@ cmyth_get_offset_mysql(cmyth_database_t db, int type, char *recordid, int chanid } } +int +cmyth_get_watched_status_mysql(cmyth_database_t db, int recordid) +{ + + MYSQL_RES *res= NULL; + MYSQL_ROW row; + const char *query_str = "SELECT watched FROM recorded WHERE recordid=?"; + int retval = 0; + cmyth_mysql_query_t * query; + + query = cmyth_mysql_query_create(db,query_str); + + if (cmyth_mysql_query_param_long(query,recordid) < 0) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); + ref_release(query); + return -1; + } + res = cmyth_mysql_query_result(query); + ref_release(query); + if(res == NULL) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution of query failed!\n", __FUNCTION__); + return -1; + } + + + if (row = mysql_fetch_row(res)) { + retval = safe_atoi(row[0]); + mysql_free_result(res); + return retval; + } + else + return 0; +} + +int +cmyth_set_watched_status_mysql(cmyth_database_t db, int recordid, int watchedStat) +{ + cmyth_mysql_query_t * query; + + if (watchedStat > 1) watchedStat = 1; + if (watchedStat < 0) watchedStat = 0; + + query = cmyth_mysql_query_create(db,"UPDATE recorded SET watched = ? WHERE recordid = ?"); + + if(cmyth_mysql_query_param_long(query,watchedStat) < 0 + || cmyth_mysql_query_param_long(query,recordid) < 0 + ) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); + ref_release(query); + return -1; + } + + if(cmyth_mysql_query(query) < 0) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution of query failed!\n", __FUNCTION__); + ref_release(query); + return -1; + } + ref_release(query); + return 0; + +} + char * cmyth_get_recordid_mysql(cmyth_database_t db, int chanid, char *title, char *subtitle, char *description, char *seriesid, char *programid) { @@ -442,7 +517,7 @@ cmyth_mysql_get_guide(cmyth_database_t db, cmyth_program_t **prog, time_t startt { MYSQL_RES *res= NULL; MYSQL_ROW row; - const char *query_str = "SELECT program.chanid,UNIX_TIMESTAMP(program.starttime),UNIX_TIMESTAMP(program.endtime),program.title,program.description,program.subtitle,program.programid,program.seriesid,program.category,channel.channum,channel.callsign,channel.name,channel.sourceid FROM program INNER JOIN channel ON program.chanid=channel.chanid WHERE ( ( starttime>=? and starttime ?) ) ORDER BY (channel.channum + 0), program.starttime ASC "; + const char *query_str = "SELECT program.chanid,UNIX_TIMESTAMP(program.starttime),UNIX_TIMESTAMP(program.endtime),program.title,program.description,program.subtitle,program.programid,program.seriesid,program.category,channel.channum,channel.callsign,channel.name,channel.sourceid FROM program INNER JOIN channel ON program.chanid=channel.chanid WHERE ((program.endtime > ? and program.endtime < ?) or (program.starttime >= ? and program.starttime <= ?) or (program.starttime <= ? and program.endtime >= ?)) ORDER BY (channel.channum + 0), program.starttime ASC "; int rows=0; int n=0; cmyth_mysql_query_t * query; @@ -451,7 +526,9 @@ cmyth_mysql_get_guide(cmyth_database_t db, cmyth_program_t **prog, time_t startt if(cmyth_mysql_query_param_unixtime(query,starttime) < 0 || cmyth_mysql_query_param_unixtime(query,endtime) < 0 || cmyth_mysql_query_param_unixtime(query,starttime) < 0 - || cmyth_mysql_query_param_unixtime(query,starttime) < 0) + || cmyth_mysql_query_param_unixtime(query,endtime) < 0 + || cmyth_mysql_query_param_unixtime(query,starttime) < 0 + || cmyth_mysql_query_param_unixtime(query,endtime) < 0) { cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); ref_release(query); @@ -936,7 +1013,7 @@ cmyth_mythtv_remove_previos_recorded(cmyth_database_t db,char *query) int cmyth_mysql_testdb_connection(cmyth_database_t db,char **message) { - char *buf=malloc(sizeof(char)*1001); + char *buf=ref_alloc(sizeof(char)*1001); int new_conn = 0; if (db->mysql != NULL) { if (mysql_stat(db->mysql) == NULL) { @@ -1052,7 +1129,7 @@ cmyth_channel_destroy(cmyth_channel_t pl) if(pl->callsign) ref_release(pl->callsign); if(pl->icon) - ref_release(pl->callsign); + ref_release(pl->icon); } long @@ -1074,6 +1151,16 @@ cmyth_channel_channum(cmyth_channel_t channel) } char * +cmyth_channel_channumstr(cmyth_channel_t channel) +{ + if (!channel) { + return NULL; + } + return channel->chanstr; +} + + +char * cmyth_channel_name(cmyth_channel_t channel) { if (!channel) { @@ -1083,6 +1170,16 @@ cmyth_channel_name(cmyth_channel_t channel) } char * +cmyth_channel_callsign(cmyth_channel_t channel) +{ + if (!channel) { + return NULL; + } + return ref_hold(channel->callsign); +} + + +char * cmyth_channel_icon(cmyth_channel_t channel) { if (!channel) { @@ -1100,6 +1197,24 @@ cmyth_channel_visible(cmyth_channel_t channel) return channel->visible; } +int +cmyth_channel_sourceid(cmyth_channel_t channel) +{ + if (!channel) { + return -EINVAL; + } + return channel->sourceid; +} + +int +cmyth_channel_multiplex(cmyth_channel_t channel) +{ + if (!channel) { + return -EINVAL; + } + return channel->multiplex; +} + cmyth_channel_t cmyth_channel_create(void) { @@ -1117,11 +1232,12 @@ cmyth_channel_create(void) } + cmyth_chanlist_t cmyth_mysql_get_chanlist(cmyth_database_t db) { MYSQL_RES *res = NULL; MYSQL_ROW row; - const char *query_str = "SELECT chanid, channum, name, icon, visible FROM channel;"; + const char *query_str = "SELECT chanid, channum, name, icon, visible, sourceid, mplexid, callsign FROM channel;"; int rows = 0; int i; cmyth_mysql_query_t * query; @@ -1153,9 +1269,13 @@ cmyth_chanlist_t cmyth_mysql_get_chanlist(cmyth_database_t db) channel = cmyth_channel_create(); channel->chanid = safe_atol(row[0]); channel->channum = safe_atoi(row[1]); + strncpy(channel->chanstr, row[1], 10); channel->name = ref_strdup(row[2]); channel->icon = ref_strdup(row[3]); channel->visible = safe_atoi(row[4]); + channel->sourceid = safe_atoi(row[5]); + channel->multiplex = safe_atoi(row[6]); + channel->callsign = ref_strdup(row[7]); chanlist->chanlist_list[rows] = channel; i = 0; rows++; @@ -1259,3 +1379,1057 @@ int cmyth_livetv_keep_recording(cmyth_recorder_t rec, cmyth_database_t db, int k return 1; } + +int cmyth_mysql_is_radio(cmyth_database_t db, int chanid) +{ + cmyth_mysql_query_t * query; + MYSQL_RES *res = NULL; + MYSQL_ROW row; + int retval=-1; + + if(cmyth_db_check_connection(db) != 0) + { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_db_check_connection failed\n", __FUNCTION__); + return -1; + } + + + query = cmyth_mysql_query_create(db,"SELECT is_audio_service FROM channelscan_channel INNER JOIN channel ON channelscan_channel.service_id=channel.serviceid WHERE channel.chanid = ? ORDER BY channelscan_channel.scanid DESC;"); + + if(cmyth_mysql_query_param_long(query,chanid) < 0) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); + ref_release(query); + return -1; + } + + res = cmyth_mysql_query_result(query); + ref_release(query); + + if (res == NULL) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s, finalisation/execution of query failed!\n", __FUNCTION__); + return -1; + } + + if (row = mysql_fetch_row(res)) { + retval = safe_atoi(row[0]); + } + else + { + cmyth_dbg(CMYTH_DBG_ERROR, "%s, Channum %i not found\n", __FUNCTION__,chanid); + return -1; + } + mysql_free_result(res); + return retval; +} + + +static void +cmyth_timer_destroy(cmyth_timer_t pl) +{ + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__); + if (!pl) { + return; + } + + if(pl->title) + ref_release(pl->title); + if(pl->description) + ref_release(pl->description); + if(pl->category) + ref_release(pl->category); + if(pl->rec_group) + ref_release(pl->rec_group); + if(pl->store_group) + ref_release(pl->store_group); + if(pl->play_group) + ref_release(pl->play_group); +} + + +cmyth_timer_t +cmyth_timer_create(void) +{ + cmyth_timer_t ret = ref_alloc(sizeof(*ret)); + memset(ret, 0, sizeof(*ret)); + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s {\n", __FUNCTION__); + if (!ret) { + cmyth_dbg(CMYTH_DBG_DEBUG, "%s }!\n", __FUNCTION__); + return NULL; + } + ref_set_destroy(ret, (ref_destroy_t)cmyth_timer_destroy); + + return ret; +} + + +static void +cmyth_timerlist_destroy(cmyth_timerlist_t pl) +{ + int i; + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__); + if (!pl) { + return; + } + for (i = 0; i < pl->timerlist_count; ++i) { + if (pl->timerlist_list[i]) { + ref_release(pl->timerlist_list[i]); + } + pl->timerlist_list[i] = NULL; + } + if (pl->timerlist_list) { + free(pl->timerlist_list); + } +} + +cmyth_timerlist_t +cmyth_timerlist_create(void) +{ + cmyth_timerlist_t ret; + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__); + ret = ref_alloc(sizeof(*ret)); + if (!ret) { + return(NULL); + } + ref_set_destroy(ret, (ref_destroy_t)cmyth_timerlist_destroy); + + ret->timerlist_list = NULL; + ret->timerlist_count = 0; + return ret; +} + + +cmyth_timerlist_t +cmyth_mysql_get_timers(cmyth_database_t db) +{ + MYSQL_RES *res= NULL; + MYSQL_ROW row; + const char *query_str = "SELECT recordid, chanid, UNIX_TIMESTAMP(ADDTIME(startdate,starttime)), UNIX_TIMESTAMP(ADDTIME(enddate,endtime)),title,description, type, category, subtitle, recpriority, startoffset, endoffset, search, inactive, station, dupmethod, dupin, recgroup, storagegroup, playgroup, autotranscode, (autouserjob1 | (autouserjob2 << 1) | (autouserjob3 << 2) | (autouserjob4 << 3)), autocommflag, autoexpire, maxepisodes, maxnewest, transcoder FROM record ORDER BY recordid"; + int rows=0; + cmyth_timer_t timer; + cmyth_timerlist_t timerlist; + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + + res = cmyth_mysql_query_result(query); + ref_release(query); + if(res == NULL) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution of query failed!\n", __FUNCTION__); + return NULL; + } + + + timerlist = cmyth_timerlist_create(); + + timerlist->timerlist_count = (int)mysql_num_rows(res); + timerlist->timerlist_list = malloc(timerlist->timerlist_count * sizeof(cmyth_timerlist_t)); + if (!timerlist->timerlist_list) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: malloc() failed for list\n", + __FUNCTION__); + ref_release(timerlist); + return NULL; + } + memset(timerlist->timerlist_list, 0, timerlist->timerlist_count * sizeof(cmyth_timerlist_t)); + + + while ((row = mysql_fetch_row(res))) { + timer = cmyth_timer_create(); + timer->recordid = safe_atol(row[0]); + timer->chanid = safe_atoi(row[1]); + timer->starttime = (time_t)safe_atol(row[2]); + timer->endtime = (time_t)safe_atol(row[3]); + timer->title = ref_strdup(row[4]); + timer->description = ref_strdup(row[5]); + timer->type = safe_atoi(row[6]); + timer->category = ref_strdup(row[7]); + timer->subtitle = ref_strdup(row[8]); + timer->priority = safe_atoi(row[9]); + timer->startoffset = safe_atoi(row[10]); + timer->endoffset = safe_atoi(row[11]); + timer->searchtype = safe_atoi(row[12]); + timer->inactive = safe_atoi(row[13]); + timer->callsign = ref_strdup(row[14]); + timer->dup_method = safe_atoi(row[15]); + timer->dup_in = safe_atoi(row[16]); + timer->rec_group = ref_strdup(row[17]); + timer->store_group = ref_strdup(row[18]); + timer->play_group = ref_strdup(row[19]); + timer->autotranscode = safe_atoi(row[20]); + timer->userjobs = safe_atoi(row[21]); + timer->autocommflag = safe_atoi(row[22]); + timer->autoexpire = safe_atoi(row[23]); + timer->maxepisodes = safe_atoi(row[24]); + timer->maxnewest = safe_atoi(row[25]); + timer->transcoder = safe_atoi(row[26]); + timerlist->timerlist_list[rows] = timer; + rows++; + } + + mysql_free_result(res); + cmyth_dbg(CMYTH_DBG_ERROR, "%s: rows= %d\n", __FUNCTION__, rows); + return timerlist; +} + + + +int +cmyth_mysql_add_timer(cmyth_database_t db, int chanid,char* callsign, char* description, time_t starttime, time_t endtime,char* title,char* category,int type,char* subtitle,int priority,int startoffset,int endoffset,int searchtype,int inactive, + int dup_method, + int dup_in, + char* rec_group, + char* store_group, + char* play_group, + int autotranscode, + int userjobs, + int autocommflag, + int autoexpire, + int maxepisodes, + int maxnewest, + int transcoder) +{ + int ret = -1; + int id=0; + MYSQL* sql=cmyth_db_get_connection(db); + const char *query_str = "INSERT INTO record (record.type, chanid, starttime, startdate, endtime, enddate,title, description, category, findid, findtime, station, subtitle , recpriority , startoffset , endoffset , search , inactive, dupmethod, dupin, recgroup, storagegroup, playgroup, autotranscode, autouserjob1, autouserjob2, autouserjob3, autouserjob4, autocommflag, autoexpire, maxepisodes, maxnewest, transcoder) VALUES (? , ? , TIME(FROM_UNIXTIME( ? )), DATE(FROM_UNIXTIME( ? )) , TIME(FROM_UNIXTIME( ? )), DATE(FROM_UNIXTIME( ? )) , ? , ?, ?, TO_DAYS(DATE(FROM_UNIXTIME( ? ))), TIME(FROM_UNIXTIME( ? )) , ?, ?, ?, ?, ?, ?, ? ,?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? ,?, ?, ?, ?);"; + + char* esctitle = cmyth_mysql_escape_chars(db,title); + char* escdescription = cmyth_mysql_escape_chars(db,description); + char* esccategory = cmyth_mysql_escape_chars(db,category); + char* esccallsign=cmyth_mysql_escape_chars(db,callsign); + char* escsubtitle = cmyth_mysql_escape_chars(db,subtitle); + + char* escrec_group = cmyth_mysql_escape_chars(db,rec_group); + char* escstore_group = cmyth_mysql_escape_chars(db,store_group); + char* escplay_group = cmyth_mysql_escape_chars(db,play_group); + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + if ( cmyth_mysql_query_param_long(query, type) < 0 + || cmyth_mysql_query_param_long(query, chanid) < 0 + || cmyth_mysql_query_param_long(query, starttime ) < 0 + || cmyth_mysql_query_param_long(query, starttime ) < 0 + || cmyth_mysql_query_param_long(query, endtime ) < 0 + || cmyth_mysql_query_param_long(query, endtime ) < 0 + || cmyth_mysql_query_param_str(query, title ) < 0 + || cmyth_mysql_query_param_str(query, description ) < 0 + || cmyth_mysql_query_param_str(query, category ) < 0 + || cmyth_mysql_query_param_long(query, starttime ) < 0 + || cmyth_mysql_query_param_long(query, starttime ) < 0 + || cmyth_mysql_query_param_str(query, callsign ) < 0 + || cmyth_mysql_query_param_str(query, subtitle ) < 0 + || cmyth_mysql_query_param_long(query, priority ) < 0 + || cmyth_mysql_query_param_long(query, startoffset ) < 0 + || cmyth_mysql_query_param_long(query, endoffset ) < 0 + || cmyth_mysql_query_param_long(query, searchtype ) < 0 + || cmyth_mysql_query_param_long(query, inactive ) < 0 + + || cmyth_mysql_query_param_long(query, dup_method ) < 0 + || cmyth_mysql_query_param_long(query, dup_in ) < 0 + || cmyth_mysql_query_param_str(query, rec_group ) < 0 + || cmyth_mysql_query_param_str(query, store_group ) < 0 + || cmyth_mysql_query_param_str(query, play_group ) < 0 + || cmyth_mysql_query_param_long(query, autotranscode ) < 0 + || cmyth_mysql_query_param_long(query, userjobs & 1) < 0 + || cmyth_mysql_query_param_long(query, userjobs & 2) < 0 + || cmyth_mysql_query_param_long(query, userjobs & 4) < 0 + || cmyth_mysql_query_param_long(query, userjobs & 8) < 0 + || cmyth_mysql_query_param_long(query, autocommflag ) < 0 + || cmyth_mysql_query_param_long(query, autoexpire ) < 0 + || cmyth_mysql_query_param_long(query, maxepisodes ) < 0 + || cmyth_mysql_query_param_long(query, maxnewest ) < 0 + || cmyth_mysql_query_param_long(query, transcoder ) < 0 + ) { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); + ref_release(query); + return -1; + } + + ret = cmyth_mysql_query(query); + + // int rrrr; + if(ret!=0) + return -1; + + id = (int)mysql_insert_id(sql); + + ref_release(query); + ref_release(esctitle); + ref_release(escdescription); + ref_release(esccategory); + ref_release(esccallsign); + ref_release(escsubtitle); + + ref_release(escrec_group); + ref_release(escstore_group); + ref_release(escplay_group); + + return id; +} + +int +cmyth_mysql_delete_timer(cmyth_database_t db, int recordid) +{ + int ret = -1; + int id=0; + + const char *query_str = "DELETE FROM record WHERE recordid = ?;"; + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + if (cmyth_mysql_query_param_long(query, recordid) < 0 + ) { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); + ref_release(query); + return -1; + } + + ret = cmyth_mysql_query(query); + + // int rrrr; + + if (ret != 0) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s, finalisation/execution of query failed!\n", __FUNCTION__); + return -1; + } + + return 0; +} + +int +cmyth_mysql_update_timer(cmyth_database_t db, int recordid, int chanid,char* callsign,char* description, time_t starttime, time_t endtime,char* title,char* category,int type,char* subtitle,int priority,int startoffset,int endoffset,int searchtype,int inactive, + int dup_method, + int dup_in, + char* rec_group, + char* store_group, + char* play_group, + int autotranscode, + int userjobs, + int autocommflag, + int autoexpire, + int maxepisodes, + int maxnewest, + int transcoder) +{ + int ret = -1; + int id=0; + + const char *query_str = "UPDATE record SET record.type = ?, `chanid` = ?, `starttime`= TIME(FROM_UNIXTIME( ? )), `startdate`= DATE(FROM_UNIXTIME( ? )), `endtime`= TIME(FROM_UNIXTIME( ? )), `enddate` = DATE(FROM_UNIXTIME( ? )) ,`title`= ?, `description`= ?, category = ?, subtitle = ?, recpriority = ?, startoffset = ?, endoffset = ?, search = ?, inactive = ?, station = ?, dupmethod = ?, dupin = ?, recgroup = ?, storagegroup = ?, playgroup = ?, autotranscode = ?, autouserjob1 = ?, autouserjob2 = ?, autouserjob3 = ?, autouserjob4 = ?, autocommflag = ?, autoexpire = ?, maxepisodes = ?, maxnewest = ?, transcoder = ? WHERE `recordid` = ? ;"; + + char* esctitle=cmyth_mysql_escape_chars(db,title); + char* escdescription=cmyth_mysql_escape_chars(db,description); + char* esccategory=cmyth_mysql_escape_chars(db,category); + char* esccallsign=cmyth_mysql_escape_chars(db,callsign); + char* escsubtitle=cmyth_mysql_escape_chars(db,subtitle); + + char* escrec_group = cmyth_mysql_escape_chars(db,rec_group); + char* escstore_group = cmyth_mysql_escape_chars(db,store_group); + char* escplay_group = cmyth_mysql_escape_chars(db,play_group); + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + if ( cmyth_mysql_query_param_long(query, type) < 0 + || cmyth_mysql_query_param_long(query, chanid) < 0 + || cmyth_mysql_query_param_long(query, starttime ) < 0 + || cmyth_mysql_query_param_long(query, starttime ) < 0 + || cmyth_mysql_query_param_long(query, endtime ) < 0 + || cmyth_mysql_query_param_long(query, endtime ) < 0 + || cmyth_mysql_query_param_str(query, title ) < 0 + || cmyth_mysql_query_param_str(query, description ) < 0 + || cmyth_mysql_query_param_str(query, category ) < 0 + || cmyth_mysql_query_param_str(query, subtitle ) < 0 + || cmyth_mysql_query_param_long(query, priority ) < 0 + || cmyth_mysql_query_param_long(query, startoffset ) < 0 + || cmyth_mysql_query_param_long(query, endoffset ) < 0 + || cmyth_mysql_query_param_long(query, searchtype ) < 0 + || cmyth_mysql_query_param_long(query, inactive ) < 0 + || cmyth_mysql_query_param_str(query, callsign ) < 0 + + || cmyth_mysql_query_param_long(query, dup_method ) < 0 + || cmyth_mysql_query_param_long(query, dup_in ) < 0 + || cmyth_mysql_query_param_str(query, rec_group ) < 0 + || cmyth_mysql_query_param_str(query, store_group ) < 0 + || cmyth_mysql_query_param_str(query, play_group ) < 0 + || cmyth_mysql_query_param_long(query, autotranscode ) < 0 + || cmyth_mysql_query_param_long(query, userjobs & 1) < 0 + || cmyth_mysql_query_param_long(query, userjobs & 2) < 0 + || cmyth_mysql_query_param_long(query, userjobs & 4) < 0 + || cmyth_mysql_query_param_long(query, userjobs & 8) < 0 + || cmyth_mysql_query_param_long(query, autocommflag ) < 0 + || cmyth_mysql_query_param_long(query, autoexpire ) < 0 + || cmyth_mysql_query_param_long(query, maxepisodes ) < 0 + || cmyth_mysql_query_param_long(query, maxnewest ) < 0 + || cmyth_mysql_query_param_long(query, transcoder ) < 0 + + || cmyth_mysql_query_param_long(query, recordid) < 0 + ) { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); + ref_release(query); + return -1; + } + + ret = cmyth_mysql_query(query); + + ref_release(query); + + if (ret == -1) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s, finalisation/execution of query failed!\n", __FUNCTION__); + return -1; + } + ref_release(esctitle); + ref_release(escdescription); + ref_release(esccategory); + ref_release(esccallsign); + ref_release(escsubtitle); + + ref_release(escrec_group); + ref_release(escstore_group); + ref_release(escplay_group); + + return 0; + +} + + +int cmyth_timer_recordid(cmyth_timer_t timer) +{ + if (!timer) { + return -EINVAL; + } + return timer->recordid; +} + + +int cmyth_timer_chanid(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->chanid; +} + +char* cmyth_timer_callsign(cmyth_timer_t timer) +{ + if (!timer) { + return NULL; + } + return ref_hold(timer->callsign); +} + +time_t cmyth_timer_starttime(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->starttime; +} + +time_t cmyth_timer_endtime(cmyth_timer_t timer) +{ + if (!timer) { + return -EINVAL; + } + return timer->endtime; +} + +char* cmyth_timer_title(cmyth_timer_t timer) +{ + if (!timer) { + return NULL; + } + return ref_hold(timer->title); +} + +char* cmyth_timer_description(cmyth_timer_t timer) +{ + if (!timer) { + return NULL; + } + return ref_hold(timer->description); +} + +int cmyth_timer_type(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->type; +} + + +char* cmyth_timer_category(cmyth_timer_t timer) +{ + if (!timer) { + return NULL; + } + return ref_hold(timer->category); +} + +char* cmyth_timer_subtitle(cmyth_timer_t timer) +{ + if (!timer) { + return NULL; + } + return ref_hold(timer->subtitle); +} + +int cmyth_timer_priority(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->priority; +} + +int cmyth_timer_startoffset(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->startoffset; +} + +int cmyth_timer_endoffset(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->endoffset; +} + +int cmyth_timer_searchtype(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->searchtype; +} + +int cmyth_timer_inactive(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->inactive; +} + + + int cmyth_timer_dup_method(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->dup_method; +} + + int cmyth_timer_dup_in(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->dup_in; +} + + char* cmyth_timer_rec_group(cmyth_timer_t timer) + { + if (!timer) { + return NULL; + } + return ref_hold(timer->rec_group); +} + + char* cmyth_timer_store_group(cmyth_timer_t timer) + { + if (!timer) { + return NULL; + } + return ref_hold(timer->store_group); +} + + char* cmyth_timer_play_group(cmyth_timer_t timer) + { + if (!timer) { + return NULL; + } + return ref_hold(timer->play_group); +} + + int cmyth_timer_autotranscode(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->autotranscode; +} + + int cmyth_timer_userjobs(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->userjobs; +} + + int cmyth_timer_autocommflag(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->autocommflag; +} + + int cmyth_timer_autoexpire(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->autoexpire; +} + + int cmyth_timer_maxepisodes(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->maxepisodes; +} + + int cmyth_timer_maxnewest(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->maxnewest; +} + +int cmyth_timer_transcoder(cmyth_timer_t timer) + { + if (!timer) { + return -EINVAL; + } + return timer->transcoder; +} + +cmyth_timer_t cmyth_timerlist_get_item(cmyth_timerlist_t pl, int index) +{ + if (!pl) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: NULL timer list\n", + __FUNCTION__); + return NULL; + } + if (!pl->timerlist_list) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: NULL list\n", + __FUNCTION__); + return NULL; + } + if ((index < 0) || (index >= pl->timerlist_count)) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: index %d out of range\n", + __FUNCTION__, index); + return NULL; + } + ref_hold(pl->timerlist_list[index]); + return pl->timerlist_list[index]; +} + +extern int cmyth_timerlist_get_count(cmyth_timerlist_t pl) +{ + if (!pl) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: NULL timer list\n", + __FUNCTION__); + return -EINVAL; + } + return pl->timerlist_count; +} + +extern int cmyth_mysql_get_channelgroups(cmyth_database_t db,cmyth_channelgroups_t** changroups) +{ + MYSQL_RES *res= NULL; + MYSQL_ROW row; + const char *query_str = "SELECT grpid, name FROM channelgroupnames"; + int rows=0; + cmyth_channelgroups_t* ret; + + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + + res = cmyth_mysql_query_result(query); + ref_release(query); + if(res == NULL) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution of query failed!\n", __FUNCTION__); + return 0; + } + + + ret = ref_alloc( sizeof( cmyth_channelgroups_t ) * (int)mysql_num_rows(res)); + + + if (!ret) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: alloc() failed for list\n", + __FUNCTION__); + mysql_free_result(res); + return 0; + } + + while ((row = mysql_fetch_row(res))) { + ret[rows].ID=safe_atoi(row[0]); + safe_strncpy(ret[rows].channelgroup, row[1], 65); + + rows++; + } + + mysql_free_result(res); + cmyth_dbg(CMYTH_DBG_ERROR, "%s: rows= %d\n", __FUNCTION__, rows); + + *changroups=ret; + return rows; +} + +extern int cmyth_mysql_get_channelids_in_group(cmyth_database_t db,unsigned int groupid,int** chanids) +{ + + MYSQL_RES *res= NULL; + MYSQL_ROW row; + const char *query_str = "SELECT chanid FROM channelgroup WHERE grpid = ?"; + int rows=0; + int* ret; + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + if (cmyth_mysql_query_param_long(query, groupid) < 0 + ) { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); + ref_release(query); + return -1; + } + + res = cmyth_mysql_query_result(query); + ref_release(query); + if(res == NULL) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution of query failed!\n", __FUNCTION__); + return 0; + } + + ret = ref_alloc(sizeof(int)* (int)mysql_num_rows(res)); + + + if (!ret) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: alloc() failed for list\n", + __FUNCTION__); + mysql_free_result(res); + return 0; + } + + while ((row = mysql_fetch_row(res))) { + ret[rows]=safe_atoi(row[0]); + rows++; + } + + mysql_free_result(res); + cmyth_dbg(CMYTH_DBG_ERROR, "%s: rows= %d\n", __FUNCTION__, rows); + *chanids=ret; + return rows; +} + + +int cmyth_mysql_get_recorder_list(cmyth_database_t db,cmyth_rec_t** reclist) +{ + MYSQL_RES *res= NULL; + MYSQL_ROW row; + const char *query_str = "SELECT cardid, sourceid FROM cardinput"; + int rows=0; + cmyth_rec_t* ret; + + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + + res = cmyth_mysql_query_result(query); + ref_release(query); + if(res == NULL) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution of query failed!\n", __FUNCTION__); + return 0; + } + + + ret = ref_alloc( sizeof( cmyth_rec_t ) * (int)mysql_num_rows(res)); + + + if (!ret) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: alloc() failed for list\n", + __FUNCTION__); + mysql_free_result(res); + return 0; + } + + while ((row = mysql_fetch_row(res))) { + ret[rows].recid=safe_atoi(row[0]); + ret[rows].sourceid=safe_atoi(row[1]); + + rows++; + } + + mysql_free_result(res); + cmyth_dbg(CMYTH_DBG_ERROR, "%s: rows= %d\n", __FUNCTION__, rows); + + *reclist=ret; + return rows; +} + +int cmyth_mysql_get_prog_finder_time_title_chan(cmyth_database_t db,cmyth_program_t *prog,char* title,time_t starttime,int chanid) +{ + MYSQL_RES *res= NULL; + MYSQL_ROW row; + const char *query_str = "SELECT program.chanid,UNIX_TIMESTAMP(program.starttime),UNIX_TIMESTAMP(program.endtime),program.title,program.description,program.subtitle,program.programid,program.seriesid,program.category,channel.channum,channel.callsign,channel.name,channel.sourceid FROM program INNER JOIN channel ON program.chanid=channel.chanid WHERE program.chanid = ? AND program.title LIKE ? AND program.starttime = FROM_UNIXTIME( ? ) AND program.manualid = 0 ORDER BY (channel.channum + 0), program.starttime ASC "; + int rows=0; + + char* esctitle=cmyth_mysql_escape_chars(db,title); + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + + if ( cmyth_mysql_query_param_long(query, chanid) < 0 + || cmyth_mysql_query_param_str(query, title ) < 0 + || cmyth_mysql_query_param_long(query, starttime ) < 0 + ) { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); + ref_release(query); + return -1; + } + + + res = cmyth_mysql_query_result(query); + ref_release(query); + + if(res == NULL) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution of query failed!\n", __FUNCTION__); + return 0; + } + + if ((row = mysql_fetch_row(res))) { + rows++; + if(prog) + { + prog->chanid = safe_atoi(row[0]); + prog->recording=0; + prog->starttime= (time_t)safe_atol(row[1]); + prog->endtime= (time_t)safe_atol(row[2]); + sizeof_strncpy(prog->title, row[3]); + sizeof_strncpy(prog->description, row[4]); + sizeof_strncpy(prog->subtitle, row[5]); + sizeof_strncpy(prog->programid, row[6]); + sizeof_strncpy(prog->seriesid, row[7]); + sizeof_strncpy(prog->category, row[8]); + prog->channum = safe_atoi(row[9]); + sizeof_strncpy(prog->callsign, row[10]); + sizeof_strncpy(prog->name, row[11]); + prog->sourceid = safe_atoi(row[12]); + prog->startoffset=0; + prog->endoffset=0; + } + } + + mysql_free_result(res); + cmyth_dbg(CMYTH_DBG_ERROR, "%s: rows= %d\n", __FUNCTION__, rows); + return rows; +} + +void destroy_char_array(void* p) +{ + char** ptr = (char**)p; + if(!ptr) + return; + while (*ptr) + { + ref_release(*ptr); + ptr++; + } +} + +int cmyth_mysql_get_storagegroups(cmyth_database_t db, char** *profiles) +{ + MYSQL_RES *res= NULL; + MYSQL_ROW row; + const char *query_str = "SELECT groupname FROM storagegroup"; + int rows=0; + char **ret;/* = profiles;*/ + + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + + res = cmyth_mysql_query_result(query); + ref_release(query); + if(res == NULL) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution of query failed!\n", __FUNCTION__); + return 0; + } + + + ret = ref_alloc( sizeof( char*) * ((int) mysql_num_rows(res) +1 ) ); + + + if (!ret) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: alloc() failed for list\n", + __FUNCTION__); + mysql_free_result(res); + return 0; + } + + ref_set_destroy(ret,destroy_char_array); + + while ((row = mysql_fetch_row(res))) { + ret[rows] = ref_strdup(row[0]); + rows++; + } + ret[rows] = NULL; + + mysql_free_result(res); + cmyth_dbg(CMYTH_DBG_ERROR, "%s: rows= %d\n", __FUNCTION__, rows); + *profiles=ret; + + return rows; +} + +int cmyth_mysql_get_playgroups(cmyth_database_t db, char** *profiles) +{ + + + MYSQL_RES *res= NULL; + MYSQL_ROW row; + const char *query_str = "SELECT name FROM playgroup"; + int rows=0; + char **ret;/* = profiles;*/ + + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + + res = cmyth_mysql_query_result(query); + ref_release(query); + if(res == NULL) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution of query failed!\n", __FUNCTION__); + return 0; + } + + + ret = ref_alloc( sizeof( char*) * ((int) mysql_num_rows(res) +1 ) ); + + + if (!ret) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: alloc() failed for list\n", + __FUNCTION__); + mysql_free_result(res); + return 0; + } + + ref_set_destroy(ret,destroy_char_array); + + while ((row = mysql_fetch_row(res))) { + ret[rows] = ref_strdup(row[0]); + rows++; + } + ret[rows] = NULL; + + mysql_free_result(res); + cmyth_dbg(CMYTH_DBG_ERROR, "%s: rows= %d\n", __FUNCTION__, rows); + *profiles=ret; + + return rows; +} + +int cmyth_mysql_get_recprofiles(cmyth_database_t db, cmyth_recprofile_t **profiles) +{ + MYSQL_RES *res= NULL; + MYSQL_ROW row; + const char *query_str = "SELECT recordingprofiles.id, recordingprofiles.name, profilegroups.cardtype FROM recordingprofiles INNER JOIN profilegroups ON recordingprofiles.profilegroup = profilegroups.id"; + int rows=0; + cmyth_recprofile_t *ret = NULL; + + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + + res = cmyth_mysql_query_result(query); + ref_release(query); + if(res == NULL) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution of query failed!\n", __FUNCTION__); + return 0; + } + + + ret = ref_alloc( sizeof( cmyth_recprofile_t ) * (int)mysql_num_rows(res)); + + + if (!ret) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: alloc() failed for list\n", + __FUNCTION__); + mysql_free_result(res); + return 0; + } + + while ((row = mysql_fetch_row(res))) { + ret[rows].id=safe_atoi(row[0]); + safe_strncpy(ret[rows].name, row[1], 128); + safe_strncpy(ret[rows].cardtype, row[2], 32); + rows++; + } + + mysql_free_result(res); + cmyth_dbg(CMYTH_DBG_ERROR, "%s: rows= %d\n", __FUNCTION__, rows); + *profiles=ret; + + return rows; +} + +char* cmyth_mysql_get_cardtype(cmyth_database_t db, int chanid) +{ + /*"SELECT cardtype FROM channel LEFT JOIN cardinput ON channel.sourceid=cardinput.sourceid LEFT JOIN capturecard ON cardinput.cardid=capturecard.cardid WHERE channel.chanid = ?"*/ + + MYSQL_RES *res= NULL; + MYSQL_ROW row; + const char *query_str = "SELECT cardtype FROM channel LEFT JOIN cardinput ON channel.sourceid=cardinput.sourceid LEFT JOIN capturecard ON cardinput.cardid=capturecard.cardid WHERE channel.chanid = ?"; + + char* retval; + + cmyth_mysql_query_t * query; + query = cmyth_mysql_query_create(db,query_str); + + if ( cmyth_mysql_query_param_long(query, chanid) < 0 + ) { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); + ref_release(query); + return NULL; + } + + + res = cmyth_mysql_query_result(query); + ref_release(query); + + if(res == NULL) + { + cmyth_dbg(CMYTH_DBG_ERROR,"%s, finalisation/execution of query failed!\n", __FUNCTION__); + return NULL; + } + + if ((row = mysql_fetch_row(res))) { + retval = ref_strdup(row[0]); + } + + mysql_free_result(res); + + return retval; + +} \ No newline at end of file diff --git a/lib/cmyth/libcmyth/proginfo.c b/lib/cmyth/libcmyth/proginfo.c index b175637..112329a 100644 --- a/lib/cmyth/libcmyth/proginfo.c +++ b/lib/cmyth/libcmyth/proginfo.c @@ -116,6 +116,9 @@ cmyth_proginfo_destroy(cmyth_proginfo_t p) if (p->proginfo_programid) { ref_release(p->proginfo_programid); } + if (p->proginfo_inetref) { + ref_release(p->proginfo_inetref); + } if (p->proginfo_stars) { ref_release(p->proginfo_stars); } @@ -217,6 +220,8 @@ cmyth_proginfo_create(void) ret->proginfo_title = NULL; ret->proginfo_subtitle = NULL; ret->proginfo_description = NULL; + ret->proginfo_season = 0; + ret->proginfo_episode = 0; ret->proginfo_category = NULL; ret->proginfo_chanId = 0; ret->proginfo_chanstr = NULL; @@ -250,6 +255,7 @@ cmyth_proginfo_create(void) ret->proginfo_chan_output_filters = NULL; ret->proginfo_seriesid = NULL; ret->proginfo_programid = NULL; + ret->proginfo_inetref = NULL; ret->proginfo_stars = NULL; ret->proginfo_version = 12; ret->proginfo_hasairdate = 0; @@ -307,6 +313,8 @@ cmyth_proginfo_dup(cmyth_proginfo_t p) ret->proginfo_title = ref_hold(p->proginfo_title); ret->proginfo_subtitle = ref_hold(p->proginfo_subtitle); ret->proginfo_description = ref_hold(p->proginfo_description); + ret->proginfo_season = p->proginfo_season; + ret->proginfo_episode = p->proginfo_episode; ret->proginfo_category = ref_hold(p->proginfo_category); ret->proginfo_chanId = p->proginfo_chanId; ret->proginfo_chanstr = ref_hold(p->proginfo_chanstr); @@ -340,6 +348,7 @@ cmyth_proginfo_dup(cmyth_proginfo_t p) ret->proginfo_chan_output_filters = ref_hold(p->proginfo_chan_output_filters); ret->proginfo_seriesid = ref_hold(p->proginfo_seriesid); ret->proginfo_programid = ref_hold(p->proginfo_programid); + ret->proginfo_inetref = ref_hold(p->proginfo_inetref); ret->proginfo_stars = ref_hold(p->proginfo_stars); ret->proginfo_version = p->proginfo_version; ret->proginfo_hasairdate = p->proginfo_hasairdate; @@ -386,7 +395,7 @@ delete_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd) char *buf; unsigned int len = ((2 * CMYTH_LONGLONG_LEN) + (6 * CMYTH_TIMESTAMP_LEN) + - (14 * CMYTH_LONG_LEN)); + (16 * CMYTH_LONG_LEN)); char start_ts[CMYTH_TIMESTAMP_LEN + 1]; char end_ts[CMYTH_TIMESTAMP_LEN + 1]; char rec_start_ts[CMYTH_TIMESTAMP_LEN + 1]; @@ -415,8 +424,12 @@ delete_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd) len += strlen(S(prog->proginfo_url)); len += strlen(S(prog->proginfo_hostname)); len += strlen(S(prog->proginfo_playgroup)); + len += strlen(S(prog->proginfo_seriesid)); + len += strlen(S(prog->proginfo_programid)); + len += strlen(S(prog->proginfo_inetref)); len += strlen(S(prog->proginfo_recpriority_2)); len += strlen(S(prog->proginfo_storagegroup)); + len += strlen(S(prog->proginfo_prodyear)); buf = alloca(len + 1+2048); if (!buf) { @@ -462,6 +475,10 @@ delete_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd) sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_title)); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_subtitle)); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_description)); + if (control->conn_version >= 67) { + sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_season); + sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_episode); + } sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_category)); sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_chanId); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_chanstr)); @@ -504,6 +521,9 @@ delete_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd) sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_chan_output_filters)); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_seriesid)); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_programid)); + if (control->conn_version >= 67) { + sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_inetref)); + } sprintf(buf + strlen(buf), "%s[]:[]", lastmodified); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_stars)); sprintf(buf + strlen(buf), "%s[]:[]", originalairdate); @@ -773,6 +793,24 @@ cmyth_proginfo_description(cmyth_proginfo_t prog) return ref_hold(prog->proginfo_description); } +unsigned short +cmyth_proginfo_season(cmyth_proginfo_t prog) +{ + if (!prog) { + return 0; + } + return prog->proginfo_season; +} + +unsigned short +cmyth_proginfo_episode(cmyth_proginfo_t prog) +{ + if (!prog) { + return 0; + } + return prog->proginfo_episode; +} + /* * cmyth_proginfo_category(cmyth_proginfo_t prog) * @@ -827,6 +865,17 @@ cmyth_proginfo_programid(cmyth_proginfo_t prog) } char * +cmyth_proginfo_inetref(cmyth_proginfo_t prog) +{ + if (!prog) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: NULL inetref\n", + __FUNCTION__); + return NULL; + } + return ref_hold(prog->proginfo_inetref); +} + +char * cmyth_proginfo_stars(cmyth_proginfo_t prog) { if (!prog) { @@ -1260,7 +1309,7 @@ fill_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd) char *buf; unsigned int len = ((2 * CMYTH_LONGLONG_LEN) + (6 * CMYTH_TIMESTAMP_LEN) + - (14 * CMYTH_LONG_LEN)); + (16 * CMYTH_LONG_LEN)); char start_ts[CMYTH_TIMESTAMP_LEN + 1]; char end_ts[CMYTH_TIMESTAMP_LEN + 1]; char rec_start_ts[CMYTH_TIMESTAMP_LEN + 1]; @@ -1288,6 +1337,9 @@ fill_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd) len += strlen(S(prog->proginfo_url)); len += strlen(S(prog->proginfo_hostname)); len += strlen(S(prog->proginfo_playgroup)); + len += strlen(S(prog->proginfo_seriesid)); + len += strlen(S(prog->proginfo_programid)); + len += strlen(S(prog->proginfo_inetref)); len += strlen(S(prog->proginfo_recpriority_2)); len += strlen(S(prog->proginfo_storagegroup)); len += strlen(S(prog->proginfo_prodyear)); @@ -1336,6 +1388,10 @@ fill_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd) sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_title)); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_subtitle)); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_description)); + if (control->conn_version >= 67) { + sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_season); + sprintf(buf + strlen(buf), "%u[]:[]", prog->proginfo_episode); + } sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_category)); sprintf(buf + strlen(buf), "%ld[]:[]", prog->proginfo_chanId); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_chanstr)); @@ -1378,6 +1434,9 @@ fill_command(cmyth_conn_t control, cmyth_proginfo_t prog, char *cmd) sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_chan_output_filters)); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_seriesid)); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_programid)); + if (control->conn_version >= 67) { + sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_inetref)); + } sprintf(buf + strlen(buf), "%s[]:[]", lastmodified); sprintf(buf + strlen(buf), "%s[]:[]", S(prog->proginfo_stars)); sprintf(buf + strlen(buf), "%s[]:[]", originalairdate); @@ -1526,7 +1585,7 @@ cmyth_proginfo_t cmyth_proginfo_get_detail(cmyth_conn_t control, cmyth_proginfo_t p) { cmyth_proginfo_t ret = cmyth_proginfo_dup(p); - + ref_release(p); if (ret == NULL) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_proginfo_dup() failed\n", @@ -1540,7 +1599,7 @@ cmyth_proginfo_get_detail(cmyth_conn_t control, cmyth_proginfo_t p) __FUNCTION__); return NULL; } - return ret; + return ret; } /* @@ -1636,6 +1695,30 @@ cmyth_proginfo_card_id(cmyth_proginfo_t prog) return prog->proginfo_card_id; } +unsigned long +cmyth_proginfo_recordid(cmyth_proginfo_t prog) +{ + if (!prog) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: no program info\n", __FUNCTION__); + return -1; + } + + return prog->proginfo_record_id; +} + +long +cmyth_proginfo_priority(cmyth_proginfo_t prog) +{ + if (!prog) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: no program info\n", __FUNCTION__); + return -1; + } + + return atoi(prog->proginfo_rec_priority); +} + char * cmyth_proginfo_recgroup(cmyth_proginfo_t prog) { diff --git a/lib/cmyth/libcmyth/proglist.c b/lib/cmyth/libcmyth/proglist.c index 28e742c..8d5ff6d 100644 --- a/lib/cmyth/libcmyth/proglist.c +++ b/lib/cmyth/libcmyth/proglist.c @@ -33,6 +33,356 @@ #include #include +extern void destroy_char_array2(void* p) +{ + char** ptr = (char**)p; + if(!ptr) + return; + while (*ptr) + { + ref_release(*ptr); + ptr++; + } +} + +int cmyth_storagegroup_filelist(cmyth_conn_t control, char** *sgFilelist, char* sg2List, char* mythostname) +{ + + char msg[256]; + int res=0; + int count; + int err = 0; + int i = 0; + char **ret; + int consumed; /* = profiles;*/ + char tmp_str[32768]; + + if (!control) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", __FUNCTION__); + return 0; + } + + pthread_mutex_lock(&mutex); + + snprintf(msg, sizeof(msg), "QUERY_SG_GETFILELIST[]:[]%s[]:[]%s[]:[][]:[]1", mythostname, sg2List); + + err = cmyth_send_message(control, msg); + if (err < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err); + res = 0; + goto out; + } + + count = cmyth_rcv_length(control); + if (count < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); + res = 0; + goto out; + } + + ret = (char**)ref_alloc( sizeof( char*) * (count + 1 ) );/*count + 1 ??*/ + if (!ret) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: alloc() failed for list\n", __FUNCTION__); + res = 0; + goto out; + } + + ref_set_destroy((void*)ret,destroy_char_array2); + + while (i < count) { + consumed = cmyth_rcv_string(control, &err, tmp_str, sizeof(tmp_str) - 1, count); + count -= consumed; + if (err) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, count); + res = 0; + goto out; + } + ret[res] = ref_strdup(tmp_str); + res++; + } + + ret[res] = NULL; + + cmyth_dbg(CMYTH_DBG_ERROR, "%s: results= %d\n", __FUNCTION__, res); + *sgFilelist=ret; + + out: + pthread_mutex_unlock(&mutex); + return res; + +} + +static void +cmyth_storagegroup_file_destroy(cmyth_storagegroup_file_t pl) +{ + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__); + if (!pl) { + return; + } + if(pl->filename) + ref_release(pl->filename); + if(pl->storagegroup) + ref_release(pl->storagegroup); + if(pl->hostname) + ref_release(pl->hostname); +} + + +cmyth_storagegroup_file_t +cmyth_storagegroup_file_create(void) +{ + cmyth_storagegroup_file_t ret = ref_alloc(sizeof(*ret)); + memset(ret, 0, sizeof(*ret)); + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s {\n", __FUNCTION__); + if (!ret) { + cmyth_dbg(CMYTH_DBG_DEBUG, "%s }!\n", __FUNCTION__); + return NULL; + } + ref_set_destroy(ret, (ref_destroy_t)cmyth_storagegroup_file_destroy); + + return ret; +} + +static void +cmyth_storagegroup_filelist_destroy(cmyth_storagegroup_filelist_t pl) +{ + int i; + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__); + if (!pl) { + return; + } + for (i = 0; i < pl->storagegroup_filelist_count; ++i) { + if (pl->storagegroup_filelist_list[i]) { + ref_release(pl->storagegroup_filelist_list[i]); + } + pl->storagegroup_filelist_list[i] = NULL; + } + if (pl->storagegroup_filelist_list) { + free(pl->storagegroup_filelist_list); + } +} + +cmyth_storagegroup_filelist_t +cmyth_storagegroup_filelist_create(void) +{ + cmyth_storagegroup_filelist_t ret; + + cmyth_dbg(CMYTH_DBG_DEBUG, "%s\n", __FUNCTION__); + ret = ref_alloc(sizeof(*ret)); + if (!ret) { + return(NULL); + } + ref_set_destroy(ret, (ref_destroy_t)cmyth_storagegroup_filelist_destroy); + + ret->storagegroup_filelist_list = NULL; + ret->storagegroup_filelist_count = 0; + return ret; +} + + int + cmyth_storagegroup_update_fileinfo(cmyth_conn_t control,cmyth_storagegroup_file_t file) + { + + char msg[256]; + int count; + int err = 0; + int consumed; /* = profiles;*/ + char tmp_str[32768]; + + if (!control) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", __FUNCTION__); + return -1; + } + + if (!file) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: no file specified\n", __FUNCTION__); + return -1; + } + + snprintf(msg, sizeof(msg), "QUERY_SG_FILEQUERY[]:[]%s[]:[]%s[]:[]%s",file->hostname , file->storagegroup, file->filename); + + err = cmyth_send_message(control, msg); + if (err < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err); + return -1; + } + + count = cmyth_rcv_length(control); + if (count < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); + return -1; + } + + consumed = cmyth_rcv_string(control, &err, tmp_str, sizeof(tmp_str) - 1, count); + count -= consumed; + + if (err) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, count); + return -1; + } else if (count == 0) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: QUERY_SG_FILEQUERY failed(%s)\n", __FUNCTION__, tmp_str); + return -1; + } + consumed = cmyth_rcv_ulong(control, &err, &(file->modified), count); + count -= consumed; + if (err) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_ulong() failed (%d)\n", __FUNCTION__, count); + return -1; + } + + consumed = cmyth_rcv_ulong(control, &err, &(file->size), count); + count -= consumed; + if (err) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_ulong_long() failed (%d)\n", __FUNCTION__, count); + return -1; + } + + return 0; + + } + + + cmyth_storagegroup_filelist_t + cmyth_storagegroup_get_filelist(cmyth_conn_t control,char* storagegroup, char* hostname) + { + char msg[256]; + int res=0; + int count = 0; + int err = 0; + int i = 0; + int listsize = 10; + cmyth_storagegroup_filelist_t ret = 0; + cmyth_storagegroup_file_t file = 0; + int consumed = 0; /* = profiles;*/ + char tmp_str[32768]; + + if (!control) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", __FUNCTION__); + return 0; + } + + pthread_mutex_lock(&mutex); + + snprintf(msg, sizeof(msg), "QUERY_SG_GETFILELIST[]:[]%s[]:[]%s[]:[][]:[]1", hostname, storagegroup); + + err = cmyth_send_message(control, msg); + if (err < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err); + goto out; + } + + count = cmyth_rcv_length(control); + if (count < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); + goto out; + } + + ret = cmyth_storagegroup_filelist_create(); + + + if (!ret) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: alloc() failed for list\n", __FUNCTION__); + ref_release(ret); + ret = 0; + goto out; + } + + ret->storagegroup_filelist_count = 0; + ret->storagegroup_filelist_list = malloc(listsize * sizeof(cmyth_storagegroup_file_t)); + if (!ret->storagegroup_filelist_list) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: alloc() failed for filelist list\n", __FUNCTION__); + ref_release(ret); + ret = 0; + goto out; + } + while (count) { + consumed = cmyth_rcv_string(control, &err, tmp_str, sizeof(tmp_str) - 1, count); + count -= consumed; + if (err) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, count); + ref_release(ret); + ret = 0; + goto out; + } + if(res>listsize-1) + { + listsize +=10; + ret->storagegroup_filelist_list = realloc(ret->storagegroup_filelist_list,listsize * sizeof(cmyth_storagegroup_file_t)); + if (!ret->storagegroup_filelist_list) { + cmyth_dbg(CMYTH_DBG_ERROR, "%s: realloc() failed for filelist list\n", __FUNCTION__); + ref_release(ret); + ret = 0; + goto out; + } + } + file = cmyth_storagegroup_file_create(); + file->filename = ref_strdup(tmp_str); + file->storagegroup = ref_strdup(storagegroup); + file->hostname = ref_strdup(hostname); + file->size = 0; + file->modified = 0; + ret->storagegroup_filelist_list[res] = file; + res++; + } + ret->storagegroup_filelist_count=res; + + for(i = 0;i< ret->storagegroup_filelist_count;i++) + { + cmyth_storagegroup_update_fileinfo(control,ret->storagegroup_filelist_list[i]); + } + + cmyth_dbg(CMYTH_DBG_ERROR, "%s: results= %d\n", __FUNCTION__, res); + + out: + pthread_mutex_unlock(&mutex); + return ret; + } + + int cmyth_storagegroup_filelist_count(cmyth_storagegroup_filelist_t fl) + { + if (!fl) { + return -EINVAL; + } + return fl->storagegroup_filelist_count; + } + + cmyth_storagegroup_file_t cmyth_storagegroup_filelist_get_item(cmyth_storagegroup_filelist_t fl, int index) + { + if (!fl||index>=fl->storagegroup_filelist_count) { + return NULL; + } + ref_hold(fl->storagegroup_filelist_list[index]); + return fl->storagegroup_filelist_list[index];; + } + +char* cmyth_storagegroup_file_get_filename(cmyth_storagegroup_file_t file) +{ + if (!file) { + return NULL; + } + return ref_hold(file->filename); +} + +unsigned long cmyth_storagegroup_file_get_lastmodified(cmyth_storagegroup_file_t file) +{ + if (!file) { + return 0; + } + return file->modified; +} + +unsigned long long cmyth_storagegroup_file_get_size(cmyth_storagegroup_file_t file) +{ + if (!file) { + return 0; + } + return file->size; +} + + /* * cmyth_proglist_destroy(void) * @@ -315,6 +665,7 @@ cmyth_proglist_get_list(cmyth_conn_t conn, cmyth_proglist_t cmyth_proglist_get_all_recorded(cmyth_conn_t control) { + char query[32]; cmyth_proglist_t proglist = cmyth_proglist_create(); if (proglist == NULL) { @@ -324,8 +675,14 @@ cmyth_proglist_get_all_recorded(cmyth_conn_t control) return NULL; } + if (control->conn_version < 65) { + strcpy(query, "QUERY_RECORDINGS Play"); + } + else { + strcpy(query, "QUERY_RECORDINGS Ascending"); + } if (cmyth_proglist_get_list(control, proglist, - "QUERY_RECORDINGS Play", + query, __FUNCTION__) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_proglist_get_list() failed\n", diff --git a/lib/cmyth/libcmyth/socket.c b/lib/cmyth/libcmyth/socket.c index f1f9a45..c3f1326 100644 --- a/lib/cmyth/libcmyth/socket.c +++ b/lib/cmyth/libcmyth/socket.c @@ -148,6 +148,7 @@ cmyth_rcv_length(cmyth_conn_t conn) char buf[16]; int rtot = 0; int r; + int hangcount = 0; int ret; struct timeval tv; fd_set fds; @@ -171,6 +172,9 @@ cmyth_rcv_length(cmyth_conn_t conn) FD_SET(conn->conn_fd, &fds); if ((r=select((int)conn->conn_fd+1, &fds, NULL, NULL, &tv)) == 0) { conn->conn_hang = 1; + hangcount++; + if(++hangcount>6&&r>0) + return -1; continue; } else if (r > 0) { conn->conn_hang = 0; @@ -882,23 +886,38 @@ cmyth_rcv_long_long(cmyth_conn_t conn, int *err, long long *buf, int count) *err = EINVAL; return 0; } - consumed = cmyth_rcv_u_long(conn, err, &hi, count); - if (*err) { - cmyth_dbg(CMYTH_DBG_ERROR, - "%s: cmyth_rcv_long_long() failed (%d)\n", - __FUNCTION__, consumed); - return consumed; + + if (conn->conn_version >= 66) { + /* + * Since protocol 66 mythbackend now sends a single 64 bit integer rather than two hi and lo + * 32 bit integers for ALL 64 bit values. + */ + consumed = cmyth_rcv_int64(conn, err, &val, count); + if (*err) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_int64() failed (%d)\n", + __FUNCTION__, consumed); + return consumed; + } } - consumed += cmyth_rcv_u_long(conn, err, &lo, count-consumed); - if (*err) { - cmyth_dbg(CMYTH_DBG_ERROR, - "%s: cmyth_rcv_long_long() failed (%d)\n", - __FUNCTION__, consumed); - return consumed; + else { + consumed = cmyth_rcv_u_long(conn, err, &hi, count); + if (*err) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_u_long_long() failed (%d)\n", + __FUNCTION__, consumed); + return consumed; + } + consumed += cmyth_rcv_u_long(conn, err, &lo, count-consumed); + if (*err) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_u_long_long() failed (%d)\n", + __FUNCTION__, consumed); + return consumed; + } + val = (((long long)hi) << 32) | ((long long)(lo & 0xFFFFFFFF)); } - val = (((long long)hi) << 32) | ((long long)(lo & 0xFFFFFFFF)); - *err = 0; *buf = val; @@ -1172,6 +1191,7 @@ cmyth_rcv_ulong_long(cmyth_conn_t conn, int *err, unsigned long long *buf, int count) { unsigned long long val; + long long val64; unsigned long hi, lo; int consumed; int tmp; @@ -1186,23 +1206,45 @@ cmyth_rcv_ulong_long(cmyth_conn_t conn, int *err, *err = EINVAL; return 0; } - consumed = cmyth_rcv_u_long(conn, err, &hi, count); - if (*err) { - cmyth_dbg(CMYTH_DBG_ERROR, - "%s: cmyth_rcv_ulong_long() failed (%d)\n", - __FUNCTION__, consumed); - return consumed; + + if (conn->conn_version >= 66) { + /* + * Since protocol 66 mythbackend now sends a single 64 bit integer rather than two hi and lo + * 32 bit integers for ALL 64 bit values. + */ + consumed = cmyth_rcv_int64(conn, err, &val64, count); + if (*err) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_int64() failed (%d)\n", + __FUNCTION__, consumed); + return consumed; + } + if (val64 < 0) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_int64() failed as signed 64 bit integer received\n", + __FUNCTION__, consumed); + *err = EINVAL; + return consumed; + } + val = (unsigned long long)val64; } - consumed += cmyth_rcv_u_long(conn, err, &lo, count); - if (*err) { - cmyth_dbg(CMYTH_DBG_ERROR, - "%s: cmyth_rcv_ulong_long() failed (%d)\n", - __FUNCTION__, consumed); - return consumed; + else { + consumed = cmyth_rcv_u_long(conn, err, &hi, count); + if (*err) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_u_long_long() failed (%d)\n", + __FUNCTION__, consumed); + return consumed; + } + consumed += cmyth_rcv_u_long(conn, err, &lo, count); + if (*err) { + cmyth_dbg(CMYTH_DBG_ERROR, + "%s: cmyth_rcv_u_long_long() failed (%d)\n", + __FUNCTION__, consumed); + return consumed; + } + val = (((unsigned long long)hi) << 32) | ((unsigned long long)(lo & 0xFFFFFFFF)); } - - val = (((unsigned long long)hi) << 32) | ((unsigned long long)(lo & 0xFFFFFFFF)); - *err = 0; *buf = val; @@ -1485,7 +1527,8 @@ cmyth_rcv_proginfo(cmyth_conn_t conn, int *err, cmyth_proginfo_t buf, if (buf->proginfo_version >= 57) { /* - * Myth now sends a single 64bit int, rather than 2 32bit ints + * Since protocol 57 mythbackend now sends a single 64 bit integer rather than two 32 bit + * hi and lo integers for the proginfo length. */ rcv_64 = &cmyth_rcv_int64; } else { @@ -1536,6 +1579,29 @@ cmyth_rcv_proginfo(cmyth_conn_t conn, int *err, cmyth_proginfo_t buf, ref_release(buf->proginfo_description); buf->proginfo_description = ref_strdup(tmp_str); + if (buf->proginfo_version >= 67) { + /* + * Get season and episode (unsigned int) + */ + consumed = cmyth_rcv_ushort(conn, err, + &buf->proginfo_season, count); + count -= consumed; + total += consumed; + if (*err) { + failed = "cmyth_rcv_ushort"; + goto fail; + } + + consumed = cmyth_rcv_ushort(conn, err, + &buf->proginfo_episode, count); + count -= consumed; + total += consumed; + if (*err) { + failed = "cmyth_rcv_ushort"; + goto fail; + } + } + /* * Get proginfo_category (string) */ @@ -1649,7 +1715,7 @@ cmyth_rcv_proginfo(cmyth_conn_t conn, int *err, cmyth_proginfo_t buf, count -= consumed; total += consumed; if (*err) { - failed = "cmyth_rcv_long_long"; + failed = "rcv_64"; goto fail; } @@ -2013,7 +2079,7 @@ cmyth_rcv_proginfo(cmyth_conn_t conn, int *err, cmyth_proginfo_t buf, count -= consumed; total += consumed; if (*err) { - failed = "cmyth_rcv_timestamp"; + failed = "cmyth_rcv_string"; goto fail; } if (buf->proginfo_programid) @@ -2021,6 +2087,23 @@ cmyth_rcv_proginfo(cmyth_conn_t conn, int *err, cmyth_proginfo_t buf, buf->proginfo_programid = ref_strdup(tmp_str); } + if (buf->proginfo_version >= 67) { + /* + * Get inetref (string) + */ + consumed = cmyth_rcv_string(conn, err, tmp_str, + sizeof(tmp_str) - 1, count); + count -= consumed; + total += consumed; + if (*err) { + failed = "cmyth_rcv_string"; + goto fail; + } + if (buf->proginfo_inetref) + ref_release(buf->proginfo_inetref); + buf->proginfo_inetref = ref_strdup(tmp_str); + } + if (buf->proginfo_version >= 12) { /* * Get lastmodified (string) diff --git a/lib/libhts/Win32/include/stdint.h b/lib/libhts/Win32/include/stdint.h deleted file mode 100644 index 81ecedc..0000000 --- a/lib/libhts/Win32/include/stdint.h +++ /dev/null @@ -1,222 +0,0 @@ -// ISO C9x compliant stdint.h for Microsoft Visual Studio -// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 -// -// Copyright (c) 2006 Alexander Chemeris -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: -// -// 1. Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// -// 2. Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// -// 3. The name of the author may be used to endorse or promote products -// derived from this software without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED -// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO -// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, -// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; -// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, -// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR -// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF -// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -// -/////////////////////////////////////////////////////////////////////////////// - -#ifndef _MSC_VER // [ -#error "Use this header only with Microsoft Visual C++ compilers!" -#endif // _MSC_VER ] - -#ifndef _MSC_STDINT_H_ // [ -#define _MSC_STDINT_H_ - -#if _MSC_VER > 1000 -#pragma once -#endif - -#include - -// For Visual Studio 6 in C++ mode wrap include with 'extern "C++" {}' -// or compiler give many errors like this: -// error C2733: second C linkage of overloaded function 'wmemchr' not allowed -#if (_MSC_VER < 1300) && defined(__cplusplus) - extern "C++" { -#endif -# include -#if (_MSC_VER < 1300) && defined(__cplusplus) - } -#endif - -// 7.18.1 Integer types - -// 7.18.1.1 Exact-width integer types -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef __int64 int64_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; -typedef unsigned __int64 uint64_t; - -// 7.18.1.2 Minimum-width integer types -typedef int8_t int_least8_t; -typedef int16_t int_least16_t; -typedef int32_t int_least32_t; -typedef int64_t int_least64_t; -typedef uint8_t uint_least8_t; -typedef uint16_t uint_least16_t; -typedef uint32_t uint_least32_t; -typedef uint64_t uint_least64_t; - -// 7.18.1.3 Fastest minimum-width integer types -typedef int8_t int_fast8_t; -typedef int16_t int_fast16_t; -typedef int32_t int_fast32_t; -typedef int64_t int_fast64_t; -typedef uint8_t uint_fast8_t; -typedef uint16_t uint_fast16_t; -typedef uint32_t uint_fast32_t; -typedef uint64_t uint_fast64_t; - -// 7.18.1.4 Integer types capable of holding object pointers -#ifdef _WIN64 // [ - typedef __int64 intptr_t; - typedef unsigned __int64 uintptr_t; -#else // _WIN64 ][ - typedef int intptr_t; - typedef unsigned int uintptr_t; -#endif // _WIN64 ] - -// 7.18.1.5 Greatest-width integer types -typedef int64_t intmax_t; -typedef uint64_t uintmax_t; - - -// 7.18.2 Limits of specified-width integer types - -#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 - -// 7.18.2.1 Limits of exact-width integer types -#define INT8_MIN ((int8_t)_I8_MIN) -#define INT8_MAX _I8_MAX -#define INT16_MIN ((int16_t)_I16_MIN) -#define INT16_MAX _I16_MAX -#define INT32_MIN ((int32_t)_I32_MIN) -#define INT32_MAX _I32_MAX -#define INT64_MIN ((int64_t)_I64_MIN) -#define INT64_MAX _I64_MAX -#define UINT8_MAX _UI8_MAX -#define UINT16_MAX _UI16_MAX -#define UINT32_MAX _UI32_MAX -#define UINT64_MAX _UI64_MAX - -// 7.18.2.2 Limits of minimum-width integer types -#define INT_LEAST8_MIN INT8_MIN -#define INT_LEAST8_MAX INT8_MAX -#define INT_LEAST16_MIN INT16_MIN -#define INT_LEAST16_MAX INT16_MAX -#define INT_LEAST32_MIN INT32_MIN -#define INT_LEAST32_MAX INT32_MAX -#define INT_LEAST64_MIN INT64_MIN -#define INT_LEAST64_MAX INT64_MAX -#define UINT_LEAST8_MAX UINT8_MAX -#define UINT_LEAST16_MAX UINT16_MAX -#define UINT_LEAST32_MAX UINT32_MAX -#define UINT_LEAST64_MAX UINT64_MAX - -// 7.18.2.3 Limits of fastest minimum-width integer types -#define INT_FAST8_MIN INT8_MIN -#define INT_FAST8_MAX INT8_MAX -#define INT_FAST16_MIN INT16_MIN -#define INT_FAST16_MAX INT16_MAX -#define INT_FAST32_MIN INT32_MIN -#define INT_FAST32_MAX INT32_MAX -#define INT_FAST64_MIN INT64_MIN -#define INT_FAST64_MAX INT64_MAX -#define UINT_FAST8_MAX UINT8_MAX -#define UINT_FAST16_MAX UINT16_MAX -#define UINT_FAST32_MAX UINT32_MAX -#define UINT_FAST64_MAX UINT64_MAX - -// 7.18.2.4 Limits of integer types capable of holding object pointers -#ifdef _WIN64 // [ -# define INTPTR_MIN INT64_MIN -# define INTPTR_MAX INT64_MAX -# define UINTPTR_MAX UINT64_MAX -#else // _WIN64 ][ -# define INTPTR_MIN INT32_MIN -# define INTPTR_MAX INT32_MAX -# define UINTPTR_MAX UINT32_MAX -#endif // _WIN64 ] - -// 7.18.2.5 Limits of greatest-width integer types -#define INTMAX_MIN INT64_MIN -#define INTMAX_MAX INT64_MAX -#define UINTMAX_MAX UINT64_MAX - -// 7.18.3 Limits of other integer types - -#ifdef _WIN64 // [ -# define PTRDIFF_MIN _I64_MIN -# define PTRDIFF_MAX _I64_MAX -#else // _WIN64 ][ -# define PTRDIFF_MIN _I32_MIN -# define PTRDIFF_MAX _I32_MAX -#endif // _WIN64 ] - -#define SIG_ATOMIC_MIN INT_MIN -#define SIG_ATOMIC_MAX INT_MAX - -#ifndef SIZE_MAX // [ -# ifdef _WIN64 // [ -# define SIZE_MAX _UI64_MAX -# else // _WIN64 ][ -# define SIZE_MAX _UI32_MAX -# endif // _WIN64 ] -#endif // SIZE_MAX ] - -// WCHAR_MIN and WCHAR_MAX are also defined in -#ifndef WCHAR_MIN // [ -# define WCHAR_MIN 0 -#endif // WCHAR_MIN ] -#ifndef WCHAR_MAX // [ -# define WCHAR_MAX _UI16_MAX -#endif // WCHAR_MAX ] - -#define WINT_MIN 0 -#define WINT_MAX _UI16_MAX - -#endif // __STDC_LIMIT_MACROS ] - - -// 7.18.4 Limits of other integer types - -#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 - -// 7.18.4.1 Macros for minimum-width integer constants - -#define INT8_C(val) val##i8 -#define INT16_C(val) val##i16 -#define INT32_C(val) val##i32 -//#define INT64_C(val) val##i64 - -#define UINT8_C(val) val##ui8 -#define UINT16_C(val) val##ui16 -#define UINT32_C(val) val##ui32 -//#define UINT64_C(val) val##ui64 - -// 7.18.4.2 Macros for greatest-width integer constants -#define INTMAX_C INT64_C -#define UINTMAX_C UINT64_C - -#endif // __STDC_CONSTANT_MACROS ] - - -#endif // _MSC_STDINT_H_ ] diff --git a/lib/libhts/Win32/libhts_2003.sln b/lib/libhts/Win32/libhts_2003.sln deleted file mode 100644 index 99b09b3..0000000 --- a/lib/libhts/Win32/libhts_2003.sln +++ /dev/null @@ -1,21 +0,0 @@ -Microsoft Visual Studio Solution File, Format Version 8.00 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhts_2003", "libhts_2003.vcproj", "{870DE8D3-B710-4CEF-9C73-36B37A9AF8A3}" - ProjectSection(ProjectDependencies) = postProject - EndProjectSection -EndProject -Global - GlobalSection(SolutionConfiguration) = preSolution - Debug = Debug - Release = Release - EndGlobalSection - GlobalSection(ProjectConfiguration) = postSolution - {870DE8D3-B710-4CEF-9C73-36B37A9AF8A3}.Debug.ActiveCfg = Debug|Win32 - {870DE8D3-B710-4CEF-9C73-36B37A9AF8A3}.Debug.Build.0 = Debug|Win32 - {870DE8D3-B710-4CEF-9C73-36B37A9AF8A3}.Release.ActiveCfg = Release|Win32 - {870DE8D3-B710-4CEF-9C73-36B37A9AF8A3}.Release.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(ExtensibilityGlobals) = postSolution - EndGlobalSection - GlobalSection(ExtensibilityAddIns) = postSolution - EndGlobalSection -EndGlobal diff --git a/lib/libhts/Win32/libhts_2003.vcproj b/lib/libhts/Win32/libhts_2003.vcproj deleted file mode 100644 index 9173877..0000000 --- a/lib/libhts/Win32/libhts_2003.vcproj +++ /dev/null @@ -1,161 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/libhts/Win32/libhts_2008.sln b/lib/libhts/Win32/libhts_2008.sln deleted file mode 100644 index f2fb0a0..0000000 --- a/lib/libhts/Win32/libhts_2008.sln +++ /dev/null @@ -1,20 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 10.00 -# Visual Studio 2008 -Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhts", "libhts_2008.vcproj", "{00700E12-A63B-4E54-B962-4011A90584BD}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Win32 = Debug|Win32 - Release|Win32 = Release|Win32 - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {00700E12-A63B-4E54-B962-4011A90584BD}.Debug|Win32.ActiveCfg = Debug|Win32 - {00700E12-A63B-4E54-B962-4011A90584BD}.Debug|Win32.Build.0 = Debug|Win32 - {00700E12-A63B-4E54-B962-4011A90584BD}.Release|Win32.ActiveCfg = Release|Win32 - {00700E12-A63B-4E54-B962-4011A90584BD}.Release|Win32.Build.0 = Release|Win32 - EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection -EndGlobal diff --git a/lib/libhts/Win32/libhts_2008.vcproj b/lib/libhts/Win32/libhts_2008.vcproj deleted file mode 100644 index ecbbe61..0000000 --- a/lib/libhts/Win32/libhts_2008.vcproj +++ /dev/null @@ -1,237 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/lib/platform/os.h b/lib/platform/os.h new file mode 100644 index 0000000..4913d7b --- /dev/null +++ b/lib/platform/os.h @@ -0,0 +1,38 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#if (defined(_WIN32) || defined(_WIN64)) +#include "windows/os-types.h" +#else +#include "posix/os-types.h" +#endif diff --git a/lib/platform/posix/os-socket.h b/lib/platform/posix/os-socket.h new file mode 100644 index 0000000..036be3f --- /dev/null +++ b/lib/platform/posix/os-socket.h @@ -0,0 +1,326 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + + +#include "../os.h" +#include "../util/timeutils.h" +#include +#include +#include +#include +#include +#include +#include +#include + +/* Needed on Mac OS/X */ +#ifndef SOL_TCP +#define SOL_TCP IPPROTO_TCP +#endif + +namespace PLATFORM +{ + // Standard sockets + //@{ + inline void SocketClose(socket_t socket) + { + if (socket != INVALID_SOCKET_VALUE) + close(socket); + } + + inline void SocketSetBlocking(socket_t socket, bool bSetTo) + { + if (socket != INVALID_SOCKET_VALUE) + { + if (bSetTo) + fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) & ~O_NONBLOCK); + else + fcntl(socket, F_SETFL, fcntl(socket, F_GETFL) | O_NONBLOCK); + } + } + + inline ssize_t SocketWrite(socket_t socket, int *iError, void* data, size_t len) + { + fd_set port; + + if (socket == INVALID_SOCKET_VALUE) + { + *iError = EINVAL; + return -EINVAL; + } + + ssize_t iBytesWritten(0); + struct timeval *tv(NULL); + + while (iBytesWritten < (ssize_t)len) + { + FD_ZERO(&port); + FD_SET(socket, &port); + int returnv = select(socket + 1, NULL, &port, NULL, tv); + if (returnv < 0) + { + *iError = errno; + return -errno; + } + else if (returnv == 0) + { + *iError = ETIMEDOUT; + return -ETIMEDOUT; + } + + returnv = write(socket, (char*)data + iBytesWritten, len - iBytesWritten); + if (returnv == -1) + { + *iError = errno; + return -errno; + } + iBytesWritten += returnv; + } + + return iBytesWritten; + } + + inline ssize_t SocketRead(socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/) + { + fd_set port; + struct timeval timeout, *tv; + int64_t iNow(0), iTarget(0); + ssize_t iBytesRead(0); + *iError = 0; + + if (socket == INVALID_SOCKET_VALUE) + { + *iError = EINVAL; + return -EINVAL; + } + + if (iTimeoutMs > 0) + { + iNow = GetTimeMs(); + iTarget = iNow + (int64_t) iTimeoutMs; + } + + while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || iTarget > iNow)) + { + if (iTimeoutMs == 0) + { + tv = NULL; + } + else + { + timeout.tv_sec = ((long int)iTarget - (long int)iNow) / (long int)1000.; + timeout.tv_usec = ((long int)iTarget - (long int)iNow) % (long int)1000.; + tv = &timeout; + } + + FD_ZERO(&port); + FD_SET(socket, &port); + int32_t returnv = select(socket + 1, &port, NULL, NULL, tv); + + if (returnv == -1) + { + *iError = errno; + return -errno; + } + else if (returnv == 0) + { + break; //nothing to read + } + + returnv = read(socket, (char*)data + iBytesRead, len - iBytesRead); + if (returnv == -1) + { + *iError = errno; + return -errno; + } + + iBytesRead += returnv; + + if (iTimeoutMs > 0) + iNow = GetTimeMs(); + } + + return iBytesRead; + } + //@} + + // TCP + //@{ + inline void TcpSocketClose(tcp_socket_t socket) + { + SocketClose(socket); + } + + inline void TcpSocketShutdown(tcp_socket_t socket) + { + if (socket != INVALID_SOCKET_VALUE) + shutdown(socket, SHUT_RDWR); + } + + inline ssize_t TcpSocketWrite(tcp_socket_t socket, int *iError, void* data, size_t len) + { + if (socket == INVALID_SOCKET_VALUE) + { + *iError = EINVAL; + return -1; + } + + ssize_t iReturn = send(socket, data, len, 0); + if (iReturn < (ssize_t)len) + *iError = errno; + return iReturn; + } + + inline ssize_t TcpSocketRead(tcp_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/) + { + int64_t iNow(0), iTarget(0); + ssize_t iBytesRead(0); + *iError = 0; + + if (socket == INVALID_SOCKET_VALUE) + { + *iError = EINVAL; + return -EINVAL; + } + + if (iTimeoutMs > 0) + { + iNow = GetTimeMs(); + iTarget = iNow + (int64_t) iTimeoutMs; + } + + struct pollfd fds; + fds.fd = socket; + fds.events = POLLIN; + fds.revents = 0; + + while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || iTarget > iNow)) + { + if (iTimeoutMs > 0) + { + int iPollResult = poll(&fds, 1, iTarget - iNow); + if (iPollResult == 0) + { + *iError = ETIMEDOUT; + return -ETIMEDOUT; + } + } + + ssize_t iReadResult = (iTimeoutMs > 0) ? + recv(socket, (char*)data + iBytesRead, len - iBytesRead, MSG_DONTWAIT) : + recv(socket, data, len, MSG_WAITALL); + if (iReadResult < 0) + { + if (errno == EAGAIN && iTimeoutMs > 0) + continue; + *iError = errno; + return -errno; + } + else if (iReadResult == 0 || (iReadResult != (ssize_t)len && iTimeoutMs == 0)) + { + *iError = ECONNRESET; + return -ECONNRESET; + } + + iBytesRead += iReadResult; + + if (iTimeoutMs > 0) + iNow = GetTimeMs(); + } + + if (iBytesRead < (ssize_t)len) + *iError = ETIMEDOUT; + return iBytesRead; + } + + inline bool TcpResolveAddress(const char *strHost, uint16_t iPort, int *iError, struct addrinfo **info) + { + struct addrinfo hints; + char service[33]; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + sprintf(service, "%d", iPort); + + *iError = getaddrinfo(strHost, service, &hints, info); + return !(*iError); + } + + inline int TcpGetSocketError(tcp_socket_t socket) + { + int iReturn(0); + socklen_t optLen = sizeof(socket_t); + getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)&iReturn, &optLen); + return iReturn; + } + + inline bool TcpSetNoDelay(tcp_socket_t socket) + { + int iSetTo(1); + setsockopt(socket, SOL_TCP, TCP_NODELAY, &iSetTo, sizeof(iSetTo)); + return true; + } + + inline bool TcpConnectSocket(tcp_socket_t socket, struct addrinfo* addr, int *iError, uint64_t iTimeout = 0) + { + *iError = 0; + int iConnectResult = connect(socket, addr->ai_addr, addr->ai_addrlen); + if (iConnectResult == -1) + { + if (errno == EINPROGRESS) + { + struct pollfd pfd; + pfd.fd = socket; + pfd.events = POLLOUT; + pfd.revents = 0; + + int iPollResult = poll(&pfd, 1, iTimeout); + if (iPollResult == 0) + *iError = ETIMEDOUT; + else if (iPollResult == -1) + *iError = errno; + + socklen_t errlen = sizeof(int); + getsockopt(socket, SOL_SOCKET, SO_ERROR, (void *)iError, &errlen); + } + else + { + *iError = errno; + } + } + + return *iError == 0; + } + //@} +} diff --git a/lib/platform/posix/os-threads.h b/lib/platform/posix/os-threads.h new file mode 100644 index 0000000..8b56731 --- /dev/null +++ b/lib/platform/posix/os-threads.h @@ -0,0 +1,119 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +namespace PLATFORM +{ + inline pthread_mutexattr_t *GetRecursiveMutexAttribute(void) + { + static pthread_mutexattr_t g_mutexAttr; + static bool bAttributeInitialised = false; + if (!bAttributeInitialised) + { + pthread_mutexattr_init(&g_mutexAttr); + pthread_mutexattr_settype(&g_mutexAttr, PTHREAD_MUTEX_RECURSIVE); + bAttributeInitialised = true; + } + return &g_mutexAttr; + } + + inline struct timespec GetAbsTime(uint64_t iIncreaseBy = 0) + { + struct timespec now; + #ifdef __APPLE__ + struct timeval tv; + gettimeofday(&tv, NULL); + now.tv_sec = tv.tv_sec; + now.tv_nsec = tv.tv_usec * 1000; + #else + clock_gettime(CLOCK_REALTIME, &now); + #endif + now.tv_nsec += iIncreaseBy % 1000 * 1000000; + now.tv_sec += iIncreaseBy / 1000 + now.tv_nsec / 1000000000; + now.tv_nsec %= 1000000000; + return now; + } + + typedef pthread_t thread_t; + + #define ThreadsCreate(thread, func, arg) (pthread_create(&thread, NULL, (void *(*) (void *))func, (void *)arg) == 0) + #define ThreadsWait(thread, retval) (pthread_join(thread, retval) == 0) + + typedef pthread_mutex_t mutex_t; + #define MutexCreate(mutex) pthread_mutex_init(&mutex, GetRecursiveMutexAttribute()); + #define MutexDelete(mutex) pthread_mutex_destroy(&mutex); + #define MutexLock(mutex) (pthread_mutex_lock(&mutex) == 0) + #define MutexTryLock(mutex) (pthread_mutex_trylock(&mutex) == 0) + #define MutexUnlock(mutex) pthread_mutex_unlock(&mutex) + + class CConditionImpl + { + public: + CConditionImpl(void) + { + pthread_cond_init(&m_condition, NULL); + } + + virtual ~CConditionImpl(void) + { + pthread_cond_destroy(&m_condition); + } + + void Signal(void) + { + pthread_cond_signal(&m_condition); + } + + void Broadcast(void) + { + pthread_cond_broadcast(&m_condition); + } + + bool Wait(mutex_t &mutex) + { + sched_yield(); + return (pthread_cond_wait(&m_condition, &mutex) == 0); + } + + bool Wait(mutex_t &mutex, uint32_t iTimeoutMs) + { + if (iTimeoutMs == 0) + return Wait(mutex); + + sched_yield(); + struct timespec timeout = GetAbsTime(iTimeoutMs); + return (pthread_cond_timedwait(&m_condition, &mutex, &timeout) == 0); + } + + pthread_cond_t m_condition; + }; +} diff --git a/lib/platform/posix/os-types.h b/lib/platform/posix/os-types.h new file mode 100644 index 0000000..b89b9cc --- /dev/null +++ b/lib/platform/posix/os-types.h @@ -0,0 +1,54 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#define _FILE_OFFSET_BITS 64 +#include +#include +#include +#include +#if !defined(__APPLE__) && !defined(__FreeBSD__) +#include +#endif +#include +#include +#include +#include + +#define LIBTYPE +#define DECLSPEC + +typedef int socket_t; +typedef socket_t tcp_socket_t; +#define INVALID_SOCKET_VALUE (-1) +typedef socket_t serial_socket_t; +#define INVALID_SERIAL_SOCKET_VALUE (-1) diff --git a/lib/platform/posix/serialport.cpp b/lib/platform/posix/serialport.cpp new file mode 100644 index 0000000..cefc212 --- /dev/null +++ b/lib/platform/posix/serialport.cpp @@ -0,0 +1,193 @@ +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "../os.h" +#include +#include +#include "../sockets/serialport.h" +#include "../util/baudrate.h" +#include "../posix/os-socket.h" + +#if defined(__APPLE__) || defined(__FreeBSD__) +#ifndef XCASE +#define XCASE 0 +#endif +#ifndef OLCUC +#define OLCUC 0 +#endif +#ifndef IUCLC +#define IUCLC 0 +#endif +#endif +using namespace std; +using namespace PLATFORM; + +void CSerialSocket::Close(void) +{ + if (IsOpen()) + SocketClose(m_socket); +} + +void CSerialSocket::Shutdown(void) +{ + if (IsOpen()) + SocketClose(m_socket); +} + +ssize_t CSerialSocket::Write(void* data, size_t len) +{ + return IsOpen() ? SocketWrite(m_socket, &m_iError, data, len) : -1; +} + +ssize_t CSerialSocket::Read(void* data, size_t len, uint64_t iTimeoutMs /* = 0 */) +{ + return IsOpen() ? SocketRead(m_socket, &m_iError, data, len, iTimeoutMs) : -1; +} + +//setting all this stuff up is a pain in the ass +bool CSerialSocket::Open(uint64_t iTimeoutMs /* = 0 */) +{ + iTimeoutMs = 0; + if (IsOpen()) + return false; + + if (m_iDatabits != SERIAL_DATA_BITS_FIVE && m_iDatabits != SERIAL_DATA_BITS_SIX && + m_iDatabits != SERIAL_DATA_BITS_SEVEN && m_iDatabits != SERIAL_DATA_BITS_EIGHT) + { + m_strError = "Databits has to be between 5 and 8"; + return false; + } + + if (m_iStopbits != SERIAL_STOP_BITS_ONE && m_iStopbits != SERIAL_STOP_BITS_TWO) + { + m_strError = "Stopbits has to be 1 or 2"; + return false; + } + + if (m_iParity != SERIAL_PARITY_NONE && m_iParity != SERIAL_PARITY_EVEN && m_iParity != SERIAL_PARITY_ODD) + { + m_strError = "Parity has to be none, even or odd"; + return false; + } + + m_socket = open(m_strName.c_str(), O_RDWR | O_NOCTTY | O_NDELAY); + + if (m_socket == INVALID_SERIAL_SOCKET_VALUE) + { + m_strError = strerror(errno); + return false; + } + + SocketSetBlocking(m_socket, false); + + if (!SetBaudRate(m_iBaudrate)) + return false; + + m_options.c_cflag |= (CLOCAL | CREAD); + m_options.c_cflag &= ~HUPCL; + + m_options.c_cflag &= ~CSIZE; + if (m_iDatabits == SERIAL_DATA_BITS_FIVE) m_options.c_cflag |= CS5; + if (m_iDatabits == SERIAL_DATA_BITS_SIX) m_options.c_cflag |= CS6; + if (m_iDatabits == SERIAL_DATA_BITS_SEVEN) m_options.c_cflag |= CS7; + if (m_iDatabits == SERIAL_DATA_BITS_EIGHT) m_options.c_cflag |= CS8; + + m_options.c_cflag &= ~PARENB; + if (m_iParity == SERIAL_PARITY_EVEN || m_iParity == SERIAL_PARITY_ODD) + m_options.c_cflag |= PARENB; + if (m_iParity == SERIAL_PARITY_ODD) + m_options.c_cflag |= PARODD; + +#ifdef CRTSCTS + m_options.c_cflag &= ~CRTSCTS; +#elif defined(CNEW_RTSCTS) + m_options.c_cflag &= ~CNEW_RTSCTS; +#endif + + if (m_iStopbits == SERIAL_STOP_BITS_ONE) m_options.c_cflag &= ~CSTOPB; + else m_options.c_cflag |= CSTOPB; + + //I guessed a little here + m_options.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG | XCASE | ECHOK | ECHONL | ECHOCTL | ECHOPRT | ECHOKE | TOSTOP); + + if (m_iParity == SERIAL_PARITY_NONE) + m_options.c_iflag &= ~INPCK; + else + m_options.c_iflag |= INPCK | ISTRIP; + + m_options.c_iflag &= ~(IXON | IXOFF | IXANY | BRKINT | INLCR | IGNCR | ICRNL | IUCLC | IMAXBEL); + m_options.c_oflag &= ~(OPOST | ONLCR | OCRNL); + + if (tcsetattr(m_socket, TCSANOW, &m_options) != 0) + { + m_strError = strerror(errno); + return false; + } + + SocketSetBlocking(m_socket, true); + m_bIsOpen = true; + + return true; +} + +bool CSerialSocket::SetBaudRate(uint32_t baudrate) +{ + int rate = IntToBaudrate(baudrate); + if (rate == -1) + { + char buff[255]; + sprintf(buff, "%i is not a valid baudrate", baudrate); + m_strError = buff; + return false; + } + + //get the current port attributes + if (tcgetattr(m_socket, &m_options) != 0) + { + m_strError = strerror(errno); + return false; + } + + if (cfsetispeed(&m_options, rate) != 0) + { + m_strError = strerror(errno); + return false; + } + + if (cfsetospeed(&m_options, rate) != 0) + { + m_strError = strerror(errno); + return false; + } + + return true; +} diff --git a/lib/platform/sockets/serialport.h b/lib/platform/sockets/serialport.h new file mode 100644 index 0000000..bdd05b9 --- /dev/null +++ b/lib/platform/sockets/serialport.h @@ -0,0 +1,115 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "../os.h" +#include "../util/buffer.h" + +#include +#include + +#if !defined(__WINDOWS__) +#include +#endif + +#include "socket.h" + +namespace PLATFORM +{ + enum SerialParity + { + SERIAL_PARITY_NONE = 0, + SERIAL_PARITY_EVEN, + SERIAL_PARITY_ODD + }; + + enum SerialStopBits + { + SERIAL_STOP_BITS_ONE = 1, + SERIAL_STOP_BITS_TWO = 2 + }; + + enum SerialDataBits + { + SERIAL_DATA_BITS_FIVE = 5, + SERIAL_DATA_BITS_SIX = 6, + SERIAL_DATA_BITS_SEVEN = 7, + SERIAL_DATA_BITS_EIGHT = 8 + }; + + class CSerialSocket : public CCommonSocket + { + public: + CSerialSocket(const CStdString &strName, uint32_t iBaudrate, SerialDataBits iDatabits = SERIAL_DATA_BITS_EIGHT, SerialStopBits iStopbits = SERIAL_STOP_BITS_ONE, SerialParity iParity = SERIAL_PARITY_NONE) : + CCommonSocket(INVALID_SERIAL_SOCKET_VALUE, strName), + m_bIsOpen(false), + m_iBaudrate(iBaudrate), + m_iDatabits(iDatabits), + m_iStopbits(iStopbits), + m_iParity(iParity) {} + + virtual ~CSerialSocket(void) { Close(); } + + virtual bool Open(uint64_t iTimeoutMs = 0); + virtual void Close(void); + virtual void Shutdown(void); + virtual ssize_t Write(void* data, size_t len); + virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0); + + virtual bool IsOpen(void) + { + return m_socket != INVALID_SERIAL_SOCKET_VALUE && + m_bIsOpen; + } + + virtual bool SetBaudRate(uint32_t baudrate); + + protected: + #ifndef __WINDOWS__ + struct termios m_options; + #endif + + bool m_bIsOpen; + uint32_t m_iBaudrate; + SerialDataBits m_iDatabits; + SerialStopBits m_iStopbits; + SerialParity m_iParity; + }; + + class CSerialPort : public CProtectedSocket + { + public: + CSerialPort(const CStdString &strName, uint32_t iBaudrate, SerialDataBits iDatabits = SERIAL_DATA_BITS_EIGHT, SerialStopBits iStopbits = SERIAL_STOP_BITS_ONE, SerialParity iParity = SERIAL_PARITY_NONE) : + CProtectedSocket (new CSerialSocket(strName, iBaudrate, iDatabits, iStopbits, iParity)) {} + virtual ~CSerialPort(void) {} + }; +}; diff --git a/lib/platform/sockets/socket.h b/lib/platform/sockets/socket.h new file mode 100644 index 0000000..f56d515 --- /dev/null +++ b/lib/platform/sockets/socket.h @@ -0,0 +1,228 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "../threads/mutex.h" +#include "../util/StdString.h" + +#if defined(__WINDOWS__) +#include "../windows/os-socket.h" +#else +#include "../posix/os-socket.h" +#endif + +// Common socket operations + +namespace PLATFORM +{ + class ISocket : public PreventCopy + { + public: + ISocket(void) {}; + virtual ~ISocket(void) {} + + virtual bool Open(uint64_t iTimeoutMs = 0) = 0; + virtual void Close(void) = 0; + virtual void Shutdown(void) = 0; + virtual bool IsOpen(void) = 0; + virtual ssize_t Write(void* data, size_t len) = 0; + virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0) = 0; + virtual CStdString GetError(void) = 0; + virtual int GetErrorNumber(void) = 0; + virtual CStdString GetName(void) = 0; + }; + + template + class CCommonSocket : public ISocket + { + public: + CCommonSocket(_SType initialSocketValue, const CStdString &strName) : + m_socket(initialSocketValue), + m_strName(strName), + m_iError(0) {} + + virtual ~CCommonSocket(void) {} + + virtual CStdString GetError(void) + { + CStdString strError; + strError = m_strError.IsEmpty() && m_iError != 0 ? strerror(m_iError) : m_strError; + return strError; + } + + virtual int GetErrorNumber(void) + { + return m_iError; + } + + virtual CStdString GetName(void) + { + CStdString strName; + strName = m_strName; + return strName; + } + + protected: + _SType m_socket; + CStdString m_strError; + CStdString m_strName; + int m_iError; + CMutex m_mutex; + }; + + template + class CProtectedSocket : public ISocket + { + public: + CProtectedSocket(_Socket *socket) : + m_socket(socket), + m_bIsIdle(true) {} + + virtual ~CProtectedSocket(void) + { + Close(); + delete m_socket; + } + + virtual bool Open(uint64_t iTimeoutMs = 0) + { + bool bReturn(false); + if (m_socket && WaitReady()) + { + bReturn = m_socket->Open(iTimeoutMs); + MarkReady(); + } + return bReturn; + } + + virtual void Close(void) + { + if (m_socket && WaitReady()) + { + m_socket->Close(); + MarkReady(); + } + } + + virtual void Shutdown(void) + { + if (m_socket && WaitReady()) + { + m_socket->Shutdown(); + MarkReady(); + } + } + + virtual bool IsOpen(void) + { + CLockObject lock(m_mutex); + return m_socket && m_socket->IsOpen(); + } + + virtual bool IsBusy(void) + { + CLockObject lock(m_mutex); + return m_socket && !m_bIsIdle; + } + + virtual bool IsIdle(void) + { + CLockObject lock(m_mutex); + return m_socket && m_bIsIdle; + } + + virtual ssize_t Write(void* data, size_t len) + { + if (!m_socket || !WaitReady()) + return -EINVAL; + + ssize_t iReturn = m_socket->Write(data, len); + MarkReady(); + + return iReturn; + } + + virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0) + { + if (!m_socket || !WaitReady()) + return -EINVAL; + + ssize_t iReturn = m_socket->Read(data, len, iTimeoutMs); + MarkReady(); + + return iReturn; + } + + virtual CStdString GetError(void) + { + CStdString strError; + CLockObject lock(m_mutex); + strError = m_socket ? m_socket->GetError() : ""; + return strError; + } + + virtual int GetErrorNumber(void) + { + CLockObject lock(m_mutex); + return m_socket ? m_socket->GetErrorNumber() : -EINVAL; + } + + virtual CStdString GetName(void) + { + CStdString strName; + CLockObject lock(m_mutex); + strName = m_socket ? m_socket->GetName() : ""; + return strName; + } + + private: + bool WaitReady(void) + { + CLockObject lock(m_mutex); + m_condition.Wait(m_mutex, m_bIsIdle); + m_bIsIdle = false; + return true; + } + + void MarkReady(void) + { + CLockObject lock(m_mutex); + m_bIsIdle = true; + m_condition.Signal(); + } + + _Socket * m_socket; + CMutex m_mutex; + CCondition m_condition; + bool m_bIsIdle; + }; +}; diff --git a/lib/platform/sockets/tcp.h b/lib/platform/sockets/tcp.h new file mode 100644 index 0000000..ffc372c --- /dev/null +++ b/lib/platform/sockets/tcp.h @@ -0,0 +1,130 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "socket.h" + +using namespace std; + +namespace PLATFORM +{ + class CTcpSocket : public CCommonSocket + { + public: + CTcpSocket(const CStdString &strHostname, uint16_t iPort) : + CCommonSocket(INVALID_SOCKET_VALUE, strHostname), + m_iPort(iPort) {} + + virtual ~CTcpSocket(void) {} + + virtual bool Open(uint64_t iTimeoutMs = 0) + { + bool bReturn(false); + struct addrinfo *address(NULL), *addr(NULL); + if (!TcpResolveAddress(m_strName.c_str(), m_iPort, &m_iError, &address)) + { + m_strError = strerror(m_iError); + return bReturn; + } + + for(addr = address; !bReturn && addr; addr = addr->ai_next) + { + m_socket = TcpCreateSocket(addr, &m_iError, iTimeoutMs); + if (m_socket != INVALID_SOCKET_VALUE) + bReturn = true; + else + m_strError = strerror(m_iError); + } + + freeaddrinfo(address); + return bReturn; + } + + virtual void Close(void) + { + TcpSocketClose(m_socket); + m_socket = INVALID_SOCKET_VALUE; + } + + virtual void Shutdown(void) + { + TcpSocketShutdown(m_socket); + m_socket = INVALID_SOCKET_VALUE; + } + + virtual ssize_t Write(void* data, size_t len) + { + return TcpSocketWrite(m_socket, &m_iError, data, len); + } + + virtual ssize_t Read(void* data, size_t len, uint64_t iTimeoutMs = 0) + { + return TcpSocketRead(m_socket, &m_iError, data, len, iTimeoutMs); + } + + virtual bool IsOpen(void) + { + return m_socket != INVALID_SOCKET_VALUE; + } + + protected: + virtual tcp_socket_t TcpCreateSocket(struct addrinfo* addr, int* iError, uint64_t iTimeout) + { + tcp_socket_t fdSock = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol); + if (fdSock == INVALID_SOCKET_VALUE) + { + *iError = errno; + return (tcp_socket_t)INVALID_SOCKET_VALUE; + } + + if (!TcpConnectSocket(fdSock, addr, iError, iTimeout)) + { + TcpSocketClose(fdSock); + return (tcp_socket_t)INVALID_SOCKET_VALUE; + } + + TcpSetNoDelay(fdSock); + + return fdSock; + } + + uint16_t m_iPort; + }; + + class CTcpConnection : public CProtectedSocket + { + public: + CTcpConnection(const CStdString &strHostname, uint16_t iPort) : + CProtectedSocket (new CTcpSocket(strHostname, iPort)) {} + virtual ~CTcpConnection(void) {} + }; +}; diff --git a/lib/platform/threads/mutex.h b/lib/platform/threads/mutex.h new file mode 100644 index 0000000..ed60ba8 --- /dev/null +++ b/lib/platform/threads/mutex.h @@ -0,0 +1,353 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "../os.h" + +#if defined(__WINDOWS__) +#include "../windows/os-threads.h" +#else +#include "../posix/os-threads.h" +#endif + +#include "../util/timeutils.h" + +namespace PLATFORM +{ + class PreventCopy + { + public: + inline PreventCopy(void) {} + inline ~PreventCopy(void) {} + + private: + inline PreventCopy(const PreventCopy &c) { *this = c; } + inline PreventCopy &operator=(const PreventCopy &c){ *this = c; return *this; } + }; + + template + class CCondition; + + class CMutex : public PreventCopy + { + template + friend class CCondition; + public: + inline CMutex(void) : + m_iLockCount(0) + { + MutexCreate(m_mutex); + } + + inline ~CMutex(void) + { + Clear(); + MutexDelete(m_mutex); + } + + inline bool TryLock(void) + { + if (MutexTryLock(m_mutex)) + { + ++m_iLockCount; + return true; + } + return false; + } + + inline bool Lock(void) + { + MutexLock(m_mutex); + ++m_iLockCount; + return true; + } + + inline void Unlock(void) + { + if (Lock()) + { + if (m_iLockCount >= 2) + { + --m_iLockCount; + MutexUnlock(m_mutex); + } + + --m_iLockCount; + MutexUnlock(m_mutex); + } + } + + inline bool Clear(void) + { + bool bReturn(false); + if (TryLock()) + { + unsigned int iLockCount = m_iLockCount; + for (unsigned int iPtr = 0; iPtr < iLockCount; iPtr++) + Unlock(); + bReturn = true; + } + return bReturn; + } + + private: + mutex_t m_mutex; + volatile unsigned int m_iLockCount; + }; + + class CLockObject : public PreventCopy + { + public: + inline CLockObject(CMutex &mutex, bool bClearOnExit = false) : + m_mutex(mutex), + m_bClearOnExit(bClearOnExit) + { + m_mutex.Lock(); + } + + inline ~CLockObject(void) + { + if (m_bClearOnExit) + Clear(); + else + Unlock(); + } + + inline bool TryLock(void) + { + return m_mutex.TryLock(); + } + + inline void Unlock(void) + { + m_mutex.Unlock(); + } + + inline bool Clear(void) + { + return m_mutex.Clear(); + } + + inline bool Lock(void) + { + return m_mutex.Lock(); + } + + private: + CMutex &m_mutex; + bool m_bClearOnExit; + }; + + class CTryLockObject : public PreventCopy + { + public: + inline CTryLockObject(CMutex &mutex, bool bClearOnExit = false) : + m_mutex(mutex), + m_bClearOnExit(bClearOnExit), + m_bIsLocked(m_mutex.TryLock()) + { + } + + inline ~CTryLockObject(void) + { + if (m_bClearOnExit) + Clear(); + else if (m_bIsLocked) + Unlock(); + } + + inline bool TryLock(void) + { + bool bReturn = m_mutex.TryLock(); + m_bIsLocked |= bReturn; + return bReturn; + } + + inline void Unlock(void) + { + if (m_bIsLocked) + { + m_bIsLocked = false; + m_mutex.Unlock(); + } + } + + inline bool Clear(void) + { + m_bIsLocked = false; + return m_mutex.Clear(); + } + + inline bool Lock(void) + { + bool bReturn = m_mutex.Lock(); + m_bIsLocked |= bReturn; + return bReturn; + } + + inline bool IsLocked(void) const + { + return m_bIsLocked; + } + + private: + CMutex & m_mutex; + bool m_bClearOnExit; + volatile bool m_bIsLocked; + }; + + template + class CCondition : public PreventCopy + { + public: + inline CCondition(void) {} + inline ~CCondition(void) + { + m_condition.Broadcast(); + } + + inline void Broadcast(void) + { + m_condition.Broadcast(); + } + + inline void Signal(void) + { + m_condition.Signal(); + } + + inline bool Wait(CMutex &mutex, _Predicate &predicate) + { + while(!predicate) + m_condition.Wait(mutex.m_mutex); + return true; + } + + inline bool Wait(CMutex &mutex, _Predicate &predicate, uint32_t iTimeout) + { + if (iTimeout == 0) + return Wait(mutex, predicate); + + if (predicate) + return true; + + bool bReturn(false); + bool bBreak(false); + CTimeout timeout(iTimeout); + uint32_t iMsLeft(0); + + while (!bReturn && !bBreak) + { + iMsLeft = timeout.TimeLeft(); + if ((bReturn = predicate) == false && (bBreak = iMsLeft == 0) == false) + m_condition.Wait(mutex.m_mutex, iMsLeft); + } + return bReturn; + } + + private: + CConditionImpl m_condition; + }; + + class CEvent + { + public: + CEvent(bool bAutoReset = true) : + m_bSignaled(false), + m_bBroadcast(false), + m_iWaitingThreads(0), + m_bAutoReset(bAutoReset) {} + virtual ~CEvent(void) {} + + void Broadcast(void) + { + Set(true); + m_condition.Broadcast(); + } + + void Signal(void) + { + Set(false); + m_condition.Signal(); + } + + bool Wait(void) + { + CLockObject lock(m_mutex); + ++m_iWaitingThreads; + + bool bReturn = m_condition.Wait(m_mutex, m_bSignaled); + return ResetAndReturn() && bReturn; + } + + bool Wait(uint32_t iTimeout) + { + if (iTimeout == 0) + return Wait(); + + CLockObject lock(m_mutex); + ++m_iWaitingThreads; + bool bReturn = m_condition.Wait(m_mutex, m_bSignaled, iTimeout); + return ResetAndReturn() && bReturn; + } + + static void Sleep(uint32_t iTimeout) + { + CEvent event; + event.Wait(iTimeout); + } + + private: + void Set(bool bBroadcast = false) + { + CLockObject lock(m_mutex); + m_bSignaled = true; + m_bBroadcast = bBroadcast; + } + + bool ResetAndReturn(void) + { + CLockObject lock(m_mutex); + bool bReturn(m_bSignaled); + if (bReturn && (--m_iWaitingThreads == 0 || !m_bBroadcast) && m_bAutoReset) + m_bSignaled = false; + return bReturn; + } + + volatile bool m_bSignaled; + CCondition m_condition; + CMutex m_mutex; + volatile bool m_bBroadcast; + unsigned int m_iWaitingThreads; + bool m_bAutoReset; + }; +} diff --git a/lib/platform/threads/threads.h b/lib/platform/threads/threads.h new file mode 100644 index 0000000..97774b3 --- /dev/null +++ b/lib/platform/threads/threads.h @@ -0,0 +1,152 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "mutex.h" + +namespace PLATFORM +{ + class CThread + { + public: + CThread(void) : + m_bStop(false), + m_bRunning(false), + m_bStopped(false) {} + + virtual ~CThread(void) + { + StopThread(0); + } + + static void *ThreadHandler(CThread *thread) + { + void *retVal = NULL; + + if (thread) + { + { + CLockObject lock(thread->m_threadMutex); + thread->m_bRunning = true; + thread->m_bStopped = false; + thread->m_threadCondition.Broadcast(); + } + + retVal = thread->Process(); + + { + CLockObject lock(thread->m_threadMutex); + thread->m_bRunning = false; + thread->m_bStopped = true; + thread->m_threadCondition.Broadcast(); + } + } + + return retVal; + } + + virtual bool IsRunning(void) + { + CLockObject lock(m_threadMutex); + return m_bRunning; + } + + virtual bool IsStopped(void) + { + CLockObject lock(m_threadMutex); + return m_bStop; + } + + virtual bool CreateThread(bool bWait = true) + { + bool bReturn(false); + CLockObject lock(m_threadMutex); + if (!IsRunning()) + { + m_bStop = false; + if (ThreadsCreate(m_thread, CThread::ThreadHandler, ((void*)static_cast(this)))) + { + if (bWait) + m_threadCondition.Wait(m_threadMutex, m_bRunning); + bReturn = true; + } + } + return bReturn; + } + + /*! + * @brief Stop the thread + * @param iWaitMs negative = don't wait, 0 = infinite, or the amount of ms to wait + */ + virtual bool StopThread(int iWaitMs = 5000) + { + bool bReturn(true); + bool bRunning(false); + { + CLockObject lock(m_threadMutex); + bRunning = IsRunning(); + m_bStop = true; + } + + if (bRunning && iWaitMs >= 0) + { + CLockObject lock(m_threadMutex); + bReturn = m_threadCondition.Wait(m_threadMutex, m_bStopped, iWaitMs); + } + else + { + bReturn = true; + } + + return bReturn; + } + + virtual bool Sleep(uint32_t iTimeout) + { + CLockObject lock(m_threadMutex); + return m_bStop ? false : m_threadCondition.Wait(m_threadMutex, m_bStopped, iTimeout); + } + + virtual void *Process(void) = 0; + + protected: + void SetRunning(bool bSetTo); + + private: + bool m_bStop; + bool m_bRunning; + bool m_bStopped; + CCondition m_threadCondition; + CMutex m_threadMutex; + thread_t m_thread; + }; +}; diff --git a/lib/platform/util/StdString.h b/lib/platform/util/StdString.h new file mode 100644 index 0000000..496dae7 --- /dev/null +++ b/lib/platform/util/StdString.h @@ -0,0 +1,4337 @@ +#pragma once +#include "../os.h" +#include +#include +#include + +#if defined(_WIN32) && !defined(va_copy) +#define va_copy(dst, src) ((dst) = (src)) +#endif + +// ============================================================================= +// FILE: StdString.h +// AUTHOR: Joe O'Leary (with outside help noted in comments) +// +// If you find any bugs in this code, please let me know: +// +// jmoleary@earthlink.net +// http://www.joeo.net/stdstring.htm (a bit outdated) +// +// The latest version of this code should always be available at the +// following link: +// +// http://www.joeo.net/code/StdString.zip (Dec 6, 2003) +// +// +// REMARKS: +// This header file declares the CStdStr template. This template derives +// the Standard C++ Library basic_string<> template and add to it the +// the following conveniences: +// - The full MFC CString set of functions (including implicit cast) +// - writing to/reading from COM IStream interfaces +// - Functional objects for use in STL algorithms +// +// From this template, we intstantiate two classes: CStdStringA and +// CStdStringW. The name "CStdString" is just a #define of one of these, +// based upone the UNICODE macro setting +// +// This header also declares our own version of the MFC/ATL UNICODE-MBCS +// conversion macros. Our version looks exactly like the Microsoft's to +// facilitate portability. +// +// NOTE: +// If you you use this in an MFC or ATL build, you should include either +// afx.h or atlbase.h first, as appropriate. +// +// PEOPLE WHO HAVE CONTRIBUTED TO THIS CLASS: +// +// Several people have helped me iron out problems and othewise improve +// this class. OK, this is a long list but in my own defense, this code +// has undergone two major rewrites. Many of the improvements became +// necessary after I rewrote the code as a template. Others helped me +// improve the CString facade. +// +// Anyway, these people are (in chronological order): +// +// - Pete the Plumber (???) +// - Julian Selman +// - Chris (of Melbsys) +// - Dave Plummer +// - John C Sipos +// - Chris Sells +// - Nigel Nunn +// - Fan Xia +// - Matthew Williams +// - Carl Engman +// - Mark Zeren +// - Craig Watson +// - Rich Zuris +// - Karim Ratib +// - Chris Conti +// - Baptiste Lepilleur +// - Greg Pickles +// - Jim Cline +// - Jeff Kohn +// - Todd Heckel +// - Ullrich Poll�hne +// - Joe Vitaterna +// - Joe Woodbury +// - Aaron (no last name) +// - Joldakowski (???) +// - Scott Hathaway +// - Eric Nitzche +// - Pablo Presedo +// - Farrokh Nejadlotfi +// - Jason Mills +// - Igor Kholodov +// - Mike Crusader +// - John James +// - Wang Haifeng +// - Tim Dowty +// - Arnt Witteveen +// - Glen Maynard +// - Paul DeMarco +// - Bagira (full name?) +// - Ronny Schulz +// - Jakko Van Hunen +// - Charles Godwin +// - Henk Demper +// - Greg Marr +// - Bill Carducci +// - Brian Groose +// - MKingman +// - Don Beusee +// +// REVISION HISTORY +// +// 2005-JAN-10 - Thanks to Don Beusee for pointing out the danger in mapping +// length-checked formatting functions to non-length-checked +// CRT equivalents. Also thanks to him for motivating me to +// optimize my implementation of Replace() +// +// 2004-APR-22 - A big, big thank you to "MKingman" (whoever you are) for +// finally spotting a silly little error in StdCodeCvt that +// has been causing me (and users of CStdString) problems for +// years in some relatively rare conversions. I had reversed +// two length arguments. +// +// 2003-NOV-24 - Thanks to a bunch of people for helping me clean up many +// compiler warnings (and yes, even a couple of actual compiler +// errors). These include Henk Demper for figuring out how +// to make the Intellisense work on with CStdString on VC6, +// something I was never able to do. Greg Marr pointed out +// a compiler warning about an unreferenced symbol and a +// problem with my version of Load in MFC builds. Bill +// Carducci took a lot of time with me to help me figure out +// why some implementations of the Standard C++ Library were +// returning error codes for apparently successful conversions +// between ASCII and UNICODE. Finally thanks to Brian Groose +// for helping me fix compiler signed unsigned warnings in +// several functions. +// +// 2003-JUL-10 - Thanks to Charles Godwin for making me realize my 'FmtArg' +// fixes had inadvertently broken the DLL-export code (which is +// normally commented out. I had to move it up higher. Also +// this helped me catch a bug in ssicoll that would prevent +// compilation, otherwise. +// +// 2003-MAR-14 - Thanks to Jakko Van Hunen for pointing out a copy-and-paste +// bug in one of the overloads of FmtArg. +// +// 2003-MAR-10 - Thanks to Ronny Schulz for (twice!) sending me some changes +// to help CStdString build on SGI and for pointing out an +// error in placement of my preprocessor macros for ssfmtmsg. +// +// 2002-NOV-26 - Thanks to Bagira for pointing out that my implementation of +// SpanExcluding was not properly handling the case in which +// the string did NOT contain any of the given characters +// +// 2002-OCT-21 - Many thanks to Paul DeMarco who was invaluable in helping me +// get this code working with Borland's free compiler as well +// as the Dev-C++ compiler (available free at SourceForge). +// +// 2002-SEP-13 - Thanks to Glen Maynard who helped me get rid of some loud +// but harmless warnings that were showing up on g++. Glen +// also pointed out that some pre-declarations of FmtArg<> +// specializations were unnecessary (and no good on G++) +// +// 2002-JUN-26 - Thanks to Arnt Witteveen for pointing out that I was using +// static_cast<> in a place in which I should have been using +// reinterpret_cast<> (the ctor for unsigned char strings). +// That's what happens when I don't unit-test properly! +// Arnt also noticed that CString was silently correcting the +// 'nCount' argument to Left() and Right() where CStdString was +// not (and crashing if it was bad). That is also now fixed! +// +// 2002-FEB-25 - Thanks to Tim Dowty for pointing out (and giving me the fix +// for) a conversion problem with non-ASCII MBCS characters. +// CStdString is now used in my favorite commercial MP3 player! +// +// 2001-DEC-06 - Thanks to Wang Haifeng for spotting a problem in one of the +// assignment operators (for _bstr_t) that would cause compiler +// errors when refcounting protection was turned off. +// +// 2001-NOV-27 - Remove calls to operator!= which involve reverse_iterators +// due to a conflict with the rel_ops operator!=. Thanks to +// John James for pointing this out. +// +// 2001-OCT-29 - Added a minor range checking fix for the Mid function to +// make it as forgiving as CString's version is. Thanks to +// Igor Kholodov for noticing this. +// - Added a specialization of std::swap for CStdString. Thanks +// to Mike Crusader for suggesting this! It's commented out +// because you're not supposed to inject your own code into the +// 'std' namespace. But if you don't care about that, it's +// there if you want it +// - Thanks to Jason Mills for catching a case where CString was +// more forgiving in the Delete() function than I was. +// +// 2001-JUN-06 - I was violating the Standard name lookup rules stated +// in [14.6.2(3)]. None of the compilers I've tried so +// far apparently caught this but HP-UX aCC 3.30 did. The +// fix was to add 'this->' prefixes in many places. +// Thanks to Farrokh Nejadlotfi for this! +// +// 2001-APR-27 - StreamLoad was calculating the number of BYTES in one +// case, not characters. Thanks to Pablo Presedo for this. +// +// 2001-FEB-23 - Replace() had a bug which caused infinite loops if the +// source string was empty. Fixed thanks to Eric Nitzsche. +// +// 2001-FEB-23 - Scott Hathaway was a huge help in providing me with the +// ability to build CStdString on Sun Unix systems. He +// sent me detailed build reports about what works and what +// does not. If CStdString compiles on your Unix box, you +// can thank Scott for it. +// +// 2000-DEC-29 - Joldakowski noticed one overload of Insert failed to do a +// range check as CString's does. Now fixed -- thanks! +// +// 2000-NOV-07 - Aaron pointed out that I was calling static member +// functions of char_traits via a temporary. This was not +// technically wrong, but it was unnecessary and caused +// problems for poor old buggy VC5. Thanks Aaron! +// +// 2000-JUL-11 - Joe Woodbury noted that the CString::Find docs don't match +// what the CString::Find code really ends up doing. I was +// trying to match the docs. Now I match the CString code +// - Joe also caught me truncating strings for GetBuffer() calls +// when the supplied length was less than the current length. +// +// 2000-MAY-25 - Better support for STLPORT's Standard library distribution +// - Got rid of the NSP macro - it interfered with Koenig lookup +// - Thanks to Joe Woodbury for catching a TrimLeft() bug that +// I introduced in January. Empty strings were not getting +// trimmed +// +// 2000-APR-17 - Thanks to Joe Vitaterna for pointing out that ReverseFind +// is supposed to be a const function. +// +// 2000-MAR-07 - Thanks to Ullrich Poll�hne for catching a range bug in one +// of the overloads of assign. +// +// 2000-FEB-01 - You can now use CStdString on the Mac with CodeWarrior! +// Thanks to Todd Heckel for helping out with this. +// +// 2000-JAN-23 - Thanks to Jim Cline for pointing out how I could make the +// Trim() function more efficient. +// - Thanks to Jeff Kohn for prompting me to find and fix a typo +// in one of the addition operators that takes _bstr_t. +// - Got rid of the .CPP file - you only need StdString.h now! +// +// 1999-DEC-22 - Thanks to Greg Pickles for helping me identify a problem +// with my implementation of CStdString::FormatV in which +// resulting string might not be properly NULL terminated. +// +// 1999-DEC-06 - Chris Conti pointed yet another basic_string<> assignment +// bug that MS has not fixed. CStdString did nothing to fix +// it either but it does now! The bug was: create a string +// longer than 31 characters, get a pointer to it (via c_str()) +// and then assign that pointer to the original string object. +// The resulting string would be empty. Not with CStdString! +// +// 1999-OCT-06 - BufferSet was erasing the string even when it was merely +// supposed to shrink it. Fixed. Thanks to Chris Conti. +// - Some of the Q172398 fixes were not checking for assignment- +// to-self. Fixed. Thanks to Baptiste Lepilleur. +// +// 1999-AUG-20 - Improved Load() function to be more efficient by using +// SizeOfResource(). Thanks to Rich Zuris for this. +// - Corrected resource ID constructor, again thanks to Rich. +// - Fixed a bug that occurred with UNICODE characters above +// the first 255 ANSI ones. Thanks to Craig Watson. +// - Added missing overloads of TrimLeft() and TrimRight(). +// Thanks to Karim Ratib for pointing them out +// +// 1999-JUL-21 - Made all calls to GetBuf() with no args check length first. +// +// 1999-JUL-10 - Improved MFC/ATL independence of conversion macros +// - Added SS_NO_REFCOUNT macro to allow you to disable any +// reference-counting your basic_string<> impl. may do. +// - Improved ReleaseBuffer() to be as forgiving as CString. +// Thanks for Fan Xia for helping me find this and to +// Matthew Williams for pointing it out directly. +// +// 1999-JUL-06 - Thanks to Nigel Nunn for catching a very sneaky bug in +// ToLower/ToUpper. They should call GetBuf() instead of +// data() in order to ensure the changed string buffer is not +// reference-counted (in those implementations that refcount). +// +// 1999-JUL-01 - Added a true CString facade. Now you can use CStdString as +// a drop-in replacement for CString. If you find this useful, +// you can thank Chris Sells for finally convincing me to give +// in and implement it. +// - Changed operators << and >> (for MFC CArchive) to serialize +// EXACTLY as CString's do. So now you can send a CString out +// to a CArchive and later read it in as a CStdString. I have +// no idea why you would want to do this but you can. +// +// 1999-JUN-21 - Changed the CStdString class into the CStdStr template. +// - Fixed FormatV() to correctly decrement the loop counter. +// This was harmless bug but a bug nevertheless. Thanks to +// Chris (of Melbsys) for pointing it out +// - Changed Format() to try a normal stack-based array before +// using to _alloca(). +// - Updated the text conversion macros to properly use code +// pages and to fit in better in MFC/ATL builds. In other +// words, I copied Microsoft's conversion stuff again. +// - Added equivalents of CString::GetBuffer, GetBufferSetLength +// - new sscpy() replacement of CStdString::CopyString() +// - a Trim() function that combines TrimRight() and TrimLeft(). +// +// 1999-MAR-13 - Corrected the "NotSpace" functional object to use _istpace() +// instead of _isspace() Thanks to Dave Plummer for this. +// +// 1999-FEB-26 - Removed errant line (left over from testing) that #defined +// _MFC_VER. Thanks to John C Sipos for noticing this. +// +// 1999-FEB-03 - Fixed a bug in a rarely-used overload of operator+() that +// caused infinite recursion and stack overflow +// - Added member functions to simplify the process of +// persisting CStdStrings to/from DCOM IStream interfaces +// - Added functional objects (e.g. StdStringLessNoCase) that +// allow CStdStrings to be used as keys STL map objects with +// case-insensitive comparison +// - Added array indexing operators (i.e. operator[]). I +// originally assumed that these were unnecessary and would be +// inherited from basic_string. However, without them, Visual +// C++ complains about ambiguous overloads when you try to use +// them. Thanks to Julian Selman to pointing this out. +// +// 1998-FEB-?? - Added overloads of assign() function to completely account +// for Q172398 bug. Thanks to "Pete the Plumber" for this +// +// 1998-FEB-?? - Initial submission +// +// COPYRIGHT: +// 2002 Joseph M. O'Leary. This code is 100% free. Use it anywhere you +// want. Rewrite it, restructure it, whatever. If you can write software +// that makes money off of it, good for you. I kinda like capitalism. +// Please don't blame me if it causes your $30 billion dollar satellite +// explode in orbit. If you redistribute it in any form, I'd appreciate it +// if you would leave this notice here. +// ============================================================================= + +// Avoid multiple inclusion + +#ifndef STDSTRING_H +#define STDSTRING_H + +// When using VC, turn off browser references +// Turn off unavoidable compiler warnings + +#if defined(_MSC_VER) && (_MSC_VER > 1100) + #pragma component(browser, off, references, "CStdString") + #pragma warning (disable : 4290) // C++ Exception Specification ignored + #pragma warning (disable : 4127) // Conditional expression is constant + #pragma warning (disable : 4097) // typedef name used as synonym for class name +#endif + +// Borland warnings to turn off + +#ifdef __BORLANDC__ + #pragma option push -w-inl +// #pragma warn -inl // Turn off inline function warnings +#endif + +// SS_IS_INTRESOURCE +// ----------------- +// A copy of IS_INTRESOURCE from VC7. Because old VC6 version of winuser.h +// doesn't have this. + +#define SS_IS_INTRESOURCE(_r) (false) + +#if !defined (SS_ANSI) && defined(_MSC_VER) + #undef SS_IS_INTRESOURCE + #if defined(_WIN64) + #define SS_IS_INTRESOURCE(_r) (((unsigned __int64)(_r) >> 16) == 0) + #else + #define SS_IS_INTRESOURCE(_r) (((unsigned long)(_r) >> 16) == 0) + #endif +#endif + + +// MACRO: SS_UNSIGNED +// ------------------ +// This macro causes the addition of a constructor and assignment operator +// which take unsigned characters. CString has such functions and in order +// to provide maximum CString-compatability, this code needs them as well. +// In practice you will likely never need these functions... + +//#define SS_UNSIGNED + +#ifdef SS_ALLOW_UNSIGNED_CHARS + #define SS_UNSIGNED +#endif + +// MACRO: SS_SAFE_FORMAT +// --------------------- +// This macro provides limited compatability with a questionable CString +// "feature". You can define it in order to avoid a common problem that +// people encounter when switching from CString to CStdString. +// +// To illustrate the problem -- With CString, you can do this: +// +// CString sName("Joe"); +// CString sTmp; +// sTmp.Format("My name is %s", sName); // WORKS! +// +// However if you were to try this with CStdString, your program would +// crash. +// +// CStdString sName("Joe"); +// CStdString sTmp; +// sTmp.Format("My name is %s", sName); // CRASHES! +// +// You must explicitly call c_str() or cast the object to the proper type +// +// sTmp.Format("My name is %s", sName.c_str()); // WORKS! +// sTmp.Format("My name is %s", static_cast(sName));// WORKS! +// sTmp.Format("My name is %s", (PCSTR)sName); // WORKS! +// +// This is because it is illegal to pass anything but a POD type as a +// variadic argument to a variadic function (i.e. as one of the "..." +// arguments). The type const char* is a POD type. The type CStdString +// is not. Of course, neither is the type CString, but CString lets you do +// it anyway due to the way they laid out the class in binary. I have no +// control over this in CStdString since I derive from whatever +// implementation of basic_string is available. +// +// However if you have legacy code (which does this) that you want to take +// out of the MFC world and you don't want to rewrite all your calls to +// Format(), then you can define this flag and it will no longer crash. +// +// Note however that this ONLY works for Format(), not sprintf, fprintf, +// etc. If you pass a CStdString object to one of those functions, your +// program will crash. Not much I can do to get around this, short of +// writing substitutes for those functions as well. + +#define SS_SAFE_FORMAT // use new template style Format() function + + +// MACRO: SS_NO_IMPLICIT_CAST +// -------------------------- +// Some people don't like the implicit cast to const char* (or rather to +// const CT*) that CStdString (and MFC's CString) provide. That was the +// whole reason I created this class in the first place, but hey, whatever +// bakes your cake. Just #define this macro to get rid of the the implicit +// cast. + +//#define SS_NO_IMPLICIT_CAST // gets rid of operator const CT*() + + +// MACRO: SS_NO_REFCOUNT +// --------------------- +// turns off reference counting at the assignment level. Only needed +// for the version of basic_string<> that comes with Visual C++ versions +// 6.0 or earlier, and only then in some heavily multithreaded scenarios. +// Uncomment it if you feel you need it. + +//#define SS_NO_REFCOUNT + +// MACRO: SS_WIN32 +// --------------- +// When this flag is set, we are building code for the Win32 platform and +// may use Win32 specific functions (such as LoadString). This gives us +// a couple of nice extras for the code. +// +// Obviously, Microsoft's is not the only compiler available for Win32 out +// there. So I can't just check to see if _MSC_VER is defined to detect +// if I'm building on Win32. So for now, if you use MS Visual C++ or +// Borland's compiler, I turn this on. Otherwise you may turn it on +// yourself, if you prefer + +#if defined(_MSC_VER) || defined(__BORLANDC__) || defined(_WIN32) + #define SS_WIN32 +#endif + +// MACRO: SS_ANSI +// -------------- +// When this macro is defined, the code attempts only to use ANSI/ISO +// standard library functions to do it's work. It will NOT attempt to use +// any Win32 of Visual C++ specific functions -- even if they are +// available. You may define this flag yourself to prevent any Win32 +// of VC++ specific functions from being called. + +// If we're not on Win32, we MUST use an ANSI build + +#ifndef SS_WIN32 + #if !defined(SS_NO_ANSI) + #define SS_ANSI + #endif +#endif + +// MACRO: SS_ALLOCA +// ---------------- +// Some implementations of the Standard C Library have a non-standard +// function known as alloca(). This functions allows one to allocate a +// variable amount of memory on the stack. It is needed to implement +// the ASCII/MBCS conversion macros. +// +// I wanted to find some way to determine automatically if alloca() is +// available on this platform via compiler flags but that is asking for +// trouble. The crude test presented here will likely need fixing on +// other platforms. Therefore I'll leave it up to you to fiddle with +// this test to determine if it exists. Just make sure SS_ALLOCA is or +// is not defined as appropriate and you control this feature. + +#if defined(_MSC_VER) && !defined(SS_ANSI) + #define SS_ALLOCA +#endif + + +// MACRO: SS_MBCS +// -------------- +// Setting this macro means you are using MBCS characters. In MSVC builds, +// this macro gets set automatically by detection of the preprocessor flag +// _MBCS. For other platforms you may set it manually if you wish. The +// only effect it currently has is to cause the allocation of more space +// for wchar_t --> char conversions. +// Note that MBCS does not mean UNICODE. +// +// #define SS_MBCS +// + +#ifdef _MBCS + #define SS_MBCS +#endif + + +// MACRO SS_NO_LOCALE +// ------------------ +// If your implementation of the Standard C++ Library lacks the header, +// you can #define this macro to make your code build properly. Note that this +// is some of my newest code and frankly I'm not very sure of it, though it does +// pass my unit tests. + +// #define SS_NO_LOCALE + + +// Compiler Error regarding _UNICODE and UNICODE +// ----------------------------------------------- +// Microsoft header files are screwy. Sometimes they depend on a preprocessor +// flag named "_UNICODE". Other times they check "UNICODE" (note the lack of +// leading underscore in the second version". In several places, they silently +// "synchronize" these two flags this by defining one of the other was defined. +// In older version of this header, I used to try to do the same thing. +// +// However experience has taught me that this is a bad idea. You get weird +// compiler errors that seem to indicate things like LPWSTR and LPTSTR not being +// equivalent in UNICODE builds, stuff like that (when they MUST be in a proper +// UNICODE build). You end up scratching your head and saying, "But that HAS +// to compile!". +// +// So what should you do if you get this error? +// +// Make sure that both macros (_UNICODE and UNICODE) are defined before this +// file is included. You can do that by either +// +// a) defining both yourself before any files get included +// b) including the proper MS headers in the proper order +// c) including this file before any other file, uncommenting +// the #defines below, and commenting out the #errors +// +// Personally I recommend solution a) but it's your call. + +#ifdef _MSC_VER + #if defined (_UNICODE) && !defined (UNICODE) + #error UNICODE defined but not UNICODE + // #define UNICODE // no longer silently fix this + #endif + #if defined (UNICODE) && !defined (_UNICODE) + #error Warning, UNICODE defined but not _UNICODE + // #define _UNICODE // no longer silently fix this + #endif +#endif + + +// ----------------------------------------------------------------------------- +// MIN and MAX. The Standard C++ template versions go by so many names (at +// at least in the MS implementation) that you never know what's available +// ----------------------------------------------------------------------------- +template +inline const Type& SSMIN(const Type& arg1, const Type& arg2) +{ + return arg2 < arg1 ? arg2 : arg1; +} +template +inline const Type& SSMAX(const Type& arg1, const Type& arg2) +{ + return arg2 > arg1 ? arg2 : arg1; +} + +// If they have not #included W32Base.h (part of my W32 utility library) then +// we need to define some stuff. Otherwise, this is all defined there. + +#if !defined(W32BASE_H) + + // If they want us to use only standard C++ stuff (no Win32 stuff) + + #ifdef SS_ANSI + + // On Win32 we have TCHAR.H so just include it. This is NOT violating + // the spirit of SS_ANSI as we are not calling any Win32 functions here. + + #ifdef SS_WIN32 + + #include + #include + #ifndef STRICT + #define STRICT + #endif + + // ... but on non-Win32 platforms, we must #define the types we need. + + #else + + typedef const char* PCSTR; + typedef char* PSTR; + typedef const wchar_t* PCWSTR; + typedef wchar_t* PWSTR; + #ifdef UNICODE + typedef wchar_t TCHAR; + #else + typedef char TCHAR; + #endif + typedef wchar_t OLECHAR; + + #endif // #ifndef _WIN32 + + + // Make sure ASSERT and verify are defined using only ANSI stuff + + #ifndef ASSERT + #include + #define ASSERT(f) assert((f)) + #endif + #ifndef VERIFY + #ifdef _DEBUG + #define VERIFY(x) ASSERT((x)) + #else + #define VERIFY(x) x + #endif + #endif + + #else // ...else SS_ANSI is NOT defined + + #include + #include + #ifndef STRICT + #define STRICT + #endif + + // Make sure ASSERT and verify are defined + + #ifndef ASSERT + #include + #define ASSERT(f) _ASSERTE((f)) + #endif + #ifndef VERIFY + #ifdef _DEBUG + #define VERIFY(x) ASSERT((x)) + #else + #define VERIFY(x) x + #endif + #endif + + #endif // #ifdef SS_ANSI + + #ifndef UNUSED + #define UNUSED(x) x + #endif + +#endif // #ifndef W32BASE_H + +// Standard headers needed + +#include // basic_string +#include // for_each, etc. +#include // for StdStringLessNoCase, et al +#ifndef SS_NO_LOCALE + #include // for various facets +#endif + +// If this is a recent enough version of VC include comdef.h, so we can write +// member functions to deal with COM types & compiler support classes e.g. +// _bstr_t + +#if defined (_MSC_VER) && (_MSC_VER >= 1100) + #include + #define SS_INC_COMDEF // signal that we #included MS comdef.h file + #define STDSTRING_INC_COMDEF + #define SS_NOTHROW __declspec(nothrow) +#else + #define SS_NOTHROW +#endif + +#ifndef TRACE + #define TRACE_DEFINED_HERE + #define TRACE +#endif + +// Microsoft defines PCSTR, PCWSTR, etc, but no PCTSTR. I hate to use the +// versions with the "L" in front of them because that's a leftover from Win 16 +// days, even though it evaluates to the same thing. Therefore, Define a PCSTR +// as an LPCTSTR. + +#if !defined(PCTSTR) && !defined(PCTSTR_DEFINED) + typedef const TCHAR* PCTSTR; + #define PCTSTR_DEFINED +#endif + +#if !defined(PCOLESTR) && !defined(PCOLESTR_DEFINED) + typedef const OLECHAR* PCOLESTR; + #define PCOLESTR_DEFINED +#endif + +#if !defined(POLESTR) && !defined(POLESTR_DEFINED) + typedef OLECHAR* POLESTR; + #define POLESTR_DEFINED +#endif + +#if !defined(PCUSTR) && !defined(PCUSTR_DEFINED) + typedef const unsigned char* PCUSTR; + typedef unsigned char* PUSTR; + #define PCUSTR_DEFINED +#endif + + +// SGI compiler 7.3 doesnt know these types - oh and btw, remember to use +// -LANG:std in the CXX Flags +#if defined(__sgi) + typedef unsigned long DWORD; + typedef void * LPCVOID; +#endif + + +// SS_USE_FACET macro and why we need it: +// +// Since I'm a good little Standard C++ programmer, I use locales. Thus, I +// need to make use of the use_facet<> template function here. Unfortunately, +// this need is complicated by the fact the MS' implementation of the Standard +// C++ Library has a non-standard version of use_facet that takes more +// arguments than the standard dictates. Since I'm trying to write CStdString +// to work with any version of the Standard library, this presents a problem. +// +// The upshot of this is that I can't do 'use_facet' directly. The MS' docs +// tell me that I have to use a macro, _USE() instead. Since _USE obviously +// won't be available in other implementations, this means that I have to write +// my OWN macro -- SS_USE_FACET -- that evaluates either to _USE or to the +// standard, use_facet. +// +// If you are having trouble with the SS_USE_FACET macro, in your implementation +// of the Standard C++ Library, you can define your own version of SS_USE_FACET. + +#ifndef schMSG + #define schSTR(x) #x + #define schSTR2(x) schSTR(x) + #define schMSG(desc) message(__FILE__ "(" schSTR2(__LINE__) "):" #desc) +#endif + +#ifndef SS_USE_FACET + + // STLPort #defines a macro (__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) for + // all MSVC builds, erroneously in my opinion. It causes problems for + // my SS_ANSI builds. In my code, I always comment out that line. You'll + // find it in \stlport\config\stl_msvc.h + + #if defined(__SGI_STL_PORT) && (__SGI_STL_PORT >= 0x400 ) + + #if defined(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS) && defined(_MSC_VER) + #ifdef SS_ANSI + #pragma schMSG(__STL_NO_EXPLICIT_FUNCTION_TMPL_ARGS defined!!) + #endif + #endif + #define SS_USE_FACET(loc, fac) std::use_facet(loc) + + #elif defined(_MSC_VER ) + + #define SS_USE_FACET(loc, fac) std::_USE(loc, fac) + + // ...and + #elif defined(_RWSTD_NO_TEMPLATE_ON_RETURN_TYPE) + + #define SS_USE_FACET(loc, fac) std::use_facet(loc, (fac*)0) + + #else + + #define SS_USE_FACET(loc, fac) std::use_facet(loc) + + #endif + +#endif + +// ============================================================================= +// UNICODE/MBCS conversion macros. Made to work just like the MFC/ATL ones. +// ============================================================================= + +#include // Added to Std Library with Amendment #1. + +// First define the conversion helper functions. We define these regardless of +// any preprocessor macro settings since their names won't collide. + +// Not sure if we need all these headers. I believe ANSI says we do. + +#include +#include +#include +#include +#include +#ifndef va_start + #include +#endif + + +#ifdef SS_NO_LOCALE + + #if defined(_WIN32) || defined (_WIN32_WCE) + + inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc, + UINT acp=CP_ACP) + { + ASSERT(0 != pSrcA); + ASSERT(0 != pDstW); + pDstW[0] = '\0'; + MultiByteToWideChar(acp, 0, pSrcA, nSrc, pDstW, nDst); + return pDstW; + } + inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCUSTR pSrcA, int nSrc, + UINT acp=CP_ACP) + { + return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, acp); + } + + inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc, + UINT acp=CP_ACP) + { + ASSERT(0 != pDstA); + ASSERT(0 != pSrcW); + pDstA[0] = '\0'; + WideCharToMultiByte(acp, 0, pSrcW, nSrc, pDstA, nDst, 0, 0); + return pDstA; + } + inline PUSTR StdCodeCvt(PUSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc, + UINT acp=CP_ACP) + { + return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, acp); + } + #else + #endif + +#else + + // StdCodeCvt - made to look like Win32 functions WideCharToMultiByte + // and MultiByteToWideChar but uses locales in SS_ANSI + // builds. There are a number of overloads. + // First argument is the destination buffer. + // Second argument is the source buffer + //#if defined (SS_ANSI) || !defined (SS_WIN32) + + // 'SSCodeCvt' - shorthand name for the codecvt facet we use + + typedef std::codecvt SSCodeCvt; + + inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCSTR pSrcA, int nSrc, + const std::locale& loc=std::locale()) + { + ASSERT(0 != pSrcA); + ASSERT(0 != pDstW); + + pDstW[0] = '\0'; + + if ( nSrc > 0 ) + { + PCSTR pNextSrcA = pSrcA; + PWSTR pNextDstW = pDstW; + SSCodeCvt::result res = SSCodeCvt::ok; + const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt); + SSCodeCvt::state_type st= { 0 }; + res = conv.in(st, + pSrcA, pSrcA + nSrc, pNextSrcA, + pDstW, pDstW + nDst, pNextDstW); +#ifdef _LINUX +#define ASSERT2(a) if (!(a)) {fprintf(stderr, "StdString: Assertion Failed on line %d\n", __LINE__);} +#else +#define ASSERT2 ASSERT +#endif + ASSERT2(SSCodeCvt::ok == res); + ASSERT2(SSCodeCvt::error != res); + ASSERT2(pNextDstW >= pDstW); + ASSERT2(pNextSrcA >= pSrcA); +#undef ASSERT2 + // Null terminate the converted string + + if ( pNextDstW - pDstW > nDst ) + *(pDstW + nDst) = '\0'; + else + *pNextDstW = '\0'; + } + return pDstW; + } + inline PWSTR StdCodeCvt(PWSTR pDstW, int nDst, PCUSTR pSrcA, int nSrc, + const std::locale& loc=std::locale()) + { + return StdCodeCvt(pDstW, nDst, (PCSTR)pSrcA, nSrc, loc); + } + + inline PSTR StdCodeCvt(PSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc, + const std::locale& loc=std::locale()) + { + ASSERT(0 != pDstA); + ASSERT(0 != pSrcW); + + pDstA[0] = '\0'; + + if ( nSrc > 0 ) + { + PSTR pNextDstA = pDstA; + PCWSTR pNextSrcW = pSrcW; + SSCodeCvt::result res = SSCodeCvt::ok; + const SSCodeCvt& conv = SS_USE_FACET(loc, SSCodeCvt); + SSCodeCvt::state_type st= { 0 }; + res = conv.out(st, + pSrcW, pSrcW + nSrc, pNextSrcW, + pDstA, pDstA + nDst, pNextDstA); +#ifdef _LINUX +#define ASSERT2(a) if (!(a)) {fprintf(stderr, "StdString: Assertion Failed on line %d\n", __LINE__);} +#else +#define ASSERT2 ASSERT +#endif + ASSERT2(SSCodeCvt::error != res); + ASSERT2(SSCodeCvt::ok == res); // strict, comment out for sanity + ASSERT2(pNextDstA >= pDstA); + ASSERT2(pNextSrcW >= pSrcW); +#undef ASSERT2 + + // Null terminate the converted string + + if ( pNextDstA - pDstA > nDst ) + *(pDstA + nDst) = '\0'; + else + *pNextDstA = '\0'; + } + return pDstA; + } + + inline PUSTR StdCodeCvt(PUSTR pDstA, int nDst, PCWSTR pSrcW, int nSrc, + const std::locale& loc=std::locale()) + { + return (PUSTR)StdCodeCvt((PSTR)pDstA, nDst, pSrcW, nSrc, loc); + } + +#endif + + + +// Unicode/MBCS conversion macros are only available on implementations of +// the "C" library that have the non-standard _alloca function. As far as I +// know that's only Microsoft's though I've heard that the function exists +// elsewhere. + +#if defined(SS_ALLOCA) && !defined SS_NO_CONVERSION + + #include // needed for _alloca + + // Define our conversion macros to look exactly like Microsoft's to + // facilitate using this stuff both with and without MFC/ATL + + #ifdef _CONVERSION_USES_THREAD_LOCALE + + #ifndef _DEBUG + #define SSCVT int _cvt; _cvt; UINT _acp=GetACP(); \ + _acp; PCWSTR _pw; _pw; PCSTR _pa; _pa + #else + #define SSCVT int _cvt = 0; _cvt; UINT _acp=GetACP();\ + _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa + #endif + #define SSA2W(pa) (\ + ((_pa = pa) == 0) ? 0 : (\ + _cvt = (sslen(_pa)),\ + StdCodeCvt((PWSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \ + _pa, _cvt, _acp))) + #define SSW2A(pw) (\ + ((_pw = pw) == 0) ? 0 : (\ + _cvt = sslen(_pw), \ + StdCodeCvt((LPSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \ + _pw, _cvt, _acp))) + #else + + #ifndef _DEBUG + #define SSCVT int _cvt; _cvt; UINT _acp=CP_ACP; _acp;\ + PCWSTR _pw; _pw; PCSTR _pa; _pa + #else + #define SSCVT int _cvt = 0; _cvt; UINT _acp=CP_ACP; \ + _acp; PCWSTR _pw=0; _pw; PCSTR _pa=0; _pa + #endif + #define SSA2W(pa) (\ + ((_pa = pa) == 0) ? 0 : (\ + _cvt = (sslen(_pa)),\ + StdCodeCvt((PWSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \ + _pa, _cvt))) + #define SSW2A(pw) (\ + ((_pw = pw) == 0) ? 0 : (\ + _cvt = (sslen(_pw)),\ + StdCodeCvt((LPSTR) _alloca((_cvt+1)*2), (_cvt+1)*2, \ + _pw, _cvt))) + #endif + + #define SSA2CW(pa) ((PCWSTR)SSA2W((pa))) + #define SSW2CA(pw) ((PCSTR)SSW2A((pw))) + + #ifdef UNICODE + #define SST2A SSW2A + #define SSA2T SSA2W + #define SST2CA SSW2CA + #define SSA2CT SSA2CW + // (Did you get a compiler error here about not being able to convert + // PTSTR into PWSTR? Then your _UNICODE and UNICODE flags are messed + // up. Best bet: #define BOTH macros before including any MS headers.) + inline PWSTR SST2W(PTSTR p) { return p; } + inline PTSTR SSW2T(PWSTR p) { return p; } + inline PCWSTR SST2CW(PCTSTR p) { return p; } + inline PCTSTR SSW2CT(PCWSTR p) { return p; } + #else + #define SST2W SSA2W + #define SSW2T SSW2A + #define SST2CW SSA2CW + #define SSW2CT SSW2CA + inline PSTR SST2A(PTSTR p) { return p; } + inline PTSTR SSA2T(PSTR p) { return p; } + inline PCSTR SST2CA(PCTSTR p) { return p; } + inline PCTSTR SSA2CT(PCSTR p) { return p; } + #endif // #ifdef UNICODE + + #if defined(UNICODE) + // in these cases the default (TCHAR) is the same as OLECHAR + inline PCOLESTR SST2COLE(PCTSTR p) { return p; } + inline PCTSTR SSOLE2CT(PCOLESTR p) { return p; } + inline POLESTR SST2OLE(PTSTR p) { return p; } + inline PTSTR SSOLE2T(POLESTR p) { return p; } + #elif defined(OLE2ANSI) + // in these cases the default (TCHAR) is the same as OLECHAR + inline PCOLESTR SST2COLE(PCTSTR p) { return p; } + inline PCTSTR SSOLE2CT(PCOLESTR p) { return p; } + inline POLESTR SST2OLE(PTSTR p) { return p; } + inline PTSTR SSOLE2T(POLESTR p) { return p; } + #else + //CharNextW doesn't work on Win95 so we use this + #define SST2COLE(pa) SSA2CW((pa)) + #define SST2OLE(pa) SSA2W((pa)) + #define SSOLE2CT(po) SSW2CA((po)) + #define SSOLE2T(po) SSW2A((po)) + #endif + + #ifdef OLE2ANSI + #define SSW2OLE SSW2A + #define SSOLE2W SSA2W + #define SSW2COLE SSW2CA + #define SSOLE2CW SSA2CW + inline POLESTR SSA2OLE(PSTR p) { return p; } + inline PSTR SSOLE2A(POLESTR p) { return p; } + inline PCOLESTR SSA2COLE(PCSTR p) { return p; } + inline PCSTR SSOLE2CA(PCOLESTR p){ return p; } + #else + #define SSA2OLE SSA2W + #define SSOLE2A SSW2A + #define SSA2COLE SSA2CW + #define SSOLE2CA SSW2CA + inline POLESTR SSW2OLE(PWSTR p) { return p; } + inline PWSTR SSOLE2W(POLESTR p) { return p; } + inline PCOLESTR SSW2COLE(PCWSTR p) { return p; } + inline PCWSTR SSOLE2CW(PCOLESTR p){ return p; } + #endif + + // Above we've defined macros that look like MS' but all have + // an 'SS' prefix. Now we need the real macros. We'll either + // get them from the macros above or from MFC/ATL. + + #if defined (USES_CONVERSION) + + #define _NO_STDCONVERSION // just to be consistent + + #else + + #ifdef _MFC_VER + + #include + #define _NO_STDCONVERSION // just to be consistent + + #else + + #define USES_CONVERSION SSCVT + #define A2CW SSA2CW + #define W2CA SSW2CA + #define T2A SST2A + #define A2T SSA2T + #define T2W SST2W + #define W2T SSW2T + #define T2CA SST2CA + #define A2CT SSA2CT + #define T2CW SST2CW + #define W2CT SSW2CT + #define ocslen sslen + #define ocscpy sscpy + #define T2COLE SST2COLE + #define OLE2CT SSOLE2CT + #define T2OLE SST2COLE + #define OLE2T SSOLE2CT + #define A2OLE SSA2OLE + #define OLE2A SSOLE2A + #define W2OLE SSW2OLE + #define OLE2W SSOLE2W + #define A2COLE SSA2COLE + #define OLE2CA SSOLE2CA + #define W2COLE SSW2COLE + #define OLE2CW SSOLE2CW + + #endif // #ifdef _MFC_VER + #endif // #ifndef USES_CONVERSION +#endif // #ifndef SS_NO_CONVERSION + +// Define ostring - generic name for std::basic_string + +#if !defined(ostring) && !defined(OSTRING_DEFINED) + typedef std::basic_string ostring; + #define OSTRING_DEFINED +#endif + +// StdCodeCvt when there's no conversion to be done +template +inline T* StdCodeCvt(T* pDst, int nDst, const T* pSrc, int nSrc) +{ + int nChars = SSMIN(nSrc, nDst); + + if ( nChars > 0 ) + { + pDst[0] = '\0'; + std::basic_string::traits_type::copy(pDst, pSrc, nChars); +// std::char_traits::copy(pDst, pSrc, nChars); + pDst[nChars] = '\0'; + } + + return pDst; +} +inline PSTR StdCodeCvt(PSTR pDst, int nDst, PCUSTR pSrc, int nSrc) +{ + return StdCodeCvt(pDst, nDst, (PCSTR)pSrc, nSrc); +} +inline PUSTR StdCodeCvt(PUSTR pDst, int nDst, PCSTR pSrc, int nSrc) +{ + return (PUSTR)StdCodeCvt((PSTR)pDst, nDst, pSrc, nSrc); +} + +// Define tstring -- generic name for std::basic_string + +#if !defined(tstring) && !defined(TSTRING_DEFINED) + typedef std::basic_string tstring; + #define TSTRING_DEFINED +#endif + +// a very shorthand way of applying the fix for KB problem Q172398 +// (basic_string assignment bug) + +#if defined ( _MSC_VER ) && ( _MSC_VER < 1200 ) + #define Q172398(x) (x).erase() +#else + #define Q172398(x) +#endif + +// ============================================================================= +// INLINE FUNCTIONS ON WHICH CSTDSTRING RELIES +// +// Usually for generic text mapping, we rely on preprocessor macro definitions +// to map to string functions. However the CStdStr<> template cannot use +// macro-based generic text mappings because its character types do not get +// resolved until template processing which comes AFTER macro processing. In +// other words, the preprocessor macro UNICODE is of little help to us in the +// CStdStr template +// +// Therefore, to keep the CStdStr declaration simple, we have these inline +// functions. The template calls them often. Since they are inline (and NOT +// exported when this is built as a DLL), they will probably be resolved away +// to nothing. +// +// Without these functions, the CStdStr<> template would probably have to broken +// out into two, almost identical classes. Either that or it would be a huge, +// convoluted mess, with tons of "if" statements all over the place checking the +// size of template parameter CT. +// ============================================================================= + +#ifdef SS_NO_LOCALE + + // -------------------------------------------------------------------------- + // Win32 GetStringTypeEx wrappers + // -------------------------------------------------------------------------- + inline bool wsGetStringType(LCID lc, DWORD dwT, PCSTR pS, int nSize, + WORD* pWd) + { + return FALSE != GetStringTypeExA(lc, dwT, pS, nSize, pWd); + } + inline bool wsGetStringType(LCID lc, DWORD dwT, PCWSTR pS, int nSize, + WORD* pWd) + { + return FALSE != GetStringTypeExW(lc, dwT, pS, nSize, pWd); + } + + + template + inline bool ssisspace (CT t) + { + WORD toYourMother; + return wsGetStringType(GetThreadLocale(), CT_CTYPE1, &t, 1, &toYourMother) + && 0 != (C1_BLANK & toYourMother); + } + +#endif + +// If they defined SS_NO_REFCOUNT, then we must convert all assignments + +#if defined (_MSC_VER) && (_MSC_VER < 1300) + #ifdef SS_NO_REFCOUNT + #define SSREF(x) (x).c_str() + #else + #define SSREF(x) (x) + #endif +#else + #define SSREF(x) (x) +#endif + +// ----------------------------------------------------------------------------- +// sslen: strlen/wcslen wrappers +// ----------------------------------------------------------------------------- +template inline int sslen(const CT* pT) +{ + return 0 == pT ? 0 : (int)std::basic_string::traits_type::length(pT); +// return 0 == pT ? 0 : std::char_traits::length(pT); +} +inline SS_NOTHROW int sslen(const std::string& s) +{ + return static_cast(s.length()); +} +inline SS_NOTHROW int sslen(const std::wstring& s) +{ + return static_cast(s.length()); +} + +// ----------------------------------------------------------------------------- +// sstolower/sstoupper -- convert characters to upper/lower case +// ----------------------------------------------------------------------------- + +#ifdef SS_NO_LOCALE + inline char sstoupper(char ch) { return (char)::toupper(ch); } + inline wchar_t sstoupper(wchar_t ch){ return (wchar_t)::towupper(ch); } + inline char sstolower(char ch) { return (char)::tolower(ch); } + inline wchar_t sstolower(wchar_t ch){ return (wchar_t)::tolower(ch); } +#else + template + inline CT sstolower(const CT& t, const std::locale& loc = std::locale()) + { + return std::tolower(t, loc); + } + template + inline CT sstoupper(const CT& t, const std::locale& loc = std::locale()) + { + return std::toupper(t, loc); + } +#endif + +// ----------------------------------------------------------------------------- +// ssasn: assignment functions -- assign "sSrc" to "sDst" +// ----------------------------------------------------------------------------- +typedef std::string::size_type SS_SIZETYPE; // just for shorthand, really +typedef std::string::pointer SS_PTRTYPE; +typedef std::wstring::size_type SW_SIZETYPE; +typedef std::wstring::pointer SW_PTRTYPE; + + +template +inline void ssasn(std::basic_string& sDst, const std::basic_string& sSrc) +{ + if ( sDst.c_str() != sSrc.c_str() ) + { + sDst.erase(); + sDst.assign(SSREF(sSrc)); + } +} +template +inline void ssasn(std::basic_string& sDst, const T *pA) +{ + // Watch out for NULLs, as always. + + if ( 0 == pA ) + { + sDst.erase(); + } + + // If pA actually points to part of sDst, we must NOT erase(), but + // rather take a substring + + else if ( pA >= sDst.c_str() && pA <= sDst.c_str() + sDst.size() ) + { + sDst =sDst.substr(static_cast::size_type>(pA-sDst.c_str())); + } + + // Otherwise (most cases) apply the assignment bug fix, if applicable + // and do the assignment + + else + { + Q172398(sDst); + sDst.assign(pA); + } +} +inline void ssasn(std::string& sDst, const std::wstring& sSrc) +{ + if ( sSrc.empty() ) + { + sDst.erase(); + } + else + { + int nDst = static_cast(sSrc.size()); + + // In MBCS builds, pad the buffer to account for the possibility of + // some 3 byte characters. Not perfect but should get most cases. + +#ifdef SS_MBCS + // In MBCS builds, we don't know how long the destination string will be. + nDst = static_cast(static_cast(nDst) * 1.3); + sDst.resize(nDst+1); + PCSTR szCvt = StdCodeCvt(const_cast(sDst.data()), nDst, + sSrc.c_str(), static_cast(sSrc.size())); + sDst.resize(sslen(szCvt)); +#else + sDst.resize(nDst+1); + StdCodeCvt(const_cast(sDst.data()), nDst, + sSrc.c_str(), static_cast(sSrc.size())); + sDst.resize(sSrc.size()); +#endif + } +} +inline void ssasn(std::string& sDst, PCWSTR pW) +{ + int nSrc = sslen(pW); + if ( nSrc > 0 ) + { + int nSrc = sslen(pW); + int nDst = nSrc; + + // In MBCS builds, pad the buffer to account for the possibility of + // some 3 byte characters. Not perfect but should get most cases. + +#ifdef SS_MBCS + nDst = static_cast(static_cast(nDst) * 1.3); + // In MBCS builds, we don't know how long the destination string will be. + sDst.resize(nDst + 1); + PCSTR szCvt = StdCodeCvt(const_cast(sDst.data()), nDst, + pW, nSrc); + sDst.resize(sslen(szCvt)); +#else + sDst.resize(nDst + 1); + StdCodeCvt(const_cast(sDst.data()), nDst, pW, nSrc); + sDst.resize(nDst); +#endif + } + else + { + sDst.erase(); + } +} +inline void ssasn(std::string& sDst, const int nNull) +{ + //UNUSED(nNull); + ASSERT(nNull==0); + sDst.assign(""); +} +#undef StrSizeType +inline void ssasn(std::wstring& sDst, const std::string& sSrc) +{ + if ( sSrc.empty() ) + { + sDst.erase(); + } + else + { + int nSrc = static_cast(sSrc.size()); + int nDst = nSrc; + + sDst.resize(nSrc+1); + PCWSTR szCvt = StdCodeCvt(const_cast(sDst.data()), nDst, + sSrc.c_str(), nSrc); + + sDst.resize(sslen(szCvt)); + } +} +inline void ssasn(std::wstring& sDst, PCSTR pA) +{ + int nSrc = sslen(pA); + + if ( 0 == nSrc ) + { + sDst.erase(); + } + else + { + int nDst = nSrc; + sDst.resize(nDst+1); + PCWSTR szCvt = StdCodeCvt(const_cast(sDst.data()), nDst, pA, + nSrc); + + sDst.resize(sslen(szCvt)); + } +} +inline void ssasn(std::wstring& sDst, const int nNull) +{ + //UNUSED(nNull); + ASSERT(nNull==0); + sDst.assign(L""); +} + +// ----------------------------------------------------------------------------- +// ssadd: string object concatenation -- add second argument to first +// ----------------------------------------------------------------------------- +inline void ssadd(std::string& sDst, const std::wstring& sSrc) +{ + int nSrc = static_cast(sSrc.size()); + + if ( nSrc > 0 ) + { + int nDst = static_cast(sDst.size()); + int nAdd = nSrc; + + // In MBCS builds, pad the buffer to account for the possibility of + // some 3 byte characters. Not perfect but should get most cases. + +#ifdef SS_MBCS + nAdd = static_cast(static_cast(nAdd) * 1.3); + sDst.resize(nDst+nAdd+1); + PCSTR szCvt = StdCodeCvt(const_cast(sDst.data()+nDst), + nAdd, sSrc.c_str(), nSrc); + sDst.resize(nDst + sslen(szCvt)); +#else + sDst.resize(nDst+nAdd+1); + StdCodeCvt(const_cast(sDst.data()+nDst), nAdd, sSrc.c_str(), nSrc); + sDst.resize(nDst + nAdd); +#endif + } +} +template +inline void ssadd(typename std::basic_string& sDst, const typename std::basic_string& sSrc) +{ + sDst += sSrc; +} +inline void ssadd(std::string& sDst, PCWSTR pW) +{ + int nSrc = sslen(pW); + if ( nSrc > 0 ) + { + int nDst = static_cast(sDst.size()); + int nAdd = nSrc; + +#ifdef SS_MBCS + nAdd = static_cast(static_cast(nAdd) * 1.3); + sDst.resize(nDst + nAdd + 1); + PCSTR szCvt = StdCodeCvt(const_cast(sDst.data()+nDst), + nAdd, pW, nSrc); + sDst.resize(nDst + sslen(szCvt)); +#else + sDst.resize(nDst + nAdd + 1); + StdCodeCvt(const_cast(sDst.data()+nDst), nAdd, pW, nSrc); + sDst.resize(nDst + nSrc); +#endif + } +} +template +inline void ssadd(typename std::basic_string& sDst, const T *pA) +{ + if ( pA ) + { + // If the string being added is our internal string or a part of our + // internal string, then we must NOT do any reallocation without + // first copying that string to another object (since we're using a + // direct pointer) + + if ( pA >= sDst.c_str() && pA <= sDst.c_str()+sDst.length()) + { + if ( sDst.capacity() <= sDst.size()+sslen(pA) ) + sDst.append(std::basic_string(pA)); + else + sDst.append(pA); + } + else + { + sDst.append(pA); + } + } +} +inline void ssadd(std::wstring& sDst, const std::string& sSrc) +{ + if ( !sSrc.empty() ) + { + int nSrc = static_cast(sSrc.size()); + int nDst = static_cast(sDst.size()); + + sDst.resize(nDst + nSrc + 1); +#ifdef SS_MBCS + PCWSTR szCvt = StdCodeCvt(const_cast(sDst.data()+nDst), + nSrc, sSrc.c_str(), nSrc+1); + sDst.resize(nDst + sslen(szCvt)); +#else + StdCodeCvt(const_cast(sDst.data()+nDst), nSrc, sSrc.c_str(), nSrc+1); + sDst.resize(nDst + nSrc); +#endif + } +} +inline void ssadd(std::wstring& sDst, PCSTR pA) +{ + int nSrc = sslen(pA); + + if ( nSrc > 0 ) + { + int nDst = static_cast(sDst.size()); + + sDst.resize(nDst + nSrc + 1); +#ifdef SS_MBCS + PCWSTR szCvt = StdCodeCvt(const_cast(sDst.data()+nDst), + nSrc, pA, nSrc+1); + sDst.resize(nDst + sslen(szCvt)); +#else + StdCodeCvt(const_cast(sDst.data()+nDst), nSrc, pA, nSrc+1); + sDst.resize(nDst + nSrc); +#endif + } +} + +// ----------------------------------------------------------------------------- +// sscmp: comparison (case sensitive, not affected by locale) +// ----------------------------------------------------------------------------- +template +inline int sscmp(const CT* pA1, const CT* pA2) +{ + CT f; + CT l; + + do + { + f = *(pA1++); + l = *(pA2++); + } while ( (f) && (f == l) ); + + return (int)(f - l); +} + +// ----------------------------------------------------------------------------- +// ssicmp: comparison (case INsensitive, not affected by locale) +// ----------------------------------------------------------------------------- +template +inline int ssicmp(const CT* pA1, const CT* pA2) +{ + // Using the "C" locale = "not affected by locale" + + std::locale loc = std::locale::classic(); + const std::ctype& ct = SS_USE_FACET(loc, std::ctype); + CT f; + CT l; + + do + { + f = ct.tolower(*(pA1++)); + l = ct.tolower(*(pA2++)); + } while ( (f) && (f == l) ); + + return (int)(f - l); +} + +// ----------------------------------------------------------------------------- +// ssupr/sslwr: Uppercase/Lowercase conversion functions +// ----------------------------------------------------------------------------- + +template +inline void sslwr(CT* pT, size_t nLen, const std::locale& loc=std::locale()) +{ + SS_USE_FACET(loc, std::ctype).tolower(pT, pT+nLen); +} +template +inline void ssupr(CT* pT, size_t nLen, const std::locale& loc=std::locale()) +{ + SS_USE_FACET(loc, std::ctype).toupper(pT, pT+nLen); +} + +// ----------------------------------------------------------------------------- +// vsprintf/vswprintf or _vsnprintf/_vsnwprintf equivalents. In standard +// builds we can't use _vsnprintf/_vsnwsprintf because they're MS extensions. +// +// ----------------------------------------------------------------------------- +// Borland's headers put some ANSI "C" functions in the 'std' namespace. +// Promote them to the global namespace so we can use them here. + +#if defined(__BORLANDC__) + using std::vsprintf; + using std::vswprintf; +#endif + + // GNU is supposed to have vsnprintf and vsnwprintf. But only the newer + // distributions do. + +#if defined(__GNUC__) + + inline int ssvsprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl) + { + return vsnprintf(pA, nCount, pFmtA, vl); + } + inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl) + { + return vswprintf(pW, nCount, pFmtW, vl); + } + + // Microsofties can use +#elif defined(_MSC_VER) && !defined(SS_ANSI) + + inline int ssvsprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl) + { + return _vsnprintf(pA, nCount, pFmtA, vl); + } + inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl) + { + return _vsnwprintf(pW, nCount, pFmtW, vl); + } + +#elif defined (SS_DANGEROUS_FORMAT) // ignore buffer size parameter if needed? + + inline int ssvsprintf(PSTR pA, size_t /*nCount*/, PCSTR pFmtA, va_list vl) + { + return vsprintf(pA, pFmtA, vl); + } + + inline int ssvsprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl) + { + // JMO: Some distributions of the "C" have a version of vswprintf that + // takes 3 arguments (e.g. Microsoft, Borland, GNU). Others have a + // version which takes 4 arguments (an extra "count" argument in the + // second position. The best stab I can take at this so far is that if + // you are NOT running with MS, Borland, or GNU, then I'll assume you + // have the version that takes 4 arguments. + // + // I'm sure that these checks don't catch every platform correctly so if + // you get compiler errors on one of the lines immediately below, it's + // probably because your implemntation takes a different number of + // arguments. You can comment out the offending line (and use the + // alternate version) or you can figure out what compiler flag to check + // and add that preprocessor check in. Regardless, if you get an error + // on these lines, I'd sure like to hear from you about it. + // + // Thanks to Ronny Schulz for the SGI-specific checks here. + +// #if !defined(__MWERKS__) && !defined(__SUNPRO_CC_COMPAT) && !defined(__SUNPRO_CC) + #if !defined(_MSC_VER) \ + && !defined (__BORLANDC__) \ + && !defined(__GNUC__) \ + && !defined(__sgi) + + return vswprintf(pW, nCount, pFmtW, vl); + + // suddenly with the current SGI 7.3 compiler there is no such function as + // vswprintf and the substitute needs explicit casts to compile + + #elif defined(__sgi) + + nCount; + return vsprintf( (char *)pW, (char *)pFmtW, vl); + + #else + + nCount; + return vswprintf(pW, pFmtW, vl); + + #endif + + } + +#endif + + // GOT COMPILER PROBLEMS HERE? + // --------------------------- + // Does your compiler choke on one or more of the following 2 functions? It + // probably means that you don't have have either vsnprintf or vsnwprintf in + // your version of the CRT. This is understandable since neither is an ANSI + // "C" function. However it still leaves you in a dilemma. In order to make + // this code build, you're going to have to to use some non-length-checked + // formatting functions that every CRT has: vsprintf and vswprintf. + // + // This is very dangerous. With the proper erroneous (or malicious) code, it + // can lead to buffer overlows and crashing your PC. Use at your own risk + // In order to use them, just #define SS_DANGEROUS_FORMAT at the top of + // this file. + // + // Even THEN you might not be all the way home due to some non-conforming + // distributions. More on this in the comments below. + + inline int ssnprintf(PSTR pA, size_t nCount, PCSTR pFmtA, va_list vl) + { + #ifdef _MSC_VER + return _vsnprintf(pA, nCount, pFmtA, vl); + #else + return vsnprintf(pA, nCount, pFmtA, vl); + #endif + } + inline int ssnprintf(PWSTR pW, size_t nCount, PCWSTR pFmtW, va_list vl) + { + #ifdef _MSC_VER + return _vsnwprintf(pW, nCount, pFmtW, vl); + #else + return vswprintf(pW, nCount, pFmtW, vl); + #endif + } + + + + +// ----------------------------------------------------------------------------- +// ssload: Type safe, overloaded ::LoadString wrappers +// There is no equivalent of these in non-Win32-specific builds. However, I'm +// thinking that with the message facet, there might eventually be one +// ----------------------------------------------------------------------------- +#if defined (SS_WIN32) && !defined(SS_ANSI) + inline int ssload(HMODULE hInst, UINT uId, PSTR pBuf, int nMax) + { + return ::LoadStringA(hInst, uId, pBuf, nMax); + } + inline int ssload(HMODULE hInst, UINT uId, PWSTR pBuf, int nMax) + { + return ::LoadStringW(hInst, uId, pBuf, nMax); + } +#if defined ( _MSC_VER ) && ( _MSC_VER >= 1500 ) + inline int ssload(HMODULE hInst, UINT uId, uint16_t *pBuf, int nMax) + { + return 0; + } + inline int ssload(HMODULE hInst, UINT uId, uint32_t *pBuf, int nMax) + { + return 0; + } +#endif +#endif + + +// ----------------------------------------------------------------------------- +// sscoll/ssicoll: Collation wrappers +// Note -- with MSVC I have reversed the arguments order here because the +// functions appear to return the opposite of what they should +// ----------------------------------------------------------------------------- +#ifndef SS_NO_LOCALE +template +inline int sscoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2) +{ + const std::collate& coll = + SS_USE_FACET(std::locale(), std::collate); + + return coll.compare(sz2, sz2+nLen2, sz1, sz1+nLen1); +} +template +inline int ssicoll(const CT* sz1, int nLen1, const CT* sz2, int nLen2) +{ + const std::locale loc; + const std::collate& coll = SS_USE_FACET(loc, std::collate); + + // Some implementations seem to have trouble using the collate<> + // facet typedefs so we'll just default to basic_string and hope + // that's what the collate facet uses (which it generally should) + +// std::collate::string_type s1(sz1); +// std::collate::string_type s2(sz2); + const std::basic_string sEmpty; + std::basic_string s1(sz1 ? sz1 : sEmpty.c_str()); + std::basic_string s2(sz2 ? sz2 : sEmpty.c_str()); + + sslwr(const_cast(s1.c_str()), nLen1, loc); + sslwr(const_cast(s2.c_str()), nLen2, loc); + return coll.compare(s2.c_str(), s2.c_str()+nLen2, + s1.c_str(), s1.c_str()+nLen1); +} +#endif + + +// ----------------------------------------------------------------------------- +// ssfmtmsg: FormatMessage equivalents. Needed because I added a CString facade +// Again -- no equivalent of these on non-Win32 builds but their might one day +// be one if the message facet gets implemented +// ----------------------------------------------------------------------------- +#if defined (SS_WIN32) && !defined(SS_ANSI) + inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId, + DWORD dwLangId, PSTR pBuf, DWORD nSize, + va_list* vlArgs) + { + return FormatMessageA(dwFlags, pSrc, dwMsgId, dwLangId, + pBuf, nSize,vlArgs); + } + inline DWORD ssfmtmsg(DWORD dwFlags, LPCVOID pSrc, DWORD dwMsgId, + DWORD dwLangId, PWSTR pBuf, DWORD nSize, + va_list* vlArgs) + { + return FormatMessageW(dwFlags, pSrc, dwMsgId, dwLangId, + pBuf, nSize,vlArgs); + } +#else +#endif + + + +// FUNCTION: sscpy. Copies up to 'nMax' characters from pSrc to pDst. +// ----------------------------------------------------------------------------- +// FUNCTION: sscpy +// inline int sscpy(PSTR pDst, PCSTR pSrc, int nMax=-1); +// inline int sscpy(PUSTR pDst, PCSTR pSrc, int nMax=-1) +// inline int sscpy(PSTR pDst, PCWSTR pSrc, int nMax=-1); +// inline int sscpy(PWSTR pDst, PCWSTR pSrc, int nMax=-1); +// inline int sscpy(PWSTR pDst, PCSTR pSrc, int nMax=-1); +// +// DESCRIPTION: +// This function is very much (but not exactly) like strcpy. These +// overloads simplify copying one C-style string into another by allowing +// the caller to specify two different types of strings if necessary. +// +// The strings must NOT overlap +// +// "Character" is expressed in terms of the destination string, not +// the source. If no 'nMax' argument is supplied, then the number of +// characters copied will be sslen(pSrc). A NULL terminator will +// also be added so pDst must actually be big enough to hold nMax+1 +// characters. The return value is the number of characters copied, +// not including the NULL terminator. +// +// PARAMETERS: +// pSrc - the string to be copied FROM. May be a char based string, an +// MBCS string (in Win32 builds) or a wide string (wchar_t). +// pSrc - the string to be copied TO. Also may be either MBCS or wide +// nMax - the maximum number of characters to be copied into szDest. Note +// that this is expressed in whatever a "character" means to pDst. +// If pDst is a wchar_t type string than this will be the maximum +// number of wchar_ts that my be copied. The pDst string must be +// large enough to hold least nMaxChars+1 characters. +// If the caller supplies no argument for nMax this is a signal to +// the routine to copy all the characters in pSrc, regardless of +// how long it is. +// +// RETURN VALUE: none +// ----------------------------------------------------------------------------- + +template +inline int sscpycvt(CT1* pDst, const CT2* pSrc, int nMax) +{ + // Note -- we assume pDst is big enough to hold pSrc. If not, we're in + // big trouble. No bounds checking. Caveat emptor. + + int nSrc = sslen(pSrc); + + const CT1* szCvt = StdCodeCvt(pDst, nMax, pSrc, nSrc); + + // If we're copying the same size characters, then all the "code convert" + // just did was basically memcpy so the #of characters copied is the same + // as the number requested. I should probably specialize this function + // template to achieve this purpose as it is silly to do a runtime check + // of a fact known at compile time. I'll get around to it. + + return sslen(szCvt); +} + +template +inline int sscpycvt(T* pDst, const T* pSrc, int nMax) +{ + int nCount = nMax; + for (; nCount > 0 && *pSrc; ++pSrc, ++pDst, --nCount) + std::basic_string::traits_type::assign(*pDst, *pSrc); + + *pDst = 0; + return nMax - nCount; +} + +inline int sscpycvt(PWSTR pDst, PCSTR pSrc, int nMax) +{ + // Note -- we assume pDst is big enough to hold pSrc. If not, we're in + // big trouble. No bounds checking. Caveat emptor. + + const PWSTR szCvt = StdCodeCvt(pDst, nMax, pSrc, nMax); + return sslen(szCvt); +} + +template +inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax, int nLen) +{ + return sscpycvt(pDst, pSrc, SSMIN(nMax, nLen)); +} +template +inline int sscpy(CT1* pDst, const CT2* pSrc, int nMax) +{ + return sscpycvt(pDst, pSrc, SSMIN(nMax, sslen(pSrc))); +} +template +inline int sscpy(CT1* pDst, const CT2* pSrc) +{ + return sscpycvt(pDst, pSrc, sslen(pSrc)); +} +template +inline int sscpy(CT1* pDst, const std::basic_string& sSrc, int nMax) +{ + return sscpycvt(pDst, sSrc.c_str(), SSMIN(nMax, (int)sSrc.length())); +} +template +inline int sscpy(CT1* pDst, const std::basic_string& sSrc) +{ + return sscpycvt(pDst, sSrc.c_str(), (int)sSrc.length()); +} + +#ifdef SS_INC_COMDEF + template + inline int sscpy(CT1* pDst, const _bstr_t& bs, int nMax) + { + return sscpycvt(pDst, static_cast(bs), + SSMIN(nMax, static_cast(bs.length()))); + } + template + inline int sscpy(CT1* pDst, const _bstr_t& bs) + { + return sscpy(pDst, bs, static_cast(bs.length())); + } +#endif + + +// ----------------------------------------------------------------------------- +// Functional objects for changing case. They also let you pass locales +// ----------------------------------------------------------------------------- + +#ifdef SS_NO_LOCALE + template + struct SSToUpper : public std::unary_function + { + inline CT operator()(const CT& t) const + { + return sstoupper(t); + } + }; + template + struct SSToLower : public std::unary_function + { + inline CT operator()(const CT& t) const + { + return sstolower(t); + } + }; +#else + template + struct SSToUpper : public std::binary_function + { + inline CT operator()(const CT& t, const std::locale& loc) const + { + return sstoupper(t, loc); + } + }; + template + struct SSToLower : public std::binary_function + { + inline CT operator()(const CT& t, const std::locale& loc) const + { + return sstolower(t, loc); + } + }; +#endif + +// This struct is used for TrimRight() and TrimLeft() function implementations. +//template +//struct NotSpace : public std::unary_function +//{ +// const std::locale& loc; +// inline NotSpace(const std::locale& locArg) : loc(locArg) {} +// inline bool operator() (CT t) { return !std::isspace(t, loc); } +//}; +template +struct NotSpace : public std::unary_function +{ + // DINKUMWARE BUG: + // Note -- using std::isspace in a COM DLL gives us access violations + // because it causes the dynamic addition of a function to be called + // when the library shuts down. Unfortunately the list is maintained + // in DLL memory but the function is in static memory. So the COM DLL + // goes away along with the function that was supposed to be called, + // and then later when the DLL CRT shuts down it unloads the list and + // tries to call the long-gone function. + // This is DinkumWare's implementation problem. If you encounter this + // problem, you may replace the calls here with good old isspace() and + // iswspace() from the CRT unless they specify SS_ANSI + +#ifdef SS_NO_LOCALE + + bool operator() (CT t) const { return !ssisspace(t); } + +#else + const std::locale loc; + NotSpace(const std::locale& locArg=std::locale()) : loc(locArg) {} + bool operator() (CT t) const { return !std::isspace(t, loc); } +#endif +}; + + + + +// Now we can define the template (finally!) +// ============================================================================= +// TEMPLATE: CStdStr +// template class CStdStr : public std::basic_string +// +// REMARKS: +// This template derives from basic_string and adds some MFC CString- +// like functionality +// +// Basically, this is my attempt to make Standard C++ library strings as +// easy to use as the MFC CString class. +// +// Note that although this is a template, it makes the assumption that the +// template argument (CT, the character type) is either char or wchar_t. +// ============================================================================= + +//#define CStdStr _SS // avoid compiler warning 4786 + +// template ARG& FmtArg(ARG& arg) { return arg; } +// PCSTR FmtArg(const std::string& arg) { return arg.c_str(); } +// PCWSTR FmtArg(const std::wstring& arg) { return arg.c_str(); } + +template +struct FmtArg +{ + explicit FmtArg(const ARG& arg) : a_(arg) {} + const ARG& operator()() const { return a_; } + const ARG& a_; +private: + FmtArg& operator=(const FmtArg&) { return *this; } +}; + +template +class CStdStr : public std::basic_string +{ + // Typedefs for shorter names. Using these names also appears to help + // us avoid some ambiguities that otherwise arise on some platforms + + #define MYBASE std::basic_string // my base class + //typedef typename std::basic_string MYBASE; // my base class + typedef CStdStr MYTYPE; // myself + typedef typename MYBASE::const_pointer PCMYSTR; // PCSTR or PCWSTR + typedef typename MYBASE::pointer PMYSTR; // PSTR or PWSTR + typedef typename MYBASE::iterator MYITER; // my iterator type + typedef typename MYBASE::const_iterator MYCITER; // you get the idea... + typedef typename MYBASE::reverse_iterator MYRITER; + typedef typename MYBASE::size_type MYSIZE; + typedef typename MYBASE::value_type MYVAL; + typedef typename MYBASE::allocator_type MYALLOC; + +public: + // shorthand conversion from PCTSTR to string resource ID + #define SSRES(pctstr) LOWORD(reinterpret_cast(pctstr)) + + bool TryLoad(const void* pT) + { + bool bLoaded = false; + +#if defined(SS_WIN32) && !defined(SS_ANSI) + if ( ( pT != NULL ) && SS_IS_INTRESOURCE(pT) ) + { + UINT nId = LOWORD(reinterpret_cast(pT)); + if ( !LoadString(nId) ) + { + TRACE(_T("Can't load string %u\n"), SSRES(pT)); + } + bLoaded = true; + } +#endif + + return bLoaded; + } + + + // CStdStr inline constructors + CStdStr() + { + } + + CStdStr(const MYTYPE& str) : MYBASE(SSREF(str)) + { + } + + CStdStr(const std::string& str) + { + ssasn(*this, SSREF(str)); + } + + CStdStr(const std::wstring& str) + { + ssasn(*this, SSREF(str)); + } + + CStdStr(PCMYSTR pT, MYSIZE n) : MYBASE(pT, n) + { + } + +#ifdef SS_UNSIGNED + CStdStr(PCUSTR pU) + { + *this = reinterpret_cast(pU); + } +#endif + + CStdStr(PCSTR pA) + { + #ifdef SS_ANSI + *this = pA; + #else + if ( !TryLoad(pA) ) + *this = pA; + #endif + } + + CStdStr(PCWSTR pW) + { + #ifdef SS_ANSI + *this = pW; + #else + if ( !TryLoad(pW) ) + *this = pW; + #endif + } + + CStdStr(uint16_t* pW) + { + #ifdef SS_ANSI + *this = pW; + #else + if ( !TryLoad(pW) ) + *this = pW; + #endif + } + + CStdStr(uint32_t* pW) + { + #ifdef SS_ANSI + *this = pW; + #else + if ( !TryLoad(pW) ) + *this = pW; + #endif + } + + CStdStr(MYCITER first, MYCITER last) + : MYBASE(first, last) + { + } + + CStdStr(MYSIZE nSize, MYVAL ch, const MYALLOC& al=MYALLOC()) + : MYBASE(nSize, ch, al) + { + } + + #ifdef SS_INC_COMDEF + CStdStr(const _bstr_t& bstr) + { + if ( bstr.length() > 0 ) + this->append(static_cast(bstr), bstr.length()); + } + #endif + + // CStdStr inline assignment operators -- the ssasn function now takes care + // of fixing the MSVC assignment bug (see knowledge base article Q172398). + MYTYPE& operator=(const MYTYPE& str) + { + ssasn(*this, str); + return *this; + } + + MYTYPE& operator=(const std::string& str) + { + ssasn(*this, str); + return *this; + } + + MYTYPE& operator=(const std::wstring& str) + { + ssasn(*this, str); + return *this; + } + + MYTYPE& operator=(PCSTR pA) + { + ssasn(*this, pA); + return *this; + } + + MYTYPE& operator=(PCWSTR pW) + { + ssasn(*this, pW); + return *this; + } + +#ifdef SS_UNSIGNED + MYTYPE& operator=(PCUSTR pU) + { + ssasn(*this, reinterpret_cast(pU)); + return *this; + } +#endif + + MYTYPE& operator=(uint16_t* pA) + { + ssasn(*this, pA); + return *this; + } + + MYTYPE& operator=(uint32_t* pA) + { + ssasn(*this, pA); + return *this; + } + + MYTYPE& operator=(CT t) + { + Q172398(*this); + this->assign(1, t); + return *this; + } + + #ifdef SS_INC_COMDEF + MYTYPE& operator=(const _bstr_t& bstr) + { + if ( bstr.length() > 0 ) + { + this->assign(static_cast(bstr), bstr.length()); + return *this; + } + else + { + this->erase(); + return *this; + } + } + #endif + + + // Overloads also needed to fix the MSVC assignment bug (KB: Q172398) + // *** Thanks to Pete The Plumber for catching this one *** + // They also are compiled if you have explicitly turned off refcounting + #if ( defined(_MSC_VER) && ( _MSC_VER < 1200 ) ) || defined(SS_NO_REFCOUNT) + + MYTYPE& assign(const MYTYPE& str) + { + Q172398(*this); + sscpy(GetBuffer(str.size()+1), SSREF(str)); + this->ReleaseBuffer(str.size()); + return *this; + } + + MYTYPE& assign(const MYTYPE& str, MYSIZE nStart, MYSIZE nChars) + { + // This overload of basic_string::assign is supposed to assign up to + // or the NULL terminator, whichever comes first. Since we + // are about to call a less forgiving overload (in which + // must be a valid length), we must adjust the length here to a safe + // value. Thanks to Ullrich Poll�hne for catching this bug + + nChars = SSMIN(nChars, str.length() - nStart); + MYTYPE strTemp(str.c_str()+nStart, nChars); + Q172398(*this); + this->assign(strTemp); + return *this; + } + + MYTYPE& assign(const MYBASE& str) + { + ssasn(*this, str); + return *this; + } + + MYTYPE& assign(const MYBASE& str, MYSIZE nStart, MYSIZE nChars) + { + // This overload of basic_string::assign is supposed to assign up to + // or the NULL terminator, whichever comes first. Since we + // are about to call a less forgiving overload (in which + // must be a valid length), we must adjust the length here to a safe + // value. Thanks to Ullrich Poll�hne for catching this bug + + nChars = SSMIN(nChars, str.length() - nStart); + + // Watch out for assignment to self + + if ( this == &str ) + { + MYTYPE strTemp(str.c_str() + nStart, nChars); + static_cast(this)->assign(strTemp); + } + else + { + Q172398(*this); + static_cast(this)->assign(str.c_str()+nStart, nChars); + } + return *this; + } + + MYTYPE& assign(const CT* pC, MYSIZE nChars) + { + // Q172398 only fix -- erase before assigning, but not if we're + // assigning from our own buffer + + #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 ) + if ( !this->empty() && + ( pC < this->data() || pC > this->data() + this->capacity() ) ) + { + this->erase(); + } + #endif + Q172398(*this); + static_cast(this)->assign(pC, nChars); + return *this; + } + + MYTYPE& assign(MYSIZE nChars, MYVAL val) + { + Q172398(*this); + static_cast(this)->assign(nChars, val); + return *this; + } + + MYTYPE& assign(const CT* pT) + { + return this->assign(pT, MYBASE::traits_type::length(pT)); + } + + MYTYPE& assign(MYCITER iterFirst, MYCITER iterLast) + { + #if defined ( _MSC_VER ) && ( _MSC_VER < 1200 ) + // Q172398 fix. don't call erase() if we're assigning from ourself + if ( iterFirst < this->begin() || + iterFirst > this->begin() + this->size() ) + { + this->erase() + } + #endif + this->replace(this->begin(), this->end(), iterFirst, iterLast); + return *this; + } + #endif + + + // ------------------------------------------------------------------------- + // CStdStr inline concatenation. + // ------------------------------------------------------------------------- + MYTYPE& operator+=(const MYTYPE& str) + { + ssadd(*this, str); + return *this; + } + + MYTYPE& operator+=(const std::string& str) + { + ssadd(*this, str); + return *this; + } + + MYTYPE& operator+=(const std::wstring& str) + { + ssadd(*this, str); + return *this; + } + + MYTYPE& operator+=(PCSTR pA) + { + ssadd(*this, pA); + return *this; + } + + MYTYPE& operator+=(PCWSTR pW) + { + ssadd(*this, pW); + return *this; + } + + MYTYPE& operator+=(uint16_t* pW) + { + ssadd(*this, pW); + return *this; + } + + MYTYPE& operator+=(uint32_t* pW) + { + ssadd(*this, pW); + return *this; + } + + MYTYPE& operator+=(CT t) + { + this->append(1, t); + return *this; + } + #ifdef SS_INC_COMDEF // if we have _bstr_t, define a += for it too. + MYTYPE& operator+=(const _bstr_t& bstr) + { + return this->operator+=(static_cast(bstr)); + } + #endif + + + // ------------------------------------------------------------------------- + // Case changing functions + // ------------------------------------------------------------------------- + + MYTYPE& ToUpper(const std::locale& loc=std::locale()) + { + // Note -- if there are any MBCS character sets in which the lowercase + // form a character takes up a different number of bytes than the + // uppercase form, this would probably not work... + + std::transform(this->begin(), + this->end(), + this->begin(), +#ifdef SS_NO_LOCALE + SSToUpper()); +#else + std::bind2nd(SSToUpper(), loc)); +#endif + + // ...but if it were, this would probably work better. Also, this way + // seems to be a bit faster when anything other then the "C" locale is + // used... + +// if ( !empty() ) +// { +// ssupr(this->GetBuf(), this->size(), loc); +// this->RelBuf(); +// } + + return *this; + } + + MYTYPE& ToLower(const std::locale& loc=std::locale()) + { + // Note -- if there are any MBCS character sets in which the lowercase + // form a character takes up a different number of bytes than the + // uppercase form, this would probably not work... + + std::transform(this->begin(), + this->end(), + this->begin(), +#ifdef SS_NO_LOCALE + SSToLower()); +#else + std::bind2nd(SSToLower(), loc)); +#endif + + // ...but if it were, this would probably work better. Also, this way + // seems to be a bit faster when anything other then the "C" locale is + // used... + +// if ( !empty() ) +// { +// sslwr(this->GetBuf(), this->size(), loc); +// this->RelBuf(); +// } + return *this; + } + + + MYTYPE& Normalize() + { + return Trim().ToLower(); + } + + + // ------------------------------------------------------------------------- + // CStdStr -- Direct access to character buffer. In the MS' implementation, + // the at() function that we use here also calls _Freeze() providing us some + // protection from multithreading problems associated with ref-counting. + // In VC 7 and later, of course, the ref-counting stuff is gone. + // ------------------------------------------------------------------------- + + CT* GetBuf(int nMinLen=-1) + { + if ( static_cast(this->size()) < nMinLen ) + this->resize(static_cast(nMinLen)); + + return this->empty() ? const_cast(this->data()) : &(this->at(0)); + } + + CT* SetBuf(int nLen) + { + nLen = ( nLen > 0 ? nLen : 0 ); + if ( this->capacity() < 1 && nLen == 0 ) + this->resize(1); + + this->resize(static_cast(nLen)); + return const_cast(this->data()); + } + void RelBuf(int nNewLen=-1) + { + this->resize(static_cast(nNewLen > -1 ? nNewLen : + sslen(this->c_str()))); + } + + void BufferRel() { RelBuf(); } // backwards compatability + CT* Buffer() { return GetBuf(); } // backwards compatability + CT* BufferSet(int nLen) { return SetBuf(nLen);}// backwards compatability + + bool Equals(const CT* pT, bool bUseCase=false) const + { + return 0 == (bUseCase ? this->compare(pT) : ssicmp(this->c_str(), pT)); + } + + // ------------------------------------------------------------------------- + // FUNCTION: CStdStr::Load + // REMARKS: + // Loads string from resource specified by nID + // + // PARAMETERS: + // nID - resource Identifier. Purely a Win32 thing in this case + // + // RETURN VALUE: + // true if successful, false otherwise + // ------------------------------------------------------------------------- + +#ifndef SS_ANSI + + bool Load(UINT nId, HMODULE hModule=NULL) + { + bool bLoaded = false; // set to true of we succeed. + + #ifdef _MFC_VER // When in Rome (or MFC land)... + + // If they gave a resource handle, use it. Note - this is archaic + // and not really what I would recommend. But then again, in MFC + // land, you ought to be using CString for resources anyway since + // it walks the resource chain for you. + + HMODULE hModuleOld = NULL; + + if ( NULL != hModule ) + { + hModuleOld = AfxGetResourceHandle(); + AfxSetResourceHandle(hModule); + } + + // ...load the string + + CString strRes; + bLoaded = FALSE != strRes.LoadString(nId); + + // ...and if we set the resource handle, restore it. + + if ( NULL != hModuleOld ) + AfxSetResourceHandle(hModule); + + if ( bLoaded ) + *this = strRes; + + #else // otherwise make our own hackneyed version of CString's Load + + // Get the resource name and module handle + + if ( NULL == hModule ) + hModule = GetResourceHandle(); + + PCTSTR szName = MAKEINTRESOURCE((nId>>4)+1); // lifted + DWORD dwSize = 0; + + // No sense continuing if we can't find the resource + + HRSRC hrsrc = ::FindResource(hModule, szName, RT_STRING); + + if ( NULL == hrsrc ) + { + TRACE(_T("Cannot find resource %d: 0x%X"), nId, ::GetLastError()); + } + else if ( 0 == (dwSize = ::SizeofResource(hModule, hrsrc) / sizeof(CT))) + { + TRACE(_T("Cant get size of resource %d 0x%X\n"),nId,GetLastError()); + } + else + { + bLoaded = 0 != ssload(hModule, nId, GetBuf(dwSize), dwSize); + ReleaseBuffer(); + } + + #endif // #ifdef _MFC_VER + + if ( !bLoaded ) + TRACE(_T("String not loaded 0x%X\n"), ::GetLastError()); + + return bLoaded; + } + +#endif // #ifdef SS_ANSI + + // ------------------------------------------------------------------------- + // FUNCTION: CStdStr::Format + // void _cdecl Formst(CStdStringA& PCSTR szFormat, ...) + // void _cdecl Format(PCSTR szFormat); + // + // DESCRIPTION: + // This function does sprintf/wsprintf style formatting on CStdStringA + // objects. It looks a lot like MFC's CString::Format. Some people + // might even call this identical. Fortunately, these people are now + // dead... heh heh. + // + // PARAMETERS: + // nId - ID of string resource holding the format string + // szFormat - a PCSTR holding the format specifiers + // argList - a va_list holding the arguments for the format specifiers. + // + // RETURN VALUE: None. + // ------------------------------------------------------------------------- + // formatting (using wsprintf style formatting) + + // If they want a Format() function that safely handles string objects + // without casting + +#ifdef SS_SAFE_FORMAT + + // Question: Joe, you wacky coder you, why do you have so many overloads + // of the Format() function + // Answer: One reason only - CString compatability. In short, by making + // the Format() function a template this way, I can do strong typing + // and allow people to pass CStdString arguments as fillers for + // "%s" format specifiers without crashing their program! The downside + // is that I need to overload on the number of arguments. If you are + // passing more arguments than I have listed below in any of my + // overloads, just add another one. + // + // Yes, yes, this is really ugly. In essence what I am doing here is + // protecting people from a bad (and incorrect) programming practice + // that they should not be doing anyway. I am protecting them from + // themselves. Why am I doing this? Well, if you had any idea the + // number of times I've been emailed by people about this + // "incompatability" in my code, you wouldn't ask. + + void Fmt(const CT* szFmt, ...) + { + va_list argList; + va_start(argList, szFmt); + FormatV(szFmt, argList); + va_end(argList); + } + +#ifndef SS_ANSI + + void Format(UINT nId) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + this->swap(strFmt); + } + template + void Format(UINT nId, const A1& v) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + Fmt(strFmt, FmtArg(v)()); + } + template + void Format(UINT nId, const A1& v1, const A2& v2) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)()); + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(),FmtArg(v5)(), + FmtArg(v6)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(),FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(),FmtArg(v10)(),FmtArg(v11)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(), FmtArg(v13)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(), FmtArg(v13)(),FmtArg(v14)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15, + const A16& v16) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)(), FmtArg(v16)()); + } + } + template + void Format(UINT nId, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15, + const A16& v16, const A17& v17) + { + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + { + Fmt(strFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)(),FmtArg(v16)(),FmtArg(v17)()); + } + } + +#endif // #ifndef SS_ANSI + + // ...now the other overload of Format: the one that takes a string literal + + void Format(const CT* szFmt) + { + *this = szFmt; + } + template + void Format(const CT* szFmt, const A1& v) + { + Fmt(szFmt, FmtArg(v)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(),FmtArg(v10)(),FmtArg(v11)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(), FmtArg(v13)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(), FmtArg(v13)(),FmtArg(v14)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15, + const A16& v16) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)(), FmtArg(v16)()); + } + template + void Format(const CT* szFmt, const A1& v1, const A2& v2, const A3& v3, + const A4& v4, const A5& v5, const A6& v6, const A7& v7, + const A8& v8, const A9& v9, const A10& v10, const A11& v11, + const A12& v12, const A13& v13, const A14& v14, const A15& v15, + const A16& v16, const A17& v17) + { + Fmt(szFmt, FmtArg(v1)(), FmtArg(v2)(), + FmtArg(v3)(), FmtArg(v4)(), FmtArg(v5)(), + FmtArg(v6)(), FmtArg(v7)(), FmtArg(v8)(), + FmtArg(v9)(), FmtArg(v10)(),FmtArg(v11)(), + FmtArg(v12)(),FmtArg(v13)(),FmtArg(v14)(), + FmtArg(v15)(),FmtArg(v16)(),FmtArg(v17)()); + } + +#else // #ifdef SS_SAFE_FORMAT + + +#ifndef SS_ANSI + + void Format(UINT nId, ...) + { + va_list argList; + va_start(argList, nId); + + MYTYPE strFmt; + if ( strFmt.Load(nId) ) + FormatV(strFmt, argList); + + va_end(argList); + } + +#endif // #ifdef SS_ANSI + + void Format(const CT* szFmt, ...) + { + va_list argList; + va_start(argList, szFmt); + FormatV(szFmt, argList); + va_end(argList); + } + +#endif // #ifdef SS_SAFE_FORMAT + + void AppendFormat(const CT* szFmt, ...) + { + va_list argList; + va_start(argList, szFmt); + AppendFormatV(szFmt, argList); + va_end(argList); + } + + #define MAX_FMT_TRIES 5 // #of times we try + #define FMT_BLOCK_SIZE 2048 // # of bytes to increment per try + #define BUFSIZE_1ST 256 + #define BUFSIZE_2ND 512 + #define STD_BUF_SIZE 1024 + + // an efficient way to add formatted characters to the string. You may only + // add up to STD_BUF_SIZE characters at a time, though + void AppendFormatV(const CT* szFmt, va_list argList) + { + CT szBuf[STD_BUF_SIZE]; + int nLen = ssnprintf(szBuf, STD_BUF_SIZE-1, szFmt, argList); + + if ( 0 < nLen ) + this->append(szBuf, nLen); + } + + // ------------------------------------------------------------------------- + // FUNCTION: FormatV + // void FormatV(PCSTR szFormat, va_list, argList); + // + // DESCRIPTION: + // This function formats the string with sprintf style format-specs. + // It makes a general guess at required buffer size and then tries + // successively larger buffers until it finds one big enough or a + // threshold (MAX_FMT_TRIES) is exceeded. + // + // PARAMETERS: + // szFormat - a PCSTR holding the format of the output + // argList - a Microsoft specific va_list for variable argument lists + // + // RETURN VALUE: + // ------------------------------------------------------------------------- + + // NOTE: Changed by JM to actually function under non-win32, + // and to remove the upper limit on size. + void FormatV(const CT* szFormat, va_list argList) + { + // try and grab a sufficient buffersize + int nChars = FMT_BLOCK_SIZE; + va_list argCopy; + + CT *p = reinterpret_cast(malloc(sizeof(CT)*nChars)); + if (!p) return; + + while (1) + { + va_copy(argCopy, argList); + + int nActual = ssvsprintf(p, nChars, szFormat, argCopy); + /* If that worked, return the string. */ + if (nActual > -1 && nActual < nChars) + { /* make sure it's NULL terminated */ + p[nActual] = '\0'; + this->assign(p, nActual); + free(p); + va_end(argCopy); + return; + } + /* Else try again with more space. */ + if (nActual > -1) /* glibc 2.1 */ + nChars = nActual + 1; /* precisely what is needed */ + else /* glibc 2.0 */ + nChars *= 2; /* twice the old size */ + + CT *np = reinterpret_cast(realloc(p, sizeof(CT)*nChars)); + if (np == NULL) + { + free(p); + va_end(argCopy); + return; // failed :( + } + p = np; + va_end(argCopy); + } + } + + // ------------------------------------------------------------------------- + // CString Facade Functions: + // + // The following methods are intended to allow you to use this class as a + // near drop-in replacement for CString. + // ------------------------------------------------------------------------- + #ifdef SS_WIN32 + BSTR AllocSysString() const + { + ostring os; + ssasn(os, *this); + return ::SysAllocString(os.c_str()); + } + #endif + +#ifndef SS_NO_LOCALE + int Collate(PCMYSTR szThat) const + { + return sscoll(this->c_str(), this->length(), szThat, sslen(szThat)); + } + + int CollateNoCase(PCMYSTR szThat) const + { + return ssicoll(this->c_str(), this->length(), szThat, sslen(szThat)); + } +#endif + int Compare(PCMYSTR szThat) const + { + return this->compare(szThat); + } + + int CompareNoCase(PCMYSTR szThat) const + { + return ssicmp(this->c_str(), szThat); + } + + int Delete(int nIdx, int nCount=1) + { + if ( nIdx < 0 ) + nIdx = 0; + + if ( nIdx < this->GetLength() ) + this->erase(static_cast(nIdx), static_cast(nCount)); + + return GetLength(); + } + + void Empty() + { + this->erase(); + } + + int Find(CT ch) const + { + MYSIZE nIdx = this->find_first_of(ch); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + int Find(PCMYSTR szSub) const + { + MYSIZE nIdx = this->find(szSub); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + int Find(CT ch, int nStart) const + { + // CString::Find docs say add 1 to nStart when it's not zero + // CString::Find code doesn't do that however. We'll stick + // with what the code does + + MYSIZE nIdx = this->find_first_of(ch, static_cast(nStart)); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + int Find(PCMYSTR szSub, int nStart) const + { + // CString::Find docs say add 1 to nStart when it's not zero + // CString::Find code doesn't do that however. We'll stick + // with what the code does + + MYSIZE nIdx = this->find(szSub, static_cast(nStart)); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + int FindOneOf(PCMYSTR szCharSet) const + { + MYSIZE nIdx = this->find_first_of(szCharSet); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + +#ifndef SS_ANSI + void FormatMessage(PCMYSTR szFormat, ...) throw(std::exception) + { + va_list argList; + va_start(argList, szFormat); + PMYSTR szTemp; + if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, + szFormat, 0, 0, + reinterpret_cast(&szTemp), 0, &argList) == 0 || + szTemp == 0 ) + { + throw std::runtime_error("out of memory"); + } + *this = szTemp; + LocalFree(szTemp); + va_end(argList); + } + + void FormatMessage(UINT nFormatId, ...) throw(std::exception) + { + MYTYPE sFormat; + VERIFY(sFormat.LoadString(nFormatId)); + va_list argList; + va_start(argList, nFormatId); + PMYSTR szTemp; + if ( ssfmtmsg(FORMAT_MESSAGE_FROM_STRING|FORMAT_MESSAGE_ALLOCATE_BUFFER, + sFormat, 0, 0, + reinterpret_cast(&szTemp), 0, &argList) == 0 || + szTemp == 0) + { + throw std::runtime_error("out of memory"); + } + *this = szTemp; + LocalFree(szTemp); + va_end(argList); + } +#endif + + // GetAllocLength -- an MSVC7 function but it costs us nothing to add it. + + int GetAllocLength() + { + return static_cast(this->capacity()); + } + + // ------------------------------------------------------------------------- + // GetXXXX -- Direct access to character buffer + // ------------------------------------------------------------------------- + CT GetAt(int nIdx) const + { + return this->at(static_cast(nIdx)); + } + + CT* GetBuffer(int nMinLen=-1) + { + return GetBuf(nMinLen); + } + + CT* GetBufferSetLength(int nLen) + { + return BufferSet(nLen); + } + + // GetLength() -- MFC docs say this is the # of BYTES but + // in truth it is the number of CHARACTERs (chars or wchar_ts) + int GetLength() const + { + return static_cast(this->length()); + } + + int Insert(int nIdx, CT ch) + { + if ( static_cast(nIdx) > this->size()-1 ) + this->append(1, ch); + else + this->insert(static_cast(nIdx), 1, ch); + + return GetLength(); + } + int Insert(int nIdx, PCMYSTR sz) + { + if ( static_cast(nIdx) >= this->size() ) + this->append(sz, static_cast(sslen(sz))); + else + this->insert(static_cast(nIdx), sz); + + return GetLength(); + } + + bool IsEmpty() const + { + return this->empty(); + } + + MYTYPE Left(int nCount) const + { + // Range check the count. + + nCount = SSMAX(0, SSMIN(nCount, static_cast(this->size()))); + return this->substr(0, static_cast(nCount)); + } + +#ifndef SS_ANSI + bool LoadString(UINT nId) + { + return this->Load(nId); + } +#endif + + void MakeLower() + { + ToLower(); + } + + void MakeReverse() + { + std::reverse(this->begin(), this->end()); + } + + void MakeUpper() + { + ToUpper(); + } + + MYTYPE Mid(int nFirst) const + { + return Mid(nFirst, this->GetLength()-nFirst); + } + + MYTYPE Mid(int nFirst, int nCount) const + { + // CString does range checking here. Since we're trying to emulate it, + // we must check too. + + if ( nFirst < 0 ) + nFirst = 0; + if ( nCount < 0 ) + nCount = 0; + + int nSize = static_cast(this->size()); + + if ( nFirst + nCount > nSize ) + nCount = nSize - nFirst; + + if ( nFirst > nSize ) + return MYTYPE(); + + ASSERT(nFirst >= 0); + ASSERT(nFirst + nCount <= nSize); + + return this->substr(static_cast(nFirst), + static_cast(nCount)); + } + + void ReleaseBuffer(int nNewLen=-1) + { + RelBuf(nNewLen); + } + + int Remove(CT ch) + { + MYSIZE nIdx = 0; + int nRemoved = 0; + while ( (nIdx=this->find_first_of(ch)) != MYBASE::npos ) + { + this->erase(nIdx, 1); + nRemoved++; + } + return nRemoved; + } + + int Replace(CT chOld, CT chNew) + { + int nReplaced = 0; + + for ( MYITER iter=this->begin(); iter != this->end(); iter++ ) + { + if ( *iter == chOld ) + { + *iter = chNew; + nReplaced++; + } + } + + return nReplaced; + } + + int Replace(PCMYSTR szOld, PCMYSTR szNew) + { + int nReplaced = 0; + MYSIZE nIdx = 0; + MYSIZE nOldLen = sslen(szOld); + + if ( 0 != nOldLen ) + { + // If the replacement string is longer than the one it replaces, this + // string is going to have to grow in size, Figure out how much + // and grow it all the way now, rather than incrementally + + MYSIZE nNewLen = sslen(szNew); + if ( nNewLen > nOldLen ) + { + int nFound = 0; + while ( nIdx < this->length() && + (nIdx=this->find(szOld, nIdx)) != MYBASE::npos ) + { + nFound++; + nIdx += nOldLen; + } + this->reserve(this->size() + nFound * (nNewLen - nOldLen)); + } + + + static const CT ch = CT(0); + PCMYSTR szRealNew = szNew == 0 ? &ch : szNew; + nIdx = 0; + + while ( nIdx < this->length() && + (nIdx=this->find(szOld, nIdx)) != MYBASE::npos ) + { + this->replace(this->begin()+nIdx, this->begin()+nIdx+nOldLen, + szRealNew); + + nReplaced++; + nIdx += nNewLen; + } + } + + return nReplaced; + } + + int ReverseFind(CT ch) const + { + MYSIZE nIdx = this->find_last_of(ch); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + // ReverseFind overload that's not in CString but might be useful + int ReverseFind(PCMYSTR szFind, MYSIZE pos=MYBASE::npos) const + { + //yuvalt - this does not compile with g++ since MYTTYPE() is different type + //MYSIZE nIdx = this->rfind(0 == szFind ? MYTYPE() : szFind, pos); + MYSIZE nIdx = this->rfind(0 == szFind ? "" : szFind, pos); + return static_cast(MYBASE::npos == nIdx ? -1 : nIdx); + } + + MYTYPE Right(int nCount) const + { + // Range check the count. + + nCount = SSMAX(0, SSMIN(nCount, static_cast(this->size()))); + return this->substr(this->size()-static_cast(nCount)); + } + + void SetAt(int nIndex, CT ch) + { + ASSERT(this->size() > static_cast(nIndex)); + this->at(static_cast(nIndex)) = ch; + } + +#ifndef SS_ANSI + BSTR SetSysString(BSTR* pbstr) const + { + ostring os; + ssasn(os, *this); + if ( !::SysReAllocStringLen(pbstr, os.c_str(), os.length()) ) + throw std::runtime_error("out of memory"); + + ASSERT(*pbstr != 0); + return *pbstr; + } +#endif + + MYTYPE SpanExcluding(PCMYSTR szCharSet) const + { + MYSIZE pos = this->find_first_of(szCharSet); + return pos == MYBASE::npos ? *this : Left(pos); + } + + MYTYPE SpanIncluding(PCMYSTR szCharSet) const + { + MYSIZE pos = this->find_first_not_of(szCharSet); + return pos == MYBASE::npos ? *this : Left(pos); + } + +#if defined SS_WIN32 && !defined(UNICODE) && !defined(SS_ANSI) + + // CString's OemToAnsi and AnsiToOem functions are available only in + // Unicode builds. However since we're a template we also need a + // runtime check of CT and a reinterpret_cast to account for the fact + // that CStdStringW gets instantiated even in non-Unicode builds. + + void AnsiToOem() + { + if ( sizeof(CT) == sizeof(char) && !empty() ) + { + ::CharToOem(reinterpret_cast(this->c_str()), + reinterpret_cast(GetBuf())); + } + else + { + ASSERT(false); + } + } + + void OemToAnsi() + { + if ( sizeof(CT) == sizeof(char) && !empty() ) + { + ::OemToChar(reinterpret_cast(this->c_str()), + reinterpret_cast(GetBuf())); + } + else + { + ASSERT(false); + } + } + +#endif + + + // ------------------------------------------------------------------------- + // Trim and its variants + // ------------------------------------------------------------------------- + MYTYPE& Trim() + { + return TrimLeft().TrimRight(); + } + + MYTYPE& TrimLeft() + { + this->erase(this->begin(), + std::find_if(this->begin(), this->end(), NotSpace())); + + return *this; + } + + MYTYPE& TrimLeft(CT tTrim) + { + this->erase(0, this->find_first_not_of(tTrim)); + return *this; + } + + MYTYPE& TrimLeft(PCMYSTR szTrimChars) + { + this->erase(0, this->find_first_not_of(szTrimChars)); + return *this; + } + + MYTYPE& TrimRight() + { + // NOTE: When comparing reverse_iterators here (MYRITER), I avoid using + // operator!=. This is because namespace rel_ops also has a template + // operator!= which conflicts with the global operator!= already defined + // for reverse_iterator in the header . + // Thanks to John James for alerting me to this. + + MYRITER it = std::find_if(this->rbegin(), this->rend(), NotSpace()); + if ( !(this->rend() == it) ) + this->erase(this->rend() - it); + + this->erase(!(it == this->rend()) ? this->find_last_of(*it) + 1 : 0); + return *this; + } + + MYTYPE& TrimRight(CT tTrim) + { + MYSIZE nIdx = this->find_last_not_of(tTrim); + this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx); + return *this; + } + + MYTYPE& TrimRight(PCMYSTR szTrimChars) + { + MYSIZE nIdx = this->find_last_not_of(szTrimChars); + this->erase(MYBASE::npos == nIdx ? 0 : ++nIdx); + return *this; + } + + void FreeExtra() + { + MYTYPE mt; + this->swap(mt); + if ( !mt.empty() ) + this->assign(mt.c_str(), mt.size()); + } + + // I have intentionally not implemented the following CString + // functions. You cannot make them work without taking advantage + // of implementation specific behavior. However if you absolutely + // MUST have them, uncomment out these lines for "sort-of-like" + // their behavior. You're on your own. + +// CT* LockBuffer() { return GetBuf(); }// won't really lock +// void UnlockBuffer(); { } // why have UnlockBuffer w/o LockBuffer? + + // Array-indexing operators. Required because we defined an implicit cast + // to operator const CT* (Thanks to Julian Selman for pointing this out) + + CT& operator[](int nIdx) + { + return static_cast(this)->operator[](static_cast(nIdx)); + } + + const CT& operator[](int nIdx) const + { + return static_cast(this)->operator[](static_cast(nIdx)); + } + + CT& operator[](unsigned int nIdx) + { + return static_cast(this)->operator[](static_cast(nIdx)); + } + + const CT& operator[](unsigned int nIdx) const + { + return static_cast(this)->operator[](static_cast(nIdx)); + } + + CT& operator[](unsigned long nIdx) + { + return static_cast(this)->operator[](static_cast(nIdx)); + } + + const CT& operator[](unsigned long nIdx) const + { + return static_cast(this)->operator[](static_cast(nIdx)); + } + +#ifndef SS_NO_IMPLICIT_CAST + operator const CT*() const + { + return this->c_str(); + } +#endif + + // IStream related functions. Useful in IPersistStream implementations + +#ifdef SS_INC_COMDEF + + // struct SSSHDR - useful for non Std C++ persistence schemes. + typedef struct SSSHDR + { + BYTE byCtrl; + ULONG nChars; + } SSSHDR; // as in "Standard String Stream Header" + + #define SSSO_UNICODE 0x01 // the string is a wide string + #define SSSO_COMPRESS 0x02 // the string is compressed + + // ------------------------------------------------------------------------- + // FUNCTION: StreamSize + // REMARKS: + // Returns how many bytes it will take to StreamSave() this CStdString + // object to an IStream. + // ------------------------------------------------------------------------- + ULONG StreamSize() const + { + // Control header plus string + ASSERT(this->size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR)); + return (this->size() * sizeof(CT)) + sizeof(SSSHDR); + } + + // ------------------------------------------------------------------------- + // FUNCTION: StreamSave + // REMARKS: + // Saves this CStdString object to a COM IStream. + // ------------------------------------------------------------------------- + HRESULT StreamSave(IStream* pStream) const + { + ASSERT(this->size()*sizeof(CT) < 0xffffffffUL - sizeof(SSSHDR)); + HRESULT hr = E_FAIL; + ASSERT(pStream != 0); + SSSHDR hdr; + hdr.byCtrl = sizeof(CT) == 2 ? SSSO_UNICODE : 0; + hdr.nChars = this->size(); + + + if ( FAILED(hr=pStream->Write(&hdr, sizeof(SSSHDR), 0)) ) + { + TRACE(_T("StreamSave: Cannot write control header, ERR=0x%X\n"),hr); + } + else if ( empty() ) + { + ; // nothing to write + } + else if ( FAILED(hr=pStream->Write(this->c_str(), + this->size()*sizeof(CT), 0)) ) + { + TRACE(_T("StreamSave: Cannot write string to stream 0x%X\n"), hr); + } + + return hr; + } + + + // ------------------------------------------------------------------------- + // FUNCTION: StreamLoad + // REMARKS: + // This method loads the object from an IStream. + // ------------------------------------------------------------------------- + HRESULT StreamLoad(IStream* pStream) + { + ASSERT(pStream != 0); + SSSHDR hdr; + HRESULT hr = E_FAIL; + + if ( FAILED(hr=pStream->Read(&hdr, sizeof(SSSHDR), 0)) ) + { + TRACE(_T("StreamLoad: Cant read control header, ERR=0x%X\n"), hr); + } + else if ( hdr.nChars > 0 ) + { + ULONG nRead = 0; + PMYSTR pMyBuf = BufferSet(hdr.nChars); + + // If our character size matches the character size of the string + // we're trying to read, then we can read it directly into our + // buffer. Otherwise, we have to read into an intermediate buffer + // and convert. + + if ( (hdr.byCtrl & SSSO_UNICODE) != 0 ) + { + ULONG nBytes = hdr.nChars * sizeof(wchar_t); + if ( sizeof(CT) == sizeof(wchar_t) ) + { + if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) ) + TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr); + } + else + { + PWSTR pBufW = reinterpret_cast(_alloca((nBytes)+1)); + if ( FAILED(hr=pStream->Read(pBufW, nBytes, &nRead)) ) + TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr); + else + sscpy(pMyBuf, pBufW, hdr.nChars); + } + } + else + { + ULONG nBytes = hdr.nChars * sizeof(char); + if ( sizeof(CT) == sizeof(char) ) + { + if ( FAILED(hr=pStream->Read(pMyBuf, nBytes, &nRead)) ) + TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr); + } + else + { + PSTR pBufA = reinterpret_cast(_alloca(nBytes)); + if ( FAILED(hr=pStream->Read(pBufA, hdr.nChars, &nRead)) ) + TRACE(_T("StreamLoad: Cannot read string: 0x%X\n"), hr); + else + sscpy(pMyBuf, pBufA, hdr.nChars); + } + } + } + else + { + this->erase(); + } + return hr; + } +#endif // #ifdef SS_INC_COMDEF + +#ifndef SS_ANSI + + // SetResourceHandle/GetResourceHandle. In MFC builds, these map directly + // to AfxSetResourceHandle and AfxGetResourceHandle. In non-MFC builds they + // point to a single static HINST so that those who call the member + // functions that take resource IDs can provide an alternate HINST of a DLL + // to search. This is not exactly the list of HMODULES that MFC provides + // but it's better than nothing. + + #ifdef _MFC_VER + static void SetResourceHandle(HMODULE hNew) + { + AfxSetResourceHandle(hNew); + } + static HMODULE GetResourceHandle() + { + return AfxGetResourceHandle(); + } + #else + static void SetResourceHandle(HMODULE hNew) + { + SSResourceHandle() = hNew; + } + static HMODULE GetResourceHandle() + { + return SSResourceHandle(); + } + #endif + +#endif +}; + +// ----------------------------------------------------------------------------- +// MSVC USERS: HOW TO EXPORT CSTDSTRING FROM A DLL +// +// If you are using MS Visual C++ and you want to export CStdStringA and +// CStdStringW from a DLL, then all you need to +// +// 1. make sure that all components link to the same DLL version +// of the CRT (not the static one). +// 2. Uncomment the 3 lines of code below +// 3. #define 2 macros per the instructions in MS KnowledgeBase +// article Q168958. The macros are: +// +// MACRO DEFINTION WHEN EXPORTING DEFINITION WHEN IMPORTING +// ----- ------------------------ ------------------------- +// SSDLLEXP (nothing, just #define it) extern +// SSDLLSPEC __declspec(dllexport) __declspec(dllimport) +// +// Note that these macros must be available to ALL clients who want to +// link to the DLL and use the class. If they +// +// A word of advice: Don't bother. +// +// Really, it is not necessary to export CStdString functions from a DLL. I +// never do. In my projects, I do generally link to the DLL version of the +// Standard C++ Library, but I do NOT attempt to export CStdString functions. +// I simply include the header where it is needed and allow for the code +// redundancy. +// +// That redundancy is a lot less than you think. This class does most of its +// work via the Standard C++ Library, particularly the base_class basic_string<> +// member functions. Most of the functions here are small enough to be inlined +// anyway. Besides, you'll find that in actual practice you use less than 1/2 +// of the code here, even in big projects and different modules will use as +// little as 10% of it. That means a lot less functions actually get linked +// your binaries. If you export this code from a DLL, it ALL gets linked in. +// +// I've compared the size of the binaries from exporting vs NOT exporting. Take +// my word for it -- exporting this code is not worth the hassle. +// +// ----------------------------------------------------------------------------- +//#pragma warning(disable:4231) // non-standard extension ("extern template") +// SSDLLEXP template class SSDLLSPEC CStdStr; +// SSDLLEXP template class SSDLLSPEC CStdStr; + + +// ============================================================================= +// END OF CStdStr INLINE FUNCTION DEFINITIONS +// ============================================================================= + +// Now typedef our class names based upon this humongous template + +typedef CStdStr CStdStringA; // a better std::string +typedef CStdStr CStdStringW; // a better std::wstring +typedef CStdStr CStdString16; // a 16bit char string +typedef CStdStr CStdString32; // a 32bit char string +typedef CStdStr CStdStringO; // almost always CStdStringW + +// ----------------------------------------------------------------------------- +// CStdStr addition functions defined as inline +// ----------------------------------------------------------------------------- + + +inline CStdStringA operator+(const CStdStringA& s1, const CStdStringA& s2) +{ + CStdStringA sRet(SSREF(s1)); + sRet.append(s2); + return sRet; +} +inline CStdStringA operator+(const CStdStringA& s1, CStdStringA::value_type t) +{ + CStdStringA sRet(SSREF(s1)); + sRet.append(1, t); + return sRet; +} +inline CStdStringA operator+(const CStdStringA& s1, PCSTR pA) +{ + CStdStringA sRet(SSREF(s1)); + sRet.append(pA); + return sRet; +} +inline CStdStringA operator+(PCSTR pA, const CStdStringA& sA) +{ + CStdStringA sRet; + CStdStringA::size_type nObjSize = sA.size(); + CStdStringA::size_type nLitSize = + static_cast(sslen(pA)); + + sRet.reserve(nLitSize + nObjSize); + sRet.assign(pA); + sRet.append(sA); + return sRet; +} + + +inline CStdStringA operator+(const CStdStringA& s1, const CStdStringW& s2) +{ + return s1 + CStdStringA(s2); +} +inline CStdStringW operator+(const CStdStringW& s1, const CStdStringW& s2) +{ + CStdStringW sRet(SSREF(s1)); + sRet.append(s2); + return sRet; +} +inline CStdStringA operator+(const CStdStringA& s1, PCWSTR pW) +{ + return s1 + CStdStringA(pW); +} + +#ifdef UNICODE + inline CStdStringW operator+(PCWSTR pW, const CStdStringA& sA) + { + return CStdStringW(pW) + CStdStringW(SSREF(sA)); + } + inline CStdStringW operator+(PCSTR pA, const CStdStringW& sW) + { + return CStdStringW(pA) + sW; + } +#else + inline CStdStringA operator+(PCWSTR pW, const CStdStringA& sA) + { + return CStdStringA(pW) + sA; + } + inline CStdStringA operator+(PCSTR pA, const CStdStringW& sW) + { + return pA + CStdStringA(sW); + } +#endif + +// ...Now the wide string versions. +inline CStdStringW operator+(const CStdStringW& s1, CStdStringW::value_type t) +{ + CStdStringW sRet(SSREF(s1)); + sRet.append(1, t); + return sRet; +} +inline CStdStringW operator+(const CStdStringW& s1, PCWSTR pW) +{ + CStdStringW sRet(SSREF(s1)); + sRet.append(pW); + return sRet; +} +inline CStdStringW operator+(PCWSTR pW, const CStdStringW& sW) +{ + CStdStringW sRet; + CStdStringW::size_type nObjSize = sW.size(); + CStdStringA::size_type nLitSize = + static_cast(sslen(pW)); + + sRet.reserve(nLitSize + nObjSize); + sRet.assign(pW); + sRet.append(sW); + return sRet; +} + +inline CStdStringW operator+(const CStdStringW& s1, const CStdStringA& s2) +{ + return s1 + CStdStringW(s2); +} +inline CStdStringW operator+(const CStdStringW& s1, PCSTR pA) +{ + return s1 + CStdStringW(pA); +} + + +// New-style format function is a template + +#ifdef SS_SAFE_FORMAT + +template<> +struct FmtArg +{ + explicit FmtArg(const CStdStringA& arg) : a_(arg) {} + PCSTR operator()() const { return a_.c_str(); } + const CStdStringA& a_; +private: + FmtArg& operator=(const FmtArg&) { return *this; } +}; +template<> +struct FmtArg +{ + explicit FmtArg(const CStdStringW& arg) : a_(arg) {} + PCWSTR operator()() const { return a_.c_str(); } + const CStdStringW& a_; +private: + FmtArg& operator=(const FmtArg&) { return *this; } +}; + +template<> +struct FmtArg +{ + explicit FmtArg(const std::string& arg) : a_(arg) {} + PCSTR operator()() const { return a_.c_str(); } + const std::string& a_; +private: + FmtArg& operator=(const FmtArg&) { return *this; } +}; +template<> +struct FmtArg +{ + explicit FmtArg(const std::wstring& arg) : a_(arg) {} + PCWSTR operator()() const { return a_.c_str(); } + const std::wstring& a_; +private: + FmtArg& operator=(const FmtArg&) {return *this;} +}; +#endif // #ifdef SS_SAFEFORMAT + +#ifndef SS_ANSI + // SSResourceHandle: our MFC-like resource handle + inline HMODULE& SSResourceHandle() + { + static HMODULE hModuleSS = GetModuleHandle(0); + return hModuleSS; + } +#endif + + +// In MFC builds, define some global serialization operators +// Special operators that allow us to serialize CStdStrings to CArchives. +// Note that we use an intermediate CString object in order to ensure that +// we use the exact same format. + +#ifdef _MFC_VER + inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringA& strA) + { + CString strTemp = strA; + return ar << strTemp; + } + inline CArchive& AFXAPI operator<<(CArchive& ar, const CStdStringW& strW) + { + CString strTemp = strW; + return ar << strTemp; + } + + inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringA& strA) + { + CString strTemp; + ar >> strTemp; + strA = strTemp; + return ar; + } + inline CArchive& AFXAPI operator>>(CArchive& ar, CStdStringW& strW) + { + CString strTemp; + ar >> strTemp; + strW = strTemp; + return ar; + } +#endif // #ifdef _MFC_VER -- (i.e. is this MFC?) + + + +// ----------------------------------------------------------------------------- +// GLOBAL FUNCTION: WUFormat +// CStdStringA WUFormat(UINT nId, ...); +// CStdStringA WUFormat(PCSTR szFormat, ...); +// +// REMARKS: +// This function allows the caller for format and return a CStdStringA +// object with a single line of code. +// ----------------------------------------------------------------------------- +#ifdef SS_ANSI +#else + inline CStdStringA WUFormatA(UINT nId, ...) + { + va_list argList; + va_start(argList, nId); + + CStdStringA strFmt; + CStdStringA strOut; + if ( strFmt.Load(nId) ) + strOut.FormatV(strFmt, argList); + + va_end(argList); + return strOut; + } + inline CStdStringA WUFormatA(PCSTR szFormat, ...) + { + va_list argList; + va_start(argList, szFormat); + CStdStringA strOut; + strOut.FormatV(szFormat, argList); + va_end(argList); + return strOut; + } + inline CStdStringW WUFormatW(UINT nId, ...) + { + va_list argList; + va_start(argList, nId); + + CStdStringW strFmt; + CStdStringW strOut; + if ( strFmt.Load(nId) ) + strOut.FormatV(strFmt, argList); + + va_end(argList); + return strOut; + } + inline CStdStringW WUFormatW(PCWSTR szwFormat, ...) + { + va_list argList; + va_start(argList, szwFormat); + CStdStringW strOut; + strOut.FormatV(szwFormat, argList); + va_end(argList); + return strOut; + } +#endif // #ifdef SS_ANSI + + + +#if defined(SS_WIN32) && !defined (SS_ANSI) + // ------------------------------------------------------------------------- + // FUNCTION: WUSysMessage + // CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID); + // CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID); + // + // DESCRIPTION: + // This function simplifies the process of obtaining a string equivalent + // of a system error code returned from GetLastError(). You simply + // supply the value returned by GetLastError() to this function and the + // corresponding system string is returned in the form of a CStdStringA. + // + // PARAMETERS: + // dwError - a DWORD value representing the error code to be translated + // dwLangId - the language id to use. defaults to english. + // + // RETURN VALUE: + // a CStdStringA equivalent of the error code. Currently, this function + // only returns either English of the system default language strings. + // ------------------------------------------------------------------------- + #define SS_DEFLANGID MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT) + inline CStdStringA WUSysMessageA(DWORD dwError, DWORD dwLangId=SS_DEFLANGID) + { + CHAR szBuf[512]; + + if ( 0 != ::FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, + dwLangId, szBuf, 511, NULL) ) + return WUFormatA("%s (0x%X)", szBuf, dwError); + else + return WUFormatA("Unknown error (0x%X)", dwError); + } + inline CStdStringW WUSysMessageW(DWORD dwError, DWORD dwLangId=SS_DEFLANGID) + { + WCHAR szBuf[512]; + + if ( 0 != ::FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwError, + dwLangId, szBuf, 511, NULL) ) + return WUFormatW(L"%s (0x%X)", szBuf, dwError); + else + return WUFormatW(L"Unknown error (0x%X)", dwError); + } +#endif + +// Define TCHAR based friendly names for some of these functions + +#ifdef UNICODE + //#define CStdString CStdStringW + typedef CStdStringW CStdString; + #define WUSysMessage WUSysMessageW + #define WUFormat WUFormatW +#else + //#define CStdString CStdStringA + typedef CStdStringA CStdString; + #define WUSysMessage WUSysMessageA + #define WUFormat WUFormatA +#endif + +// ...and some shorter names for the space-efficient + +#define WUSysMsg WUSysMessage +#define WUSysMsgA WUSysMessageA +#define WUSysMsgW WUSysMessageW +#define WUFmtA WUFormatA +#define WUFmtW WUFormatW +#define WUFmt WUFormat +#define WULastErrMsg() WUSysMessage(::GetLastError()) +#define WULastErrMsgA() WUSysMessageA(::GetLastError()) +#define WULastErrMsgW() WUSysMessageW(::GetLastError()) + + +// ----------------------------------------------------------------------------- +// FUNCTIONAL COMPARATORS: +// REMARKS: +// These structs are derived from the std::binary_function template. They +// give us functional classes (which may be used in Standard C++ Library +// collections and algorithms) that perform case-insensitive comparisons of +// CStdString objects. This is useful for maps in which the key may be the +// proper string but in the wrong case. +// ----------------------------------------------------------------------------- +#define StdStringLessNoCaseW SSLNCW // avoid VC compiler warning 4786 +#define StdStringEqualsNoCaseW SSENCW +#define StdStringLessNoCaseA SSLNCA +#define StdStringEqualsNoCaseA SSENCA + +#ifdef UNICODE + #define StdStringLessNoCase SSLNCW + #define StdStringEqualsNoCase SSENCW +#else + #define StdStringLessNoCase SSLNCA + #define StdStringEqualsNoCase SSENCA +#endif + +struct StdStringLessNoCaseW + : std::binary_function +{ + inline + bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const + { return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; } +}; +struct StdStringEqualsNoCaseW + : std::binary_function +{ + inline + bool operator()(const CStdStringW& sLeft, const CStdStringW& sRight) const + { return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; } +}; +struct StdStringLessNoCaseA + : std::binary_function +{ + inline + bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const + { return ssicmp(sLeft.c_str(), sRight.c_str()) < 0; } +}; +struct StdStringEqualsNoCaseA + : std::binary_function +{ + inline + bool operator()(const CStdStringA& sLeft, const CStdStringA& sRight) const + { return ssicmp(sLeft.c_str(), sRight.c_str()) == 0; } +}; + +// If we had to define our own version of TRACE above, get rid of it now + +#ifdef TRACE_DEFINED_HERE + #undef TRACE + #undef TRACE_DEFINED_HERE +#endif + + +// These std::swap specializations come courtesy of Mike Crusader. + +//namespace std +//{ +// inline void swap(CStdStringA& s1, CStdStringA& s2) throw() +// { +// s1.swap(s2); +// } +// template<> +// inline void swap(CStdStringW& s1, CStdStringW& s2) throw() +// { +// s1.swap(s2); +// } +//} + +// Turn back on any Borland warnings we turned off. + +#ifdef __BORLANDC__ + #pragma option pop // Turn back on inline function warnings +// #pragma warn +inl // Turn back on inline function warnings +#endif + +typedef std::vector CStdStringArray; + +#endif // #ifndef STDSTRING_H diff --git a/lib/platform/util/baudrate.h b/lib/platform/util/baudrate.h new file mode 100644 index 0000000..1411452 --- /dev/null +++ b/lib/platform/util/baudrate.h @@ -0,0 +1,211 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +//every baudrate I could find is in here in an #ifdef block +//so it should compile on everything + +#ifndef __WINDOWS__ +#include +#endif + +namespace PLATFORM +{ + static struct sbaudrate + { + int32_t rate; + int32_t symbol; + } + + baudrates[] = + { + #ifdef B50 + { 50, B50 }, + #endif + #ifdef B75 + { 75, B75 }, + #endif + #ifdef B110 + { 110, B110 }, + #endif + #ifdef B134 + { 134, B134 }, + #endif + #ifdef B150 + { 150, B150 }, + #endif + #ifdef B200 + { 200, B200 }, + #endif + #ifdef B300 + { 300, B300 }, + #endif + #ifdef B600 + { 600, B600 }, + #endif + #ifdef B1200 + { 1200, B1200 }, + #endif + #ifdef B1800 + { 1800, B1800 }, + #endif + #ifdef B2400 + { 2400, B2400 }, + #endif + #ifdef B4800 + { 4800, B4800 }, + #endif + #ifdef B9600 + { 9600, B9600 }, + #endif + #ifdef B14400 + { 14400, B14400 }, + #endif + #ifdef B19200 + { 19200, B19200 }, + #endif + #ifdef B28800 + { 28800, B28800 }, + #endif + #ifdef B38400 + { 38400, B38400 }, + #endif + #ifdef B57600 + { 57600, B57600 }, + #endif + #ifdef B76800 + { 76800, B76800 }, + #endif + #ifdef B115200 + { 115200, B115200 }, + #endif + #ifdef B230400 + { 230400, B230400 }, + #endif + #ifdef B250000 + { 250000, B250000 }, + #endif + #ifdef B460800 + { 460800, B460800 }, + #endif + #ifdef B500000 + { 500000, B500000 }, + #endif + #ifdef B576000 + { 576000, B576000 }, + #endif + #ifdef B921600 + { 921600, B921600 }, + #endif + #ifdef B1000000 + { 1000000, B1000000 }, + #endif + #ifdef B1152000 + { 1152000, B1152000 }, + #endif + #ifdef B1500000 + { 1500000, B1500000 }, + #endif + #ifdef B2000000 + { 2000000, B2000000 }, + #endif + #ifdef B2500000 + { 2500000, B2500000 }, + #endif + #ifdef B3000000 + { 3000000, B3000000 }, + #endif + #ifdef B3500000 + { 3500000, B3500000 }, + #endif + #ifdef B4000000 + { 4000000, B4000000 }, + #endif + #ifdef CBR_110 + { 110, CBR_110 }, + #endif + #ifdef CBR_300 + { 300, CBR_300 }, + #endif + #ifdef CBR_600 + { 600, CBR_600 }, + #endif + #ifdef CBR_1200 + { 1200, CBR_1200 }, + #endif + #ifdef CBR_2400 + { 2400, CBR_2400 }, + #endif + #ifdef CBR_4800 + { 4800, CBR_4800 }, + #endif + #ifdef CBR_9600 + { 9600, CBR_9600 }, + #endif + #ifdef CBR_11400 + { 11400, CBR_14400 }, + #endif + #ifdef CBR_19200 + { 19200, CBR_19200 }, + #endif + #ifdef CBR_38400 + { 38400, CBR_38400 }, + #endif + #ifdef CBR_56000 + { 56000, CBR_56000 }, + #endif + #ifdef CBR_57600 + { 57600, CBR_57600 }, + #endif + #ifdef CBR_115200 + { 115200, CBR_115200 }, + #endif + #ifdef CBR_128000 + { 128000, CBR_128000 }, + #endif + #ifdef CBR_256000 + { 256000, CBR_256000 }, + #endif + { -1, -1} + }; + + inline int32_t IntToBaudrate(uint32_t baudrate) + { + for (unsigned int i = 0; i < sizeof(baudrates) / sizeof(PLATFORM::sbaudrate) - 1; i++) + { + if (baudrates[i].rate == (int32_t) baudrate) + return baudrates[i].symbol; + } + + return -1; + }; +}; diff --git a/lib/platform/util/buffer.h b/lib/platform/util/buffer.h new file mode 100644 index 0000000..56ffd64 --- /dev/null +++ b/lib/platform/util/buffer.h @@ -0,0 +1,98 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "../threads/mutex.h" +#include + +namespace PLATFORM +{ + template + struct SyncedBuffer + { + public: + SyncedBuffer(size_t iMaxSize = 100) : + m_maxSize(iMaxSize) {} + + virtual ~SyncedBuffer(void) + { + Clear(); + } + + void Clear(void) + { + CLockObject lock(m_mutex); + while (!m_buffer.empty()) + m_buffer.pop(); + } + + size_t Size(void) + { + CLockObject lock(m_mutex); + return m_buffer.size(); + } + + bool IsEmpty(void) + { + CLockObject lock(m_mutex); + return m_buffer.empty(); + } + + bool Push(_BType entry) + { + CLockObject lock(m_mutex); + if (m_buffer.size() == m_maxSize) + return false; + + m_buffer.push(entry); + return true; + } + + bool Pop(_BType &entry) + { + bool bReturn(false); + CLockObject lock(m_mutex); + if (!m_buffer.empty()) + { + entry = m_buffer.front(); + m_buffer.pop(); + bReturn = true; + } + return bReturn; + } + + private: + size_t m_maxSize; + std::queue<_BType> m_buffer; + CMutex m_mutex; + }; +}; diff --git a/lib/platform/util/timeutils.h b/lib/platform/util/timeutils.h new file mode 100644 index 0000000..5f2d27a --- /dev/null +++ b/lib/platform/util/timeutils.h @@ -0,0 +1,122 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "../os.h" + +#if defined(__APPLE__) +#include +#include +#elif defined(__WINDOWS__) +#include +#else +#include +#endif + +namespace PLATFORM +{ + #if defined(__WINDOWS__) + struct timezone + { + int tz_minuteswest; + int tz_dsttime; + }; + + #define usleep(t) Sleep((DWORD)(t)/1000) + + inline int gettimeofday(struct timeval *pcur_time, struct timezone *tz) + { + if (pcur_time == NULL) + { + SetLastError(EFAULT); + return -1; + } + struct _timeb current; + + _ftime(¤t); + + pcur_time->tv_sec = (long) current.time; + pcur_time->tv_usec = current.millitm * 1000L; + if (tz) + { + tz->tz_minuteswest = current.timezone; /* minutes west of Greenwich */ + tz->tz_dsttime = current.dstflag; /* type of dst correction */ + } + return 0; + } + #endif + + inline int64_t GetTimeMs() + { + #if defined(__APPLE__) + return (int64_t) (CVGetCurrentHostTime() / (int64_t)(CVGetHostClockFrequency() * 0.001)); + #elif defined(__WINDOWS__) + LARGE_INTEGER tickPerSecond; + LARGE_INTEGER tick; + if (QueryPerformanceFrequency(&tickPerSecond)) + { + QueryPerformanceCounter(&tick); + return (int64_t) (tick.QuadPart / (tickPerSecond.QuadPart / 1000.)); + } + return -1; + #else + timespec time; + clock_gettime(CLOCK_MONOTONIC, &time); + return (int64_t)time.tv_sec * 1000 + time.tv_nsec / 1000000; + #endif + } + + template + inline T GetTimeSec() + { + return (T)GetTimeMs() / (T)1000.0; + } + + class CTimeout + { + public: + CTimeout(void) : m_iTarget(0) {} + CTimeout(uint32_t iTimeout) { Init(iTimeout); } + + bool IsSet(void) const { return m_iTarget > 0; } + void Init(uint32_t iTimeout) { m_iTarget = GetTimeMs() + iTimeout; } + + uint32_t TimeLeft(void) const + { + uint64_t iNow = GetTimeMs(); + return (iNow > m_iTarget) ? 0 : (uint32_t)(m_iTarget - iNow); + } + + private: + uint64_t m_iTarget; + }; +}; diff --git a/lib/platform/windows/dlfcn-win32.cpp b/lib/platform/windows/dlfcn-win32.cpp new file mode 100644 index 0000000..5839921 --- /dev/null +++ b/lib/platform/windows/dlfcn-win32.cpp @@ -0,0 +1,263 @@ +/* + * dlfcn-win32 + * Copyright (c) 2007 Ramiro Polla + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include +#include + +#include "dlfcn-win32.h" + +/* Note: + * MSDN says these functions are not thread-safe. We make no efforts to have + * any kind of thread safety. + */ + +/* I have no special reason to have set MAX_GLOBAL_OBJECTS to this value. Any + * comments are welcome. + */ +#define MAX_OBJECTS 255 + +static HMODULE global_objects[MAX_OBJECTS]; + +/* This function adds an object to the list of global objects. + * The implementation is very simple and slow. + * TODO: should failing this function be enough to fail the call to dlopen( )? + */ +static void global_object_add( HMODULE hModule ) +{ + int i; + + for( i = 0 ; i < MAX_OBJECTS ; i++ ) + { + if( !global_objects[i] ) + { + global_objects[i] = hModule; + break; + } + } +} + +static void global_object_rem( HMODULE hModule ) +{ + int i; + + for( i = 0 ; i < MAX_OBJECTS ; i++ ) + { + if( global_objects[i] == hModule ) + { + global_objects[i] = 0; + break; + } + } +} + +/* Argument to last function. Used in dlerror( ) */ +static char last_name[MAX_PATH]; + +static int copy_string( char *dest, int dest_size, const char *src ) +{ + int i = 0; + + if( src && dest ) + { + for( i = 0 ; i < dest_size-1 ; i++ ) + { + if( !src[i] ) + break; + else + dest[i] = src[i]; + } + } + dest[i] = '\0'; + + return i; +} + +void *dlopen( const char *file, int mode ) +{ + HMODULE hModule; + UINT uMode; + + /* Do not let Windows display the critical-error-handler message box */ + uMode = SetErrorMode( SEM_FAILCRITICALERRORS ); + + if( file == 0 ) + { + /* Save NULL pointer for error message */ + _snprintf_s( last_name, MAX_PATH, MAX_PATH, "0x%p", file ); + + /* POSIX says that if the value of file is 0, a handle on a global + * symbol object must be provided. That object must be able to access + * all symbols from the original program file, and any objects loaded + * with the RTLD_GLOBAL flag. + * The return value from GetModuleHandle( ) allows us to retrieve + * symbols only from the original program file. For objects loaded with + * the RTLD_GLOBAL flag, we create our own list later on. + */ + hModule = GetModuleHandle( NULL ); + } + else + { + char lpFileName[MAX_PATH]; + int i; + + /* MSDN says backslashes *must* be used instead of forward slashes. */ + for( i = 0 ; i < sizeof(lpFileName)-1 ; i++ ) + { + if( !file[i] ) + break; + else if( file[i] == '/' ) + lpFileName[i] = '\\'; + else + lpFileName[i] = file[i]; + } + lpFileName[i] = '\0'; + + /* Save file name for error message */ + copy_string( last_name, sizeof(last_name), lpFileName ); + + /* POSIX says the search path is implementation-defined. + * LOAD_WITH_ALTERED_SEARCH_PATH is used to make it behave more closely + * to UNIX's search paths (start with system folders instead of current + * folder). + */ + hModule = LoadLibraryEx( (LPSTR) lpFileName, NULL, + LOAD_WITH_ALTERED_SEARCH_PATH ); + /* If the object was loaded with RTLD_GLOBAL, add it to list of global + * objects, so that its symbols may be retrieved even if the handle for + * the original program file is passed. POSIX says that if the same + * file is specified in multiple invocations, and any of them are + * RTLD_GLOBAL, even if any further invocations use RTLD_LOCAL, the + * symbols will remain global. + */ + + if( hModule && (mode & RTLD_GLOBAL) ) + global_object_add( hModule ); + } + + /* Return to previous state of the error-mode bit flags. */ + SetErrorMode( uMode ); + + return (void *) hModule; +} + +int dlclose( void *handle ) +{ + HMODULE hModule = (HMODULE) handle; + BOOL ret; + + /* Save handle for error message */ + _snprintf_s( last_name, MAX_PATH, MAX_PATH, "0x%p", handle ); + + ret = FreeLibrary( hModule ); + + /* If the object was loaded with RTLD_GLOBAL, remove it from list of global + * objects. + */ + if( ret ) + global_object_rem( hModule ); + + /* dlclose's return value in inverted in relation to FreeLibrary's. */ + ret = !ret; + + return (int) ret; +} + +void *dlsym( void *handle, const char *name ) +{ + FARPROC symbol; + HMODULE myhandle = (HMODULE) handle; + + /* Save symbol name for error message */ + copy_string( last_name, sizeof(last_name), name ); + + symbol = GetProcAddress( myhandle, name ); +#if 0 + if( symbol == NULL ) + { + HMODULE hModule; + + /* If the handle for the original program file is passed, also search + * in all globally loaded objects. + */ + + hModule = GetModuleHandle( NULL ); + + if( hModule == handle ) + { + int i; + + for( i = 0 ; i < MAX_OBJECTS ; i++ ) + { + if( global_objects[i] != 0 ) + { + symbol = GetProcAddress( global_objects[i], name ); + if( symbol != NULL ) + break; + } + } + } + + + CloseHandle( hModule ); + } +#endif + return (void*) symbol; +} + +char *dlerror( void ) +{ + DWORD dwMessageId; + /* POSIX says this function doesn't have to be thread-safe, so we use one + * static buffer. + * MSDN says the buffer cannot be larger than 64K bytes, so we set it to + * the limit. + */ + static char lpBuffer[65535]; + DWORD ret; + + dwMessageId = GetLastError( ); + + if( dwMessageId == 0 ) + return NULL; + + /* Format error message to: + * "": + */ + ret = copy_string( lpBuffer, sizeof(lpBuffer), "\"" ); + ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, last_name ); + ret += copy_string( lpBuffer+ret, sizeof(lpBuffer)-ret, "\": " ); + ret += FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM, NULL, dwMessageId, + MAKELANGID( LANG_NEUTRAL, SUBLANG_DEFAULT ), + lpBuffer+ret, sizeof(lpBuffer)-ret, NULL ); + + if( ret > 1 ) + { + /* POSIX says the string must not have trailing */ + if( lpBuffer[ret-2] == '\r' && lpBuffer[ret-1] == '\n' ) + lpBuffer[ret-2] = '\0'; + } + + /* POSIX says that invoking dlerror( ) a second time, immediately following + * a prior invocation, shall result in NULL being returned. + */ + SetLastError(0); + + return lpBuffer; +} + diff --git a/lib/platform/windows/dlfcn-win32.h b/lib/platform/windows/dlfcn-win32.h new file mode 100644 index 0000000..b93a029 --- /dev/null +++ b/lib/platform/windows/dlfcn-win32.h @@ -0,0 +1,46 @@ +#pragma once +/* + * dlfcn-win32 + * Copyright (c) 2007 Ramiro Polla + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef DLFCN_H +#define DLFCN_H + +/* POSIX says these are implementation-defined. + * To simplify use with Windows API, we treat them the same way. + */ + +#define RTLD_LAZY 0 +#define RTLD_NOW 0 + +#define RTLD_GLOBAL (1 << 1) +#define RTLD_LOCAL (1 << 2) + +/* These two were added in The Open Group Base Specifications Issue 6. + * Note: All other RTLD_* flags in any dlfcn.h are not standard compliant. + */ + +#define RTLD_DEFAULT 0 +#define RTLD_NEXT 0 + +void *dlopen ( const char *file, int mode ); +int dlclose( void *handle ); +void *dlsym ( void *handle, const char *name ); +char *dlerror( void ); + +#endif /* DLFCN-WIN32_H */ diff --git a/lib/platform/windows/os-socket.h b/lib/platform/windows/os-socket.h new file mode 100644 index 0000000..5174cba --- /dev/null +++ b/lib/platform/windows/os-socket.h @@ -0,0 +1,297 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "../os.h" +#include "../util/timeutils.h" + +#include +#include +#include + +#define SHUT_RDWR SD_BOTH + +#ifndef ETIMEDOUT +#define ETIMEDOUT 138 +#endif + +namespace PLATFORM +{ + #ifndef MSG_WAITALL + #define MSG_WAITALL 0x8 + #endif + + inline int GetSocketError(void) + { + int error = WSAGetLastError(); + switch(error) + { + case WSAEINPROGRESS: return EINPROGRESS; + case WSAECONNRESET : return ECONNRESET; + case WSAETIMEDOUT : return ETIMEDOUT; + case WSAEWOULDBLOCK: return EAGAIN; + default : return error; + } + } + + // Serial port + //@{ + inline void SerialSocketClose(serial_socket_t socket) + { + if (socket != INVALID_HANDLE_VALUE) + CloseHandle(socket); + } + + inline ssize_t SerialSocketWrite(serial_socket_t socket, int *iError, void* data, size_t len) + { + if (len != (DWORD)len) + { + *iError = EINVAL; + return -1; + } + + DWORD iBytesWritten(0); + if (socket != INVALID_HANDLE_VALUE) + { + if (!WriteFile(socket, data, (DWORD)len, &iBytesWritten, NULL)) + { + *iError = GetLastError(); + return -1; + } + return (ssize_t)iBytesWritten; + } + + return -1; + } + + inline ssize_t SerialSocketRead(serial_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/) + { + if (len != (DWORD)len) + { + *iError = EINVAL; + return -1; + } + + DWORD iBytesRead(0); + if (socket != INVALID_HANDLE_VALUE) + { + if(!ReadFile(socket, data, (DWORD)len, &iBytesRead, NULL) != 0) + { + *iError = GetLastError(); + return -1; + } + return (ssize_t)iBytesRead; + } + return -1; + } + //@} + + // TCP + //@{ + inline void TcpSocketSetBlocking(tcp_socket_t socket, bool bSetTo) + { + u_long iSetTo = bSetTo ? 0 : 1; + ioctlsocket(socket, FIONBIO, &iSetTo); + } + + inline void TcpSocketClose(tcp_socket_t socket) + { + closesocket(socket); + } + + inline void TcpSocketShutdown(tcp_socket_t socket) + { + if (socket != INVALID_SOCKET && + socket != SOCKET_ERROR) + shutdown(socket, SHUT_RDWR); + } + + inline ssize_t TcpSocketWrite(tcp_socket_t socket, int *iError, void* data, size_t len) + { + if (socket == INVALID_SOCKET || + socket == SOCKET_ERROR || + len != (int)len) + { + *iError = EINVAL; + return -1; + } + + ssize_t iReturn = send(socket, (char*)data, (int)len, 0); + if (iReturn < (ssize_t)len) + *iError = GetSocketError(); + return iReturn; + } + + inline ssize_t TcpSocketRead(tcp_socket_t socket, int *iError, void* data, size_t len, uint64_t iTimeoutMs /*= 0*/) + { + int64_t iNow(0), iTarget(0); + ssize_t iBytesRead(0); + *iError = 0; + + if (socket == INVALID_SOCKET || + socket == SOCKET_ERROR || + len != (int)len) + { + *iError = EINVAL; + return -1; + } + + if (iTimeoutMs > 0) + { + iNow = GetTimeMs(); + iTarget = iNow + (int64_t) iTimeoutMs; + } + + fd_set fd_read; + struct timeval tv; + while (iBytesRead >= 0 && iBytesRead < (ssize_t)len && (iTimeoutMs == 0 || iTarget > iNow)) + { + if (iTimeoutMs > 0) + { + tv.tv_sec = (long)(iTimeoutMs / 1000); + tv.tv_usec = 1000 * (long)(iTimeoutMs % 1000); + + FD_ZERO(&fd_read); + FD_SET(socket, &fd_read); + + if (select((int)socket + 1, &fd_read, NULL, NULL, &tv) == 0) + { + *iError = ETIMEDOUT; + return ETIMEDOUT; + } + TcpSocketSetBlocking(socket, false); + } + + ssize_t iReadResult = (iTimeoutMs > 0) ? + recv(socket, (char*)data + iBytesRead, (int)(len - iBytesRead), 0) : + recv(socket, (char*)data, (int)len, MSG_WAITALL); + *iError = GetSocketError(); + + if (iTimeoutMs > 0) + { + TcpSocketSetBlocking(socket, true); + iNow = GetTimeMs(); + } + + if (iReadResult < 0) + { + if (*iError == EAGAIN && iTimeoutMs > 0) + continue; + return -1; + } + else if (iReadResult == 0 || (iReadResult != (ssize_t)len && iTimeoutMs == 0)) + { + *iError = ECONNRESET; + return -1; + } + + iBytesRead += iReadResult; + } + + if (iBytesRead < (ssize_t)len && *iError == 0) + *iError = ETIMEDOUT; + + return iBytesRead; + } + + inline bool TcpResolveAddress(const char *strHost, uint16_t iPort, int *iError, struct addrinfo **info) + { + struct addrinfo hints; + char service[33]; + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_UNSPEC; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + sprintf(service, "%d", iPort); + + *iError = getaddrinfo(strHost, service, &hints, info); + return !(*iError); + } + + inline int TcpGetSocketError(tcp_socket_t socket) + { + int iReturn(0); + socklen_t optLen = sizeof(tcp_socket_t); + getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)&iReturn, &optLen); + return iReturn; + } + + inline bool TcpSetNoDelay(tcp_socket_t socket) + { + int iSetTo(1); + setsockopt(socket, IPPROTO_TCP, TCP_NODELAY, (const char*)&iSetTo, sizeof(iSetTo)); + return true; + } + + inline bool TcpConnectSocket(tcp_socket_t socket, struct addrinfo* addr, int *iError, uint64_t iTimeout = 0) + { + TcpSocketSetBlocking(socket, false); + + *iError = 0; + int iConnectResult = connect(socket, addr->ai_addr, (int)addr->ai_addrlen); + if (iConnectResult == -1) + { + if (GetSocketError() == EINPROGRESS || + GetSocketError() == EAGAIN) + { + fd_set fd_write, fd_except; + struct timeval tv; + tv.tv_sec = (long)(iTimeout / 1000); + tv.tv_usec = 1000 * (long)(iTimeout % 1000); + + FD_ZERO(&fd_write); + FD_ZERO(&fd_except); + FD_SET(socket, &fd_write); + FD_SET(socket, &fd_except); + + int iPollResult = select(sizeof(socket)*8, NULL, &fd_write, &fd_except, &tv); + if (iPollResult == 0) + *iError = ETIMEDOUT; + else if (iPollResult == -1) + *iError = GetSocketError(); + else + { + socklen_t errlen = sizeof(int); + getsockopt(socket, SOL_SOCKET, SO_ERROR, (char *)iError, &errlen); + } + } + else + { + *iError = GetSocketError(); + } + } + + TcpSocketSetBlocking(socket, true); + + return *iError == 0; + } +} diff --git a/lib/platform/windows/os-threads.cpp b/lib/platform/windows/os-threads.cpp new file mode 100644 index 0000000..7c06d41 --- /dev/null +++ b/lib/platform/windows/os-threads.cpp @@ -0,0 +1,136 @@ +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "../os.h" +#include "os-threads.h" +using namespace PLATFORM; + +static ConditionArg g_InitializeConditionVariable; +static ConditionArg g_WakeConditionVariable; +static ConditionArg g_WakeAllConditionVariable; +static ConditionMutexArg g_SleepConditionVariableCS; + +// check whether vista+ conditions are available at runtime +static bool CheckVistaConditionFunctions(void) +{ + static int iHasVistaConditionFunctions(-1); + if (iHasVistaConditionFunctions == -1) + { + HMODULE handle = GetModuleHandle("Kernel32"); + if (handle == NULL) + { + iHasVistaConditionFunctions = 0; + } + else + { + g_InitializeConditionVariable = (ConditionArg) GetProcAddress(handle,"InitializeConditionVariable"); + g_WakeConditionVariable = (ConditionArg) GetProcAddress(handle,"WakeConditionVariable"); + g_WakeAllConditionVariable = (ConditionArg) GetProcAddress(handle,"WakeAllConditionVariable"); + g_SleepConditionVariableCS = (ConditionMutexArg)GetProcAddress(handle,"SleepConditionVariableCS"); + + // 1 when everything is resolved, 0 otherwise + iHasVistaConditionFunctions = g_InitializeConditionVariable && + g_WakeConditionVariable && + g_WakeAllConditionVariable && + g_SleepConditionVariableCS ? 1 : 0; + } + } + return iHasVistaConditionFunctions == 1; +} + +CConditionImpl::CConditionImpl(void) +{ + m_bOnVista = CheckVistaConditionFunctions(); + if (m_bOnVista) + (*g_InitializeConditionVariable)(m_conditionVista = new CONDITION_VARIABLE); + else + m_conditionPreVista = ::CreateEvent(NULL, TRUE, FALSE, NULL); +} + +CConditionImpl::~CConditionImpl(void) +{ + if (m_bOnVista) + delete m_conditionVista; + else + ::CloseHandle(m_conditionPreVista); +} + +void CConditionImpl::Signal(void) +{ + if (m_bOnVista) + (*g_WakeConditionVariable)(m_conditionVista); + else + ::SetEvent(m_conditionPreVista); +} + +void CConditionImpl::Broadcast(void) +{ + if (m_bOnVista) + (*g_WakeAllConditionVariable)(m_conditionVista); + else + ::SetEvent(m_conditionPreVista); +} + +bool CConditionImpl::Wait(mutex_t &mutex) +{ + if (m_bOnVista) + { + return ((*g_SleepConditionVariableCS)(m_conditionVista, mutex, INFINITE) ? true : false); + } + else + { + ::ResetEvent(m_conditionPreVista); + MutexUnlock(mutex); + DWORD iWaitReturn = ::WaitForSingleObject(m_conditionPreVista, 1000); + MutexLock(mutex); + return (iWaitReturn == 0); + } +} + +bool CConditionImpl::Wait(mutex_t &mutex, uint32_t iTimeoutMs) +{ + if (iTimeoutMs == 0) + return Wait(mutex); + + if (m_bOnVista) + { + return ((*g_SleepConditionVariableCS)(m_conditionVista, mutex, iTimeoutMs) ? true : false); + } + else + { + ::ResetEvent(m_conditionPreVista); + MutexUnlock(mutex); + DWORD iWaitReturn = ::WaitForSingleObject(m_conditionPreVista, iTimeoutMs); + MutexLock(mutex); + return (iWaitReturn == 0); + } +} diff --git a/lib/platform/windows/os-threads.h b/lib/platform/windows/os-threads.h new file mode 100644 index 0000000..3714c16 --- /dev/null +++ b/lib/platform/windows/os-threads.h @@ -0,0 +1,65 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +namespace PLATFORM +{ + #define thread_t HANDLE + #define ThreadsWait(thread, retVal) (::WaitForSingleObject(thread, INFINITE) < 0) + #define ThreadsCreate(thread, func, arg) ((thread = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)func, arg, 0, NULL)) == NULL ? false : true) + + typedef CRITICAL_SECTION* mutex_t; + #define MutexCreate(mutex) ::InitializeCriticalSection(mutex = new CRITICAL_SECTION) + #define MutexDelete(mutex) ::DeleteCriticalSection(mutex); delete mutex + #define MutexLock(mutex) ::EnterCriticalSection(mutex) + #define MutexTryLock(mutex) (::TryEnterCriticalSection(mutex) != 0) + #define MutexUnlock(mutex) ::LeaveCriticalSection(mutex) + + // windows vista+ conditions + typedef VOID (WINAPI *ConditionArg) (CONDITION_VARIABLE*); + typedef BOOL (WINAPI *ConditionMutexArg)(CONDITION_VARIABLE*, CRITICAL_SECTION*, DWORD); + + class CConditionImpl + { + public: + CConditionImpl(void); + virtual ~CConditionImpl(void); + void Signal(void); + void Broadcast(void); + bool Wait(mutex_t &mutex); + bool Wait(mutex_t &mutex, uint32_t iTimeoutMs); + + bool m_bOnVista; + CONDITION_VARIABLE *m_conditionVista; + HANDLE m_conditionPreVista; + }; +} diff --git a/lib/platform/windows/os-types.h b/lib/platform/windows/os-types.h new file mode 100644 index 0000000..9b0dca0 --- /dev/null +++ b/lib/platform/windows/os-types.h @@ -0,0 +1,80 @@ +#pragma once +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#if !defined(__WINDOWS__) +#define __WINDOWS__ +#endif + +#ifndef _WINSOCKAPI_ +#define _WINSOCKAPI_ +#endif + +#pragma warning(disable:4005) // Disable "warning C4005: '_WINSOCKAPI_' : macro redefinition" +#include +#pragma warning(default:4005) + +#include +#include +#include +#include +#include +#include +#include + +typedef SOCKET tcp_socket_t; +#define INVALID_SOCKET_VALUE INVALID_SOCKET +typedef HANDLE serial_socket_t; +#define INVALID_SERIAL_SOCKET_VALUE INVALID_HANDLE_VALUE + +#ifndef _SSIZE_T_DEFINED +#ifdef _WIN64 +typedef __int64 ssize_t; +#else +typedef _W64 int ssize_t; +#endif +#define _SSIZE_T_DEFINED +#endif + +#define snprintf _snprintf + +#if defined(_MSC_VER) +#pragma warning (push) +#endif + +#define NOGDI +#if defined(_MSC_VER) /* prevent inclusion of wingdi.h */ +#pragma warning (pop) +#endif + +#pragma warning(disable:4189) /* disable 'defined but not used' */ +#pragma warning(disable:4100) /* disable 'unreferenced formal parameter' */ diff --git a/lib/platform/windows/serialport.cpp b/lib/platform/windows/serialport.cpp new file mode 100644 index 0000000..c0cdd93 --- /dev/null +++ b/lib/platform/windows/serialport.cpp @@ -0,0 +1,211 @@ +/* + * This file is part of the libCEC(R) library. + * + * libCEC(R) is Copyright (C) 2011-2012 Pulse-Eight Limited. All rights reserved. + * libCEC(R) is an original work, containing original code. + * + * libCEC(R) is a trademark of Pulse-Eight Limited. + * + * This program is dual-licensed; 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * + * Alternatively, you can license this library under a commercial license, + * please contact Pulse-Eight Licensing for more information. + * + * For more information contact: + * Pulse-Eight Licensing + * http://www.pulse-eight.com/ + * http://www.pulse-eight.net/ + */ + +#include "../sockets/serialport.h" +#include "../util/baudrate.h" +#include "../util/timeutils.h" + +using namespace std; +using namespace PLATFORM; + +void FormatWindowsError(int iErrorCode, CStdString &strMessage) +{ + if (iErrorCode != ERROR_SUCCESS) + { + char strAddMessage[1024]; + FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, iErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), strAddMessage, 1024, NULL); + strMessage.append(": "); + strMessage.append(strAddMessage); + } +} + +bool SetTimeouts(serial_socket_t socket, int* iError, bool bBlocking) +{ + if (socket == INVALID_HANDLE_VALUE) + return false; + + COMMTIMEOUTS cto; + if (!GetCommTimeouts(socket, &cto)) + { + *iError = GetLastError(); + return false; + } + + if (bBlocking) + { + cto.ReadIntervalTimeout = 0; + cto.ReadTotalTimeoutConstant = 0; + cto.ReadTotalTimeoutMultiplier = 0; + } + else + { + cto.ReadIntervalTimeout = MAXDWORD; + cto.ReadTotalTimeoutConstant = 0; + cto.ReadTotalTimeoutMultiplier = 0; + } + + if (!SetCommTimeouts(socket, &cto)) + { + *iError = GetLastError(); + return false; + } + + return true; +} + +void CSerialSocket::Close(void) +{ + if (IsOpen()) + SerialSocketClose(m_socket); + m_socket = INVALID_SERIAL_SOCKET_VALUE; +} + +void CSerialSocket::Shutdown(void) +{ + if (IsOpen()) + SerialSocketClose(m_socket); + m_socket = INVALID_SERIAL_SOCKET_VALUE; +} + +ssize_t CSerialSocket::Write(void* data, size_t len) +{ + return IsOpen() ? SerialSocketWrite(m_socket, &m_iError, data, len) : -1; +} + +ssize_t CSerialSocket::Read(void* data, size_t len, uint64_t iTimeoutMs /* = 0 */) +{ + return IsOpen() ? SerialSocketRead(m_socket, &m_iError, data, len, iTimeoutMs) : -1; +} + +bool CSerialSocket::Open(uint64_t iTimeoutMs /* = 0 */) +{ + iTimeoutMs = 0; + if (IsOpen()) + return false; + + CStdString strComPath = "\\\\.\\" + m_strName; + CLockObject lock(m_mutex); + m_socket = CreateFile(strComPath.c_str(), GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + if (m_socket == INVALID_HANDLE_VALUE) + { + m_strError = "Unable to open COM port"; + FormatWindowsError(GetLastError(), m_strError); + return false; + } + + COMMCONFIG commConfig = {0}; + DWORD dwSize = sizeof(commConfig); + commConfig.dwSize = dwSize; + if (GetDefaultCommConfig(strComPath.c_str(), &commConfig,&dwSize)) + { + if (!SetCommConfig(m_socket, &commConfig,dwSize)) + { + m_strError = "unable to set default config"; + FormatWindowsError(GetLastError(), m_strError); + } + } + else + { + m_strError = "unable to get default config"; + FormatWindowsError(GetLastError(), m_strError); + } + + if (!SetupComm(m_socket, 64, 64)) + { + m_strError = "unable to set up the com port"; + FormatWindowsError(GetLastError(), m_strError); + } + + if (!SetBaudRate(m_iBaudrate)) + { + m_strError = "unable to set baud rate"; + FormatWindowsError(GetLastError(), m_strError); + Close(); + return false; + } + + if (!SetTimeouts(m_socket, &m_iError, false)) + { + m_strError = "unable to set timeouts"; + FormatWindowsError(GetLastError(), m_strError); + Close(); + return false; + } + + m_bIsOpen = true; + return m_bIsOpen; +} + +bool CSerialSocket::SetBaudRate(uint32_t baudrate) +{ + int32_t rate = IntToBaudrate(baudrate); + if (rate < 0) + m_iBaudrate = baudrate > 0 ? baudrate : 0; + else + m_iBaudrate = rate; + + DCB dcb; + memset(&dcb,0,sizeof(dcb)); + dcb.DCBlength = sizeof(dcb); + dcb.BaudRate = IntToBaudrate(m_iBaudrate); + dcb.fBinary = true; + dcb.fDtrControl = DTR_CONTROL_DISABLE; + dcb.fRtsControl = RTS_CONTROL_DISABLE; + dcb.fOutxCtsFlow = false; + dcb.fOutxDsrFlow = false; + dcb.fOutX = false; + dcb.fInX = false; + dcb.fAbortOnError = true; + + if (m_iParity == SERIAL_PARITY_NONE) + dcb.Parity = NOPARITY; + else if (m_iParity == SERIAL_PARITY_EVEN) + dcb.Parity = EVENPARITY; + else + dcb.Parity = ODDPARITY; + + if (m_iStopbits == SERIAL_STOP_BITS_TWO) + dcb.StopBits = TWOSTOPBITS; + else + dcb.StopBits = ONESTOPBIT; + + dcb.ByteSize = (BYTE)m_iDatabits; + + if(!SetCommState(m_socket,&dcb)) + { + m_strError = "SetCommState failed"; + FormatWindowsError(GetLastError(), m_strError); + return false; + } + + return true; +} diff --git a/lib/platform/windows/stdint.h b/lib/platform/windows/stdint.h new file mode 100644 index 0000000..d02608a --- /dev/null +++ b/lib/platform/windows/stdint.h @@ -0,0 +1,247 @@ +// ISO C9x compliant stdint.h for Microsoft Visual Studio +// Based on ISO/IEC 9899:TC2 Committee draft (May 6, 2005) WG14/N1124 +// +// Copyright (c) 2006-2008 Alexander Chemeris +// +// Redistribution and use in source and binary forms, with or without +// modification, are permitted provided that the following conditions are met: +// +// 1. Redistributions of source code must retain the above copyright notice, +// this list of conditions and the following disclaimer. +// +// 2. Redistributions in binary form must reproduce the above copyright +// notice, this list of conditions and the following disclaimer in the +// documentation and/or other materials provided with the distribution. +// +// 3. The name of the author may be used to endorse or promote products +// derived from this software without specific prior written permission. +// +// THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED +// WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO +// EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, +// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; +// OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, +// WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR +// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF +// ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef _MSC_VER // [ +#error "Use this header only with Microsoft Visual C++ compilers!" +#endif // _MSC_VER ] + +#ifndef _MSC_STDINT_H_ // [ +#define _MSC_STDINT_H_ + +#if _MSC_VER > 1000 +#pragma once +#endif + +#include + +// For Visual Studio 6 in C++ mode and for many Visual Studio versions when +// compiling for ARM we should wrap include with 'extern "C++" {}' +// or compiler give many errors like this: +// error C2733: second C linkage of overloaded function 'wmemchr' not allowed +#ifdef __cplusplus +extern "C" { +#endif +# include +#ifdef __cplusplus +} +#endif + +// Define _W64 macros to mark types changing their size, like intptr_t. +#ifndef _W64 +# if !defined(__midl) && (defined(_X86_) || defined(_M_IX86)) && _MSC_VER >= 1300 +# define _W64 __w64 +# else +# define _W64 +# endif +#endif + + +// 7.18.1 Integer types + +// 7.18.1.1 Exact-width integer types + +// Visual Studio 6 and Embedded Visual C++ 4 doesn't +// realize that, e.g. char has the same size as __int8 +// so we give up on __intX for them. +#if (_MSC_VER < 1300) + typedef signed char int8_t; + typedef signed short int16_t; + typedef signed int int32_t; + typedef unsigned char uint8_t; + typedef unsigned short uint16_t; + typedef unsigned int uint32_t; +#else + typedef signed __int8 int8_t; + typedef signed __int16 int16_t; + typedef signed __int32 int32_t; + typedef unsigned __int8 uint8_t; + typedef unsigned __int16 uint16_t; + typedef unsigned __int32 uint32_t; +#endif +typedef signed __int64 int64_t; +typedef unsigned __int64 uint64_t; + + +// 7.18.1.2 Minimum-width integer types +typedef int8_t int_least8_t; +typedef int16_t int_least16_t; +typedef int32_t int_least32_t; +typedef int64_t int_least64_t; +typedef uint8_t uint_least8_t; +typedef uint16_t uint_least16_t; +typedef uint32_t uint_least32_t; +typedef uint64_t uint_least64_t; + +// 7.18.1.3 Fastest minimum-width integer types +typedef int8_t int_fast8_t; +typedef int16_t int_fast16_t; +typedef int32_t int_fast32_t; +typedef int64_t int_fast64_t; +typedef uint8_t uint_fast8_t; +typedef uint16_t uint_fast16_t; +typedef uint32_t uint_fast32_t; +typedef uint64_t uint_fast64_t; + +// 7.18.1.4 Integer types capable of holding object pointers +#ifdef _WIN64 // [ + typedef signed __int64 intptr_t; + typedef unsigned __int64 uintptr_t; +#else // _WIN64 ][ + typedef _W64 signed int intptr_t; + typedef _W64 unsigned int uintptr_t; +#endif // _WIN64 ] + +// 7.18.1.5 Greatest-width integer types +typedef int64_t intmax_t; +typedef uint64_t uintmax_t; + + +// 7.18.2 Limits of specified-width integer types + +#if !defined(__cplusplus) || defined(__STDC_LIMIT_MACROS) // [ See footnote 220 at page 257 and footnote 221 at page 259 + +// 7.18.2.1 Limits of exact-width integer types +#define INT8_MIN ((int8_t)_I8_MIN) +#define INT8_MAX _I8_MAX +#define INT16_MIN ((int16_t)_I16_MIN) +#define INT16_MAX _I16_MAX +#define INT32_MIN ((int32_t)_I32_MIN) +#define INT32_MAX _I32_MAX +#define INT64_MIN ((int64_t)_I64_MIN) +#define INT64_MAX _I64_MAX +#define UINT8_MAX _UI8_MAX +#define UINT16_MAX _UI16_MAX +#define UINT32_MAX _UI32_MAX +#define UINT64_MAX _UI64_MAX + +// 7.18.2.2 Limits of minimum-width integer types +#define INT_LEAST8_MIN INT8_MIN +#define INT_LEAST8_MAX INT8_MAX +#define INT_LEAST16_MIN INT16_MIN +#define INT_LEAST16_MAX INT16_MAX +#define INT_LEAST32_MIN INT32_MIN +#define INT_LEAST32_MAX INT32_MAX +#define INT_LEAST64_MIN INT64_MIN +#define INT_LEAST64_MAX INT64_MAX +#define UINT_LEAST8_MAX UINT8_MAX +#define UINT_LEAST16_MAX UINT16_MAX +#define UINT_LEAST32_MAX UINT32_MAX +#define UINT_LEAST64_MAX UINT64_MAX + +// 7.18.2.3 Limits of fastest minimum-width integer types +#define INT_FAST8_MIN INT8_MIN +#define INT_FAST8_MAX INT8_MAX +#define INT_FAST16_MIN INT16_MIN +#define INT_FAST16_MAX INT16_MAX +#define INT_FAST32_MIN INT32_MIN +#define INT_FAST32_MAX INT32_MAX +#define INT_FAST64_MIN INT64_MIN +#define INT_FAST64_MAX INT64_MAX +#define UINT_FAST8_MAX UINT8_MAX +#define UINT_FAST16_MAX UINT16_MAX +#define UINT_FAST32_MAX UINT32_MAX +#define UINT_FAST64_MAX UINT64_MAX + +// 7.18.2.4 Limits of integer types capable of holding object pointers +#ifdef _WIN64 // [ +# define INTPTR_MIN INT64_MIN +# define INTPTR_MAX INT64_MAX +# define UINTPTR_MAX UINT64_MAX +#else // _WIN64 ][ +# define INTPTR_MIN INT32_MIN +# define INTPTR_MAX INT32_MAX +# define UINTPTR_MAX UINT32_MAX +#endif // _WIN64 ] + +// 7.18.2.5 Limits of greatest-width integer types +#define INTMAX_MIN INT64_MIN +#define INTMAX_MAX INT64_MAX +#define UINTMAX_MAX UINT64_MAX + +// 7.18.3 Limits of other integer types + +#ifdef _WIN64 // [ +# define PTRDIFF_MIN _I64_MIN +# define PTRDIFF_MAX _I64_MAX +#else // _WIN64 ][ +# define PTRDIFF_MIN _I32_MIN +# define PTRDIFF_MAX _I32_MAX +#endif // _WIN64 ] + +#define SIG_ATOMIC_MIN INT_MIN +#define SIG_ATOMIC_MAX INT_MAX + +#ifndef SIZE_MAX // [ +# ifdef _WIN64 // [ +# define SIZE_MAX _UI64_MAX +# else // _WIN64 ][ +# define SIZE_MAX _UI32_MAX +# endif // _WIN64 ] +#endif // SIZE_MAX ] + +// WCHAR_MIN and WCHAR_MAX are also defined in +#ifndef WCHAR_MIN // [ +# define WCHAR_MIN 0 +#endif // WCHAR_MIN ] +#ifndef WCHAR_MAX // [ +# define WCHAR_MAX _UI16_MAX +#endif // WCHAR_MAX ] + +#define WINT_MIN 0 +#define WINT_MAX _UI16_MAX + +#endif // __STDC_LIMIT_MACROS ] + + +// 7.18.4 Limits of other integer types + +#if !defined(__cplusplus) || defined(__STDC_CONSTANT_MACROS) // [ See footnote 224 at page 260 + +// 7.18.4.1 Macros for minimum-width integer constants + +#define INT8_C(val) val##i8 +#define INT16_C(val) val##i16 +#define INT32_C(val) val##i32 +#define INT64_C(val) val##i64 + +#define UINT8_C(val) val##ui8 +#define UINT16_C(val) val##ui16 +#define UINT32_C(val) val##ui32 +#define UINT64_C(val) val##ui64 + +// 7.18.4.2 Macros for greatest-width integer constants +#define INTMAX_C INT64_C +#define UINTMAX_C UINT64_C + +#endif // __STDC_CONSTANT_MACROS ] + + +#endif // _MSC_STDINT_H_ ] diff --git a/project/VS2010Express/XBMC for Windows.sln b/project/VS2010Express/XBMC for Windows.sln index 9834bfc..ece2861 100644 --- a/project/VS2010Express/XBMC for Windows.sln +++ b/project/VS2010Express/XBMC for Windows.sln @@ -10,6 +10,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhts", "..\..\lib\libhts\ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libass_dll", "..\..\lib\libass\xbmc\libass_win32\libass_win32_vs2010.vcxproj", "{BA5B08FC-2ECB-4571-9F25-F8054522FC65}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pvrclient_vnsi", "..\..\xbmc\pvrclients\vdr-vnsi\project\VS2010Express\XBMC_VDR_vnsi.vcxproj", "{3AD3147B-8E7F-4C70-B049-19FA1916BF12}" +EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "visMilkdrop", "..\..\xbmc\visualizations\Milkdrop\Plugin.vcxproj", "{5E479372-4F34-426D-AA1E-9879E94C105D}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcmyth_dll", "..\..\lib\cmyth\Win32\libcmyth.vcxproj", "{F9E6874D-60A8-49BA-9393-A2105E63ABCF}" @@ -72,298 +74,543 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libmp3lame_dll", "..\..\lib EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhdhomerun_dll", "..\..\lib\libhdhomerun\hdhomerun\hdhomerun.vcxproj", "{1E2FB608-3DD2-4021-A598-90008FA6DE85}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libXBMC_addon", "..\..\lib\addons\library.xbmc.addon\project\VS2010Express\libXBMC_addon.vcxproj", "{2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libXBMC_gui", "..\..\lib\addons\library.xbmc.gui\project\VS2010Express\libXBMC_gui.vcxproj", "{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libXBMC_pvr", "..\..\lib\addons\library.xbmc.pvr\project\VS2010Express\libXBMC_pvr.vcxproj", "{6D8C91F8-992F-4C83-9DE3-485D64EF8420}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pvrclient_mptv", "..\..\xbmc\pvrclients\MediaPortal\project\VS2010Express\XBMC_MPTV.vcxproj", "{74C9642E-1988-48DC-8404-11717C355378}" +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pvrclient_tvheadend", "..\..\xbmc\pvrclients\tvheadend\project\VS2010Express\XBMC_tvheadend.vcxproj", "{C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}" + ProjectSection(ProjectDependencies) = postProject + {00700E12-A63B-4E54-B962-4011A90584BD} = {00700E12-A63B-4E54-B962-4011A90584BD} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "pvrclient_mythtv_cmyth", "..\..\xbmc\pvrclients\mythtv-cmyth\project\VS2010Express\XBMC_mythtc_cmyth.vcxproj", "{A55ACC6B-837D-4784-8E41-66947B1D9B8C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug (DirectX)|Win32 = Debug (DirectX)|Win32 Debug (OpenGL)|Win32 = Debug (OpenGL)|Win32 + Debug|Win32 = Debug|Win32 Release (DirectX)|Win32 = Release (DirectX)|Win32 Release (OpenGL)|Win32 = Release (OpenGL)|Win32 + Release|Win32 = Release|Win32 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {3A68081D-E8F9-4523-9436-530DE9E5530A}.Debug (DirectX)|Win32.ActiveCfg = Debug (DirectX)|Win32 {3A68081D-E8F9-4523-9436-530DE9E5530A}.Debug (DirectX)|Win32.Build.0 = Debug (DirectX)|Win32 {3A68081D-E8F9-4523-9436-530DE9E5530A}.Debug (OpenGL)|Win32.ActiveCfg = Debug (OpenGL)|Win32 {3A68081D-E8F9-4523-9436-530DE9E5530A}.Debug (OpenGL)|Win32.Build.0 = Debug (OpenGL)|Win32 + {3A68081D-E8F9-4523-9436-530DE9E5530A}.Debug|Win32.ActiveCfg = Debug (OpenGL)|Win32 + {3A68081D-E8F9-4523-9436-530DE9E5530A}.Debug|Win32.Build.0 = Debug (OpenGL)|Win32 {3A68081D-E8F9-4523-9436-530DE9E5530A}.Release (DirectX)|Win32.ActiveCfg = Release (DirectX)|Win32 {3A68081D-E8F9-4523-9436-530DE9E5530A}.Release (DirectX)|Win32.Build.0 = Release (DirectX)|Win32 {3A68081D-E8F9-4523-9436-530DE9E5530A}.Release (OpenGL)|Win32.ActiveCfg = Release (OpenGL)|Win32 {3A68081D-E8F9-4523-9436-530DE9E5530A}.Release (OpenGL)|Win32.Build.0 = Release (OpenGL)|Win32 + {3A68081D-E8F9-4523-9436-530DE9E5530A}.Release|Win32.ActiveCfg = Release (OpenGL)|Win32 + {3A68081D-E8F9-4523-9436-530DE9E5530A}.Release|Win32.Build.0 = Release (OpenGL)|Win32 {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Debug|Win32.ActiveCfg = Debug|Win32 + {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Debug|Win32.Build.0 = Debug|Win32 {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Release (DirectX)|Win32.Build.0 = Release|Win32 {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Release|Win32.ActiveCfg = Release|Win32 + {B2975495-FBE4-4F94-AAC5-B21A9842BF50}.Release|Win32.Build.0 = Release|Win32 {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Debug (DirectX)|Win32.ActiveCfg = Debug (DirectX)|Win32 {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Debug (DirectX)|Win32.Build.0 = Debug (DirectX)|Win32 {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Debug (OpenGL)|Win32.ActiveCfg = Debug (OpenGL)|Win32 {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Debug (OpenGL)|Win32.Build.0 = Debug (OpenGL)|Win32 + {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Debug|Win32.ActiveCfg = Debug (OpenGL)|Win32 + {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Debug|Win32.Build.0 = Debug (OpenGL)|Win32 {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Release (DirectX)|Win32.ActiveCfg = Release (DirectX)|Win32 {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Release (DirectX)|Win32.Build.0 = Release (DirectX)|Win32 {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Release (OpenGL)|Win32.ActiveCfg = Release (OpenGL)|Win32 {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Release (OpenGL)|Win32.Build.0 = Release (OpenGL)|Win32 + {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Release|Win32.ActiveCfg = Release (OpenGL)|Win32 + {FE0A91C0-E30A-47CD-8A92-A508C9292452}.Release|Win32.Build.0 = Release (OpenGL)|Win32 {00700E12-A63B-4E54-B962-4011A90584BD}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {00700E12-A63B-4E54-B962-4011A90584BD}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {00700E12-A63B-4E54-B962-4011A90584BD}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {00700E12-A63B-4E54-B962-4011A90584BD}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {00700E12-A63B-4E54-B962-4011A90584BD}.Debug|Win32.ActiveCfg = Debug|Win32 + {00700E12-A63B-4E54-B962-4011A90584BD}.Debug|Win32.Build.0 = Debug|Win32 {00700E12-A63B-4E54-B962-4011A90584BD}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {00700E12-A63B-4E54-B962-4011A90584BD}.Release (DirectX)|Win32.Build.0 = Release|Win32 {00700E12-A63B-4E54-B962-4011A90584BD}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {00700E12-A63B-4E54-B962-4011A90584BD}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {00700E12-A63B-4E54-B962-4011A90584BD}.Release|Win32.ActiveCfg = Release|Win32 + {00700E12-A63B-4E54-B962-4011A90584BD}.Release|Win32.Build.0 = Release|Win32 {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Debug|Win32.ActiveCfg = Debug|Win32 + {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Debug|Win32.Build.0 = Debug|Win32 {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Release (DirectX)|Win32.Build.0 = Release|Win32 {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Release|Win32.ActiveCfg = Release|Win32 + {BA5B08FC-2ECB-4571-9F25-F8054522FC65}.Release|Win32.Build.0 = Release|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Debug|Win32.ActiveCfg = Debug|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Debug|Win32.Build.0 = Debug|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Release (DirectX)|Win32.Build.0 = Release|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Release|Win32.ActiveCfg = Release|Win32 + {3AD3147B-8E7F-4C70-B049-19FA1916BF12}.Release|Win32.Build.0 = Release|Win32 {5E479372-4F34-426D-AA1E-9879E94C105D}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {5E479372-4F34-426D-AA1E-9879E94C105D}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {5E479372-4F34-426D-AA1E-9879E94C105D}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 + {5E479372-4F34-426D-AA1E-9879E94C105D}.Debug|Win32.ActiveCfg = Debug|Win32 + {5E479372-4F34-426D-AA1E-9879E94C105D}.Debug|Win32.Build.0 = Debug|Win32 {5E479372-4F34-426D-AA1E-9879E94C105D}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {5E479372-4F34-426D-AA1E-9879E94C105D}.Release (DirectX)|Win32.Build.0 = Release|Win32 {5E479372-4F34-426D-AA1E-9879E94C105D}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 + {5E479372-4F34-426D-AA1E-9879E94C105D}.Release|Win32.ActiveCfg = Release|Win32 + {5E479372-4F34-426D-AA1E-9879E94C105D}.Release|Win32.Build.0 = Release|Win32 {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Debug|Win32.ActiveCfg = Debug|Win32 + {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Debug|Win32.Build.0 = Debug|Win32 {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Release (DirectX)|Win32.Build.0 = Release|Win32 {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Release|Win32.ActiveCfg = Release|Win32 + {F9E6874D-60A8-49BA-9393-A2105E63ABCF}.Release|Win32.Build.0 = Release|Win32 {D8097C41-605D-4917-8957-9DF7F44A18CD}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {D8097C41-605D-4917-8957-9DF7F44A18CD}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {D8097C41-605D-4917-8957-9DF7F44A18CD}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {D8097C41-605D-4917-8957-9DF7F44A18CD}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {D8097C41-605D-4917-8957-9DF7F44A18CD}.Debug|Win32.ActiveCfg = Debug|Win32 + {D8097C41-605D-4917-8957-9DF7F44A18CD}.Debug|Win32.Build.0 = Debug|Win32 {D8097C41-605D-4917-8957-9DF7F44A18CD}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {D8097C41-605D-4917-8957-9DF7F44A18CD}.Release (DirectX)|Win32.Build.0 = Release|Win32 {D8097C41-605D-4917-8957-9DF7F44A18CD}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {D8097C41-605D-4917-8957-9DF7F44A18CD}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {D8097C41-605D-4917-8957-9DF7F44A18CD}.Release|Win32.ActiveCfg = Release|Win32 + {D8097C41-605D-4917-8957-9DF7F44A18CD}.Release|Win32.Build.0 = Release|Win32 {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Debug|Win32.ActiveCfg = Debug|Win32 + {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Debug|Win32.Build.0 = Debug|Win32 {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Release (DirectX)|Win32.Build.0 = Release|Win32 {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Release|Win32.ActiveCfg = Release|Win32 + {19B16CD0-3B47-47B7-AB0E-81EF2BF1B187}.Release|Win32.Build.0 = Release|Win32 {22B25AEC-7223-46FC-8356-4418327EFDE1}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {22B25AEC-7223-46FC-8356-4418327EFDE1}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {22B25AEC-7223-46FC-8356-4418327EFDE1}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {22B25AEC-7223-46FC-8356-4418327EFDE1}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {22B25AEC-7223-46FC-8356-4418327EFDE1}.Debug|Win32.ActiveCfg = Debug|Win32 + {22B25AEC-7223-46FC-8356-4418327EFDE1}.Debug|Win32.Build.0 = Debug|Win32 {22B25AEC-7223-46FC-8356-4418327EFDE1}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {22B25AEC-7223-46FC-8356-4418327EFDE1}.Release (DirectX)|Win32.Build.0 = Release|Win32 {22B25AEC-7223-46FC-8356-4418327EFDE1}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {22B25AEC-7223-46FC-8356-4418327EFDE1}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {22B25AEC-7223-46FC-8356-4418327EFDE1}.Release|Win32.ActiveCfg = Release|Win32 + {22B25AEC-7223-46FC-8356-4418327EFDE1}.Release|Win32.Build.0 = Release|Win32 {3B424C94-2005-44CC-BFB1-4B6C89090732}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {3B424C94-2005-44CC-BFB1-4B6C89090732}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {3B424C94-2005-44CC-BFB1-4B6C89090732}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {3B424C94-2005-44CC-BFB1-4B6C89090732}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {3B424C94-2005-44CC-BFB1-4B6C89090732}.Debug|Win32.ActiveCfg = Debug|Win32 + {3B424C94-2005-44CC-BFB1-4B6C89090732}.Debug|Win32.Build.0 = Debug|Win32 {3B424C94-2005-44CC-BFB1-4B6C89090732}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {3B424C94-2005-44CC-BFB1-4B6C89090732}.Release (DirectX)|Win32.Build.0 = Release|Win32 {3B424C94-2005-44CC-BFB1-4B6C89090732}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {3B424C94-2005-44CC-BFB1-4B6C89090732}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {3B424C94-2005-44CC-BFB1-4B6C89090732}.Release|Win32.ActiveCfg = Release|Win32 + {3B424C94-2005-44CC-BFB1-4B6C89090732}.Release|Win32.Build.0 = Release|Win32 {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Debug|Win32.ActiveCfg = Debug|Win32 + {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Debug|Win32.Build.0 = Debug|Win32 {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Release (DirectX)|Win32.Build.0 = Release|Win32 {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Release|Win32.ActiveCfg = Release|Win32 + {3843C3D4-E5A6-4030-87EC-E7EE57242106}.Release|Win32.Build.0 = Release|Win32 {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Debug|Win32.ActiveCfg = Debug|Win32 + {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Debug|Win32.Build.0 = Debug|Win32 {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Release (DirectX)|Win32.Build.0 = Release|Win32 {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Release|Win32.ActiveCfg = Release|Win32 + {88E7E431-3752-4D58-BCD2-A7E6A1B74247}.Release|Win32.Build.0 = Release|Win32 {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Debug|Win32.ActiveCfg = Debug|Win32 + {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Debug|Win32.Build.0 = Debug|Win32 {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Release (DirectX)|Win32.Build.0 = Release|Win32 {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Release|Win32.ActiveCfg = Release|Win32 + {145287C8-24EA-42FE-8D7D-C13D5E4B054C}.Release|Win32.Build.0 = Release|Win32 {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Debug|Win32.ActiveCfg = Debug|Win32 + {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Debug|Win32.Build.0 = Debug|Win32 {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Release (DirectX)|Win32.Build.0 = Release|Win32 {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Release|Win32.ActiveCfg = Release|Win32 + {8E5F7DBE-2E8B-4FD2-BFFE-1960CE7EDC09}.Release|Win32.Build.0 = Release|Win32 {783701E9-4A65-4505-97B0-39E580AA680D}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {783701E9-4A65-4505-97B0-39E580AA680D}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {783701E9-4A65-4505-97B0-39E580AA680D}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {783701E9-4A65-4505-97B0-39E580AA680D}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {783701E9-4A65-4505-97B0-39E580AA680D}.Debug|Win32.ActiveCfg = Debug|Win32 + {783701E9-4A65-4505-97B0-39E580AA680D}.Debug|Win32.Build.0 = Debug|Win32 {783701E9-4A65-4505-97B0-39E580AA680D}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {783701E9-4A65-4505-97B0-39E580AA680D}.Release (DirectX)|Win32.Build.0 = Release|Win32 {783701E9-4A65-4505-97B0-39E580AA680D}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {783701E9-4A65-4505-97B0-39E580AA680D}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {783701E9-4A65-4505-97B0-39E580AA680D}.Release|Win32.ActiveCfg = Release|Win32 + {783701E9-4A65-4505-97B0-39E580AA680D}.Release|Win32.Build.0 = Release|Win32 {44BF83C4-F73A-4093-A29A-11B9016318C4}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {44BF83C4-F73A-4093-A29A-11B9016318C4}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {44BF83C4-F73A-4093-A29A-11B9016318C4}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {44BF83C4-F73A-4093-A29A-11B9016318C4}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {44BF83C4-F73A-4093-A29A-11B9016318C4}.Debug|Win32.ActiveCfg = Debug|Win32 + {44BF83C4-F73A-4093-A29A-11B9016318C4}.Debug|Win32.Build.0 = Debug|Win32 {44BF83C4-F73A-4093-A29A-11B9016318C4}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {44BF83C4-F73A-4093-A29A-11B9016318C4}.Release (DirectX)|Win32.Build.0 = Release|Win32 {44BF83C4-F73A-4093-A29A-11B9016318C4}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {44BF83C4-F73A-4093-A29A-11B9016318C4}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {44BF83C4-F73A-4093-A29A-11B9016318C4}.Release|Win32.ActiveCfg = Release|Win32 + {44BF83C4-F73A-4093-A29A-11B9016318C4}.Release|Win32.Build.0 = Release|Win32 {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Debug|Win32.ActiveCfg = Debug|Win32 + {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Debug|Win32.Build.0 = Debug|Win32 {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Release (DirectX)|Win32.Build.0 = Release|Win32 {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Release|Win32.ActiveCfg = Release|Win32 + {8735F1ED-317D-4F7A-A512-B2BF9DAEA25A}.Release|Win32.Build.0 = Release|Win32 {96798038-06CE-4382-BD5B-F9C366724DEB}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {96798038-06CE-4382-BD5B-F9C366724DEB}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {96798038-06CE-4382-BD5B-F9C366724DEB}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {96798038-06CE-4382-BD5B-F9C366724DEB}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {96798038-06CE-4382-BD5B-F9C366724DEB}.Debug|Win32.ActiveCfg = Debug|Win32 + {96798038-06CE-4382-BD5B-F9C366724DEB}.Debug|Win32.Build.0 = Debug|Win32 {96798038-06CE-4382-BD5B-F9C366724DEB}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {96798038-06CE-4382-BD5B-F9C366724DEB}.Release (DirectX)|Win32.Build.0 = Release|Win32 {96798038-06CE-4382-BD5B-F9C366724DEB}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {96798038-06CE-4382-BD5B-F9C366724DEB}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {96798038-06CE-4382-BD5B-F9C366724DEB}.Release|Win32.ActiveCfg = Release|Win32 + {96798038-06CE-4382-BD5B-F9C366724DEB}.Release|Win32.Build.0 = Release|Win32 {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Debug (DirectX)|Win32.ActiveCfg = Release (DLL)|Win32 {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Debug (DirectX)|Win32.Build.0 = Release (DLL)|Win32 {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Debug (OpenGL)|Win32.ActiveCfg = Release (DLL)|Win32 {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Debug (OpenGL)|Win32.Build.0 = Release (DLL)|Win32 + {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Debug|Win32.ActiveCfg = Debug|Win32 + {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Debug|Win32.Build.0 = Debug|Win32 {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Release (DirectX)|Win32.ActiveCfg = Release (DLL)|Win32 {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Release (DirectX)|Win32.Build.0 = Release (DLL)|Win32 {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Release (OpenGL)|Win32.ActiveCfg = Release (DLL)|Win32 {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Release (OpenGL)|Win32.Build.0 = Release (DLL)|Win32 + {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Release|Win32.ActiveCfg = Release|Win32 + {AD20A3E2-09CB-42DB-9A70-27F7CDC886CE}.Release|Win32.Build.0 = Release|Win32 {0D91724A-E6F6-4708-AF47-9F88BBE2114C}.Debug (DirectX)|Win32.ActiveCfg = Debug (DirectX)|Win32 {0D91724A-E6F6-4708-AF47-9F88BBE2114C}.Debug (DirectX)|Win32.Build.0 = Debug (DirectX)|Win32 {0D91724A-E6F6-4708-AF47-9F88BBE2114C}.Debug (OpenGL)|Win32.ActiveCfg = Debug (DirectX)|Win32 + {0D91724A-E6F6-4708-AF47-9F88BBE2114C}.Debug|Win32.ActiveCfg = Debug (DirectX)|Win32 + {0D91724A-E6F6-4708-AF47-9F88BBE2114C}.Debug|Win32.Build.0 = Debug (DirectX)|Win32 {0D91724A-E6F6-4708-AF47-9F88BBE2114C}.Release (DirectX)|Win32.ActiveCfg = Release (DirectX)|Win32 {0D91724A-E6F6-4708-AF47-9F88BBE2114C}.Release (DirectX)|Win32.Build.0 = Release (DirectX)|Win32 {0D91724A-E6F6-4708-AF47-9F88BBE2114C}.Release (OpenGL)|Win32.ActiveCfg = Release (DirectX)|Win32 + {0D91724A-E6F6-4708-AF47-9F88BBE2114C}.Release|Win32.ActiveCfg = Release (DirectX)|Win32 + {0D91724A-E6F6-4708-AF47-9F88BBE2114C}.Release|Win32.Build.0 = Release (DirectX)|Win32 {C15B374E-7126-48FF-B618-A375D7B17FCF}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {C15B374E-7126-48FF-B618-A375D7B17FCF}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {C15B374E-7126-48FF-B618-A375D7B17FCF}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {C15B374E-7126-48FF-B618-A375D7B17FCF}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {C15B374E-7126-48FF-B618-A375D7B17FCF}.Debug|Win32.ActiveCfg = Debug|Win32 + {C15B374E-7126-48FF-B618-A375D7B17FCF}.Debug|Win32.Build.0 = Debug|Win32 {C15B374E-7126-48FF-B618-A375D7B17FCF}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {C15B374E-7126-48FF-B618-A375D7B17FCF}.Release (DirectX)|Win32.Build.0 = Release|Win32 {C15B374E-7126-48FF-B618-A375D7B17FCF}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {C15B374E-7126-48FF-B618-A375D7B17FCF}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {C15B374E-7126-48FF-B618-A375D7B17FCF}.Release|Win32.ActiveCfg = Release|Win32 + {C15B374E-7126-48FF-B618-A375D7B17FCF}.Release|Win32.Build.0 = Release|Win32 {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Debug|Win32.ActiveCfg = Debug|Win32 + {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Debug|Win32.Build.0 = Debug|Win32 {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Release (DirectX)|Win32.Build.0 = Release|Win32 {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Release|Win32.ActiveCfg = Release|Win32 + {BDD2CB99-93C5-4A70-ACBF-396FFB961AD3}.Release|Win32.Build.0 = Release|Win32 {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Debug|Win32.ActiveCfg = Debug|Win32 + {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Debug|Win32.Build.0 = Debug|Win32 {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Release (DirectX)|Win32.Build.0 = Release|Win32 {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Release|Win32.ActiveCfg = Release|Win32 + {DD4818AE-7E35-40B7-A6A0-0FF83AA1C916}.Release|Win32.Build.0 = Release|Win32 {D450FE9A-CE56-4496-B4AB-379094E642F2}.Debug (DirectX)|Win32.ActiveCfg = Debug (DirectX)|Win32 {D450FE9A-CE56-4496-B4AB-379094E642F2}.Debug (DirectX)|Win32.Build.0 = Debug (DirectX)|Win32 {D450FE9A-CE56-4496-B4AB-379094E642F2}.Debug (OpenGL)|Win32.ActiveCfg = Debug (OpenGL)|Win32 {D450FE9A-CE56-4496-B4AB-379094E642F2}.Debug (OpenGL)|Win32.Build.0 = Debug (OpenGL)|Win32 + {D450FE9A-CE56-4496-B4AB-379094E642F2}.Debug|Win32.ActiveCfg = Debug (OpenGL)|Win32 + {D450FE9A-CE56-4496-B4AB-379094E642F2}.Debug|Win32.Build.0 = Debug (OpenGL)|Win32 {D450FE9A-CE56-4496-B4AB-379094E642F2}.Release (DirectX)|Win32.ActiveCfg = Release (DirectX)|Win32 {D450FE9A-CE56-4496-B4AB-379094E642F2}.Release (DirectX)|Win32.Build.0 = Release (DirectX)|Win32 {D450FE9A-CE56-4496-B4AB-379094E642F2}.Release (OpenGL)|Win32.ActiveCfg = Release (OpenGL)|Win32 {D450FE9A-CE56-4496-B4AB-379094E642F2}.Release (OpenGL)|Win32.Build.0 = Release (OpenGL)|Win32 + {D450FE9A-CE56-4496-B4AB-379094E642F2}.Release|Win32.ActiveCfg = Release (OpenGL)|Win32 + {D450FE9A-CE56-4496-B4AB-379094E642F2}.Release|Win32.Build.0 = Release (OpenGL)|Win32 {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug|Win32.ActiveCfg = Debug|Win32 + {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Debug|Win32.Build.0 = Debug|Win32 {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Release (DirectX)|Win32.Build.0 = Release|Win32 {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Release|Win32.ActiveCfg = Release|Win32 + {6A8518C3-D81A-4428-BD7F-C37933088AC1}.Release|Win32.Build.0 = Release|Win32 {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Debug|Win32.ActiveCfg = Debug|Win32 + {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Debug|Win32.Build.0 = Debug|Win32 {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Release (DirectX)|Win32.Build.0 = Release|Win32 {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Release|Win32.ActiveCfg = Release|Win32 + {D9885434-4B9D-41FB-B5FC-5E89D41AEFF0}.Release|Win32.Build.0 = Release|Win32 {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Debug|Win32.ActiveCfg = Debug|Win32 + {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Debug|Win32.Build.0 = Debug|Win32 {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Release (DirectX)|Win32.Build.0 = Release|Win32 {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Release|Win32.ActiveCfg = Release|Win32 + {AF6C8945-5DDC-4F62-A48C-86B11B7ED996}.Release|Win32.Build.0 = Release|Win32 {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Debug|Win32.ActiveCfg = Debug|Win32 + {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Debug|Win32.Build.0 = Debug|Win32 {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Release (DirectX)|Win32.Build.0 = Release|Win32 {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Release|Win32.ActiveCfg = Release|Win32 + {3600E1C5-FECA-468C-83F3-FE467DBE2A66}.Release|Win32.Build.0 = Release|Win32 {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Debug|Win32.ActiveCfg = Debug|Win32 + {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Debug|Win32.Build.0 = Debug|Win32 {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Release (DirectX)|Win32.Build.0 = Release|Win32 {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Release|Win32.ActiveCfg = Release|Win32 + {AEABB6CE-8F0F-4507-8DC4-5E3BCE5962DA}.Release|Win32.Build.0 = Release|Win32 {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Debug|Win32.ActiveCfg = Debug|Win32 + {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Debug|Win32.Build.0 = Debug|Win32 {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Release (DirectX)|Win32.Build.0 = Release|Win32 {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Release|Win32.ActiveCfg = Release|Win32 + {2A8CBFB5-C226-4BB3-8C03-7C75D511A4A2}.Release|Win32.Build.0 = Release|Win32 {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Debug|Win32.ActiveCfg = Debug|Win32 + {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Debug|Win32.Build.0 = Debug|Win32 {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Release (DirectX)|Win32.Build.0 = Release|Win32 {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Release|Win32.ActiveCfg = Release|Win32 + {17238C64-04D6-4B51-B205-4A5A84ADB9FA}.Release|Win32.Build.0 = Release|Win32 {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Debug|Win32.ActiveCfg = Debug|Win32 + {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Debug|Win32.Build.0 = Debug|Win32 {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Release (DirectX)|Win32.Build.0 = Release|Win32 {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Release|Win32.ActiveCfg = Release|Win32 + {FB3AB83A-C37A-4636-87FD-827F8506A8FC}.Release|Win32.Build.0 = Release|Win32 {88968763-3D6B-48A8-B495-CC8C187FAC02}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {88968763-3D6B-48A8-B495-CC8C187FAC02}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {88968763-3D6B-48A8-B495-CC8C187FAC02}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {88968763-3D6B-48A8-B495-CC8C187FAC02}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {88968763-3D6B-48A8-B495-CC8C187FAC02}.Debug|Win32.ActiveCfg = Debug|Win32 + {88968763-3D6B-48A8-B495-CC8C187FAC02}.Debug|Win32.Build.0 = Debug|Win32 {88968763-3D6B-48A8-B495-CC8C187FAC02}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {88968763-3D6B-48A8-B495-CC8C187FAC02}.Release (DirectX)|Win32.Build.0 = Release|Win32 {88968763-3D6B-48A8-B495-CC8C187FAC02}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {88968763-3D6B-48A8-B495-CC8C187FAC02}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {88968763-3D6B-48A8-B495-CC8C187FAC02}.Release|Win32.ActiveCfg = Release|Win32 + {88968763-3D6B-48A8-B495-CC8C187FAC02}.Release|Win32.Build.0 = Release|Win32 {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Debug|Win32.ActiveCfg = Debug|Win32 + {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Debug|Win32.Build.0 = Debug|Win32 {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Release (DirectX)|Win32.ActiveCfg = ReleaseNASM|Win32 {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Release (DirectX)|Win32.Build.0 = ReleaseNASM|Win32 {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Release (OpenGL)|Win32.ActiveCfg = ReleaseNASM|Win32 {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Release (OpenGL)|Win32.Build.0 = ReleaseNASM|Win32 + {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Release|Win32.ActiveCfg = Release|Win32 + {92BD50AA-04D6-4FBF-ACE1-468FAF6778F2}.Release|Win32.Build.0 = Release|Win32 {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Debug|Win32.ActiveCfg = Debug|Win32 + {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Debug|Win32.Build.0 = Debug|Win32 {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Release (DirectX)|Win32.Build.0 = Release|Win32 {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Release|Win32.ActiveCfg = Release|Win32 + {1E2FB608-3DD2-4021-A598-90008FA6DE85}.Release|Win32.Build.0 = Release|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Debug|Win32.ActiveCfg = Debug|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Debug|Win32.Build.0 = Debug|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Release (DirectX)|Win32.Build.0 = Release|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Release|Win32.ActiveCfg = Release|Win32 + {2DCEA60B-4EBC-4DB7-9FBD-297C1EFD95D7}.Release|Win32.Build.0 = Release|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug|Win32.ActiveCfg = Debug|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Debug|Win32.Build.0 = Debug|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release (DirectX)|Win32.Build.0 = Release|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release|Win32.ActiveCfg = Release|Win32 + {8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}.Release|Win32.Build.0 = Release|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Debug|Win32.ActiveCfg = Debug|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Debug|Win32.Build.0 = Debug|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Release (DirectX)|Win32.Build.0 = Release|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Release|Win32.ActiveCfg = Release|Win32 + {6D8C91F8-992F-4C83-9DE3-485D64EF8420}.Release|Win32.Build.0 = Release|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Debug|Win32.ActiveCfg = Debug|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Debug|Win32.Build.0 = Debug|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Release (DirectX)|Win32.Build.0 = Release|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Release|Win32.ActiveCfg = Release|Win32 + {74C9642E-1988-48DC-8404-11717C355378}.Release|Win32.Build.0 = Release|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Debug|Win32.ActiveCfg = Debug|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Debug|Win32.Build.0 = Debug|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Release (DirectX)|Win32.Build.0 = Release|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Release|Win32.ActiveCfg = Release|Win32 + {C04B0FB1-667D-4F1C-BDAE-A07CDFFA74A3}.Release|Win32.Build.0 = Release|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Debug (DirectX)|Win32.ActiveCfg = Debug|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Debug (DirectX)|Win32.Build.0 = Debug|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Debug (OpenGL)|Win32.ActiveCfg = Debug|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Debug (OpenGL)|Win32.Build.0 = Debug|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Debug|Win32.ActiveCfg = Debug|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Debug|Win32.Build.0 = Debug|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Release (DirectX)|Win32.ActiveCfg = Release|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Release (DirectX)|Win32.Build.0 = Release|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Release (OpenGL)|Win32.ActiveCfg = Release|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Release (OpenGL)|Win32.Build.0 = Release|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Release|Win32.ActiveCfg = Release|Win32 + {A55ACC6B-837D-4784-8E41-66947B1D9B8C}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/project/VS2010Express/XBMC.vcxproj b/project/VS2010Express/XBMC.vcxproj index f3b44da..993eb6c 100644 --- a/project/VS2010Express/XBMC.vcxproj +++ b/project/VS2010Express/XBMC.vcxproj @@ -143,6 +143,10 @@ VC90.CRT.x86.manifest;%(AdditionalManifestFiles) true + + copy "$(TargetPath)" "$(ProjectDir)..\.." +copy "$(TargetDir)*.dll" "$(ProjectDir)..\.." + @@ -186,6 +190,10 @@ VC90.CRT.x86.manifest;%(AdditionalManifestFiles) true + + copy "$(TargetPath)" "$(ProjectDir)..\.." +copy "$(TargetDir)*.dll" "$(ProjectDir)..\.." + @@ -234,6 +242,9 @@ VC90.CRT.x86.manifest;%(AdditionalManifestFiles) true + + copy "$(TargetPath)" "$(ProjectDir)..\.." + @@ -278,6 +289,16 @@ VC90.CRT.x86.manifest;%(AdditionalManifestFiles) true + + copy "$(TargetPath)" "$(ProjectDir)..\.." +copy "$(TargetDir)*.dll" "$(ProjectDir)..\.." + + + + + copy "$(TargetPath)" "$(ProjectDir)..\.." +copy "$(TargetDir)*.dll" "$(ProjectDir)..\.." + @@ -285,6 +306,10 @@ + + + + @@ -302,7 +327,9 @@ + + @@ -318,6 +345,7 @@ + @@ -340,6 +368,12 @@ + + + + + + @@ -349,6 +383,8 @@ + + @@ -473,6 +509,7 @@ + @@ -719,6 +756,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -758,6 +827,7 @@ + @@ -802,6 +872,7 @@ + @@ -818,6 +889,7 @@ + @@ -1204,10 +1276,15 @@ + + + + + @@ -1222,7 +1299,9 @@ + + @@ -1237,6 +1316,7 @@ + @@ -1259,6 +1339,12 @@ + + + + + + @@ -1278,6 +1364,8 @@ + + @@ -1586,6 +1674,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -1674,6 +1794,7 @@ + @@ -1692,6 +1813,7 @@ + diff --git a/project/VS2010Express/XBMC.vcxproj.filters b/project/VS2010Express/XBMC.vcxproj.filters index 62a6f25..f061c12 100644 --- a/project/VS2010Express/XBMC.vcxproj.filters +++ b/project/VS2010Express/XBMC.vcxproj.filters @@ -226,6 +226,30 @@ {9592a005-d33b-48d1-8462-d95c42c383c2} + + {5d07f015-2e93-4085-bda3-2be566fb07a8} + + + {5fb53298-e501-4f23-bf84-fc61acf9b814} + + + {ef8e21c9-b588-4255-ba38-57c6ae82d0aa} + + + {43455925-2158-4eff-97ce-1fa3f6597a3a} + + + {14af7c50-6457-48ec-87b2-4efb3986bdd8} + + + {eab084ef-b5b5-4a61-b2a5-eac88bbcc73a} + + + {7be58f63-0e53-4a26-9894-e52c2bd78709} + + + {dbfd4898-7df3-4393-8b04-ab0cc1265c33} + {dfa70c36-927b-4540-b505-35919e64eb3d} @@ -2408,6 +2432,39 @@ addons + + epg + + + epg + + + epg + + + epg + + + epg + + + filesystem + + + filesystem + + + utils + + + cores\dvdplayer\DVDInputStreams + + + cores\dvdplayer\DVDDemuxers + + + utils + utils @@ -2417,12 +2474,120 @@ win32 + + pvr\windows + + + pvr\timers + + + pvr\timers + + + pvr\recordings + + + pvr\recordings + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\channels + + + pvr\channels + + + pvr\channels + + + pvr\channels + + + pvr\channels + + + pvr\addons + + + dialogs + + + pvr + + + pvr + interfaces\python\xbmcmodule cores\VideoRenderers + + pvr\windows + + + pvr\windows + + + pvr\windows + + + pvr\windows + + + pvr\windows + + + pvr\windows + + + pvr\windows + + + pvr\addons + + + addons + + + addons + + + addons + + + addons + libs\SlingboxLib @@ -2432,6 +2597,9 @@ dialogs + + pvr + interfaces\json-rpc @@ -2451,6 +2619,9 @@ filesystem + + epg + input @@ -2565,6 +2736,9 @@ filesystem + + interfaces\json-rpc + cores\paplayer @@ -4960,8 +5134,41 @@ addons - - cores\dvdplayer\DVDHeaders + + epg + + + epg + + + epg + + + epg + + + epg + + + filesystem + + + filesystem + + + addons + + + utils + + + cores\dvdplayer\DVDInputStreams + + + cores\dvdplayer\DVDDemuxers + + + utils utils @@ -4972,12 +5179,121 @@ win32 + + + pvr\windows + + + pvr\timers + + + pvr\timers + + + pvr\recordings + + + pvr\recordings + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\dialogs + + + pvr\channels + + + pvr\channels + + + pvr\channels + + + pvr\channels + + + pvr\channels + + + pvr\addons + + + dialogs + + + pvr + + + pvr + cores\VideoRenderers + + pvr\windows + + + pvr\windows + + + pvr\windows + + + pvr\windows + + + pvr\windows + + + pvr\windows + + + pvr\windows + utils + + pvr\addons + + + addons + + + addons + + + addons + + + addons + libs\SlingboxLib @@ -4990,6 +5306,9 @@ dialogs + + pvr + interfaces\json-rpc @@ -5003,6 +5322,9 @@ interfaces\json-rpc + + epg + input @@ -5153,6 +5475,9 @@ filesystem + + interfaces\json-rpc + interfaces\python\xbmcmodule @@ -5171,4 +5496,4 @@ win32 - \ No newline at end of file + diff --git a/system/PVRDemoAddonSettings.xml b/system/PVRDemoAddonSettings.xml new file mode 100644 index 0000000..008930a --- /dev/null +++ b/system/PVRDemoAddonSettings.xml @@ -0,0 +1,460 @@ + + + + Demo TV Channel 1 + 0 + 1 + 0 + + + + + Demo TV Channel 2 + 0 + 2 + 0 + + + + + Demo TV Channel 3 + 0 + 3 + 0 + + + + + Demo TV Channel 4 + 0 + 4 + 0 + + + + + Demo TV Channel 5 + 0 + 5 + 0 + + + + + Demo TV Channel 10 + 0 + 10 + 0 + + + + + Demo TV Channel 11 + 0 + 11 + 0 + + + + + Demo TV Channel 12 + 0 + 12 + 0 + + + + + Demo TV Channel 13 + 0 + 13 + 0 + + + + + Demo TV Channel 14 + 0 + 14 + 0 + + + + + Demo TV Channel 15 + 0 + 15 + 0 + + + + + + Demo Radio Channel #1 + 1 + 1 + 0 + + + + + Demo Radio Channel #2 + 1 + 2 + 0 + + + + + Demo Radio Channel #3 + 1 + 3 + 0 + + + + + Demo Radio Channel #4 + 1 + 4 + 0 + + + + + Demo Radio Channel #5 + 1 + 5 + 0 + + + + + Demo Radio Channel #6 + 1 + 6 + 0 + + + + + Demo Radio Channel #7 + 1 + 7 + 0 + + + + + Demo Radio Channel #8 + 1 + 8 + 0 + + + + + Demo Radio Channel #9 + 1 + 9 + 0 + + + + + Demo Radio Channel #10 + 1 + 10 + 0 + + + + + + + Demo Group #1 + 0 + + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + + + + Demo Group #2 + 0 + + 1 + 3 + 5 + 7 + 9 + 11 + + + + + + 100 + Demo EPG entry #1 + 1 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 10 + 0 + + + 200 + Demo EPG entry #2 + 2 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 20 + 0 + + + 300 + Demo EPG entry #3 + 3 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + + 0 + + + 400 + Demo EPG entry #4 + 4 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 30 + 0 + + + 500 + Demo EPG entry #5 + 5 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + + 0 + + + 600 + Demo EPG entry #6 + 6 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 10 + 0 + + + 700 + Demo EPG entry #7 + 7 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 10 + 0 + + + 800 + Demo EPG entry #8 + 8 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 20 + 0 + + + 900 + Demo EPG entry #9 + 9 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 30 + 0 + + + 1000 + Demo EPG entry #10 + 10 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 10 + 0 + + + 1100 + Demo EPG entry #11 + 11 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 20 + 0 + + + + 1200 + Demo Radio EPG entry #1 + 12 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 30 + 0 + + + 1300 + Demo Radio EPG entry #2 + 13 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 10 + 0 + + + 1400 + Demo Radio EPG entry #3 + 14 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 20 + 0 + + + 1500 + Demo Radio EPG entry #4 + 15 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 30 + 0 + + + 1600 + Demo Radio EPG entry #5 + 16 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 10 + 0 + + + 1700 + Demo Radio EPG entry #6 + 17 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 20 + 0 + + + 1800 + Demo Radio EPG entry #7 + 18 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 30 + 0 + + + 1900 + Demo Radio EPG entry #8 + 19 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 10 + 0 + + + 2000 + Demo Radio EPG entry #9 + 20 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 20 + 0 + + + 2100 + Demo Radio EPG entry #10 + 21 + 0 + 7200 + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nam cursus consectetur ipsum, eu tincidunt dui aliquam ac. Sed scelerisque, augue eu lacinia ultrices, libero ante ullamcorper augue, vel malesuada justo risus ac nulla. Quisque ac libero libero. Sed tincidunt, orci eu condimentum laoreet, felis odio mattis est, et lacinia metus enim in leo. Fusce faucibus tristique risus in varius. Etiam sagittis venenatis ligula nec rutrum. Etiam gravida dictum hendrerit. Sed sodales felis in sapien rutrum non malesuada nisi lobortis. Mauris iaculis ante odio. Nunc gravida erat convallis purus dignissim et ultricies orci dapibus. Aliquam erat volutpat. Vestibulum mi felis, malesuada ac tincidunt sit amet, pulvinar nec dolor. Pellentesque vehicula est vulputate mi adipiscing euismod. Donec ac mauris nulla. Nullam suscipit felis eu quam sodales ac bibendum nisi interdum. Curabitur non lectus a ante venenatis semper eget id justo. Ut facilisis, ligula pretium dictum congue, lacus dolor commodo nibh, sit amet sodales sed. + + 30 + 0 + + + + diff --git a/system/keymaps/keyboard.xml b/system/keymaps/keyboard.xml index fe15ce2..f35c79c 100644 --- a/system/keymaps/keyboard.xml +++ b/system/keymaps/keyboard.xml @@ -94,6 +94,12 @@ ToggleFullScreen FirstPage LastPage + + XBMC.ActivateWindowAndFocus(MyPVR, 31,0, 10,0) + XBMC.ActivateWindowAndFocus(MyPVR, 32,0, 11,0) + XBMC.ActivateWindowAndFocus(MyPVR, 33,0, 12,0) + XBMC.ActivateWindowAndFocus(MyPVR, 34,0, 13,0) + XBMC.ActivateWindowAndFocus(MyPVR, 35,0, 14,0) Back @@ -159,6 +165,13 @@ Backspace + + + Delete + Move + Rename + + Highlight @@ -220,6 +233,7 @@ BigStepBack AudioDelay Fullscreen + Playlist XBMC.ActivateWindow(Teletext) SubtitleShiftUp SubtitleShiftDown @@ -267,6 +281,8 @@ CodecInfo LockPreset FullScreen + XBMC.ActivateWindow(PVROSDGuide) + XBMC.ActivateWindow(PVROSDChannels) @@ -454,6 +470,46 @@ Back + + + Close + + + + + Close + + + + + Close + Close + Close + + + + + Close + Close + + + + + Close + Close + + + + + Close + Close + + + + + PreviousMenu + + Highlight diff --git a/system/keymaps/remote.xml b/system/keymaps/remote.xml index 2a9ab3c..4001a3b 100644 --- a/system/keymaps/remote.xml +++ b/system/keymaps/remote.xml @@ -66,8 +66,13 @@ XBMC.ActivateWindow(MyVideos) XBMC.ActivateWindow(MyMusic) XBMC.ActivateWindow(MyPictures) - XBMC.ActivateWindow(VideoLibrary,TvShows) - XBMC.ActivateWindow(Home) + XBMC.ActivateWindow(MyPVR) + XBMC.ActivateWindowAndFocus(MyPVR, 31,0, 10,0) + XBMC.ActivateWindowAndFocus(MyPVR, 32,0, 11,0) + XBMC.ActivateWindowAndFocus(MyPVR, 33,0, 12,0) + XBMC.ActivateWindowAndFocus(MyPVR, 34,0, 13,0) + XBMC.ActivateWindowAndFocus(MyPVR, 35,0, 14,0) + XBMC.ActivateWindow(MyPVR) XBMC.ActivateWindow(MyVideos) XBMC.ActivateWindow(MyMusic) XBMC.ActivateWindow(MyPictures) @@ -90,6 +95,11 @@ XBMC.ActivateWindow(Settings) + + + Delete + + Delete @@ -143,10 +153,13 @@ CodecInfo Info + XBMC.ActivateWindow(PVROSDGuide) XBMC.ActivateWindow(Teletext) NextSubtitle NextSubtitle AudioNextLanguage + Playlist + Language AudioNextLanguage @@ -180,6 +193,8 @@ XBMC.ActivateWindow(MusicOSD) XBMC.ActivateWindow(MusicOSD) Info + XBMC.ActivateWindow(PVROSDGuide) + XBMC.ActivateWindow(PVROSDChannels) @@ -339,6 +354,103 @@ BackSpace + + + PreviousMenu + + + + + Red + Green + Yellow + Blue + + + + + PreviousMenu + + + + + + + + + Close + + + + + Close + + + + + Close + + + + + PreviousMenu + + + + + PreviousMenu + + + + + PreviousMenu + + + + + PreviousMenu + + + + + PreviousMenu + + + + + PreviousMenu + + + + + PreviousMenu + + + + + PreviousMenu + + + + + PreviousMenu + + + + + PreviousMenu + + + + + PreviousMenu + + + + + PreviousMenu + + Back @@ -388,6 +500,44 @@ Back + + + Close + + + + + Close + Close + Close + Close + + + + + Close + Close + Close + Close + + + + + Close + Close + + + + + Close + Close + + + + + PreviousMenu + + Delete diff --git a/system/playercorefactory.xml b/system/playercorefactory.xml index 66784de..6fc8c20 100644 --- a/system/playercorefactory.xml +++ b/system/playercorefactory.xml @@ -33,5 +33,8 @@ + + + diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp index df7de6e..d170340 100644 --- a/xbmc/Application.cpp +++ b/xbmc/Application.cpp @@ -225,6 +225,7 @@ #include "dialogs/GUIDialogYesNo.h" #include "dialogs/GUIDialogOK.h" #include "dialogs/GUIDialogProgress.h" +#include "dialogs/GUIDialogExtendedProgressBar.h" #include "dialogs/GUIDialogSelect.h" #include "dialogs/GUIDialogSeekBar.h" #include "dialogs/GUIDialogKaiToast.h" @@ -248,6 +249,24 @@ #ifdef HAS_LINUX_NETWORK #include "network/GUIDialogAccessPoints.h" #endif + +/* PVR related include Files */ +#include "pvr/PVRManager.h" +#include "pvr/timers/PVRTimers.h" +#include "pvr/windows/GUIWindowPVR.h" +#include "pvr/dialogs/GUIDialogPVRChannelManager.h" +#include "pvr/dialogs/GUIDialogPVRChannelsOSD.h" +#include "pvr/dialogs/GUIDialogPVRCutterOSD.h" +#include "pvr/dialogs/GUIDialogPVRDirectorOSD.h" +#include "pvr/dialogs/GUIDialogPVRGroupManager.h" +#include "pvr/dialogs/GUIDialogPVRGuideInfo.h" +#include "pvr/dialogs/GUIDialogPVRGuideOSD.h" +#include "pvr/dialogs/GUIDialogPVRGuideSearch.h" +#include "pvr/dialogs/GUIDialogPVRRecordingInfo.h" +#include "pvr/dialogs/GUIDialogPVRTimerSettings.h" + +#include "epg/EpgContainer.h" + #include "video/dialogs/GUIDialogFullScreenInfo.h" #include "video/dialogs/GUIDialogTeletext.h" #include "dialogs/GUIDialogSlider.h" @@ -323,6 +342,8 @@ using namespace EVENTSERVER; using namespace JSONRPC; #endif using namespace ANNOUNCEMENT; +using namespace PVR; +using namespace EPG; using namespace PERIPHERALS; using namespace XbmcThreads; @@ -344,6 +365,7 @@ CApplication::CApplication(void) , m_progressTrackingItem(new CFileItem) { m_iPlaySpeed = 1; + m_bInhibitIdleShutdown = false; m_bScreenSave = false; m_dpms = NULL; m_dpmsIsActive = false; @@ -1089,7 +1111,6 @@ bool CApplication::Initialize() #ifdef HAS_DX g_windowManager.Add(new CGUIWindowTestPatternDX); // window id = 8 #endif - g_windowManager.Add(new CGUIDialogTeletext); // window id = g_windowManager.Add(new CGUIWindowSettingsScreenCalibration); // window id = 11 g_windowManager.Add(new CGUIWindowSettingsCategory); // window id = 12 slideshow:window id 2007 g_windowManager.Add(new CGUIWindowVideoNav); // window id = 36 @@ -1102,6 +1123,7 @@ bool CApplication::Initialize() g_windowManager.Add(new CGUIWindowPointer); // window id = 99 g_windowManager.Add(new CGUIDialogYesNo); // window id = 100 g_windowManager.Add(new CGUIDialogProgress); // window id = 101 + g_windowManager.Add(new CGUIDialogExtendedProgressBar); // window id = 148 g_windowManager.Add(new CGUIDialogKeyboard); // window id = 103 g_windowManager.Add(new CGUIDialogVolumeBar); // window id = 104 g_windowManager.Add(new CGUIDialogSeekBar); // window id = 115 @@ -1140,7 +1162,6 @@ bool CApplication::Initialize() #ifdef HAS_LINUX_NETWORK g_windowManager.Add(new CGUIDialogAccessPoints); // window id = 141 #endif - g_windowManager.Add(new CGUIDialogLockSettings); // window id = 131 g_windowManager.Add(new CGUIDialogContentSettings); // window id = 132 @@ -1155,6 +1176,20 @@ bool CApplication::Initialize() g_windowManager.Add(new CGUIWindowMusicNav); // window id = 502 g_windowManager.Add(new CGUIWindowMusicPlaylistEditor); // window id = 503 + /* Load PVR related Windows and Dialogs */ + g_windowManager.Add(new CGUIWindowPVR); // window id = 600 + g_windowManager.Add(new CGUIDialogPVRGuideInfo); // window id = 601 + g_windowManager.Add(new CGUIDialogPVRRecordingInfo); // window id = 602 + g_windowManager.Add(new CGUIDialogPVRTimerSettings); // window id = 603 + g_windowManager.Add(new CGUIDialogPVRGroupManager); // window id = 604 + g_windowManager.Add(new CGUIDialogPVRChannelManager); // window id = 605 + g_windowManager.Add(new CGUIDialogPVRGuideSearch); // window id = 606 + g_windowManager.Add(new CGUIDialogPVRChannelsOSD); // window id = 609 + g_windowManager.Add(new CGUIDialogPVRGuideOSD); // window id = 610 + g_windowManager.Add(new CGUIDialogPVRDirectorOSD); // window id = 611 + g_windowManager.Add(new CGUIDialogPVRCutterOSD); // window id = 612 + g_windowManager.Add(new CGUIDialogTeletext); // window id = 613 + g_windowManager.Add(new CGUIDialogSelect); // window id = 2000 g_windowManager.Add(new CGUIDialogMusicInfo); // window id = 2001 g_windowManager.Add(new CGUIDialogOK); // window id = 2002 @@ -1184,6 +1219,9 @@ bool CApplication::Initialize() FatalErrorHandler(true, true, true); } + StartEPGManager(); + StartPVRManager(); + if (g_advancedSettings.m_splashImage) SAFE_DELETE(m_splash); @@ -1556,6 +1594,29 @@ void CApplication::StopZeroconf() #endif } +void CApplication::StartPVRManager() +{ + if (g_guiSettings.GetBool("pvrmanager.enabled")) + g_PVRManager.Start(); +} + +void CApplication::StartEPGManager(void) +{ + g_EpgContainer.Start(); +} + +void CApplication::StopPVRManager() +{ + CLog::Log(LOGINFO, "stopping PVRManager"); + StopPlaying(); + g_PVRManager.Stop(); +} + +void CApplication::StopEPGManager(void) +{ + g_EpgContainer.Stop(); +} + void CApplication::DimLCDOnPlayback(bool dim) { #ifdef HAS_LCD @@ -2476,7 +2537,7 @@ bool CApplication::OnAction(const CAction &action) return true; } - if ( IsPlaying()) + if (IsPlaying() && !CurrentFileItem().IsLiveTV()) { // pause : pauses current audio song if (action.GetID() == ACTION_PAUSE && m_iPlaySpeed == 1) @@ -2556,6 +2617,7 @@ bool CApplication::OnAction(const CAction &action) } } } + if (action.GetID() == ACTION_MUTE) { ToggleMute(); @@ -3184,11 +3246,24 @@ bool CApplication::Cleanup() g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS); g_windowManager.Delete(WINDOW_DIALOG_SLIDER); + /* Delete PVR related windows and dialogs */ + g_windowManager.Delete(WINDOW_PVR); + g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_INFO); + g_windowManager.Delete(WINDOW_DIALOG_PVR_RECORDING_INFO); + g_windowManager.Delete(WINDOW_DIALOG_PVR_TIMER_SETTING); + g_windowManager.Delete(WINDOW_DIALOG_PVR_GROUP_MANAGER); + g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_MANAGER); + g_windowManager.Delete(WINDOW_DIALOG_PVR_GUIDE_SEARCH); + g_windowManager.Delete(WINDOW_DIALOG_PVR_CHANNEL_SCAN); + g_windowManager.Delete(WINDOW_DIALOG_PVR_UPDATE_PROGRESS); + g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CHANNELS); + g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_GUIDE); + g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_DIRECTOR); + g_windowManager.Delete(WINDOW_DIALOG_PVR_OSD_CUTTER); g_windowManager.Delete(WINDOW_DIALOG_OSD_TELETEXT); - g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER); + g_windowManager.Delete(WINDOW_DIALOG_TEXT_VIEWER); g_windowManager.Delete(WINDOW_DIALOG_PLAY_EJECT); - g_windowManager.Delete(WINDOW_STARTUP_ANIM); g_windowManager.Delete(WINDOW_LOGIN_SCREEN); g_windowManager.Delete(WINDOW_VISUALISATION); @@ -3204,6 +3279,7 @@ bool CApplication::Cleanup() g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OVERLAY); g_windowManager.Delete(WINDOW_DIALOG_VIDEO_OVERLAY); g_windowManager.Delete(WINDOW_SLIDESHOW); + g_windowManager.Delete(WINDOW_ADDON_BROWSER); g_windowManager.Delete(WINDOW_HOME); g_windowManager.Delete(WINDOW_PROGRAMS); @@ -3218,6 +3294,7 @@ bool CApplication::Cleanup() g_windowManager.Remove(WINDOW_SETTINGS_MYVIDEOS); g_windowManager.Remove(WINDOW_SETTINGS_NETWORK); g_windowManager.Remove(WINDOW_SETTINGS_APPEARANCE); + g_windowManager.Remove(WINDOW_SETTINGS_MYPVR); g_windowManager.Remove(WINDOW_DIALOG_KAI_TOAST); g_windowManager.Remove(WINDOW_DIALOG_SEEK_BAR); @@ -3337,6 +3414,8 @@ void CApplication::Stop(int exitCode) m_applicationMessenger.Cleanup(); + StopPVRManager(); + StopEPGManager(); StopServices(); //Sleep(5000); @@ -4144,7 +4223,7 @@ bool CApplication::IsPlayingFullScreenVideo() const void CApplication::SaveFileState() { - if (!g_settings.GetCurrentProfile().canWriteDatabases()) + if (m_progressTrackingItem->IsPVRChannel() || !g_settings.GetCurrentProfile().canWriteDatabases()) return; CJob* job = new CSaveFileStateJob(*m_progressTrackingItem, m_progressTrackingVideoResumeBookmark, @@ -4226,6 +4305,9 @@ void CApplication::StopPlaying() m_pKaraokeMgr->Stop(); #endif + if (g_PVRManager.IsPlayingTV() || g_PVRManager.IsPlayingRadio()) + g_PVRManager.SaveCurrentChannelSettings(); + if (m_pPlayer) m_pPlayer->CloseFile(); @@ -4445,7 +4527,7 @@ void CApplication::ActivateScreenSaver(bool forceType /*= false */) if (!forceType) { // set to Dim in the case of a dialog on screen or playing video - if (g_windowManager.HasModalDialog() || (IsPlayingVideo() && g_guiSettings.GetBool("screensaver.usedimonpause"))) + if (g_windowManager.HasModalDialog() || (IsPlayingVideo() && g_guiSettings.GetBool("screensaver.usedimonpause")) || g_PVRManager.IsRunningChannelScan()) { if (!CAddonMgr::Get().GetAddon("screensaver.xbmc.builtin.dim", m_screenSaver)) m_screenSaver.reset(new CScreenSaver("")); @@ -4487,7 +4569,8 @@ void CApplication::CheckShutdown() CGUIDialogVideoScan *pVideoScan = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN); // first check if we should reset the timer - bool resetTimer = false; + bool resetTimer = m_bInhibitIdleShutdown; + if (IsPlaying() || IsPaused()) // is something playing? resetTimer = true; @@ -4500,6 +4583,9 @@ void CApplication::CheckShutdown() if (g_windowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen resetTimer = true; + if (g_guiSettings.GetBool("pvrmanager.enabled") && !g_PVRManager.IsIdle()) + resetTimer = true; + if (resetTimer) { m_shutdownTimer.StartZero(); @@ -4516,6 +4602,16 @@ void CApplication::CheckShutdown() } } +void CApplication::InhibitIdleShutdown(bool inhibit) +{ + m_bInhibitIdleShutdown = inhibit; +} + +bool CApplication::IsIdleShutdownInhibited() const +{ + return m_bInhibitIdleShutdown; +} + bool CApplication::OnMessage(CGUIMessage& message) { switch ( message.GetMessage() ) @@ -5427,7 +5523,8 @@ bool CApplication::ProcessAndStartPlaylist(const CStdString& strPlayList, CPlayL void CApplication::SaveCurrentFileSettings() { - if (m_itemCurrentFile->IsVideo()) + // don't store settings for PVR in video database + if (m_itemCurrentFile->IsVideo() && !m_itemCurrentFile->IsPVRChannel()) { // save video settings if (g_settings.m_currentVideoSettings != g_settings.m_defaultVideoSettings) @@ -5438,6 +5535,10 @@ void CApplication::SaveCurrentFileSettings() dbs.Close(); } } + else if (m_itemCurrentFile->IsPVRChannel()) + { + g_PVRManager.SaveCurrentChannelSettings(); + } } bool CApplication::AlwaysProcess(const CAction& action) diff --git a/xbmc/Application.h b/xbmc/Application.h index 6e6a005..1be029e 100644 --- a/xbmc/Application.h +++ b/xbmc/Application.h @@ -108,6 +108,10 @@ public: void StopUPnPRenderer(); void StartUPnPServer(); void StopUPnPServer(); + void StartPVRManager(); + void StartEPGManager(void); + void StopPVRManager(); + void StopEPGManager(void); bool StartEventServer(); bool StopEventServer(bool bWait, bool promptuser); void RefreshEventServer(); @@ -153,6 +157,8 @@ public: bool OnAppCommand(const CAction &action); bool OnAction(const CAction &action); void CheckShutdown(); + void InhibitIdleShutdown(bool inhibit); + bool IsIdleShutdownInhibited() const; // Checks whether the screensaver and / or DPMS should become active. void CheckScreenSaverAndDPMS(); void CheckPlayingProgress(); @@ -311,6 +317,8 @@ protected: CStopWatch m_screenSaverTimer; CStopWatch m_shutdownTimer; + bool m_bInhibitIdleShutdown; + DPMSSupport* m_dpms; bool m_dpmsIsActive; bool m_dpmsIsManual; diff --git a/xbmc/ApplicationMessenger.cpp b/xbmc/ApplicationMessenger.cpp index 74a0a6b..a920952 100644 --- a/xbmc/ApplicationMessenger.cpp +++ b/xbmc/ApplicationMessenger.cpp @@ -53,6 +53,8 @@ #elif defined __APPLE__ #include "CocoaInterface.h" #endif +#include "addons/AddonCallbacks.h" +#include "addons/AddonCallbacksGUI.h" #include "storage/MediaManager.h" #include "guilib/LocalizeStrings.h" #include "threads/SingleLock.h" @@ -244,7 +246,7 @@ void CApplicationMessenger::ProcessMessage(ThreadMessage *pMsg) } break; -case TMSG_POWERDOWN: + case TMSG_POWERDOWN: { g_application.Stop(EXITCODE_POWERDOWN); g_powerManager.Powerdown(); @@ -286,6 +288,12 @@ case TMSG_POWERDOWN: } break; + case TMSG_INHIBITIDLESHUTDOWN: + { + g_application.InhibitIdleShutdown((bool)pMsg->dwParam1); + } + break; + case TMSG_MEDIA_PLAY: { // first check if we were called from the PlayFile() function @@ -675,6 +683,15 @@ case TMSG_POWERDOWN: } break; + case TMSG_GUI_ADDON_DIALOG: + { + if (pMsg->lpVoid) + { // TODO: This is ugly - really these python dialogs should just be normal XBMC dialogs + ((ADDON::CGUIAddonWindowDialog *) pMsg->lpVoid)->Show_Internal(pMsg->dwParam2 > 0); + } + } + break; + case TMSG_GUI_PYTHON_DIALOG: { if (pMsg->lpVoid) @@ -868,10 +885,10 @@ void CApplicationMessenger::PlayFile(const CFileItem &item, bool bRestart /*= fa SendMessage(tMsg, false); } -void CApplicationMessenger::MediaStop() +void CApplicationMessenger::MediaStop(bool bWait /* = true */) { ThreadMessage tMsg = {TMSG_MEDIA_STOP}; - SendMessage(tMsg, true); + SendMessage(tMsg, bWait); } void CApplicationMessenger::MediaPause() @@ -1076,6 +1093,12 @@ void CApplicationMessenger::RestartApp() SendMessage(tMsg); } +void CApplicationMessenger::InhibitIdleShutdown(bool inhibit) +{ + ThreadMessage tMsg = {TMSG_INHIBITIDLESHUTDOWN, (DWORD)inhibit}; + SendMessage(tMsg); +} + void CApplicationMessenger::NetworkMessage(DWORD dwMessage, DWORD dwParam) { ThreadMessage tMsg = {TMSG_NETWORKMESSAGE, dwMessage, dwParam}; diff --git a/xbmc/ApplicationMessenger.h b/xbmc/ApplicationMessenger.h index 393ee4d..87ee93a 100644 --- a/xbmc/ApplicationMessenger.h +++ b/xbmc/ApplicationMessenger.h @@ -78,6 +78,7 @@ class CGUIMessage; #define TMSG_TOGGLEFULLSCREEN 310 #define TMSG_SETLANGUAGE 311 #define TMSG_RENDERER_FLUSH 312 +#define TMSG_INHIBITIDLESHUTDOWN 313 #define TMSG_HTTPAPI 400 @@ -91,7 +92,8 @@ class CGUIMessage; #define TMSG_GUI_ACTION 607 #define TMSG_GUI_INFOLABEL 608 #define TMSG_GUI_INFOBOOL 609 -#define TMSG_GUI_MESSAGE 610 +#define TMSG_GUI_ADDON_DIALOG 610 +#define TMSG_GUI_MESSAGE 611 #define TMSG_CALLBACK 800 @@ -144,7 +146,7 @@ public: void MediaPlay(const CFileItem &item); void MediaPlay(const CFileItemList &item, int song = 0); void MediaPlay(int playlistid, int song = -1); - void MediaStop(); + void MediaStop(bool bWait = true); void MediaPause(); void MediaRestart(bool bWait); @@ -176,6 +178,7 @@ public: void Restart(); void RestartApp(); void Reset(); + void InhibitIdleShutdown(bool inhibit); void SwitchToFullscreen(); // void Minimize(bool wait = false); void ExecOS(const CStdString command, bool waitExit = false); diff --git a/xbmc/FileItem.cpp b/xbmc/FileItem.cpp index 9db1df6..21a10f9 100644 --- a/xbmc/FileItem.cpp +++ b/xbmc/FileItem.cpp @@ -40,6 +40,11 @@ #include "music/MusicDatabase.h" #include "SortFileItem.h" #include "utils/TuxBoxUtil.h" +#include "epg/Epg.h" +#include "pvr/channels/PVRChannel.h" +#include "pvr/recordings/PVRRecording.h" +#include "pvr/timers/PVRTimerInfoTag.h" +#include "utils/Observer.h" #include "video/VideoInfoTag.h" #include "threads/SingleLock.h" #include "music/tags/MusicInfoTag.h" @@ -61,11 +66,17 @@ using namespace std; using namespace XFILE; using namespace PLAYLIST; using namespace MUSIC_INFO; +using namespace PVR; +using namespace EPG; CFileItem::CFileItem(const CSong& song) { m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; Reset(); SetLabel(song.strTitle); @@ -80,6 +91,10 @@ CFileItem::CFileItem(const CStdString &path, const CAlbum& album) { m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; Reset(); SetLabel(album.strAlbum); @@ -100,6 +115,10 @@ CFileItem::CFileItem(const CVideoInfoTag& movie) { m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; Reset(); SetLabel(movie.m_strTitle); @@ -120,10 +139,145 @@ CFileItem::CFileItem(const CVideoInfoTag& movie) SetCachedVideoThumb(); } +CFileItem::CFileItem(const CEpgInfoTag& tag) +{ + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; + m_pictureInfoTag = NULL; + + Reset(); + + m_strPath = tag.Path(); + m_bIsFolder = false; + *GetEPGInfoTag() = tag; + SetLabel(tag.Title()); + m_strLabel2 = tag.Plot(); + m_dateTime = tag.StartAsLocalTime(); + + if (!tag.Icon().IsEmpty()) + { + SetThumbnailImage(tag.Icon()); + SetIconImage(tag.Icon()); + } +} + +CFileItem::CFileItem(const CPVRChannel& channel) +{ + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; + m_pictureInfoTag = NULL; + + Reset(); + CEpgInfoTag epgNow; + bool bHasEpgNow = channel.GetEPGNow(epgNow); + + m_strPath = channel.Path(); + m_bIsFolder = false; + *GetPVRChannelInfoTag() = channel; + SetLabel(channel.ChannelName()); + m_strLabel2 = bHasEpgNow ? epgNow.Title() : g_localizeStrings.Get(19055); + + if (channel.IsRadio() && bHasEpgNow) + { + CMusicInfoTag* musictag = GetMusicInfoTag(); + if (musictag) + { + musictag->SetURL(channel.Path()); + musictag->SetTitle(bHasEpgNow ? epgNow.Title() : g_localizeStrings.Get(19055)); + musictag->SetArtist(channel.ChannelName()); + musictag->SetAlbumArtist(channel.ChannelName()); + musictag->SetGenre(bHasEpgNow ? epgNow.Genre() : ""); + musictag->SetDuration(bHasEpgNow ? epgNow.GetDuration() : 3600); + musictag->SetLoaded(true); + musictag->SetComment(""); + musictag->SetLyrics(""); + } + } + + if (!channel.IconPath().IsEmpty()) + { + SetThumbnailImage(channel.IconPath()); + SetIconImage(channel.IconPath()); + } + + SetProperty("channelid", channel.ChannelID()); + SetProperty("path", channel.Path()); +} + +CFileItem::CFileItem(const CPVRRecording& record) +{ + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; + m_pictureInfoTag = NULL; + + Reset(); + + m_strPath = record.m_strFileNameAndPath; + m_bIsFolder = false; + *GetPVRRecordingInfoTag() = record; + SetLabel(record.m_strTitle); + m_strLabel2 = record.m_strPlot; + if ((!record.m_defualt_icon.IsEmpty()) && + ((record.m_defualt_icon.Left(1).CompareNoCase("/") == 0) || + (record.m_defualt_icon.Left(8).CompareNoCase("special:") == 0))) + { + SetIconImage(record.m_defualt_icon.c_str()); + } + if ((!record.m_fanart_image.IsEmpty()) && + ((record.m_fanart_image.Left(1).CompareNoCase("/") == 0) || + (record.m_fanart_image.Left(8).CompareNoCase("special:") == 0))) + { + SetProperty("Fanart_Image",record.m_fanart_image.c_str()); + } + +} + +CFileItem::CFileItem(const CPVRTimerInfoTag& timer) +{ + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; + m_pictureInfoTag = NULL; + + Reset(); + + m_strPath = timer.m_strFileNameAndPath; + m_bIsFolder = false; + *GetPVRTimerInfoTag() = timer; + SetLabel(timer.m_strTitle); + m_strLabel2 = timer.m_strSummary; + m_dateTime = timer.StartAsLocalTime(); + + if (!timer.ChannelIcon().IsEmpty()) + { + SetThumbnailImage(timer.ChannelIcon()); + SetIconImage(timer.ChannelIcon()); + } +} + CFileItem::CFileItem(const CArtist& artist) { m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; Reset(); SetLabel(artist.strArtist); @@ -137,6 +291,10 @@ CFileItem::CFileItem(const CGenre& genre) { m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; Reset(); SetLabel(genre.strGenre); @@ -150,6 +308,10 @@ CFileItem::CFileItem(const CFileItem& item): CGUIListItem() { m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; *this = item; } @@ -158,6 +320,10 @@ CFileItem::CFileItem(const CGUIListItem& item) { m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; Reset(); // not particularly pretty, but it gets around the issue of Reset() defaulting @@ -169,6 +335,10 @@ CFileItem::CFileItem(void) { m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; Reset(); } @@ -178,6 +348,10 @@ CFileItem::CFileItem(const CStdString& strLabel) { m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; Reset(); SetLabel(strLabel); @@ -187,6 +361,10 @@ CFileItem::CFileItem(const CStdString& strPath, bool bIsFolder) { m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; Reset(); m_strPath = strPath; @@ -200,6 +378,10 @@ CFileItem::CFileItem(const CMediaSource& share) { m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; Reset(); m_bIsFolder = true; @@ -225,10 +407,18 @@ CFileItem::~CFileItem(void) { delete m_musicInfoTag; delete m_videoInfoTag; + delete m_epgInfoTag; + delete m_pvrChannelInfoTag; + delete m_pvrRecordingInfoTag; + delete m_pvrTimerInfoTag; delete m_pictureInfoTag; m_musicInfoTag = NULL; m_videoInfoTag = NULL; + m_epgInfoTag = NULL; + m_pvrChannelInfoTag = NULL; + m_pvrRecordingInfoTag = NULL; + m_pvrTimerInfoTag = NULL; m_pictureInfoTag = NULL; } @@ -268,6 +458,62 @@ const CFileItem& CFileItem::operator=(const CFileItem& item) m_videoInfoTag = NULL; } + if (item.HasEPGInfoTag()) + { + m_epgInfoTag = GetEPGInfoTag(); + if (m_epgInfoTag) + *m_epgInfoTag = *item.m_epgInfoTag; + } + else + { + if (m_epgInfoTag) + delete m_epgInfoTag; + + m_epgInfoTag = NULL; + } + + if (item.HasPVRChannelInfoTag()) + { + m_pvrChannelInfoTag = GetPVRChannelInfoTag(); + if (m_pvrChannelInfoTag) + *m_pvrChannelInfoTag = *item.m_pvrChannelInfoTag; + } + else + { + if (m_pvrChannelInfoTag) + delete m_pvrChannelInfoTag; + + m_pvrChannelInfoTag = NULL; + } + + if (item.HasPVRRecordingInfoTag()) + { + m_pvrRecordingInfoTag = GetPVRRecordingInfoTag(); + if (m_pvrRecordingInfoTag) + *m_pvrRecordingInfoTag = *item.m_pvrRecordingInfoTag; + } + else + { + if (m_pvrRecordingInfoTag) + delete m_pvrRecordingInfoTag; + + m_pvrRecordingInfoTag = NULL; + } + + if (item.HasPVRTimerInfoTag()) + { + m_pvrTimerInfoTag = GetPVRTimerInfoTag(); + if (m_pvrTimerInfoTag) + *m_pvrTimerInfoTag = *item.m_pvrTimerInfoTag; + } + else + { + if (m_pvrTimerInfoTag) + delete m_pvrTimerInfoTag; + + m_pvrTimerInfoTag = NULL; + } + if (item.HasPictureInfoTag()) { m_pictureInfoTag = GetPictureInfoTag(); @@ -330,6 +576,14 @@ void CFileItem::Reset() m_musicInfoTag=NULL; delete m_videoInfoTag; m_videoInfoTag=NULL; + delete m_epgInfoTag; + m_epgInfoTag=NULL; + delete m_pvrChannelInfoTag; + m_pvrChannelInfoTag=NULL; + delete m_pvrRecordingInfoTag; + m_pvrRecordingInfoTag=NULL; + delete m_pvrTimerInfoTag; + m_pvrTimerInfoTag=NULL; delete m_pictureInfoTag; m_pictureInfoTag=NULL; m_extrainfo.Empty(); @@ -492,6 +746,7 @@ bool CFileItem::IsVideo() const if (HasVideoInfoTag()) return true; if (HasMusicInfoTag()) return false; if (HasPictureInfoTag()) return false; + if (IsPVRRecording()) return true; if (IsHDHomeRun() || IsTuxBox() || URIUtils::IsDVD(m_strPath) || IsSlingbox()) return true; @@ -516,6 +771,30 @@ bool CFileItem::IsVideo() const return (g_settings.m_videoExtensions.Find(extension) != -1); } +bool CFileItem::IsEPG() const +{ + if (HasEPGInfoTag()) return true; /// is this enough? + return false; +} + +bool CFileItem::IsPVRChannel() const +{ + if (HasPVRChannelInfoTag()) return true; /// is this enough? + return false; +} + +bool CFileItem::IsPVRRecording() const +{ + if (HasPVRRecordingInfoTag()) return true; /// is this enough? + return false; +} + +bool CFileItem::IsPVRTimer() const +{ + if (HasPVRTimerInfoTag()) return true; /// is this enough? + return false; +} + bool CFileItem::IsDiscStub() const { CStdString strExtension; @@ -836,6 +1115,11 @@ bool CFileItem::IsVTP() const return URIUtils::IsVTP(m_strPath); } +bool CFileItem::IsPVR() const +{ + return CUtil::IsPVR(m_strPath); +} + bool CFileItem::IsLiveTV() const { return URIUtils::IsLiveTV(m_strPath); @@ -900,7 +1184,19 @@ void CFileItem::FillInDefaultIcon() * in mind the complexity of the code behind the check in the * case of IsWhatater() returns false. */ - if ( IsAudio() ) + if (IsPVRChannel()) + { + if (GetPVRChannelInfoTag()->IsRadio()) + SetIconImage("DefaultAudio.png"); + else + SetIconImage("DefaultVideo.png"); + } + else if ( IsLiveTV() ) + { + // Live TV Channel + SetIconImage("DefaultVideo.png"); + } + else if ( IsAudio() ) { // audio SetIconImage("DefaultAudio.png"); @@ -910,6 +1206,14 @@ void CFileItem::FillInDefaultIcon() // video SetIconImage("DefaultVideo.png"); } + else if (IsPVRRecording()) + { + SetIconImage("DefaultVideo.png"); + } + else if (IsPVRTimer()) + { + SetIconImage("DefaultVideo.png"); + } else if ( IsPicture() ) { // picture @@ -1046,6 +1350,12 @@ void CFileItem::SetLabel(const CStdString &strLabel) CGUIListItem::SetLabel(strLabel); } +void CFileItem::SetLabel2(const CStdString &strLabel) +{ + m_strLabel2 = strLabel; +} + + void CFileItem::SetFileSizeLabel() { if( m_bIsFolder && m_dwSize == 0 ) @@ -1629,6 +1939,9 @@ void CFileItemList::Sort(SORT_METHOD sortMethod, SORT_ORDER sortOrder) case SORT_METHOD_LISTENERS: FillSortFields(SSortFileItem::ByListeners); break; + case SORT_METHOD_CHANNEL: + FillSortFields(SSortFileItem::ByChannel); + break; default: break; } @@ -2377,6 +2690,8 @@ bool CFileItemList::AlwaysCache() const return CMusicDatabaseDirectory::CanCache(GetPath()); if (IsVideoDb()) return CVideoDatabaseDirectory::CanCache(GetPath()); + if (IsEPG()) + return true; // always cache return false; } @@ -3051,6 +3366,38 @@ CVideoInfoTag* CFileItem::GetVideoInfoTag() return m_videoInfoTag; } +CEpgInfoTag* CFileItem::GetEPGInfoTag() +{ + if (!m_epgInfoTag) + m_epgInfoTag = new CEpgInfoTag; + + return m_epgInfoTag; +} + +CPVRChannel* CFileItem::GetPVRChannelInfoTag() +{ + if (!m_pvrChannelInfoTag) + m_pvrChannelInfoTag = new CPVRChannel; + + return m_pvrChannelInfoTag; +} + +CPVRRecording* CFileItem::GetPVRRecordingInfoTag() +{ + if (!m_pvrRecordingInfoTag) + m_pvrRecordingInfoTag = new CPVRRecording; + + return m_pvrRecordingInfoTag; +} + +CPVRTimerInfoTag* CFileItem::GetPVRTimerInfoTag() +{ + if (!m_pvrTimerInfoTag) + m_pvrTimerInfoTag = new CPVRTimerInfoTag; + + return m_pvrTimerInfoTag; +} + CPictureInfoTag* CFileItem::GetPictureInfoTag() { if (!m_pictureInfoTag) diff --git a/xbmc/FileItem.h b/xbmc/FileItem.h index 73faf0d..e781823 100644 --- a/xbmc/FileItem.h +++ b/xbmc/FileItem.h @@ -42,6 +42,16 @@ namespace MUSIC_INFO class CMusicInfoTag; } class CVideoInfoTag; +namespace EPG +{ + class CEpgInfoTag; +} +namespace PVR +{ + class CPVRChannel; + class CPVRRecording; + class CPVRTimerInfoTag; +} class CPictureInfoTag; class CAlbum; @@ -74,6 +84,10 @@ public: CFileItem(const CArtist& artist); CFileItem(const CGenre& genre); CFileItem(const CVideoInfoTag& movie); + CFileItem(const EPG::CEpgInfoTag& tag); + CFileItem(const PVR::CPVRChannel& channel); + CFileItem(const PVR::CPVRRecording& record); + CFileItem(const PVR::CPVRTimerInfoTag& timer); CFileItem(const CMediaSource& share); virtual ~CFileItem(void); virtual CGUIListItem *Clone() const { return new CFileItem(*this); }; @@ -131,6 +145,10 @@ public: bool IsMultiPath() const; bool IsMusicDb() const; bool IsVideoDb() const; + bool IsEPG() const; + bool IsPVRChannel() const; + bool IsPVRRecording() const; + bool IsPVRTimer() const; bool IsType(const char *ext) const; bool IsVirtualDirectoryRoot() const; bool IsReadOnly() const; @@ -144,6 +162,7 @@ public: bool IsHDHomeRun() const; bool IsSlingbox() const; bool IsVTP() const; + bool IsPVR() const; bool IsLiveTV() const; bool IsRSS() const; @@ -153,6 +172,7 @@ public: void SetMusicThumb(bool alwaysCheckRemote = false); void SetFileSizeLabel(); virtual void SetLabel(const CStdString &strLabel); + virtual void SetLabel2(const CStdString &strLabel); CURL GetAsUrl() const; int GetVideoContentType() const; /* return VIDEODB_CONTENT_TYPE, but don't want to include videodb in this header */ bool IsLabelPreformated() const { return m_bLabelPreformated; } @@ -185,6 +205,54 @@ public: return m_videoInfoTag; } + inline bool HasEPGInfoTag() const + { + return m_epgInfoTag != NULL; + } + + EPG::CEpgInfoTag* GetEPGInfoTag(); + + inline const EPG::CEpgInfoTag* GetEPGInfoTag() const + { + return m_epgInfoTag; + } + + inline bool HasPVRChannelInfoTag() const + { + return m_pvrChannelInfoTag != NULL; + } + + PVR::CPVRChannel* GetPVRChannelInfoTag(); + + inline const PVR::CPVRChannel* GetPVRChannelInfoTag() const + { + return m_pvrChannelInfoTag; + } + + inline bool HasPVRRecordingInfoTag() const + { + return m_pvrRecordingInfoTag != NULL; + } + + PVR::CPVRRecording* GetPVRRecordingInfoTag(); + + inline const PVR::CPVRRecording* GetPVRRecordingInfoTag() const + { + return m_pvrRecordingInfoTag; + } + + inline bool HasPVRTimerInfoTag() const + { + return m_pvrTimerInfoTag != NULL; + } + + PVR::CPVRTimerInfoTag* GetPVRTimerInfoTag(); + + inline const PVR::CPVRTimerInfoTag* GetPVRTimerInfoTag() const + { + return m_pvrTimerInfoTag; + } + inline bool HasPictureInfoTag() const { return m_pictureInfoTag != NULL; @@ -333,6 +401,10 @@ private: CStdString m_extrainfo; MUSIC_INFO::CMusicInfoTag* m_musicInfoTag; CVideoInfoTag* m_videoInfoTag; + EPG::CEpgInfoTag* m_epgInfoTag; + PVR::CPVRChannel* m_pvrChannelInfoTag; + PVR::CPVRRecording* m_pvrRecordingInfoTag; + PVR::CPVRTimerInfoTag * m_pvrTimerInfoTag; CPictureInfoTag* m_pictureInfoTag; bool m_bIsAlbum; }; diff --git a/xbmc/GUIInfoManager.cpp b/xbmc/GUIInfoManager.cpp index 72f5f95..2e4f7b5 100644 --- a/xbmc/GUIInfoManager.cpp +++ b/xbmc/GUIInfoManager.cpp @@ -74,6 +74,12 @@ #include "threads/SingleLock.h" #include "utils/log.h" +#include "pvr/PVRManager.h" +#include "pvr/channels/PVRChannelGroupsContainer.h" +#include "epg/EpgInfoTag.h" +#include "pvr/timers/PVRTimers.h" +#include "pvr/recordings/PVRRecording.h" + #include "addons/AddonManager.h" #include "interfaces/info/InfoBool.h" @@ -83,9 +89,12 @@ using namespace std; using namespace XFILE; using namespace MUSIC_INFO; using namespace ADDON; +using namespace PVR; using namespace INFO; +using namespace EPG; -CGUIInfoManager::CGUIInfoManager(void) +CGUIInfoManager::CGUIInfoManager(void) : + Observable() { m_lastSysHeatInfoTime = -SYSHEATUPDATEINTERVAL; // make sure we grab CPU temp on the first pass m_lastMusicBitrateTime = 0; @@ -255,6 +264,8 @@ const infomap system_labels[] = {{ "hasnetwork", SYSTEM_ETHERNET_LINK_ACT { "batterylevel", SYSTEM_BATTERY_LEVEL }, { "friendlyname", SYSTEM_FRIENDLY_NAME }, { "alarmpos", SYSTEM_ALARM_POS }, + { "isinhibit", SYSTEM_ISINHIBIT }, + { "hasshutdown", SYSTEM_HAS_SHUTDOWN }, { "haspvr", SYSTEM_HAS_PVR }}; const infomap system_param[] = {{ "hasalarm", SYSTEM_HAS_ALARM }, @@ -334,7 +345,11 @@ const infomap musicplayer[] = {{ "title", MUSICPLAYER_TITLE }, { "hasprevious", MUSICPLAYER_HASPREVIOUS }, { "hasnext", MUSICPLAYER_HASNEXT }, { "playcount", MUSICPLAYER_PLAYCOUNT }, - { "lastplayed", MUSICPLAYER_LASTPLAYED }}; + { "lastplayed", MUSICPLAYER_LASTPLAYED }, + { "channelname", MUSICPLAYER_CHANNEL_NAME }, + { "channelnumber", MUSICPLAYER_CHANNEL_NUMBER }, + { "channelgroup", MUSICPLAYER_CHANNEL_GROUP } +}; const infomap videoplayer[] = {{ "title", VIDEOPLAYER_TITLE }, { "genre", VIDEOPLAYER_GENRE }, @@ -376,7 +391,20 @@ const infomap videoplayer[] = {{ "title", VIDEOPLAYER_TITLE }, { "lastplayed", VIDEOPLAYER_LASTPLAYED }, { "playcount", VIDEOPLAYER_PLAYCOUNT }, { "hassubtitles", VIDEOPLAYER_HASSUBTITLES }, - { "subtitlesenabled", VIDEOPLAYER_SUBTITLESENABLED }}; + { "subtitlesenabled", VIDEOPLAYER_SUBTITLESENABLED }, + { "endtime", VIDEOPLAYER_ENDTIME }, + { "nexttitle", VIDEOPLAYER_NEXT_TITLE }, + { "nextgenre", VIDEOPLAYER_NEXT_GENRE }, + { "nextplot", VIDEOPLAYER_NEXT_PLOT }, + { "nextplotoutline", VIDEOPLAYER_NEXT_PLOT_OUTLINE }, + { "nextstarttime", VIDEOPLAYER_NEXT_STARTTIME }, + { "nextendtime", VIDEOPLAYER_NEXT_ENDTIME }, + { "nextduration", VIDEOPLAYER_NEXT_DURATION }, + { "channelname", VIDEOPLAYER_CHANNEL_NAME }, + { "channelnumber", VIDEOPLAYER_CHANNEL_NUMBER }, + { "channelgroup", VIDEOPLAYER_CHANNEL_GROUP }, + { "hasepg", VIDEOPLAYER_HAS_EPG }, + { "parentalrating", VIDEOPLAYER_PARENTAL_RATING }}; const infomap mediacontainer[] = {{ "hasfiles", CONTAINER_HASFILES }, { "hasfolders", CONTAINER_HASFOLDERS }, @@ -475,7 +503,27 @@ const infomap listitem_labels[]= {{ "thumb", LISTITEM_THUMB }, { "originaltitle", LISTITEM_ORIGINALTITLE }, { "lastplayed", LISTITEM_LASTPLAYED }, { "playcount", LISTITEM_PLAYCOUNT }, - { "discnumber", LISTITEM_DISC_NUMBER }}; + { "discnumber", LISTITEM_DISC_NUMBER }, + { "starttime", LISTITEM_STARTTIME }, + { "endtime", LISTITEM_ENDTIME }, + { "startdate", LISTITEM_STARTDATE }, + { "enddate", LISTITEM_ENDDATE }, + { "nexttitle", LISTITEM_NEXT_TITLE }, + { "nextgenre", LISTITEM_NEXT_GENRE }, + { "nextplot", LISTITEM_NEXT_PLOT }, + { "nextplotoutline", LISTITEM_NEXT_PLOT_OUTLINE }, + { "nextstarttime", LISTITEM_NEXT_STARTTIME }, + { "nextendtime", LISTITEM_NEXT_ENDTIME }, + { "nextstartdate", LISTITEM_NEXT_STARTDATE }, + { "nextenddate", LISTITEM_NEXT_ENDDATE }, + { "channelname", LISTITEM_CHANNEL_NAME }, + { "channelnumber", LISTITEM_CHANNEL_NUMBER }, + { "channelgroup", LISTITEM_CHANNEL_GROUP }, + { "hasepg", LISTITEM_HAS_EPG }, + { "hastimer", LISTITEM_HASTIMER }, + { "isrecording", LISTITEM_ISRECORDING }, + { "isencrypted", LISTITEM_ISENCRYPTED }, + { "progress", LISTITEM_PROGRESS }}; const infomap visualisation[] = {{ "locked", VISUALISATION_LOCKED }, { "preset", VISUALISATION_PRESET }, @@ -512,6 +560,51 @@ const infomap playlist[] = {{ "length", PLAYLIST_LENGTH }, { "isrepeat", PLAYLIST_ISREPEAT }, { "isrepeatone", PLAYLIST_ISREPEATONE }}; +const infomap pvr[] = {{ "isrecording", PVR_IS_RECORDING }, + { "hastimer", PVR_HAS_TIMER }, + { "hasnonrecordingtimer", PVR_HAS_NONRECORDING_TIMER }, + { "nowrecordingtitle", PVR_NOW_RECORDING_TITLE }, + { "nowrecordingdatetime", PVR_NOW_RECORDING_DATETIME }, + { "nowrecordingchannel", PVR_NOW_RECORDING_CHANNEL }, + { "nowrecordingchannelicon", PVR_NOW_RECORDING_CHAN_ICO }, + { "nextrecordingtitle", PVR_NEXT_RECORDING_TITLE }, + { "nextrecordingdatetime", PVR_NEXT_RECORDING_DATETIME }, + { "nextrecordingchannel", PVR_NEXT_RECORDING_CHANNEL }, + { "nextrecordingchannelicon", PVR_NEXT_RECORDING_CHAN_ICO }, + { "backendname", PVR_BACKEND_NAME }, + { "backendversion", PVR_BACKEND_VERSION }, + { "backendhost", PVR_BACKEND_HOST }, + { "backenddiskspace", PVR_BACKEND_DISKSPACE }, + { "backendchannels", PVR_BACKEND_CHANNELS }, + { "backendtimers", PVR_BACKEND_TIMERS }, + { "backendrecordings", PVR_BACKEND_RECORDINGS }, + { "backendnumber", PVR_BACKEND_NUMBER }, + { "hasepg", PVR_HAS_EPG }, + { "hastxt", PVR_HAS_TXT }, + { "hasdirector", PVR_HAS_DIRECTOR }, + { "totaldiscspace", PVR_TOTAL_DISKSPACE }, + { "nexttimer", PVR_NEXT_TIMER }, + { "isplayingtv", PVR_IS_PLAYING_TV }, + { "isplayingradio", PVR_IS_PLAYING_RADIO }, + { "isplayingrecording", PVR_IS_PLAYING_RECORDING }, + { "duration", PVR_PLAYING_DURATION }, + { "time", PVR_PLAYING_TIME }, + { "progress", PVR_PLAYING_PROGRESS }, + { "actstreamclient", PVR_ACTUAL_STREAM_CLIENT }, + { "actstreamdevice", PVR_ACTUAL_STREAM_DEVICE }, + { "actstreamstatus", PVR_ACTUAL_STREAM_STATUS }, + { "actstreamsignal", PVR_ACTUAL_STREAM_SIG }, + { "actstreamsnr", PVR_ACTUAL_STREAM_SNR }, + { "actstreamber", PVR_ACTUAL_STREAM_BER }, + { "actstreamunc", PVR_ACTUAL_STREAM_UNC }, + { "actstreamvideobitrate", PVR_ACTUAL_STREAM_VIDEO_BR }, + { "actstreamaudiobitrate", PVR_ACTUAL_STREAM_AUDIO_BR }, + { "actstreamdolbybitrate", PVR_ACTUAL_STREAM_DOLBY_BR }, + { "actstreamprogrsignal", PVR_ACTUAL_STREAM_SIG_PROGR }, + { "actstreamprogrsnr", PVR_ACTUAL_STREAM_SNR_PROGR }, + { "actstreamisencrypted", PVR_ACTUAL_STREAM_ENCRYPTED }, + { "actstreamencryptionname", PVR_ACTUAL_STREAM_CRYPTION }}; + const infomap slideshow[] = {{ "ispaused", SLIDESHOW_ISPAUSED }, { "isactive", SLIDESHOW_ISACTIVE }, { "israndom", SLIDESHOW_ISRANDOM }}; @@ -968,6 +1061,14 @@ int CGUIInfoManager::TranslateSingleString(const CStdString &strCondition) return playlist[i].val; } } + else if (cat.name == "pvr") + { + for (size_t i = 0; i < sizeof(pvr) / sizeof(infomap); i++) + { + if (prop.name == pvr[i].str) + return pvr[i].val; + } + } } else if (info.size() == 3) { @@ -1085,6 +1186,42 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow) switch (info) { + case PVR_NEXT_RECORDING_CHANNEL: + case PVR_NEXT_RECORDING_CHAN_ICO: + case PVR_NEXT_RECORDING_DATETIME: + case PVR_NEXT_RECORDING_TITLE: + case PVR_NOW_RECORDING_CHANNEL: + case PVR_NOW_RECORDING_CHAN_ICO: + case PVR_NOW_RECORDING_DATETIME: + case PVR_NOW_RECORDING_TITLE: + case PVR_BACKEND_NAME: + case PVR_BACKEND_VERSION: + case PVR_BACKEND_HOST: + case PVR_BACKEND_DISKSPACE: + case PVR_BACKEND_CHANNELS: + case PVR_BACKEND_TIMERS: + case PVR_BACKEND_RECORDINGS: + case PVR_BACKEND_NUMBER: + case PVR_TOTAL_DISKSPACE: + case PVR_NEXT_TIMER: + case PVR_PLAYING_DURATION: + case PVR_PLAYING_TIME: + case PVR_PLAYING_PROGRESS: + case PVR_ACTUAL_STREAM_CLIENT: + case PVR_ACTUAL_STREAM_DEVICE: + case PVR_ACTUAL_STREAM_STATUS: + case PVR_ACTUAL_STREAM_SIG: + case PVR_ACTUAL_STREAM_SNR: + case PVR_ACTUAL_STREAM_SIG_PROGR: + case PVR_ACTUAL_STREAM_SNR_PROGR: + case PVR_ACTUAL_STREAM_BER: + case PVR_ACTUAL_STREAM_UNC: + case PVR_ACTUAL_STREAM_VIDEO_BR: + case PVR_ACTUAL_STREAM_AUDIO_BR: + case PVR_ACTUAL_STREAM_DOLBY_BR: + case PVR_ACTUAL_STREAM_CRYPTION: + g_PVRManager.TranslateCharInfo(info, strLabel); + break; case WEATHER_CONDITIONS: strLabel = g_weatherManager.GetInfo(WEATHER_LABEL_CURRENT_COND); strLabel = strLabel.Trim(); @@ -1185,6 +1322,9 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow) case MUSICPLAYER_RATING: case MUSICPLAYER_COMMENT: case MUSICPLAYER_LYRICS: + case MUSICPLAYER_CHANNEL_NAME: + case MUSICPLAYER_CHANNEL_NUMBER: + case MUSICPLAYER_CHANNEL_GROUP: case MUSICPLAYER_PLAYCOUNT: case MUSICPLAYER_LASTPLAYED: strLabel = GetMusicLabel(info); @@ -1215,6 +1355,19 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow) case VIDEOPLAYER_WRITER: case VIDEOPLAYER_TAGLINE: case VIDEOPLAYER_TRAILER: + case VIDEOPLAYER_STARTTIME: + case VIDEOPLAYER_ENDTIME: + case VIDEOPLAYER_NEXT_TITLE: + case VIDEOPLAYER_NEXT_GENRE: + case VIDEOPLAYER_NEXT_PLOT: + case VIDEOPLAYER_NEXT_PLOT_OUTLINE: + case VIDEOPLAYER_NEXT_STARTTIME: + case VIDEOPLAYER_NEXT_ENDTIME: + case VIDEOPLAYER_NEXT_DURATION: + case VIDEOPLAYER_CHANNEL_NAME: + case VIDEOPLAYER_CHANNEL_NUMBER: + case VIDEOPLAYER_CHANNEL_GROUP: + case VIDEOPLAYER_PARENTAL_RATING: case VIDEOPLAYER_PLAYCOUNT: case VIDEOPLAYER_LASTPLAYED: strLabel = GetVideoLabel(info); @@ -1736,6 +1889,11 @@ bool CGUIInfoManager::GetInt(int &value, int info, int contextWindow, const CGUI case SYSTEM_CPU_USAGE: value = g_cpuInfo.getUsedPercentage(); return true; + case PVR_PLAYING_PROGRESS: + case PVR_ACTUAL_STREAM_SIG_PROGR: + case PVR_ACTUAL_STREAM_SNR_PROGR: + value = g_PVRManager.TranslateIntInfo(info); + return true; case SYSTEM_BATTERY_LEVEL: value = g_powerManager.BatteryLevel(); return true; @@ -1927,6 +2085,10 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI bReturn = g_Windowing.IsFullScreen(); else if (condition == SYSTEM_ISSTANDALONE) bReturn = g_application.IsStandAlone(); + else if (condition == SYSTEM_ISINHIBIT) + bReturn = g_application.IsIdleShutdownInhibited(); + else if (condition == SYSTEM_HAS_SHUTDOWN) + bReturn = (g_guiSettings.GetInt("powermanagement.shutdowntime") > 0); else if (condition == SYSTEM_LOGGEDON) bReturn = !(g_windowManager.GetActiveWindow() == WINDOW_LOGIN_SCREEN); else if (condition == SYSTEM_SHOW_EXIT_BUTTON) @@ -1935,6 +2097,9 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI bReturn = g_settings.UsingLoginScreen(); else if (condition == WEATHER_IS_FETCHED) bReturn = g_weatherManager.IsFetched(); + else if (condition >= PVR_CONDITIONS_START && condition <= PVR_CONDITIONS_END) + bReturn = g_PVRManager.TranslateBoolInfo(condition); + else if (condition == SYSTEM_INTERNET_STATE) { g_sysinfo.GetInfo(condition); @@ -1993,7 +2158,8 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI } } else if (condition == VIDEOPLAYER_HAS_INFO) - bReturn = (m_currentFile->HasVideoInfoTag() && !m_currentFile->GetVideoInfoTag()->IsEmpty()); + bReturn = ((m_currentFile->HasVideoInfoTag() && !m_currentFile->GetVideoInfoTag()->IsEmpty()) || + (m_currentFile->HasPVRChannelInfoTag() && !m_currentFile->GetPVRChannelInfoTag()->IsEmpty())); else if (condition >= CONTAINER_SCROLL_PREVIOUS && condition <= CONTAINER_SCROLL_NEXT) { // no parameters, so we assume it's just requested for a media window. It therefore @@ -2191,6 +2357,13 @@ bool CGUIInfoManager::GetBool(int condition1, int contextWindow, const CGUIListI case VISUALISATION_ENABLED: bReturn = !g_guiSettings.GetString("musicplayer.visualisation").IsEmpty(); break; + case VIDEOPLAYER_HAS_EPG: + if (m_currentFile->HasPVRChannelInfoTag()) + { + CEpgInfoTag epgTag; + bReturn = m_currentFile->GetPVRChannelInfoTag()->GetEPGNow(epgTag); + } + break; default: // default, use integer value different from 0 as true { int val; @@ -2531,6 +2704,8 @@ bool CGUIInfoManager::GetMultiInfoBool(const GUIInfo &info, int contextWindow, c strContent = "musicvideos"; if (m_currentFile->HasVideoInfoTag() && m_currentFile->GetVideoInfoTag()->m_strStatus == "livetv") strContent = "livetv"; + if (m_currentFile->HasPVRChannelInfoTag()) + strContent = "livetv"; bReturn = m_stringParameters[info.GetData1()].Equals(strContent); } break; @@ -3266,6 +3441,31 @@ CStdString CGUIInfoManager::GetMusicTagLabel(int info, const CFileItem *item) return GetItemLabel(item, LISTITEM_COMMENT); case MUSICPLAYER_DURATION: return GetItemLabel(item, LISTITEM_DURATION); + case MUSICPLAYER_CHANNEL_NAME: + { + CPVRChannel* channeltag = m_currentFile->GetPVRChannelInfoTag(); + if (channeltag) + return channeltag->ChannelName(); + } + break; + case MUSICPLAYER_CHANNEL_NUMBER: + { + CPVRChannel* channeltag = m_currentFile->GetPVRChannelInfoTag(); + if (channeltag) + { + CStdString strNumber; + strNumber.Format("%i", channeltag->ChannelNumber()); + return strNumber; + } + } + break; + case MUSICPLAYER_CHANNEL_GROUP: + { + CPVRChannel* channeltag = m_currentFile->GetPVRChannelInfoTag(); + if (channeltag && channeltag->IsRadio()) + return g_PVRManager.GetPlayingGroup(true)->GroupName(); + } + break; case MUSICPLAYER_PLAYCOUNT: return GetItemLabel(item, LISTITEM_PLAYCOUNT); case MUSICPLAYER_LASTPLAYED: @@ -3281,6 +3481,11 @@ CStdString CGUIInfoManager::GetVideoLabel(int item) if (item == VIDEOPLAYER_TITLE) { + if (m_currentFile->HasPVRChannelInfoTag()) + { + CEpgInfoTag tag; + return m_currentFile->GetPVRChannelInfoTag()->GetEPGNow(tag) ? tag.Title() : g_localizeStrings.Get(19055); + } if (m_currentFile->HasVideoInfoTag() && !m_currentFile->GetVideoInfoTag()->m_strTitle.IsEmpty()) return m_currentFile->GetVideoInfoTag()->m_strTitle; // don't have the title, so use dvdplayer, label, or drop down to title from path @@ -3300,6 +3505,73 @@ CStdString CGUIInfoManager::GetVideoLabel(int item) if (g_playlistPlayer.GetCurrentPlaylist() == PLAYLIST_VIDEO) return GetPlaylistLabel(PLAYLIST_POSITION); } + else if (m_currentFile->HasPVRChannelInfoTag()) + { + CPVRChannel* tag = m_currentFile->GetPVRChannelInfoTag(); + CEpgInfoTag epgTag; + + switch (item) + { + /* Now playing infos */ + case VIDEOPLAYER_ORIGINALTITLE: + return tag->GetEPGNow(epgTag) ? epgTag.Title() : g_localizeStrings.Get(19055); + case VIDEOPLAYER_GENRE: + return tag->GetEPGNow(epgTag) ? epgTag.Genre() : StringUtils::EmptyString; + case VIDEOPLAYER_PLOT: + return tag->GetEPGNow(epgTag) ? epgTag.Plot() : StringUtils::EmptyString; + case VIDEOPLAYER_PLOT_OUTLINE: + return tag->GetEPGNow(epgTag) ? epgTag.PlotOutline() : StringUtils::EmptyString; + case VIDEOPLAYER_STARTTIME: + return tag->GetEPGNow(epgTag) ? epgTag.StartAsLocalTime().GetAsLocalizedTime("", false) : CDateTime::GetCurrentDateTime().GetAsLocalizedTime("", false); + case VIDEOPLAYER_ENDTIME: + return tag->GetEPGNow(epgTag) ? epgTag.EndAsLocalTime().GetAsLocalizedTime("", false) : CDateTime::GetCurrentDateTime().GetAsLocalizedTime("", false); + + /* Next playing infos */ + case VIDEOPLAYER_NEXT_TITLE: + return tag->GetEPGNext(epgTag) ? epgTag.Title() : g_localizeStrings.Get(19055); + case VIDEOPLAYER_NEXT_GENRE: + return tag->GetEPGNext(epgTag) ? epgTag.Genre() : StringUtils::EmptyString; + case VIDEOPLAYER_NEXT_PLOT: + return tag->GetEPGNext(epgTag) ? epgTag.Plot() : StringUtils::EmptyString; + case VIDEOPLAYER_NEXT_PLOT_OUTLINE: + return tag->GetEPGNext(epgTag) ? epgTag.PlotOutline() : StringUtils::EmptyString; + case VIDEOPLAYER_NEXT_STARTTIME: + return tag->GetEPGNext(epgTag) ? epgTag.StartAsLocalTime().GetAsLocalizedTime("", false) : CDateTime::GetCurrentDateTime().GetAsLocalizedTime("", false); + case VIDEOPLAYER_NEXT_ENDTIME: + return tag->GetEPGNext(epgTag) ? epgTag.EndAsLocalTime().GetAsLocalizedTime("", false) : CDateTime::GetCurrentDateTime().GetAsLocalizedTime("", false); + case VIDEOPLAYER_NEXT_DURATION: + { + CStdString duration; + if (tag->GetEPGNext(epgTag) && epgTag.GetDuration() > 0) + duration = StringUtils::SecondsToTimeString(epgTag.GetDuration()); + return duration; + } + + case VIDEOPLAYER_PARENTAL_RATING: + { + CStdString rating; + if (tag->GetEPGNow(epgTag) && epgTag.ParentalRating() > 0) + rating.Format("%i", epgTag.ParentalRating()); + return rating; + } + break; + + /* General channel infos */ + case VIDEOPLAYER_CHANNEL_NAME: + return tag->ChannelName(); + case VIDEOPLAYER_CHANNEL_NUMBER: + { + CStdString strNumber; + strNumber.Format("%i", tag->ChannelNumber()); + return strNumber; + } + case VIDEOPLAYER_CHANNEL_GROUP: + { + if (tag && !tag->IsRadio()) + return g_PVRManager.GetPlayingGroup(false)->GroupName(); + } + } + } else if (m_currentFile->HasVideoInfoTag()) { switch (item) @@ -3476,6 +3748,9 @@ void CGUIInfoManager::SetCurrentItem(CFileItem &item) SetCurrentSong(item); else SetCurrentMovie(item); + + SetChanged(); + NotifyObservers("current-item", true); } void CGUIInfoManager::SetCurrentAlbumThumb(const CStdString thumbFileName) @@ -3532,11 +3807,15 @@ void CGUIInfoManager::SetCurrentMovie(CFileItem &item) CLog::Log(LOGDEBUG,"CGUIInfoManager::SetCurrentMovie(%s)",item.GetPath().c_str()); *m_currentFile = item; - CVideoDatabase dbs; - if (dbs.Open()) + /* also call GetMovieInfo() when a VideoInfoTag is already present or additional info won't be present in the tag */ + if (!m_currentFile->HasPVRChannelInfoTag()) { - dbs.LoadVideoInfo(item.GetPath(), *m_currentFile->GetVideoInfoTag()); - dbs.Close(); + CVideoDatabase dbs; + if (dbs.Open()) + { + dbs.LoadVideoInfo(item.GetPath(), *m_currentFile->GetVideoInfoTag()); + dbs.Close(); + } } // Find a thumb for this file. @@ -3783,6 +4062,27 @@ bool CGUIInfoManager::GetItemInt(int &value, const CGUIListItem *item, int info) switch (info) { + case LISTITEM_PROGRESS: + { + value = 0; + if (item->IsFileItem()) + { + const CFileItem *pItem = (const CFileItem *)item; + if (pItem && pItem->HasPVRChannelInfoTag()) + { + CEpgInfoTag epgNow; + if (pItem->GetPVRChannelInfoTag()->GetEPGNow(epgNow)) + value = (int) epgNow.ProgressPercentage(); + } + else if (pItem && pItem->HasEPGInfoTag()) + { + value = (int) pItem->GetEPGInfoTag()->ProgressPercentage(); + } + } + + return true; + } + break; case LISTITEM_PERCENT_PLAYED: if (item->IsFileItem() && ((const CFileItem *)item)->HasVideoInfoTag() && ((const CFileItem *)item)->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds > 0) value = (int)(100 * ((const CFileItem *)item)->GetVideoInfoTag()->m_resumePoint.timeInSeconds / ((const CFileItem *)item)->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds); @@ -3815,6 +4115,17 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info) case LISTITEM_LABEL2: return item->GetLabel2(); case LISTITEM_TITLE: + if (item->HasPVRChannelInfoTag()) + { + CEpgInfoTag epgTag; + return item->GetPVRChannelInfoTag()->GetEPGNow(epgTag) ? epgTag.Title() : g_localizeStrings.Get(19055); + } + if (item->HasPVRRecordingInfoTag()) + return item->GetPVRRecordingInfoTag()->m_strTitle; + if (item->HasEPGInfoTag()) + return item->GetEPGInfoTag()->Title(); + if (item->HasPVRTimerInfoTag()) + return item->GetPVRTimerInfoTag()->m_strTitle; if (item->HasVideoInfoTag()) return item->GetVideoInfoTag()->m_strTitle; if (item->HasMusicInfoTag()) @@ -3901,6 +4212,15 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info) return item->GetVideoInfoTag()->m_strGenre; if (item->HasMusicInfoTag()) return item->GetMusicInfoTag()->GetGenre(); + if (item->HasPVRChannelInfoTag()) + { + CEpgInfoTag epgTag; + return item->GetPVRChannelInfoTag()->GetEPGNow(epgTag) ? epgTag.Genre() : ""; + } + if (item->HasPVRRecordingInfoTag()) + return item->GetPVRRecordingInfoTag()->m_strGenre; + if (item->HasEPGInfoTag()) + return item->GetEPGInfoTag()->Genre(); break; case LISTITEM_FILENAME: case LISTITEM_FILE_EXTENSION: @@ -3922,6 +4242,17 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info) } break; case LISTITEM_DATE: + if (item->HasEPGInfoTag()) + return item->GetEPGInfoTag()->StartAsLocalTime().GetAsLocalizedDateTime(false, false); + if (item->HasPVRChannelInfoTag()) + { + CEpgInfoTag epgTag; + return item->GetPVRChannelInfoTag()->GetEPGNow(epgTag) ? epgTag.StartAsLocalTime().GetAsLocalizedDateTime(false, false) : CDateTime::GetCurrentDateTime().GetAsLocalizedDateTime(false, false); + } + if (item->HasPVRRecordingInfoTag()) + return item->GetPVRRecordingInfoTag()->RecordingTimeAsLocalTime().GetAsLocalizedDateTime(false, false); + if (item->HasPVRTimerInfoTag()) + return item->GetPVRTimerInfoTag()->m_strSummary; if (item->m_dateTime.IsValid()) return item->m_dateTime.GetAsLocalizedDate(); break; @@ -3962,12 +4293,30 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info) case LISTITEM_DURATION: { CStdString duration; - if (item->HasVideoInfoTag()) + if (item->HasPVRChannelInfoTag()) + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNow(tag)) + return StringUtils::SecondsToTimeString(tag.GetDuration()); + return StringUtils::EmptyString; + } + else if (item->HasPVRRecordingInfoTag()) + { + if (item->GetPVRRecordingInfoTag()->GetDuration() > 0) + duration = StringUtils::SecondsToTimeString(item->GetPVRRecordingInfoTag()->GetDuration()); + } + else if (item->HasEPGInfoTag()) + { + if (item->GetEPGInfoTag()->GetDuration() > 0) + duration = StringUtils::SecondsToTimeString(item->GetEPGInfoTag()->GetDuration()); + } + else if (item->HasVideoInfoTag()) { if (!item->GetVideoInfoTag()->m_strRuntime.IsEmpty()) duration = item->GetVideoInfoTag()->m_strRuntime; } - if (item->HasMusicInfoTag()) + else if (item->HasMusicInfoTag()) { if (item->GetMusicInfoTag()->GetDuration() > 0) duration = StringUtils::SecondsToTimeString(item->GetMusicInfoTag()->GetDuration()); @@ -3975,6 +4324,18 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info) return duration; } case LISTITEM_PLOT: + if (item->HasPVRChannelInfoTag()) + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNow(tag)) + return tag.Plot(); + return StringUtils::EmptyString; + } + if (item->HasEPGInfoTag()) + return item->GetEPGInfoTag()->Plot(); + if (item->HasPVRRecordingInfoTag()) + return item->GetPVRRecordingInfoTag()->m_strPlot; if (item->HasVideoInfoTag()) { if (!(!item->GetVideoInfoTag()->m_strShowTitle.IsEmpty() && item->GetVideoInfoTag()->m_iSeason == -1)) // dont apply to tvshows @@ -3985,6 +4346,18 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info) } break; case LISTITEM_PLOT_OUTLINE: + if (item->HasPVRChannelInfoTag()) + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNow(tag)) + return tag.PlotOutline(); + return StringUtils::EmptyString; + } + if (item->HasEPGInfoTag()) + return item->GetEPGInfoTag()->PlotOutline(); + if (item->HasPVRRecordingInfoTag()) + return item->GetPVRRecordingInfoTag()->m_strPlotOutline; if (item->HasVideoInfoTag()) return item->GetVideoInfoTag()->m_strPlotOutline; break; @@ -4015,6 +4388,8 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info) return item->GetVideoInfoTag()->m_strShowTitle; break; case LISTITEM_COMMENT: + if (item->HasPVRTimerInfoTag()) + return item->GetPVRTimerInfoTag()->GetStatus(); if (item->HasMusicInfoTag()) return item->GetMusicInfoTag()->GetComment(); break; @@ -4169,6 +4544,173 @@ CStdString CGUIInfoManager::GetItemLabel(const CFileItem *item, int info) if (item->HasVideoInfoTag()) return item->GetVideoInfoTag()->m_streamDetails.GetSubtitleLanguage(); break; + case LISTITEM_STARTTIME: + if (item->HasPVRChannelInfoTag()) + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNow(tag)) + return tag.StartAsLocalTime().GetAsLocalizedTime("", false); + return CDateTime::GetCurrentDateTime().GetAsLocalizedTime("", false); + } + if (item->HasEPGInfoTag()) + return item->GetEPGInfoTag()->StartAsLocalTime().GetAsLocalizedTime("", false); + if (item->HasPVRTimerInfoTag()) + return item->GetPVRTimerInfoTag()->StartAsLocalTime().GetAsLocalizedTime("", false); + if (item->HasPVRRecordingInfoTag()) + return item->GetPVRRecordingInfoTag()->RecordingTimeAsLocalTime().GetAsLocalizedTime("", false); + if (item->m_dateTime.IsValid()) + return item->m_dateTime.GetAsLocalizedTime("", false); + break; + case LISTITEM_ENDTIME: + if (item->HasPVRChannelInfoTag()) + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNow(tag)) + return tag.EndAsLocalTime().GetAsLocalizedTime("", false); + return CDateTime::GetCurrentDateTime().GetAsLocalizedTime("", false); + } + if (item->HasEPGInfoTag()) + return item->GetEPGInfoTag()->EndAsLocalTime().GetAsLocalizedTime("", false); + if (item->HasPVRTimerInfoTag()) + return item->GetPVRTimerInfoTag()->EndAsLocalTime().GetAsLocalizedTime("", false); + break; + case LISTITEM_STARTDATE: + if (item->HasPVRChannelInfoTag()) + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNow(tag)) + return tag.StartAsLocalTime().GetAsLocalizedDate(true); + return CDateTime::GetCurrentDateTime().GetAsLocalizedDate(true); + } + if (item->HasEPGInfoTag()) + return item->GetEPGInfoTag()->StartAsLocalTime().GetAsLocalizedDate(true); + if (item->HasPVRTimerInfoTag()) + return item->GetPVRTimerInfoTag()->StartAsLocalTime().GetAsLocalizedDate(true); + if (item->HasPVRRecordingInfoTag()) + return item->GetPVRRecordingInfoTag()->RecordingTimeAsLocalTime().GetAsLocalizedDate(true); + if (item->m_dateTime.IsValid()) + return item->m_dateTime.GetAsLocalizedDate(true); + break; + case LISTITEM_ENDDATE: + if (item->HasPVRChannelInfoTag()) + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNow(tag)) + return tag.EndAsLocalTime().GetAsLocalizedDate(true); + return CDateTime::GetCurrentDateTime().GetAsLocalizedDate(true); + } + if (item->HasEPGInfoTag()) + return item->GetEPGInfoTag()->EndAsLocalTime().GetAsLocalizedDate(true); + if (item->HasPVRTimerInfoTag()) + return item->GetPVRTimerInfoTag()->EndAsLocalTime().GetAsLocalizedDate(true); + break; + case LISTITEM_CHANNEL_NUMBER: + { + CStdString number; + if (item->HasPVRChannelInfoTag()) + number.Format("%i", item->GetPVRChannelInfoTag()->ChannelNumber()); + if (item->HasEPGInfoTag() && item->GetEPGInfoTag()->HasPVRChannel()) + number.Format("%i", item->GetEPGInfoTag()->PVRChannelNumber()); + if (item->HasPVRTimerInfoTag()) + number.Format("%i", item->GetPVRTimerInfoTag()->ChannelNumber()); + + return number; + } + break; + case LISTITEM_CHANNEL_NAME: + if (item->HasPVRChannelInfoTag()) + return item->GetPVRChannelInfoTag()->ChannelName(); + if (item->HasEPGInfoTag() && item->GetEPGInfoTag()->HasPVRChannel()) + return item->GetEPGInfoTag()->PVRChannelName(); + if (item->HasPVRRecordingInfoTag()) + return item->GetPVRRecordingInfoTag()->m_strChannelName; + if (item->HasPVRTimerInfoTag()) + return item->GetPVRTimerInfoTag()->ChannelName(); + break; + case LISTITEM_NEXT_STARTTIME: + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNext(tag)) + return tag.StartAsLocalTime().GetAsLocalizedTime("", false); + } + return CDateTime::GetCurrentDateTime().GetAsLocalizedTime("", false); + case LISTITEM_NEXT_ENDTIME: + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNext(tag)) + return tag.EndAsLocalTime().GetAsLocalizedTime("", false); + } + return CDateTime::GetCurrentDateTime().GetAsLocalizedTime("", false); + case LISTITEM_NEXT_STARTDATE: + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNext(tag)) + return tag.StartAsLocalTime().GetAsLocalizedDate(true); + } + return CDateTime::GetCurrentDateTime().GetAsLocalizedDate(true); + case LISTITEM_NEXT_ENDDATE: + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNext(tag)) + return tag.EndAsLocalTime().GetAsLocalizedDate(true); + } + return CDateTime::GetCurrentDateTime().GetAsLocalizedDate(true); + case LISTITEM_NEXT_PLOT: + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNext(tag)) + return tag.Plot(); + } + return StringUtils::EmptyString; + case LISTITEM_NEXT_PLOT_OUTLINE: + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNext(tag)) + return tag.PlotOutline(); + } + return StringUtils::EmptyString; + case LISTITEM_NEXT_DURATION: + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNext(tag)) + return StringUtils::SecondsToTimeString(tag.GetDuration()); + } + return StringUtils::EmptyString; + case LISTITEM_NEXT_GENRE: + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNext(tag)) + return tag.Genre(); + } + return StringUtils::EmptyString; + case LISTITEM_NEXT_TITLE: + { + const CPVRChannel *channel = item->HasPVRChannelInfoTag() ? item->GetPVRChannelInfoTag() : NULL; + CEpgInfoTag tag; + if (channel && channel->GetEPGNext(tag)) + return tag.Title(); + } + return StringUtils::EmptyString; + case LISTITEM_PARENTALRATING: + { + CStdString rating; + if (item->HasEPGInfoTag() && item->GetEPGInfoTag()->ParentalRating() > 0) + rating.Format("%i", item->GetEPGInfoTag()->ParentalRating()); + return rating; + } + break; case LISTITEM_PERCENT_PLAYED: { int val; @@ -4245,8 +4787,68 @@ bool CGUIInfoManager::GetItemBool(const CGUIListItem *item, int condition) const return item->IsSelected(); else if (condition == LISTITEM_IS_FOLDER) return item->m_bIsFolder; - else if (condition == LISTITEM_IS_RESUMABLE) - return (item->IsFileItem() && ((const CFileItem *)item)->HasVideoInfoTag() && ((const CFileItem *)item)->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds > 0); + + if (item->IsFileItem()) + { + const CFileItem *pItem = (const CFileItem *)item; + if (condition == LISTITEM_IS_RESUMABLE) + return (pItem->HasVideoInfoTag() && pItem->GetVideoInfoTag()->m_resumePoint.totalTimeInSeconds > 0); + else if (condition == LISTITEM_ISRECORDING) + { + if (!g_PVRManager.IsStarted()) + return false; + + if (pItem->HasPVRChannelInfoTag()) + { + return pItem->GetPVRChannelInfoTag()->IsRecording(); + } + else if (pItem->HasEPGInfoTag()) + { + CPVRTimerInfoTag *timer = g_PVRTimers->GetMatch(pItem); + if (timer) + return timer->IsRecording(); + } + else if (pItem->HasPVRTimerInfoTag()) + { + const CPVRTimerInfoTag *timer = pItem->GetPVRTimerInfoTag(); + if (timer) + return timer->IsRecording(); + } + } + else if (condition == LISTITEM_HASTIMER) + { + if (pItem->HasEPGInfoTag()) + { + CPVRTimerInfoTag *timer = g_PVRTimers->GetMatch(pItem); + if (timer) + return timer->IsActive(); + } + } + else if (condition == LISTITEM_HAS_EPG) + { + if (pItem->HasPVRChannelInfoTag()) + { + CEpgInfoTag epgTag; + return pItem->GetPVRChannelInfoTag()->GetEPGNow(epgTag); + } + else + { + return pItem->HasEPGInfoTag(); + } + } + else if (condition == LISTITEM_ISENCRYPTED) + { + if (pItem->HasPVRChannelInfoTag()) + { + return pItem->GetPVRChannelInfoTag()->IsEncrypted(); + } + else if (pItem->HasEPGInfoTag() && pItem->GetEPGInfoTag()->HasPVRChannel()) + { + return pItem->GetEPGInfoTag()->ChannelTag()->IsEncrypted(); + } + } + } + return false; } diff --git a/xbmc/GUIInfoManager.h b/xbmc/GUIInfoManager.h index eb4501e..6db2df6 100644 --- a/xbmc/GUIInfoManager.h +++ b/xbmc/GUIInfoManager.h @@ -32,6 +32,7 @@ #include "guilib/IMsgTargetCallback.h" #include "inttypes.h" #include "XBDateTime.h" +#include "utils/Observer.h" #include "interfaces/info/SkinVariable.h" #include @@ -143,7 +144,7 @@ namespace INFO #define SYSTEM_HASLOCKS 140 #define SYSTEM_ISMASTER 141 #define SYSTEM_TRAYOPEN 142 -#define SYSTEM_SHOW_EXIT_BUTTON 143 +#define SYSTEM_SHOW_EXIT_BUTTON 143 #define SYSTEM_ALARM_POS 144 #define SYSTEM_LOGGEDON 145 #define SYSTEM_PROFILENAME 146 @@ -178,7 +179,9 @@ namespace INFO #define SYSTEM_PROFILECOUNT 181 #define SYSTEM_ISFULLSCREEN 182 #define SYSTEM_ISSTANDALONE 183 -#define SYSTEM_HAS_PVR 184 +#define SYSTEM_ISINHIBIT 184 +#define SYSTEM_HAS_SHUTDOWN 185 +#define SYSTEM_HAS_PVR 186 #define NETWORK_IP_ADDRESS 190 #define NETWORK_MAC_ADDRESS 191 @@ -216,6 +219,9 @@ namespace INFO #define MUSICPLAYER_ALBUM_ARTIST 226 #define MUSICPLAYER_PLAYCOUNT 227 #define MUSICPLAYER_LASTPLAYED 228 +#define MUSICPLAYER_CHANNEL_NAME 229 +#define MUSICPLAYER_CHANNEL_NUMBER 230 +#define MUSICPLAYER_CHANNEL_GROUP 231 #define VIDEOPLAYER_TITLE 250 #define VIDEOPLAYER_GENRE 251 @@ -261,14 +267,29 @@ namespace INFO #define VIDEOPLAYER_PLAYCOUNT 293 #define VIDEOPLAYER_LASTPLAYED 294 -#define AUDIOSCROBBLER_ENABLED 300 -#define AUDIOSCROBBLER_CONN_STATE 301 -#define AUDIOSCROBBLER_SUBMIT_INT 302 -#define AUDIOSCROBBLER_FILES_CACHED 303 -#define AUDIOSCROBBLER_SUBMIT_STATE 304 -#define LASTFM_RADIOPLAYING 305 -#define LASTFM_CANLOVE 306 -#define LASTFM_CANBAN 307 +#define VIDEOPLAYER_STARTTIME 295 +#define VIDEOPLAYER_ENDTIME 296 +#define VIDEOPLAYER_NEXT_TITLE 297 +#define VIDEOPLAYER_NEXT_GENRE 298 +#define VIDEOPLAYER_NEXT_PLOT 299 +#define VIDEOPLAYER_NEXT_PLOT_OUTLINE 300 +#define VIDEOPLAYER_NEXT_STARTTIME 301 +#define VIDEOPLAYER_NEXT_ENDTIME 302 +#define VIDEOPLAYER_NEXT_DURATION 303 +#define VIDEOPLAYER_CHANNEL_NAME 304 +#define VIDEOPLAYER_CHANNEL_NUMBER 305 +#define VIDEOPLAYER_CHANNEL_GROUP 306 +#define VIDEOPLAYER_PARENTAL_RATING 307 +#define VIDEOPLAYER_HAS_EPG 308 + +#define AUDIOSCROBBLER_ENABLED 325 +#define AUDIOSCROBBLER_CONN_STATE 326 +#define AUDIOSCROBBLER_SUBMIT_INT 327 +#define AUDIOSCROBBLER_FILES_CACHED 328 +#define AUDIOSCROBBLER_SUBMIT_STATE 329 +#define LASTFM_RADIOPLAYING 330 +#define LASTFM_CANLOVE 331 +#define LASTFM_CANBAN 332 #define CONTAINER_SCROLL_PREVIOUS 345 // NOTE: These 5 must be kept in this consecutive order #define CONTAINER_MOVE_PREVIOUS 346 @@ -409,6 +430,56 @@ namespace INFO #define FANART_COLOR3 1002 #define FANART_IMAGE 1003 +#define PVR_CONDITIONS_START 1100 +#define PVR_IS_RECORDING (PVR_CONDITIONS_START) +#define PVR_HAS_TIMER (PVR_CONDITIONS_START + 1) +#define PVR_HAS_NONRECORDING_TIMER (PVR_CONDITIONS_START + 2) +#define PVR_HAS_EPG (PVR_CONDITIONS_START + 3) +#define PVR_HAS_TXT (PVR_CONDITIONS_START + 4) +#define PVR_HAS_DIRECTOR (PVR_CONDITIONS_START + 5) +#define PVR_IS_PLAYING_TV (PVR_CONDITIONS_START + 6) +#define PVR_IS_PLAYING_RADIO (PVR_CONDITIONS_START + 7) +#define PVR_IS_PLAYING_RECORDING (PVR_CONDITIONS_START + 8) +#define PVR_ACTUAL_STREAM_ENCRYPTED (PVR_CONDITIONS_START + 9) +#define PVR_CONDITIONS_END PVR_ACTUAL_STREAM_ENCRYPTED + +#define PVR_STRINGS_START 1200 +#define PVR_NEXT_RECORDING_CHANNEL (PVR_STRINGS_START) +#define PVR_NEXT_RECORDING_CHAN_ICO (PVR_STRINGS_START + 1) +#define PVR_NEXT_RECORDING_DATETIME (PVR_STRINGS_START + 2) +#define PVR_NEXT_RECORDING_TITLE (PVR_STRINGS_START + 3) +#define PVR_NOW_RECORDING_CHANNEL (PVR_STRINGS_START + 4) +#define PVR_NOW_RECORDING_CHAN_ICO (PVR_STRINGS_START + 5) +#define PVR_NOW_RECORDING_DATETIME (PVR_STRINGS_START + 6) +#define PVR_NOW_RECORDING_TITLE (PVR_STRINGS_START + 7) +#define PVR_BACKEND_NAME (PVR_STRINGS_START + 8) +#define PVR_BACKEND_VERSION (PVR_STRINGS_START + 9) +#define PVR_BACKEND_HOST (PVR_STRINGS_START + 10) +#define PVR_BACKEND_DISKSPACE (PVR_STRINGS_START + 11) +#define PVR_BACKEND_CHANNELS (PVR_STRINGS_START + 12) +#define PVR_BACKEND_TIMERS (PVR_STRINGS_START + 13) +#define PVR_BACKEND_RECORDINGS (PVR_STRINGS_START + 14) +#define PVR_BACKEND_NUMBER (PVR_STRINGS_START + 15) +#define PVR_TOTAL_DISKSPACE (PVR_STRINGS_START + 16) +#define PVR_NEXT_TIMER (PVR_STRINGS_START + 17) +#define PVR_PLAYING_DURATION (PVR_STRINGS_START + 18) +#define PVR_PLAYING_TIME (PVR_STRINGS_START + 19) +#define PVR_PLAYING_PROGRESS (PVR_STRINGS_START + 20) +#define PVR_ACTUAL_STREAM_CLIENT (PVR_STRINGS_START + 21) +#define PVR_ACTUAL_STREAM_DEVICE (PVR_STRINGS_START + 22) +#define PVR_ACTUAL_STREAM_STATUS (PVR_STRINGS_START + 23) +#define PVR_ACTUAL_STREAM_SIG (PVR_STRINGS_START + 24) +#define PVR_ACTUAL_STREAM_SNR (PVR_STRINGS_START + 25) +#define PVR_ACTUAL_STREAM_SIG_PROGR (PVR_STRINGS_START + 26) +#define PVR_ACTUAL_STREAM_SNR_PROGR (PVR_STRINGS_START + 27) +#define PVR_ACTUAL_STREAM_BER (PVR_STRINGS_START + 28) +#define PVR_ACTUAL_STREAM_UNC (PVR_STRINGS_START + 29) +#define PVR_ACTUAL_STREAM_VIDEO_BR (PVR_STRINGS_START + 30) +#define PVR_ACTUAL_STREAM_AUDIO_BR (PVR_STRINGS_START + 31) +#define PVR_ACTUAL_STREAM_DOLBY_BR (PVR_STRINGS_START + 32) +#define PVR_ACTUAL_STREAM_CRYPTION (PVR_STRINGS_START + 33) +#define PVR_STRINGS_END PVR_ACTUAL_STREAM_CRYPTION + #define WINDOW_PROPERTY 9993 #define WINDOW_IS_TOPMOST 9994 #define WINDOW_IS_VISIBLE 9995 @@ -488,9 +559,31 @@ namespace INFO #define LISTITEM_LASTPLAYED (LISTITEM_START + 57) #define LISTITEM_FOLDERPATH (LISTITEM_START + 58) #define LISTITEM_DISC_NUMBER (LISTITEM_START + 59) -#define LISTITEM_FILE_EXTENSION (LISTITEM_START + 60) -#define LISTITEM_IS_RESUMABLE (LISTITEM_START + 61) -#define LISTITEM_PERCENT_PLAYED (LISTITEM_START + 62) +#define LISTITEM_STARTTIME (LISTITEM_START + 60) +#define LISTITEM_ENDTIME (LISTITEM_START + 61) +#define LISTITEM_STARTDATE (LISTITEM_START + 62) +#define LISTITEM_ENDDATE (LISTITEM_START + 63) +#define LISTITEM_NEXT_TITLE (LISTITEM_START + 64) +#define LISTITEM_NEXT_GENRE (LISTITEM_START + 65) +#define LISTITEM_NEXT_PLOT (LISTITEM_START + 66) +#define LISTITEM_NEXT_PLOT_OUTLINE (LISTITEM_START + 67) +#define LISTITEM_NEXT_STARTTIME (LISTITEM_START + 68) +#define LISTITEM_NEXT_ENDTIME (LISTITEM_START + 69) +#define LISTITEM_NEXT_STARTDATE (LISTITEM_START + 70) +#define LISTITEM_NEXT_ENDDATE (LISTITEM_START + 71) +#define LISTITEM_NEXT_DURATION (LISTITEM_START + 72) +#define LISTITEM_CHANNEL_NAME (LISTITEM_START + 73) +#define LISTITEM_CHANNEL_NUMBER (LISTITEM_START + 74) +#define LISTITEM_CHANNEL_GROUP (LISTITEM_START + 75) +#define LISTITEM_HASTIMER (LISTITEM_START + 76) +#define LISTITEM_ISRECORDING (LISTITEM_START + 77) +#define LISTITEM_ISENCRYPTED (LISTITEM_START + 78) +#define LISTITEM_PARENTALRATING (LISTITEM_START + 79) +#define LISTITEM_PROGRESS (LISTITEM_START + 80) +#define LISTITEM_FILE_EXTENSION (LISTITEM_START + 81) +#define LISTITEM_IS_RESUMABLE (LISTITEM_START + 82) +#define LISTITEM_PERCENT_PLAYED (LISTITEM_START + 83) +#define LISTITEM_HAS_EPG (LISTITEM_START + 84) #define LISTITEM_PROPERTY_START (LISTITEM_START + 200) #define LISTITEM_PROPERTY_END (LISTITEM_PROPERTY_START + 1000) @@ -547,7 +640,7 @@ private: \ingroup strings \brief */ -class CGUIInfoManager : public IMsgTargetCallback +class CGUIInfoManager : public IMsgTargetCallback, public Observable { public: CGUIInfoManager(void); diff --git a/xbmc/GUIViewControl.cpp b/xbmc/GUIViewControl.cpp index ce0b945..0f043fc 100644 --- a/xbmc/GUIViewControl.cpp +++ b/xbmc/GUIViewControl.cpp @@ -124,8 +124,9 @@ void CGUIViewControl::SetCurrentView(int viewMode) g_windowManager.SendMessage(msg); } - // Update our view control - UpdateViewAsControl(((CGUIBaseContainer *)pNewView)->GetLabel()); + // Update our view control only if we are not in the TV Window + if (m_parentWindow != WINDOW_PVR) + UpdateViewAsControl(((CGUIBaseContainer *)pNewView)->GetLabel()); } void CGUIViewControl::SetItems(CFileItemList &items) diff --git a/xbmc/GUIViewState.cpp b/xbmc/GUIViewState.cpp index 2c5f7c7..3a1dc98 100644 --- a/xbmc/GUIViewState.cpp +++ b/xbmc/GUIViewState.cpp @@ -20,6 +20,7 @@ */ #include "GUIViewState.h" +#include "pvr/windows/GUIViewStatePVR.h" #include "addons/GUIViewStateAddonBrowser.h" #include "music/GUIViewStateMusic.h" #include "video/GUIViewStateVideo.h" @@ -47,6 +48,7 @@ using namespace std; using namespace ADDON; +using namespace PVR; CStdString CGUIViewState::m_strPlaylistDirectory; VECSOURCES CGUIViewState::m_sources; @@ -119,6 +121,9 @@ CGUIViewState* CGUIViewState::GetViewState(int windowId, const CFileItemList& it if (windowId==WINDOW_VIDEO_PLAYLIST) return new CGUIViewStateWindowVideoPlaylist(items); + if (windowId==WINDOW_PVR) + return new CGUIViewStatePVR(items); + if (windowId==WINDOW_PICTURES) return new CGUIViewStateWindowPictures(items); diff --git a/xbmc/SortFileItem.cpp b/xbmc/SortFileItem.cpp index e69ca91..8268022 100644 --- a/xbmc/SortFileItem.cpp +++ b/xbmc/SortFileItem.cpp @@ -20,6 +20,10 @@ */ #include "SortFileItem.h" +#include "video/VideoInfoTag.h" +#include "pvr/channels/PVRChannel.h" +#include "epg/Epg.h" +#include "pvr/timers/PVRTimerInfoTag.h" #include "settings/AdvancedSettings.h" #include "utils/StringUtils.h" #include "music/tags/MusicInfoTag.h" @@ -28,6 +32,8 @@ #include "utils/log.h" #include "video/VideoInfoTag.h" +using namespace PVR; + #define RETURN_IF_NULL(x,y) if ((x) == NULL) { CLog::Log(LOGWARNING, "%s, sort item is null", __FUNCTION__); return y; } CStdString SSortFileItem::RemoveArticles(const CStdString &label) @@ -483,6 +489,18 @@ void SSortFileItem::ByProductionCode(CFileItemPtr &item) item->SetSortLabel(item->GetVideoInfoTag()->m_strProductionCode); } +void SSortFileItem::ByChannel(CFileItemPtr &item) +{ + if (!item) return; + + if (item->IsEPG() || item->IsPVRChannel()) + { + CPVRChannel *channel = item->GetPVRChannelInfoTag(); + if (channel) + item->SetSortLabel(channel->ChannelName()); + } +} + void SSortFileItem::ByBitrate(CFileItemPtr &item) { if (!item) return; diff --git a/xbmc/SortFileItem.h b/xbmc/SortFileItem.h index 9c64c57..3e088d1 100644 --- a/xbmc/SortFileItem.h +++ b/xbmc/SortFileItem.h @@ -57,6 +57,7 @@ struct SSortFileItem static void BySongTrackNum(CFileItemPtr &item); static void BySongDuration(CFileItemPtr &item); static void BySongRating(CFileItemPtr &item); + static void ByChannel(CFileItemPtr &item); static void ByProgramCount(CFileItemPtr &item); @@ -120,6 +121,7 @@ typedef enum { SORT_METHOD_PLAYCOUNT, SORT_METHOD_LISTENERS, SORT_METHOD_UNSORTED, + SORT_METHOD_CHANNEL, SORT_METHOD_BITRATE, SORT_METHOD_MAX } SORT_METHOD; diff --git a/xbmc/URL.cpp b/xbmc/URL.cpp index 05781f4..951912f 100644 --- a/xbmc/URL.cpp +++ b/xbmc/URL.cpp @@ -157,6 +157,7 @@ void CURL::Parse(const CStdString& strURL1) int iEnd = strURL.length(); const char* sep = NULL; + //TODO fix all Addon paths CStdString strProtocol2 = GetTranslatedProtocol(); if(m_strProtocol.Equals("rss") || m_strProtocol.Equals("rar") || @@ -166,6 +167,7 @@ void CURL::Parse(const CStdString& strURL1) if(strProtocol2.Equals("http") || strProtocol2.Equals("https") || strProtocol2.Equals("plugin") + || m_strProtocol.Equals("addon") || strProtocol2.Equals("hdhomerun") || strProtocol2.Equals("rtsp") || strProtocol2.Equals("zip")) @@ -290,6 +292,7 @@ void CURL::Parse(const CStdString& strURL1) || m_strProtocol.CompareNoCase("videodb") == 0 || m_strProtocol.CompareNoCase("sources") == 0 || m_strProtocol.CompareNoCase("lastfm") == 0 + || m_strProtocol.CompareNoCase("pvr") == 0 || m_strProtocol.Left(3).CompareNoCase("mem") == 0) { if (m_strHostName != "" && m_strFileName != "") diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp index 7e6489b..a43ac2a 100644 --- a/xbmc/Util.cpp +++ b/xbmc/Util.cpp @@ -43,6 +43,7 @@ #include "Util.h" #include "addons/Addon.h" #include "storage/IoSupport.h" +#include "filesystem/PVRDirectory.h" #include "filesystem/StackDirectory.h" #include "filesystem/MultiPathDirectory.h" #include "filesystem/DirectoryCache.h" @@ -562,6 +563,39 @@ void CUtil::GetHomePath(CStdString& strPath, const CStdString& strTarget) #endif } +bool CUtil::IsPVR(const CStdString& strFile) +{ + return strFile.Left(4).Equals("pvr:"); +} + +bool CUtil::IsHTSP(const CStdString& strFile) +{ + return strFile.Left(5).Equals("htsp:"); +} + +bool CUtil::IsLiveTV(const CStdString& strFile) +{ + if (strFile.Left(14).Equals("pvr://channels")) + return true; + + if(URIUtils::IsTuxBox(strFile) + || URIUtils::IsVTP(strFile) + || URIUtils::IsHDHomeRun(strFile) + || URIUtils::IsHTSP(strFile) + || strFile.Left(4).Equals("sap:")) + return true; + + if (URIUtils::IsMythTV(strFile) && CMythDirectory::IsLiveTV(strFile)) + return true; + + return false; +} + +bool CUtil::IsTVRecording(const CStdString& strFile) +{ + return strFile.Left(15).Equals("pvr://recording"); +} + bool CUtil::IsPicture(const CStdString& strFile) { CStdString extension = URIUtils::GetExtension(strFile); @@ -1896,6 +1930,8 @@ bool CUtil::SupportsFileOperations(const CStdString& strPath) return true; if (URIUtils::IsSmb(strPath)) return true; + if (CUtil::IsTVRecording(strPath)) + return CPVRDirectory::SupportsFileOperations(strPath); if (URIUtils::IsNfs(strPath)) return true; if (URIUtils::IsAfp(strPath)) diff --git a/xbmc/Util.h b/xbmc/Util.h index 96de5d1..ef94385 100644 --- a/xbmc/Util.h +++ b/xbmc/Util.h @@ -65,6 +65,10 @@ public: static void GetQualifiedFilename(const CStdString &strBasePath, CStdString &strFilename); static void RunShortcut(const char* szPath); static void GetHomePath(CStdString& strPath, const CStdString& strTarget = "XBMC_HOME"); + static bool IsPVR(const CStdString& strFile); + static bool IsHTSP(const CStdString& strFile); + static bool IsLiveTV(const CStdString& strFile); + static bool IsTVRecording(const CStdString& strFile); static bool ExcludeFileOrFolder(const CStdString& strFileOrFolder, const CStdStringArray& regexps); static void GetFileAndProtocol(const CStdString& strURL, CStdString& strDir); static int GetDVDIfoTitle(const CStdString& strPathFile); diff --git a/xbmc/XBDateTime.cpp b/xbmc/XBDateTime.cpp index 5e97385..47d59e9 100644 --- a/xbmc/XBDateTime.cpp +++ b/xbmc/XBDateTime.cpp @@ -862,6 +862,45 @@ CStdString CDateTime::GetAsDBDateTime() const return date; } +CStdString CDateTime::GetAsSaveString() const +{ + SYSTEMTIME st; + GetAsSystemTime(st); + + CStdString date; + date.Format("%04i%02i%02i_%02i%02i%02i", st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); + + return date; +} + +void CDateTime::SetFromUTCDateTime(const CDateTime &dateTime) +{ + TIME_ZONE_INFORMATION tz; + CDateTime tmp(dateTime); + + switch(GetTimeZoneInformation(&tz)) + { + case TIME_ZONE_ID_DAYLIGHT: + tmp -= CDateTimeSpan(0, 0, tz.Bias + tz.DaylightBias, 0); + break; + case TIME_ZONE_ID_STANDARD: + tmp -= CDateTimeSpan(0, 0, tz.Bias + tz.StandardBias, 0); + break; + case TIME_ZONE_ID_UNKNOWN: + tmp -= CDateTimeSpan(0, 0, tz.Bias, 0); + break; + } + + m_time = tmp.m_time; + m_state = tmp.m_state; +} + +void CDateTime::SetFromUTCDateTime(const time_t &dateTime) +{ + CDateTime tmp(dateTime); + SetFromUTCDateTime(tmp); +} + void CDateTime::SetFromW3CDate(const CStdString &dateTime) { CStdString date, time, zone; diff --git a/xbmc/XBDateTime.h b/xbmc/XBDateTime.h index d4a36fe..c161616 100644 --- a/xbmc/XBDateTime.h +++ b/xbmc/XBDateTime.h @@ -169,6 +169,8 @@ public: void SetFromDBDate(const CStdString &date); void SetFromDBTime(const CStdString &time); void SetFromW3CDate(const CStdString &date); + void SetFromUTCDateTime(const CDateTime &dateTime); + void SetFromUTCDateTime(const time_t &dateTime); /*! \brief set from a database datetime format YYYY-MM-DD HH:MM:SS \sa GetAsDBDateTime() @@ -181,6 +183,7 @@ public: void GetAsTimeStamp(FILETIME& time) const; CDateTime GetAsUTCDateTime() const; + CStdString GetAsSaveString() const; CStdString GetAsDBDateTime() const; CStdString GetAsDBDate() const; CStdString GetAsLocalizedDate(bool longDate=false, bool withShortNames=true) const; diff --git a/xbmc/addons/Addon.cpp b/xbmc/addons/Addon.cpp index 98e7f57..9ce8b9b 100644 --- a/xbmc/addons/Addon.cpp +++ b/xbmc/addons/Addon.cpp @@ -75,7 +75,7 @@ static const TypeMapping types[] = {"xbmc.gui.skin", ADDON_SKIN, 166, "DefaultAddonSkin.png" }, {"xbmc.gui.webinterface", ADDON_WEB_INTERFACE, 199, "DefaultAddonWebSkin.png" }, {"xbmc.addon.repository", ADDON_REPOSITORY, 24011, "DefaultAddonRepository.png" }, - {"pvrclient", ADDON_PVRDLL, 0, "" }, + {"xbmc.pvrclient", ADDON_PVRDLL, 24019, "" }, {"xbmc.addon.video", ADDON_VIDEO, 1037, "DefaultAddonVideo.png" }, {"xbmc.addon.audio", ADDON_AUDIO, 1038, "DefaultAddonMusic.png" }, {"xbmc.addon.image", ADDON_IMAGE, 1039, "DefaultAddonPicture.png" }, @@ -281,6 +281,9 @@ void CAddon::BuildLibName(const cp_extension_t *extension) case ADDON_VIZ: ext = ADDON_VIS_EXT; break; + case ADDON_PVRDLL: + ext = ADDON_PVRDLL_EXT; + break; case ADDON_SCRIPT: case ADDON_SCRIPT_LIBRARY: case ADDON_SCRIPT_LYRICS: @@ -316,6 +319,7 @@ void CAddon::BuildLibName(const cp_extension_t *extension) case ADDON_SCRAPER_MUSICVIDEOS: case ADDON_SCRAPER_TVSHOWS: case ADDON_SCRAPER_LIBRARY: + case ADDON_PVRDLL: case ADDON_PLUGIN: case ADDON_SERVICE: { diff --git a/xbmc/addons/Addon.h b/xbmc/addons/Addon.h index 7dc63b9..704d54e 100644 --- a/xbmc/addons/Addon.h +++ b/xbmc/addons/Addon.h @@ -29,6 +29,7 @@ class CURL; class TiXmlElement; +class CAddonCallbacksAddon; typedef struct cp_plugin_info_t cp_plugin_info_t; typedef struct cp_extension_t cp_extension_t; @@ -171,6 +172,8 @@ public: virtual bool ReloadSettings(); protected: + friend class CAddonCallbacksAddon; + CAddon(const CAddon&); // protected as all copying is handled by Clone() CAddon(const CAddon&, const AddonPtr&); const AddonPtr Parent() const { return m_parent; } @@ -209,7 +212,7 @@ protected: bool m_userSettingsLoaded; private: - friend class AddonMgr; + friend class CAddonMgr; AddonProps m_props; const AddonPtr m_parent; CStdString m_userSettingsPath; diff --git a/xbmc/addons/AddonCallbacks.cpp b/xbmc/addons/AddonCallbacks.cpp new file mode 100644 index 0000000..50bde6e --- /dev/null +++ b/xbmc/addons/AddonCallbacks.cpp @@ -0,0 +1,142 @@ +/* + * 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 "Addon.h" +#include "AddonCallbacks.h" +#include "AddonCallbacksAddon.h" +#include "AddonCallbacksGUI.h" +#include "AddonCallbacksPVR.h" +#include "filesystem/SpecialProtocol.h" +#include "utils/log.h" + +namespace ADDON +{ + +CAddonCallbacks::CAddonCallbacks(CAddon* addon) +{ + m_addon = addon; + m_callbacks = new AddonCB; + m_helperAddon = NULL; + m_helperGUI = NULL; + m_helperPVR = NULL; + + m_callbacks->libBasePath = strdup(_P("special://xbmcbin/addons")); + m_callbacks->addonData = this; + m_callbacks->AddOnLib_RegisterMe = CAddonCallbacks::AddOnLib_RegisterMe; + m_callbacks->AddOnLib_UnRegisterMe = CAddonCallbacks::AddOnLib_UnRegisterMe; + m_callbacks->GUILib_RegisterMe = CAddonCallbacks::GUILib_RegisterMe; + m_callbacks->GUILib_UnRegisterMe = CAddonCallbacks::GUILib_UnRegisterMe; + m_callbacks->PVRLib_RegisterMe = CAddonCallbacks::PVRLib_RegisterMe; + m_callbacks->PVRLib_UnRegisterMe = CAddonCallbacks::PVRLib_UnRegisterMe; +} + +CAddonCallbacks::~CAddonCallbacks() +{ + delete m_helperAddon; + m_helperAddon = NULL; + delete m_helperGUI; + m_helperGUI = NULL; + delete m_helperPVR; + m_helperPVR = NULL; + delete m_callbacks->libBasePath; + delete m_callbacks; + m_callbacks = NULL; +} + +CB_AddOnLib* CAddonCallbacks::AddOnLib_RegisterMe(void *addonData) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacks - %s - called with a null pointer", __FUNCTION__); + return NULL; + } + + addon->m_helperAddon = new CAddonCallbacksAddon(addon->m_addon); + return addon->m_helperAddon->GetCallbacks(); +} + +void CAddonCallbacks::AddOnLib_UnRegisterMe(void *addonData, CB_AddOnLib *cbTable) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacks - %s - called with a null pointer", __FUNCTION__); + return; + } + + delete addon->m_helperAddon; + addon->m_helperAddon = NULL; +} + +CB_GUILib* CAddonCallbacks::GUILib_RegisterMe(void *addonData) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacks - %s - called with a null pointer", __FUNCTION__); + return NULL; + } + + addon->m_helperGUI = new CAddonCallbacksGUI(addon->m_addon); + return addon->m_helperGUI->GetCallbacks(); +} + +void CAddonCallbacks::GUILib_UnRegisterMe(void *addonData, CB_GUILib *cbTable) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacks - %s - called with a null pointer", __FUNCTION__); + return; + } + + delete addon->m_helperGUI; + addon->m_helperGUI = NULL; +} + +CB_PVRLib* CAddonCallbacks::PVRLib_RegisterMe(void *addonData) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacks - %s - called with a null pointer", __FUNCTION__); + return NULL; + } + + addon->m_helperPVR = new CAddonCallbacksPVR(addon->m_addon); + return addon->m_helperPVR->GetCallbacks(); +} + +void CAddonCallbacks::PVRLib_UnRegisterMe(void *addonData, CB_PVRLib *cbTable) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacks - %s - called with a null pointer", __FUNCTION__); + return; + } + + delete addon->m_helperPVR; + addon->m_helperPVR = NULL; +} + +}; /* namespace ADDON */ diff --git a/xbmc/addons/AddonCallbacks.h b/xbmc/addons/AddonCallbacks.h new file mode 100644 index 0000000..89d2518 --- /dev/null +++ b/xbmc/addons/AddonCallbacks.h @@ -0,0 +1,292 @@ +#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 "cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.h" +#include "addons/include/xbmc_pvr_types.h" +#include "../../addons/library.xbmc.addon/libXBMC_addon.h" +#include "../../addons/library.xbmc.gui/libXBMC_gui.h" + +typedef void (*AddOnLogCallback)(void *addonData, const ADDON::addon_log_t loglevel, const char *msg); +typedef void (*AddOnQueueNotification)(void *addonData, const ADDON::queue_msg_t type, const char *msg); +typedef bool (*AddOnGetSetting)(void *addonData, const char *settingName, void *settingValue); +typedef char* (*AddOnUnknownToUTF8)(const char *sourceDest); +typedef const char* (*AddOnGetLocalizedString)(const void* addonData, long dwCode); +typedef const char* (*AddOnGetDVDMenuLanguage)(const void* addonData); +typedef const char* (*AddOnGetLocalizedDate)(const void* addonData,time_t time, bool bLongDate, bool bWithShortNames); +typedef const char* (*AddOnGetLocalizedTime)(const void* addonData,time_t time, bool bWithSeconds); + +typedef struct CB_AddOn +{ + AddOnLogCallback Log; + AddOnQueueNotification QueueNotification; + AddOnGetSetting GetSetting; + AddOnUnknownToUTF8 UnknownToUTF8; + AddOnGetLocalizedString GetLocalizedString; + AddOnGetDVDMenuLanguage GetDVDMenuLanguage; + AddOnGetLocalizedDate GetLocalizedDate; + AddOnGetLocalizedTime GetLocalizedTime; +} CB_AddOnLib; + +typedef void (*GUILock)(); +typedef void (*GUIUnlock)(); +typedef int (*GUIGetScreenHeight)(); +typedef int (*GUIGetScreenWidth)(); +typedef int (*GUIGetVideoResolution)(); +typedef int (*GUIDialog_ShowYesNo)(const char* heading, const char* line0, const char* line1, const char* line2, int* bCanceled, const char* noLabel, const char* yesLabel); +typedef GUIHANDLE (*GUIWindow_New)(void *addonData, const char *xmlFilename, const char *defaultSkin, bool forceFallback, bool asDialog); +typedef void (*GUIWindow_Delete)(void *addonData, GUIHANDLE handle); +typedef void (*GUIWindow_SetCallbacks)(void *addonData, GUIHANDLE handle, GUIHANDLE clienthandle, bool (*)(GUIHANDLE handle), bool (*)(GUIHANDLE handle, int), bool (*)(GUIHANDLE handle, int), bool (*)(GUIHANDLE handle, int),bool (*)(GUIHANDLE ,int ,int , unsigned int)); +typedef bool (*GUIWindow_Show)(void *addonData, GUIHANDLE handle); +typedef bool (*GUIWindow_Close)(void *addonData, GUIHANDLE handle); +typedef bool (*GUIWindow_DoModal)(void *addonData, GUIHANDLE handle); +typedef bool (*GUIWindow_SetFocusId)(void *addonData, GUIHANDLE handle, int iControlId); +typedef int (*GUIWindow_GetFocusId)(void *addonData, GUIHANDLE handle); +typedef bool (*GUIWindow_SetCoordinateResolution)(void *addonData, GUIHANDLE handle, int res); +typedef void (*GUIWindow_SetProperty)(void *addonData, GUIHANDLE handle, const char *key, const char *value); +typedef void (*GUIWindow_SetPropertyInt)(void *addonData, GUIHANDLE handle, const char *key, int value); +typedef void (*GUIWindow_SetPropertyBool)(void *addonData, GUIHANDLE handle, const char *key, bool value); +typedef void (*GUIWindow_SetPropertyDouble)(void *addonData, GUIHANDLE handle, const char *key, double value); +typedef const char* (*GUIWindow_GetProperty)(void *addonData, GUIHANDLE handle, const char *key); +typedef int (*GUIWindow_GetPropertyInt)(void *addonData, GUIHANDLE handle, const char *key); +typedef bool (*GUIWindow_GetPropertyBool)(void *addonData, GUIHANDLE handle, const char *key); +typedef double (*GUIWindow_GetPropertyDouble)(void *addonData, GUIHANDLE handle, const char *key); +typedef void (*GUIWindow_ClearProperties)(void *addonData, GUIHANDLE handle); +typedef int (*GUIWindow_GetListSize)(void *addonData, GUIHANDLE handle); +typedef void (*GUIWindow_ClearList)(void *addonData, GUIHANDLE handle); +typedef GUIHANDLE (*GUIWindow_AddItem)(void *addonData, GUIHANDLE handle, GUIHANDLE item, int itemPosition); +typedef GUIHANDLE (*GUIWindow_AddStringItem)(void *addonData, GUIHANDLE handle, const char *itemName, int itemPosition); +typedef void (*GUIWindow_RemoveItem)(void *addonData, GUIHANDLE handle, int itemPosition); +typedef GUIHANDLE (*GUIWindow_GetListItem)(void *addonData, GUIHANDLE handle, int listPos); +typedef void (*GUIWindow_AddContextMenuButton)(void *addonData, GUIHANDLE handle,int controlId,unsigned int contextButtonId,const char* label); +typedef void (*GUIWindow_SetCurrentListPosition)(void *addonData, GUIHANDLE handle, int listPos); +typedef int (*GUIWindow_GetCurrentListPosition)(void *addonData, GUIHANDLE handle); +typedef GUIHANDLE (*GUIWindow_GetControl_Spin)(void *addonData, GUIHANDLE handle, int controlId); +typedef GUIHANDLE (*GUIWindow_GetControl_ListContainer)(void *addonData, GUIHANDLE handle, int controlId,GUIHANDLE *listItems); +typedef void (*GUIWindow_ReleaseControl_ListContainer)(GUIHANDLE listItems); +typedef GUIHANDLE (*GUIWindow_GetControl_Button)(void *addonData, GUIHANDLE handle, int controlId); +typedef GUIHANDLE (*GUIWindow_GetControl_RadioButton)(void *addonData, GUIHANDLE handle, int controlId); +typedef GUIHANDLE (*GUIWindow_GetControl_Edit)(void *addonData, GUIHANDLE handle, int controlId); +typedef GUIHANDLE (*GUIWindow_GetControl_Progress)(void *addonData, GUIHANDLE handle, int controlId); +typedef void (*GUIWindow_SetControlLabel)(void *addonData, GUIHANDLE handle, int controlId, const char *label); +typedef void (*GUIControl_Spin_SetVisible)(void *addonData, GUIHANDLE spinhandle, bool yesNo); +typedef void (*GUIControl_Spin_SetText)(void *addonData, GUIHANDLE spinhandle, const char *label); +typedef void (*GUIControl_Spin_Clear)(void *addonData, GUIHANDLE spinhandle); +typedef void (*GUIControl_Spin_AddLabel)(void *addonData, GUIHANDLE spinhandle, const char *label, int iValue); +typedef int (*GUIControl_Spin_GetValue)(void *addonData, GUIHANDLE spinhandle); +typedef void (*GUIControl_Spin_SetValue)(void *addonData, GUIHANDLE spinhandle, int iValue); +typedef void (*GUIControl_ListContainer_SetVisible)(void *addonData, GUIHANDLE handle, bool yesNo); +typedef void (*GUIControl_ListContainer_AddItems)(void *addonData, GUIHANDLE handle,GUIHANDLE listItems,GUIHANDLE items[],int size); +typedef GUIHANDLE (*GUIControl_ListContainer_GetItem)(void *addonData, GUIHANDLE handle,GUIHANDLE listItems,int index); +typedef int (*GUIControl_ListContainer_GetSelected)(void *addonData, GUIHANDLE handle); +typedef void (*GUIControl_ListContainer_Reset)(void *addonData, GUIHANDLE handle,GUIHANDLE listItems); +typedef void (*GUIControl_RadioButton_SetVisible)(void *addonData, GUIHANDLE handle, bool yesNo); +typedef void (*GUIControl_RadioButton_SetText)(void *addonData, GUIHANDLE handle, const char *label); +typedef void (*GUIControl_RadioButton_SetSelected)(void *addonData, GUIHANDLE handle, bool yesNo); +typedef bool (*GUIControl_RadioButton_IsSelected)(void *addonData, GUIHANDLE handle); +typedef void (*GUIControl_Progress_SetPercentage)(void *addonData, GUIHANDLE handle, float fPercent); +typedef float (*GUIControl_Progress_GetPercentage)(void *addonData, GUIHANDLE handle); +typedef void (*GUIControl_Progress_SetInfo)(void *addonData, GUIHANDLE handle, int iInfo); +typedef int (*GUIControl_Progress_GetInfo)(void *addonData, GUIHANDLE handle); +typedef const char* (*GUIControl_Progress_GetDescription)(void *addonData, GUIHANDLE handle); +typedef GUIHANDLE (*GUIListItem_Create)(void *addonData, const char *label, const char *label2, const char *iconImage, const char *thumbnailImage, const char *path); +typedef void (*GUIListItem_Destroy)(void *addonData, GUIHANDLE handle); +typedef const char* (*GUIListItem_GetLabel)(void *addonData, GUIHANDLE handle); +typedef void (*GUIListItem_SetLabel)(void *addonData, GUIHANDLE handle, const char *label); +typedef const char* (*GUIListItem_GetLabel2)(void *addonData, GUIHANDLE handle); +typedef void (*GUIListItem_SetLabel2)(void *addonData, GUIHANDLE handle, const char *label); +typedef void (*GUIListItem_SetIconImage)(void *addonData, GUIHANDLE handle, const char *image); +typedef void (*GUIListItem_SetThumbnailImage)(void *addonData, GUIHANDLE handle, const char *image); +typedef void (*GUIListItem_SetInfo)(void *addonData, GUIHANDLE handle, const char *info); +typedef void (*GUIListItem_SetProperty)(void *addonData, GUIHANDLE handle, const char *key, const char *value); +typedef const char* (*GUIListItem_GetProperty)(void *addonData, GUIHANDLE handle, const char *key); +typedef void (*GUIListItem_SetPath)(void *addonData, GUIHANDLE handle, const char *path); + +typedef struct CB_GUILib +{ + GUILock Lock; + GUIUnlock Unlock; + GUIGetScreenHeight GetScreenHeight; + GUIGetScreenWidth GetScreenWidth; + GUIGetVideoResolution GetVideoResolution; + GUIDialog_ShowYesNo Dialog_ShowYesNo; + GUIWindow_New Window_New; + GUIWindow_Delete Window_Delete; + GUIWindow_SetCallbacks Window_SetCallbacks; + GUIWindow_Show Window_Show; + GUIWindow_Close Window_Close; + GUIWindow_DoModal Window_DoModal; + GUIWindow_SetFocusId Window_SetFocusId; + GUIWindow_GetFocusId Window_GetFocusId; + GUIWindow_SetCoordinateResolution Window_SetCoordinateResolution; + GUIWindow_SetProperty Window_SetProperty; + GUIWindow_SetPropertyInt Window_SetPropertyInt; + GUIWindow_SetPropertyBool Window_SetPropertyBool; + GUIWindow_SetPropertyDouble Window_SetPropertyDouble; + GUIWindow_GetProperty Window_GetProperty; + GUIWindow_GetPropertyInt Window_GetPropertyInt; + GUIWindow_GetPropertyBool Window_GetPropertyBool; + GUIWindow_GetPropertyDouble Window_GetPropertyDouble; + GUIWindow_ClearProperties Window_ClearProperties; + GUIWindow_GetListSize Window_GetListSize; + GUIWindow_ClearList Window_ClearList; + GUIWindow_AddItem Window_AddItem; + GUIWindow_AddStringItem Window_AddStringItem; + GUIWindow_RemoveItem Window_RemoveItem; + GUIWindow_GetListItem Window_GetListItem; + GUIWindow_AddContextMenuButton Window_AddContextMenuButton; + GUIWindow_SetCurrentListPosition Window_SetCurrentListPosition; + GUIWindow_GetCurrentListPosition Window_GetCurrentListPosition; + GUIWindow_GetControl_Spin Window_GetControl_Spin; + GUIWindow_GetControl_ListContainer Window_GetControl_ListContainer; + GUIWindow_ReleaseControl_ListContainer Window_ReleaseControl_ListContainer; + GUIWindow_GetControl_Button Window_GetControl_Button; + GUIWindow_GetControl_RadioButton Window_GetControl_RadioButton; + GUIWindow_GetControl_Edit Window_GetControl_Edit; + GUIWindow_GetControl_Progress Window_GetControl_Progress; + GUIWindow_SetControlLabel Window_SetControlLabel; + GUIControl_Spin_SetVisible Control_Spin_SetVisible; + GUIControl_Spin_SetText Control_Spin_SetText; + GUIControl_Spin_Clear Control_Spin_Clear; + GUIControl_Spin_AddLabel Control_Spin_AddLabel; + GUIControl_Spin_GetValue Control_Spin_GetValue; + GUIControl_Spin_SetValue Control_Spin_SetValue; + GUIControl_ListContainer_SetVisible Control_ListContainer_SetVisible; + GUIControl_ListContainer_AddItems Control_ListContainer_AddItems; + GUIControl_ListContainer_GetItem Control_ListContainer_GetItem; + GUIControl_ListContainer_GetSelected Control_ListContainer_GetSelected; + GUIControl_ListContainer_Reset Control_ListContainer_Reset; + GUIControl_RadioButton_SetVisible Control_RadioButton_SetVisible; + GUIControl_RadioButton_SetText Control_RadioButton_SetText; + GUIControl_RadioButton_SetSelected Control_RadioButton_SetSelected; + GUIControl_RadioButton_IsSelected Control_RadioButton_IsSelected; + GUIControl_Progress_SetPercentage Control_Progress_SetPercentage; + GUIControl_Progress_GetPercentage Control_Progress_GetPercentage; + GUIControl_Progress_SetInfo Control_Progress_SetInfo; + GUIControl_Progress_GetInfo Control_Progress_GetInfo; + GUIControl_Progress_GetDescription Control_Progress_GetDescription; + GUIListItem_Create ListItem_Create; + GUIListItem_Destroy ListItem_Destroy; + GUIListItem_GetLabel ListItem_GetLabel; + GUIListItem_SetLabel ListItem_SetLabel; + GUIListItem_GetLabel2 ListItem_GetLabel2; + GUIListItem_SetLabel2 ListItem_SetLabel2; + GUIListItem_SetIconImage ListItem_SetIconImage; + GUIListItem_SetThumbnailImage ListItem_SetThumbnailImage; + GUIListItem_SetInfo ListItem_SetInfo; + GUIListItem_SetProperty ListItem_SetProperty; + GUIListItem_GetProperty ListItem_GetProperty; + GUIListItem_SetPath ListItem_SetPath; + +} CB_GUILib; + +typedef void (*PVRTransferEpgEntry)(void *userData, const PVR_HANDLE handle, const EPG_TAG *epgentry); +typedef void (*PVRTransferChannelEntry)(void *userData, const PVR_HANDLE handle, const PVR_CHANNEL *chan); +typedef void (*PVRTransferTimerEntry)(void *userData, const PVR_HANDLE handle, const PVR_TIMER *timer); +typedef void (*PVRTransferRecordingEntry)(void *userData, const PVR_HANDLE handle, const PVR_RECORDING *recording); +typedef void (*PVRAddMenuHook)(void *addonData, PVR_MENUHOOK *hook); +typedef void (*PVRRecording)(void *addonData, const char *Name, const char *FileName, bool On); +typedef void (*PVRTriggerChannelUpdate)(void *addonData); +typedef void (*PVRTriggerTimerUpdate)(void *addonData); +typedef void (*PVRTriggerRecordingUpdate)(void *addonData); +typedef void (*PVRTriggerChannelGroupsUpdate)(void *addonData); + +typedef void (*PVRTransferChannelGroup)(void *addonData, const PVR_HANDLE handle, const PVR_CHANNEL_GROUP *group); +typedef void (*PVRTransferChannelGroupMember)(void *addonData, const PVR_HANDLE handle, const PVR_CHANNEL_GROUP_MEMBER *member); + +typedef void (*PVRFreeDemuxPacket)(void *addonData, DemuxPacket* pPacket); +typedef DemuxPacket* (*PVRAllocateDemuxPacket)(void *addonData, int iDataSize); + +typedef struct CB_PVRLib +{ + PVRTransferEpgEntry TransferEpgEntry; + PVRTransferChannelEntry TransferChannelEntry; + PVRTransferTimerEntry TransferTimerEntry; + PVRTransferRecordingEntry TransferRecordingEntry; + PVRAddMenuHook AddMenuHook; + PVRRecording Recording; + PVRTriggerChannelUpdate TriggerChannelUpdate; + PVRTriggerTimerUpdate TriggerTimerUpdate; + PVRTriggerRecordingUpdate TriggerRecordingUpdate; + PVRTriggerChannelGroupsUpdate TriggerChannelGroupsUpdate; + PVRFreeDemuxPacket FreeDemuxPacket; + PVRAllocateDemuxPacket AllocateDemuxPacket; + PVRTransferChannelGroup TransferChannelGroup; + PVRTransferChannelGroupMember TransferChannelGroupMember; + +} CB_PVRLib; + + +typedef CB_AddOnLib* (*XBMCAddOnLib_RegisterMe)(void *addonData); +typedef void (*XBMCAddOnLib_UnRegisterMe)(void *addonData, CB_AddOnLib *cbTable); +typedef CB_GUILib* (*XBMCGUILib_RegisterMe)(void *addonData); +typedef void (*XBMCGUILib_UnRegisterMe)(void *addonData, CB_GUILib *cbTable); +typedef CB_PVRLib* (*XBMCPVRLib_RegisterMe)(void *addonData); +typedef void (*XBMCPVRLib_UnRegisterMe)(void *addonData, CB_PVRLib *cbTable); + +typedef struct AddonCB +{ + const char *libBasePath; ///> Never, never change this!!! + void *addonData; + XBMCAddOnLib_RegisterMe AddOnLib_RegisterMe; + XBMCAddOnLib_UnRegisterMe AddOnLib_UnRegisterMe; + XBMCGUILib_RegisterMe GUILib_RegisterMe; + XBMCGUILib_UnRegisterMe GUILib_UnRegisterMe; + XBMCPVRLib_RegisterMe PVRLib_RegisterMe; + XBMCPVRLib_UnRegisterMe PVRLib_UnRegisterMe; +} AddonCB; + + +namespace ADDON +{ + +class CAddon; +class CAddonCallbacksAddon; +class CAddonCallbacksGUI; +class CAddonCallbacksPVR; + +class CAddonCallbacks +{ +public: + CAddonCallbacks(CAddon* addon); + ~CAddonCallbacks(); + AddonCB *GetCallbacks() { return m_callbacks; } + + static CB_AddOnLib* AddOnLib_RegisterMe(void *addonData); + static void AddOnLib_UnRegisterMe(void *addonData, CB_AddOnLib *cbTable); + static CB_GUILib* GUILib_RegisterMe(void *addonData); + static void GUILib_UnRegisterMe(void *addonData, CB_GUILib *cbTable); + static CB_PVRLib* PVRLib_RegisterMe(void *addonData); + static void PVRLib_UnRegisterMe(void *addonData, CB_PVRLib *cbTable); + + CAddonCallbacksAddon *GetHelperAddon() { return m_helperAddon; } + CAddonCallbacksGUI *GetHelperGUI() { return m_helperGUI; } + CAddonCallbacksPVR *GetHelperPVR() { return m_helperPVR; } + +private: + AddonCB *m_callbacks; + CAddon *m_addon; + CAddonCallbacksAddon *m_helperAddon; + CAddonCallbacksGUI *m_helperGUI; + CAddonCallbacksPVR *m_helperPVR; +}; + +}; /* namespace ADDON */ diff --git a/xbmc/addons/AddonCallbacksAddon.cpp b/xbmc/addons/AddonCallbacksAddon.cpp new file mode 100644 index 0000000..7d290b4 --- /dev/null +++ b/xbmc/addons/AddonCallbacksAddon.cpp @@ -0,0 +1,359 @@ +/* + * 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 "Application.h" +#include "Addon.h" +#include "AddonCallbacksAddon.h" +#include "utils/log.h" +#include "LangInfo.h" +#include "dialogs/GUIDialogKaiToast.h" +#include "XBDateTime.h" + +namespace ADDON +{ + +CAddonCallbacksAddon::CAddonCallbacksAddon(CAddon* addon) +{ + m_addon = addon; + m_callbacks = new CB_AddOnLib; + + /* write XBMC addon-on specific add-on function addresses to the callback table */ + m_callbacks->Log = AddOnLog; + m_callbacks->QueueNotification = QueueNotification; + m_callbacks->GetSetting = GetAddonSetting; + m_callbacks->UnknownToUTF8 = UnknownToUTF8; + m_callbacks->GetLocalizedString = GetLocalizedString; + m_callbacks->GetDVDMenuLanguage = GetDVDMenuLanguage; + m_callbacks->GetLocalizedDate = GetLocalizedDate; + m_callbacks->GetLocalizedTime = GetLocalizedTime; +} + +CAddonCallbacksAddon::~CAddonCallbacksAddon() +{ + /* delete the callback table */ + delete m_callbacks; +} + +void CAddonCallbacksAddon::AddOnLog(void *addonData, const addon_log_t addonLogLevel, const char *strMessage) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL || strMessage == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - called with a null pointer", __FUNCTION__); + return; + } + + CAddonCallbacksAddon* addonHelper = addon->GetHelperAddon(); + + try + { + int xbmcLogLevel = LOGNONE; + switch (addonLogLevel) + { + case LOG_ERROR: + xbmcLogLevel = LOGERROR; + break; + case LOG_INFO: + xbmcLogLevel = LOGINFO; + break; + case LOG_NOTICE: + xbmcLogLevel = LOGNOTICE; + break; + case LOG_DEBUG: + default: + xbmcLogLevel = LOGDEBUG; + break; + } + + CStdString strXbmcMessage; + strXbmcMessage.Format("AddOnLog: %s: %s", addonHelper->m_addon->Name().c_str(), strMessage); + CLog::Log(xbmcLogLevel, "%s", strXbmcMessage.c_str()); + } + catch (std::exception &e) + { + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - exception '%s' caught in call in add-on '%s'. please contact the developer of this addon: %s", + __FUNCTION__, e.what(), addonHelper->m_addon->Name().c_str(), addonHelper->m_addon->Author().c_str()); + } +} + +void CAddonCallbacksAddon::QueueNotification(void *addonData, const queue_msg_t type, const char *strMessage) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL || strMessage == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - called with a null pointer", __FUNCTION__); + return; + } + + CAddonCallbacksAddon* addonHelper = addon->GetHelperAddon(); + + try + { + switch (type) + { + case QUEUE_WARNING: + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Warning, addonHelper->m_addon->Name(), strMessage, 3000, true); + CLog::Log(LOGDEBUG, "CAddonCallbacksAddon - %s - %s - Warning Message: '%s'", __FUNCTION__, addonHelper->m_addon->Name().c_str(), strMessage); + break; + + case QUEUE_ERROR: + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Error, addonHelper->m_addon->Name(), strMessage, 3000, true); + CLog::Log(LOGDEBUG, "CAddonCallbacksAddon - %s - %s - Error Message : '%s'", __FUNCTION__, addonHelper->m_addon->Name().c_str(), strMessage); + break; + + case QUEUE_INFO: + default: + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, addonHelper->m_addon->Name(), strMessage, 3000, false); + CLog::Log(LOGDEBUG, "CAddonCallbacksAddon - %s - %s - Info Message : '%s'", __FUNCTION__, addonHelper->m_addon->Name().c_str(), strMessage); + break; + } + } + catch (std::exception &e) + { + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - exception '%s' caught in call in add-on '%s'. please contact the developer of this addon: %s", + __FUNCTION__, e.what(), addonHelper->m_addon->Name().c_str(), addonHelper->m_addon->Author().c_str()); + } +} + +/*bool CAddonCallbacksAddon::UpdateAddonSetting(void *addonData, const char *strSettingName, void *settingValue) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL || strSettingName == NULL || settingValue == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - called with a null pointer", __FUNCTION__); + return false; + } + + CAddonCallbacksAddon* addonHelper = addon->GetHelperAddon(); + + try + { + CLog::Log(LOGDEBUG, "CAddonCallbacksAddon - %s - add-on '%s' requests update of setting '%s'", __FUNCTION__, addonHelper->m_addon->Name().c_str(), strSettingName); + + if (!addonHelper->m_addon->ReloadSettings()) + { + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - could't get settings for add-on '%s'", __FUNCTION__, addonHelper->m_addon->Name().c_str()); + return false; + } + + const TiXmlElement *category = addonHelper->m_addon->GetSettingsXML()->FirstChildElement("category"); + if (!category) // add a default one... + category = addonHelper->m_addon->GetSettingsXML(); + + while (category) + { + const TiXmlElement *setting = category->FirstChildElement("setting"); + while (setting) + { + const char *id = setting->Attribute("id"); + const char *type = setting->Attribute("type"); + CStdString value; + if (strcmpi(id, strSettingName) == 0 && type) + { + if (strcmpi(type, "text") == 0 || strcmpi(type, "ipaddress") == 0 || + strcmpi(type, "folder") == 0 || strcmpi(type, "action") == 0 || + strcmpi(type, "music") == 0 || strcmpi(type, "pictures") == 0 || + strcmpi(type, "folder") == 0 || strcmpi(type, "programs") == 0 || + strcmpi(type, "files") == 0 || strcmpi(type, "fileenum") == 0) + { + value = (char*) settingValue; + addonHelper->m_addon->UpdateSetting(id).c_str(), value); + return true; + } + else if (strcmpi(type, "number") == 0 || strcmpi(type, "enum") == 0 || + strcmpi(type, "labelenum") == 0) + { + value.Format("%i",*(int*) settingValue); + addonHelper->m_addon->UpdateSetting(id).c_str(), value); + return true; + } + else if (strcmpi(type, "bool") == 0) + { + value = *(bool*) settingValue?"true" : "false"; + addonHelper->m_addon->UpdateSetting(id).c_str(), value); + return true; + } + } + setting = setting->NextSiblingElement("setting"); + } + category = category->NextSiblingElement("category"); + } + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - can't find setting '%s' in '%s'", __FUNCTION__, strSettingName, addonHelper->m_addon->Name().c_str()); + } + catch (std::exception &e) + { + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - exception '%s' caught in call in add-on '%s'. please contact the developer of this addon: %s", + __FUNCTION__, e.what(), addonHelper->m_addon->Name().c_str(), addonHelper->m_addon->Author().c_str()); + } + + return false; +}*/ + + +bool CAddonCallbacksAddon::GetAddonSetting(void *addonData, const char *strSettingName, void *settingValue) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL || strSettingName == NULL || settingValue == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - called with a null pointer", __FUNCTION__); + return false; + } + + CAddonCallbacksAddon* addonHelper = addon->GetHelperAddon(); + + try + { + CLog::Log(LOGDEBUG, "CAddonCallbacksAddon - %s - add-on '%s' requests setting '%s'", __FUNCTION__, addonHelper->m_addon->Name().c_str(), strSettingName); + + if (!addonHelper->m_addon->ReloadSettings()) + { + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - could't get settings for add-on '%s'", __FUNCTION__, addonHelper->m_addon->Name().c_str()); + return false; + } + + const TiXmlElement *category = addonHelper->m_addon->GetSettingsXML()->FirstChildElement("category"); + if (!category) // add a default one... + category = addonHelper->m_addon->GetSettingsXML(); + + while (category) + { + const TiXmlElement *setting = category->FirstChildElement("setting"); + while (setting) + { + const char *id = setting->Attribute("id"); + const char *type = setting->Attribute("type"); + + if (strcmpi(id, strSettingName) == 0 && type) + { + if (strcmpi(type, "text") == 0 || strcmpi(type, "ipaddress") == 0 || + strcmpi(type, "folder") == 0 || strcmpi(type, "action") == 0 || + strcmpi(type, "music") == 0 || strcmpi(type, "pictures") == 0 || + strcmpi(type, "folder") == 0 || strcmpi(type, "programs") == 0 || + strcmpi(type, "files") == 0 || strcmpi(type, "fileenum") == 0) + { + strcpy((char*) settingValue, addonHelper->m_addon->GetSetting(id).c_str()); + return true; + } + else if (strcmpi(type, "number") == 0 || strcmpi(type, "enum") == 0 || + strcmpi(type, "labelenum") == 0) + { + *(int*) settingValue = (int) atoi(addonHelper->m_addon->GetSetting(id)); + return true; + } + else if (strcmpi(type, "bool") == 0) + { + *(bool*) settingValue = (bool) (addonHelper->m_addon->GetSetting(id) == "true" ? true : false); + return true; + } + } + setting = setting->NextSiblingElement("setting"); + } + category = category->NextSiblingElement("category"); + } + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - can't find setting '%s' in '%s'", __FUNCTION__, strSettingName, addonHelper->m_addon->Name().c_str()); + } + catch (std::exception &e) + { + CLog::Log(LOGERROR, "CAddonCallbacksAddon - %s - exception '%s' caught in call in add-on '%s'. please contact the developer of this addon: %s", + __FUNCTION__, e.what(), addonHelper->m_addon->Name().c_str(), addonHelper->m_addon->Author().c_str()); + } + + return false; +} + +char* CAddonCallbacksAddon::UnknownToUTF8(const char *strSource) +{ + CStdString string; + if (strSource != NULL) + g_charsetConverter.unknownToUTF8(strSource, string); + else + string = ""; + char *buffer = (char*) malloc (string.length()+1); + strcpy(buffer, string.c_str()); + return buffer; +} + +const char* CAddonCallbacksAddon::GetLocalizedString(const void* addonData, long dwCode) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || g_application.m_bStop) + return NULL; + + CAddonCallbacksAddon* addonHelper = helper->GetHelperAddon(); + + CStdString string; + if (dwCode >= 30000 && dwCode <= 30999) + string = addonHelper->m_addon->GetString(dwCode).c_str(); + else if (dwCode >= 32000 && dwCode <= 32999) + string = addonHelper->m_addon->GetString(dwCode).c_str(); + else + string = g_localizeStrings.Get(dwCode).c_str(); + + char *buffer = (char*) malloc (string.length()+1); + strcpy(buffer, string.c_str()); + return buffer; +} + +const char* CAddonCallbacksAddon::GetDVDMenuLanguage(const void* addonData) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return NULL; + + CStdString string = g_langInfo.GetDVDMenuLanguage(); + + char *buffer = (char*) malloc (string.length()+1); + strcpy(buffer, string.c_str()); + return buffer; +} + +const char* CAddonCallbacksAddon::GetLocalizedDate(const void* addonData,time_t time, bool bLongDate, bool bWithShortNames) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return NULL; + + CDateTime date(time); + + CStdString string = date.GetAsLocalizedDate(bLongDate,bWithShortNames); + + char *buffer = (char*) malloc (string.length()+1); + strcpy(buffer, string.c_str()); + return buffer; +} + +const char* CAddonCallbacksAddon::GetLocalizedTime(const void* addonData,time_t time, bool bWithSeconds) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return NULL; + + CDateTime date(time); + + CStdString string = date.GetAsLocalizedTime("",bWithSeconds); + + char *buffer = (char*) malloc (string.length()+1); + strcpy(buffer, string.c_str()); + return buffer; +} + + +}; /* namespace ADDON */ diff --git a/xbmc/addons/AddonCallbacksAddon.h b/xbmc/addons/AddonCallbacksAddon.h new file mode 100644 index 0000000..143e669 --- /dev/null +++ b/xbmc/addons/AddonCallbacksAddon.h @@ -0,0 +1,109 @@ +#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 "AddonCallbacks.h" + +namespace ADDON +{ + +class CAddonCallbacksAddon +{ +public: + CAddonCallbacksAddon(CAddon* addon); + ~CAddonCallbacksAddon(); + + /*! + * @return The callback table. + */ + CB_AddOnLib *GetCallbacks() { return m_callbacks; } + + /*! + * @brief Add a message to XBMC's log. + * @param addonData A pointer to the add-on. + * @param addonLogLevel The log level of the message. + * @param strMessage The message itself. + */ + static void AddOnLog(void *addonData, const addon_log_t addonLogLevel, const char *strMessage); + + /*! + * @brief Queue a notification in the GUI. + * @param addonData A pointer to the add-on. + * @param type The message type. + * @param strMessage The message to display. + */ + static void QueueNotification(void *addonData, const queue_msg_t type, const char *strMessage); + + /*! + * @brief Get a settings value for this add-on. + * @param addonData A pointer to the add-on. + * @param settingName The name of the setting to get. + * @param settingValue The value. + * @return True if the settings was fetched successfully, false otherwise. + */ + static bool GetAddonSetting(void *addonData, const char *strSettingName, void *settingValue); + + /*! + * @brief Translate a string with an unknown encoding to UTF8. + * @param sourceDest The source string. + * @return The converted string. + */ + static char *UnknownToUTF8(const char *strSource); + + /*! + * @brief Get a localised message. + * @param addonData A pointer to the add-on. + * @param dwCode The code of the message to get. + * @return The message. + */ + static const char *GetLocalizedString(const void* addonData, long dwCode); + + /*! + * @brief Get the DVD menu language. + * @param addonData A pointer to the add-on. + * @return The language. + */ + static const char *GetDVDMenuLanguage(const void* addonData); + + /*! + * @brief Get a localised date + * @param addonData A pointer to the add-on. + * @param time The time_t to convert + * @param bLongDate Use long date format + * @param bWithShortNames Abbreviation month and weekday + * @return The localised date + */ + static const char *GetLocalizedDate(const void* addonData,time_t time, bool bLongDate, bool bWithShortNames); + + /*! + * @brief Get the localised time + * @param addonData A pointer to the add-on. + * @param time The time_t to convert + * @param bWithSeconds Include seconds + * @return The localised time + */ + static const char *GetLocalizedTime(const void* addonData,time_t time, bool bWithSeconds); +private: + CB_AddOnLib *m_callbacks; /*!< callback addresses */ + CAddon *m_addon; /*!< the add-on */ +}; + +}; /* namespace ADDON */ diff --git a/xbmc/addons/AddonCallbacksGUI.cpp b/xbmc/addons/AddonCallbacksGUI.cpp new file mode 100644 index 0000000..4a2665b --- /dev/null +++ b/xbmc/addons/AddonCallbacksGUI.cpp @@ -0,0 +1,1762 @@ +/* + * Copyright (C) 2005-2010 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 "Application.h" +#include "Addon.h" +#include "AddonCallbacksGUI.h" +#include "utils/log.h" +#include "Skin.h" +#include "FileItem.h" +#include "filesystem/File.h" +#include "utils/URIUtils.h" +#include "utils/TimeUtils.h" +#include "guilib/GUIWindowManager.h" +#include "guilib/TextureManager.h" +#include "settings/GUISettings.h" +#include "guilib/GUISpinControlEx.h" +#include "guilib/GUIRadioButtonControl.h" +#include "guilib/GUISettingsSliderControl.h" +#include "guilib/GUIEditControl.h" +#include "guilib/GUIProgressControl.h" +#include "guilib/GUIListContainer.h" +#include "guilib/GUIWrappingListContainer.h" +#include "guilib/GUIPanelContainer.h" +#include "guilib/GUIFixedListContainer.h" +#include "epg/GUIEPGGridContainer.h" +#include "dialogs/GUIDialogYesNo.h" +#include "GUIInfoManager.h" + +#define CONTROL_BTNVIEWASICONS 2 +#define CONTROL_BTNSORTBY 3 +#define CONTROL_BTNSORTASC 4 +#define CONTROL_LABELFILES 12 + +using namespace std; + +namespace ADDON +{ + +static int iXBMCGUILockRef = 0; + +CAddonCallbacksGUI::CAddonCallbacksGUI(CAddon* addon) +{ + m_addon = addon; + m_callbacks = new CB_GUILib; + + /* GUI Helper functions */ + m_callbacks->Lock = CAddonCallbacksGUI::Lock; + m_callbacks->Unlock = CAddonCallbacksGUI::Unlock; + m_callbacks->GetScreenHeight = CAddonCallbacksGUI::GetScreenHeight; + m_callbacks->GetScreenWidth = CAddonCallbacksGUI::GetScreenWidth; + m_callbacks->GetVideoResolution = CAddonCallbacksGUI::GetVideoResolution; + m_callbacks->Dialog_ShowYesNo = CAddonCallbacksGUI::Dialog_ShowYesNo; + m_callbacks->Window_New = CAddonCallbacksGUI::Window_New; + m_callbacks->Window_Delete = CAddonCallbacksGUI::Window_Delete; + m_callbacks->Window_SetCallbacks = CAddonCallbacksGUI::Window_SetCallbacks; + m_callbacks->Window_Show = CAddonCallbacksGUI::Window_Show; + m_callbacks->Window_Close = CAddonCallbacksGUI::Window_Close; + m_callbacks->Window_DoModal = CAddonCallbacksGUI::Window_DoModal; + m_callbacks->Window_SetFocusId = CAddonCallbacksGUI::Window_SetFocusId; + m_callbacks->Window_GetFocusId = CAddonCallbacksGUI::Window_GetFocusId; + m_callbacks->Window_SetCoordinateResolution = CAddonCallbacksGUI::Window_SetCoordinateResolution; + m_callbacks->Window_SetProperty = CAddonCallbacksGUI::Window_SetProperty; + m_callbacks->Window_SetPropertyInt = CAddonCallbacksGUI::Window_SetPropertyInt; + m_callbacks->Window_SetPropertyBool = CAddonCallbacksGUI::Window_SetPropertyBool; + m_callbacks->Window_SetPropertyDouble = CAddonCallbacksGUI::Window_SetPropertyDouble; + m_callbacks->Window_GetProperty = CAddonCallbacksGUI::Window_GetProperty; + m_callbacks->Window_GetPropertyInt = CAddonCallbacksGUI::Window_GetPropertyInt; + m_callbacks->Window_GetPropertyBool = CAddonCallbacksGUI::Window_GetPropertyBool; + m_callbacks->Window_GetPropertyDouble = CAddonCallbacksGUI::Window_GetPropertyDouble; + m_callbacks->Window_ClearProperties = CAddonCallbacksGUI::Window_ClearProperties; + + m_callbacks->Window_GetListSize = CAddonCallbacksGUI::Window_GetListSize; + m_callbacks->Window_ClearList = CAddonCallbacksGUI::Window_ClearList; + m_callbacks->Window_AddItem = CAddonCallbacksGUI::Window_AddItem; + m_callbacks->Window_AddStringItem = CAddonCallbacksGUI::Window_AddStringItem; + m_callbacks->Window_RemoveItem = CAddonCallbacksGUI::Window_RemoveItem; + m_callbacks->Window_GetListItem = CAddonCallbacksGUI::Window_GetListItem; + m_callbacks->Window_SetCurrentListPosition = CAddonCallbacksGUI::Window_SetCurrentListPosition; + m_callbacks->Window_GetCurrentListPosition = CAddonCallbacksGUI::Window_GetCurrentListPosition; + + m_callbacks->Window_AddContextMenuButton = CAddonCallbacksGUI::Window_AddContextMenuButton; + + m_callbacks->Window_GetControl_Spin = CAddonCallbacksGUI::Window_GetControl_Spin; + m_callbacks->Window_GetControl_ListContainer= CAddonCallbacksGUI::Window_GetControl_ListContainer; + m_callbacks->Window_ReleaseControl_ListContainer= CAddonCallbacksGUI::Window_ReleaseControl_ListContainer; + m_callbacks->Window_GetControl_Button = CAddonCallbacksGUI::Window_GetControl_Button; + m_callbacks->Window_GetControl_RadioButton = CAddonCallbacksGUI::Window_GetControl_RadioButton; + m_callbacks->Window_GetControl_Edit = CAddonCallbacksGUI::Window_GetControl_Edit; + m_callbacks->Window_GetControl_Progress = CAddonCallbacksGUI::Window_GetControl_Progress; + + m_callbacks->Window_SetControlLabel = CAddonCallbacksGUI::Window_SetControlLabel; + + m_callbacks->Control_Spin_SetVisible = CAddonCallbacksGUI::Control_Spin_SetVisible; + m_callbacks->Control_Spin_SetText = CAddonCallbacksGUI::Control_Spin_SetText; + m_callbacks->Control_Spin_Clear = CAddonCallbacksGUI::Control_Spin_Clear; + m_callbacks->Control_Spin_AddLabel = CAddonCallbacksGUI::Control_Spin_AddLabel; + m_callbacks->Control_Spin_GetValue = CAddonCallbacksGUI::Control_Spin_GetValue; + m_callbacks->Control_Spin_SetValue = CAddonCallbacksGUI::Control_Spin_SetValue; + + m_callbacks->Control_ListContainer_AddItems = CAddonCallbacksGUI::Control_ListContainer_AddItems; + m_callbacks->Control_ListContainer_GetItem = CAddonCallbacksGUI::Control_ListContainer_GetItem; + m_callbacks->Control_ListContainer_GetSelected = CAddonCallbacksGUI::Control_ListContainer_GetSelected; + m_callbacks->Control_ListContainer_Reset = CAddonCallbacksGUI::Control_ListContainer_Reset; + m_callbacks->Control_ListContainer_SetVisible=CAddonCallbacksGUI::Control_ListContainer_SetVisible; + + m_callbacks->Control_RadioButton_SetVisible = CAddonCallbacksGUI::Control_RadioButton_SetVisible; + m_callbacks->Control_RadioButton_SetText = CAddonCallbacksGUI::Control_RadioButton_SetText; + m_callbacks->Control_RadioButton_SetSelected= CAddonCallbacksGUI::Control_RadioButton_SetSelected; + m_callbacks->Control_RadioButton_IsSelected = CAddonCallbacksGUI::Control_RadioButton_IsSelected; + + m_callbacks->Control_Progress_SetPercentage = CAddonCallbacksGUI::Control_Progress_SetPercentage; + m_callbacks->Control_Progress_GetPercentage = CAddonCallbacksGUI::Control_Progress_GetPercentage; + m_callbacks->Control_Progress_SetInfo = CAddonCallbacksGUI::Control_Progress_SetInfo; + m_callbacks->Control_Progress_GetInfo = CAddonCallbacksGUI::Control_Progress_GetInfo; + m_callbacks->Control_Progress_GetDescription= CAddonCallbacksGUI::Control_Progress_GetDescription; + + m_callbacks->ListItem_Create = CAddonCallbacksGUI::ListItem_Create; + m_callbacks->ListItem_Destroy = CAddonCallbacksGUI::ListItem_Destroy; + m_callbacks->ListItem_GetLabel = CAddonCallbacksGUI::ListItem_GetLabel; + m_callbacks->ListItem_SetLabel = CAddonCallbacksGUI::ListItem_SetLabel; + m_callbacks->ListItem_GetLabel2 = CAddonCallbacksGUI::ListItem_GetLabel2; + m_callbacks->ListItem_SetLabel2 = CAddonCallbacksGUI::ListItem_SetLabel2; + m_callbacks->ListItem_SetIconImage = CAddonCallbacksGUI::ListItem_SetIconImage; + m_callbacks->ListItem_SetThumbnailImage = CAddonCallbacksGUI::ListItem_SetThumbnailImage; + m_callbacks->ListItem_SetInfo = CAddonCallbacksGUI::ListItem_SetInfo; + m_callbacks->ListItem_SetProperty = CAddonCallbacksGUI::ListItem_SetProperty; + m_callbacks->ListItem_GetProperty = CAddonCallbacksGUI::ListItem_GetProperty; + m_callbacks->ListItem_SetPath = CAddonCallbacksGUI::ListItem_SetPath; +} + +CAddonCallbacksGUI::~CAddonCallbacksGUI() +{ + delete m_callbacks; +} + +void CAddonCallbacksGUI::Lock() +{ + if (iXBMCGUILockRef == 0) g_graphicsContext.Lock(); + iXBMCGUILockRef++; +} + +void CAddonCallbacksGUI::Unlock() +{ + if (iXBMCGUILockRef > 0) + { + iXBMCGUILockRef--; + if (iXBMCGUILockRef == 0) g_graphicsContext.Unlock(); + } +} + +int CAddonCallbacksGUI::GetScreenHeight() +{ + return g_graphicsContext.GetHeight(); +} + +int CAddonCallbacksGUI::GetScreenWidth() +{ + return g_graphicsContext.GetWidth(); +} + +int CAddonCallbacksGUI::GetVideoResolution() +{ + return (int)g_graphicsContext.GetVideoResolution(); +} + +int CAddonCallbacksGUI::Dialog_ShowYesNo(const char* heading, const char* line0, const char* line1, const char* line2, int* bCanceled, const char* noLabel, const char* yesLabel) +{ + const CStdString strHeading = heading? heading : ""; + const CStdString strLine0 = line0? line0 : ""; + const CStdString strLine1 = line1? line1 : ""; + const CStdString strLine2 = line2? line2 : ""; + bool boolCanceled=false; + const CStdString strNoLabel = noLabel? noLabel : ""; + const CStdString strYesLabel = yesLabel? yesLabel : ""; + bool retval = CGUIDialogYesNo::ShowAndGetInput(strHeading, strLine0, strLine1, strLine2, boolCanceled, strNoLabel, strYesLabel); + if(bCanceled) + *bCanceled = boolCanceled? 1 : 0; + return static_cast(retval); +} + +GUIHANDLE CAddonCallbacksGUI::Window_New(void *addonData, const char *xmlFilename, const char *defaultSkin, bool forceFallback, bool asDialog) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return NULL; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + RESOLUTION_INFO res; + CStdString strSkinPath; + if (!forceFallback) + { + /* Check to see if the XML file exists in current skin. If not use + fallback path to find a skin for the addon */ + strSkinPath = g_SkinInfo->GetSkinPath(xmlFilename, &res); + + if (!XFILE::CFile::Exists(strSkinPath)) + { + /* Check for the matching folder for the skin in the fallback skins folder */ + CStdString basePath; + URIUtils::AddFileToFolder(guiHelper->m_addon->Path(), "resources", basePath); + URIUtils::AddFileToFolder(basePath, "skins", basePath); + URIUtils::AddFileToFolder(basePath, URIUtils::GetFileName(g_SkinInfo->Path()), basePath); + strSkinPath = g_SkinInfo->GetSkinPath(xmlFilename, &res, basePath); + if (!XFILE::CFile::Exists(strSkinPath)) + { + /* Finally fallback to the DefaultSkin as it didn't exist in either the + XBMC Skin folder or the fallback skin folder */ + forceFallback = true; + } + } + } + + if (forceFallback) + { + //FIXME make this static method of current skin? + CStdString str("none"); + AddonProps props(str, ADDON_SKIN, str, str); + CSkinInfo skinInfo(props); + CStdString basePath; + URIUtils::AddFileToFolder(guiHelper->m_addon->Path(), "resources", basePath); + URIUtils::AddFileToFolder(basePath, "skins", basePath); + URIUtils::AddFileToFolder(basePath, defaultSkin, basePath); + + skinInfo.Start(basePath); + strSkinPath = skinInfo.GetSkinPath(xmlFilename, &res, basePath); + + if (!XFILE::CFile::Exists(strSkinPath)) + { + CLog::Log(LOGERROR, "Window_New: %s/%s - XML File '%s' for Window is missing, contact Developer '%s' of this AddOn", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str(), strSkinPath.c_str(), guiHelper->m_addon->Author().c_str()); + return NULL; + } + } + // window id's 14000 - 14100 are reserved for addons + // get first window id that is not in use + int id = WINDOW_ADDON_START; + // if window 14099 is in use it means addon can't create more windows + Lock(); + if (g_windowManager.GetWindow(WINDOW_ADDON_END)) + { + Unlock(); + CLog::Log(LOGERROR, "Window_New: %s/%s - maximum number of windows reached", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return NULL; + } + while(id < WINDOW_ADDON_END && g_windowManager.GetWindow(id) != NULL) id++; + Unlock(); + + CGUIWindow *window; + if (!asDialog) + window = new CGUIAddonWindow(id, strSkinPath, guiHelper->m_addon); + else + window = new CGUIAddonWindowDialog(id, strSkinPath, guiHelper->m_addon); + + Lock(); + g_windowManager.Add(window); + Unlock(); + + window->SetCoordsRes(res); + + return window; +} + +void CAddonCallbacksGUI::Window_Delete(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_Show: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return; + + Lock(); + // first change to an existing window + if (g_windowManager.GetActiveWindow() == pAddonWindow->m_iWindowId && !g_application.m_bStop) + { + if(g_windowManager.GetWindow(pAddonWindow->m_iOldWindowId)) + g_windowManager.ActivateWindow(pAddonWindow->m_iOldWindowId); + else // old window does not exist anymore, switch to home + g_windowManager.ActivateWindow(WINDOW_HOME); + } + // Free any window properties + pAddonWindow->ClearProperties(); + // free the window's resources and unload it (free all guicontrols) + pAddonWindow->FreeResources(true); + + g_windowManager.Remove(pAddonWindow->GetID()); + delete pAddonWindow; + Unlock(); +} + +void CAddonCallbacksGUI::Window_SetCallbacks(void *addonData, GUIHANDLE handle, GUIHANDLE clienthandle, bool (*initCB)(GUIHANDLE), bool (*clickCB)(GUIHANDLE, int), bool (*focusCB)(GUIHANDLE, int), bool (*onActionCB)(GUIHANDLE handle, int),bool (*onContextMenuCB)(GUIHANDLE ,int ,int , unsigned int)) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + + Lock(); + pAddonWindow->m_clientHandle = clienthandle; + pAddonWindow->CBOnInit = initCB; + pAddonWindow->CBOnClick = clickCB; + pAddonWindow->CBOnFocus = focusCB; + pAddonWindow->CBOnAction = onActionCB; + pAddonWindow->CBOnContextMenu = onContextMenuCB; + Unlock(); +} + +bool CAddonCallbacksGUI::Window_Show(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return false; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_Show: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return false; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return false; + + if (pAddonWindow->m_iOldWindowId != pAddonWindow->m_iWindowId && pAddonWindow->m_iWindowId != g_windowManager.GetActiveWindow()) + pAddonWindow->m_iOldWindowId = g_windowManager.GetActiveWindow(); + + Lock(); + if (pAddonWindow->IsDialog()) + ((CGUIAddonWindowDialog*)pAddonWindow)->Show(); + else + g_windowManager.ActivateWindow(pAddonWindow->m_iWindowId); + Unlock(); + + return true; +} + +bool CAddonCallbacksGUI::Window_Close(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return false; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_Close: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return false; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return false; + + pAddonWindow->m_bModal = false; + if (pAddonWindow->IsDialog()) + ((CGUIAddonWindowDialog*)pAddonWindow)->PulseActionEvent(); + else + ((CGUIAddonWindow*)pAddonWindow)->PulseActionEvent(); + + Lock(); + // if it's a dialog, we have to close it a bit different + if (pAddonWindow->IsDialog()) + ((CGUIAddonWindowDialog*)pAddonWindow)->Show(false); + else + g_windowManager.ActivateWindow(pAddonWindow->m_iOldWindowId); + pAddonWindow->m_iOldWindowId = 0; + + Unlock(); + + return true; +} + +bool CAddonCallbacksGUI::Window_DoModal(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return false; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_DoModal: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return false; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return false; + + pAddonWindow->m_bModal = true; + + if (pAddonWindow->m_iWindowId != g_windowManager.GetActiveWindow()) + Window_Show(addonData, handle); + + return true; +} + +bool CAddonCallbacksGUI::Window_SetFocusId(void *addonData, GUIHANDLE handle, int iControlId) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return false; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_SetFocusId: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return false; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return false; + + if(!pWindow->GetControl(iControlId)) + { + CLog::Log(LOGERROR, "Window_SetFocusId: %s/%s - Control does not exist in window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return false; + } + + Lock(); + CGUIMessage msg = CGUIMessage(GUI_MSG_SETFOCUS, pAddonWindow->m_iWindowId, iControlId); + pWindow->OnMessage(msg); + Unlock(); + + return true; +} + +int CAddonCallbacksGUI::Window_GetFocusId(void *addonData, GUIHANDLE handle) +{ + int iControlId = -1; + + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return iControlId; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_GetFocusId: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return iControlId; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return iControlId; + + Lock(); + iControlId = pWindow->GetFocusedControlID(); + Unlock(); + + if (iControlId == -1) + { + CLog::Log(LOGERROR, "Window_GetFocusId: %s/%s - No control in this window has focus", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return iControlId; + } + + return iControlId; +} + +bool CAddonCallbacksGUI::Window_SetCoordinateResolution(void *addonData, GUIHANDLE handle, int res) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return false; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "SetCoordinateResolution: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return false; + } + + if (res < RES_HDTV_1080i || res > RES_AUTORES) + { + CLog::Log(LOGERROR, "SetCoordinateResolution: %s/%s - Invalid resolution", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return false; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return false; + + pWindow->SetCoordsRes((RESOLUTION)res); + + return true; +} + +void CAddonCallbacksGUI::Window_SetProperty(void *addonData, GUIHANDLE handle, const char *key, const char *value) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_SetProperty: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return; + + CStdString lowerKey = key; + + Lock(); + pWindow->SetProperty(lowerKey.ToLower(), value); + Unlock(); +} + +void CAddonCallbacksGUI::Window_SetPropertyInt(void *addonData, GUIHANDLE handle, const char *key, int value) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_SetPropertyInt: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return; + + CStdString lowerKey = key; + + Lock(); + pWindow->SetProperty(lowerKey.ToLower(), value); + Unlock(); +} + +void CAddonCallbacksGUI::Window_SetPropertyBool(void *addonData, GUIHANDLE handle, const char *key, bool value) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_SetPropertyBool: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return; + + CStdString lowerKey = key; + + Lock(); + pWindow->SetProperty(lowerKey.ToLower(), value); + Unlock(); +} + +void CAddonCallbacksGUI::Window_SetPropertyDouble(void *addonData, GUIHANDLE handle, const char *key, double value) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_SetPropertyDouble: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return; + + CStdString lowerKey = key; + + Lock(); + pWindow->SetProperty(lowerKey.ToLower(), value); + Unlock(); +} + +const char* CAddonCallbacksGUI::Window_GetProperty(void *addonData, GUIHANDLE handle, const char *key) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return NULL; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_GetProperty: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return NULL; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return NULL; + + Lock(); + CStdString lowerKey = key; + string value = pWindow->GetProperty(lowerKey.ToLower()).asString(); + Unlock(); + + return value.c_str(); +} + +int CAddonCallbacksGUI::Window_GetPropertyInt(void *addonData, GUIHANDLE handle, const char *key) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return -1; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_GetPropertyInt: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return -1; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return -1; + + Lock(); + CStdString lowerKey = key; + int value = pWindow->GetProperty(lowerKey.ToLower()).asInteger(); + Unlock(); + + return value; +} + +bool CAddonCallbacksGUI::Window_GetPropertyBool(void *addonData, GUIHANDLE handle, const char *key) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return false; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_GetPropertyBool: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return false; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return false; + + Lock(); + CStdString lowerKey = key; + bool value = pWindow->GetProperty(lowerKey.ToLower()).asBoolean(); + Unlock(); + + return value; +} + +double CAddonCallbacksGUI::Window_GetPropertyDouble(void *addonData, GUIHANDLE handle, const char *key) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return 0.0; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_GetPropertyDouble: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return 0.0; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return 0.0; + + Lock(); + CStdString lowerKey = key; + double value = pWindow->GetProperty(lowerKey.ToLower()).asDouble(); + Unlock(); + + return value; +} + +void CAddonCallbacksGUI::Window_ClearProperties(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + + if (!handle) + { + CLog::Log(LOGERROR, "Window_ClearProperties: %s/%s - No Window", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return; + } + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIWindow *pWindow = (CGUIWindow*)g_windowManager.GetWindow(pAddonWindow->m_iWindowId); + if (!pWindow) + return; + + Lock(); + pWindow->ClearProperties(); + Unlock(); +} + +int CAddonCallbacksGUI::Window_GetListSize(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return -1; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + + Lock(); + int listSize = pAddonWindow->GetListSize(); + Unlock(); + + return listSize; +} + +void CAddonCallbacksGUI::Window_ClearList(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + + Lock(); + pAddonWindow->ClearList(); + Unlock(); + + return; +} + +GUIHANDLE CAddonCallbacksGUI::Window_AddItem(void *addonData, GUIHANDLE handle, GUIHANDLE item, int itemPosition) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle || !item) + return NULL; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CFileItemPtr pItem((CFileItem*)item); + Lock(); + pAddonWindow->AddItem(pItem, itemPosition); + Unlock(); + + return item; +} + +GUIHANDLE CAddonCallbacksGUI::Window_AddStringItem(void *addonData, GUIHANDLE handle, const char *itemName, int itemPosition) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle || !itemName) + return NULL; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CFileItemPtr item(new CFileItem(itemName)); + Lock(); + pAddonWindow->AddItem(item, itemPosition); + Unlock(); + + return item.get(); +} + +void CAddonCallbacksGUI::Window_RemoveItem(void *addonData, GUIHANDLE handle, int itemPosition) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + + Lock(); + pAddonWindow->RemoveItem(itemPosition); + Unlock(); + + return; +} + +GUIHANDLE CAddonCallbacksGUI::Window_GetListItem(void *addonData, GUIHANDLE handle, int listPos) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + + CAddonCallbacksGUI* guiHelper = helper->GetHelperGUI(); + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + + Lock(); + CFileItemPtr fi = pAddonWindow->GetListItem(listPos); + if (fi == NULL) + { + Unlock(); + CLog::Log(LOGERROR, "Window_GetListItem: %s/%s - Index out of range", TranslateType(guiHelper->m_addon->Type()).c_str(), guiHelper->m_addon->Name().c_str()); + return NULL; + } + Unlock(); + + return fi.get(); +} + +void CAddonCallbacksGUI::Window_SetCurrentListPosition(void *addonData, GUIHANDLE handle, int listPos) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + + Lock(); + pAddonWindow->SetCurrentListPosition(listPos); + Unlock(); + + return; +} + +int CAddonCallbacksGUI::Window_GetCurrentListPosition(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return -1; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + + Lock(); + int listPos = pAddonWindow->GetCurrentListPosition(); + Unlock(); + + return listPos; +} + +void CAddonCallbacksGUI::Window_AddContextMenuButton(void *addonData, GUIHANDLE handle,int controlId,unsigned int contextButtonId,const char* label) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + + Lock(); + pAddonWindow->AddContextMenuButton(controlId,contextButtonId,label); + Unlock(); +} + +GUIHANDLE CAddonCallbacksGUI::Window_GetControl_Spin(void *addonData, GUIHANDLE handle, int controlId) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIControl* pGUIControl = (CGUIControl*)pAddonWindow->GetControl(controlId); + if (pGUIControl && pGUIControl->GetControlType() != CGUIControl::GUICONTROL_SPINEX) + return NULL; + + return pGUIControl; +} + +GUIHANDLE CAddonCallbacksGUI::Window_GetControl_ListContainer(void *addonData, GUIHANDLE handle, int controlId,GUIHANDLE *listItems) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIControl* pGUIControl = (CGUIControl*)pAddonWindow->GetControl(controlId); + if (pGUIControl && pGUIControl->GetControlType() != CGUIControl::GUICONTAINER_LIST) + return NULL; + + *listItems = (GUIHANDLE) new CFileItemList(); + return pGUIControl; +} + +void CAddonCallbacksGUI::Window_ReleaseControl_ListContainer(GUIHANDLE listItems) +{ + CFileItemList* pListItems = (CFileItemList*) listItems; + if(pListItems) + delete pListItems; +} + +GUIHANDLE CAddonCallbacksGUI::Window_GetControl_Button(void *addonData, GUIHANDLE handle, int controlId) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIControl* pGUIControl = (CGUIControl*)pAddonWindow->GetControl(controlId); + if (pGUIControl && pGUIControl->GetControlType() != CGUIControl::GUICONTROL_BUTTON) + return NULL; + + return pGUIControl; +} + +GUIHANDLE CAddonCallbacksGUI::Window_GetControl_RadioButton(void *addonData, GUIHANDLE handle, int controlId) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIControl* pGUIControl = (CGUIControl*)pAddonWindow->GetControl(controlId); + if (pGUIControl && pGUIControl->GetControlType() != CGUIControl::GUICONTROL_RADIO) + return NULL; + + return pGUIControl; +} + +GUIHANDLE CAddonCallbacksGUI::Window_GetControl_Edit(void *addonData, GUIHANDLE handle, int controlId) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIControl* pGUIControl = (CGUIControl*)pAddonWindow->GetControl(controlId); + if (pGUIControl && pGUIControl->GetControlType() != CGUIControl::GUICONTROL_EDIT) + return NULL; + + return pGUIControl; +} + +GUIHANDLE CAddonCallbacksGUI::Window_GetControl_Progress(void *addonData, GUIHANDLE handle, int controlId) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + CGUIControl* pGUIControl = (CGUIControl*)pAddonWindow->GetControl(controlId); + if (pGUIControl && pGUIControl->GetControlType() != CGUIControl::GUICONTROL_PROGRESS) + return NULL; + + return pGUIControl; +} + +void CAddonCallbacksGUI::Window_SetControlLabel(void *addonData, GUIHANDLE handle, int controlId, const char *label) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIAddonWindow *pAddonWindow = (CGUIAddonWindow*)handle; + + CGUIMessage msg(GUI_MSG_LABEL_SET, pAddonWindow->m_iWindowId, controlId); + msg.SetLabel(label); + pAddonWindow->OnMessage(msg); +} + +void CAddonCallbacksGUI::Control_Spin_SetVisible(void *addonData, GUIHANDLE spinhandle, bool yesNo) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !spinhandle) + return; + + CGUISpinControlEx *pSpin = (CGUISpinControlEx*)spinhandle; + pSpin->SetVisible(yesNo); +} + +void CAddonCallbacksGUI::Control_Spin_SetText(void *addonData, GUIHANDLE spinhandle, const char *label) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !spinhandle) + return; + + CGUISpinControlEx *pSpin = (CGUISpinControlEx*)spinhandle; + pSpin->SetText(label); +} + +void CAddonCallbacksGUI::Control_Spin_Clear(void *addonData, GUIHANDLE spinhandle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !spinhandle) + return; + + CGUISpinControlEx *pSpin = (CGUISpinControlEx*)spinhandle; + pSpin->Clear(); +} + +void CAddonCallbacksGUI::Control_Spin_AddLabel(void *addonData, GUIHANDLE spinhandle, const char *label, int iValue) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !spinhandle) + return; + + CGUISpinControlEx *pSpin = (CGUISpinControlEx*)spinhandle; + pSpin->AddLabel(label, iValue); +} + +int CAddonCallbacksGUI::Control_Spin_GetValue(void *addonData, GUIHANDLE spinhandle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !spinhandle) + return -1; + + CGUISpinControlEx *pSpin = (CGUISpinControlEx*)spinhandle; + return pSpin->GetValue(); +} + +void CAddonCallbacksGUI::Control_Spin_SetValue(void *addonData, GUIHANDLE spinhandle, int iValue) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !spinhandle) + return; + + CGUISpinControlEx *pSpin = (CGUISpinControlEx*)spinhandle; + pSpin->SetValue(iValue); +} + + +void CAddonCallbacksGUI::Control_ListContainer_SetVisible(void *addonData, GUIHANDLE handle, bool yesNo) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIListContainer *pListContainer = (CGUIListContainer*) handle; + pListContainer->SetVisible(yesNo); +} + + +void CAddonCallbacksGUI::Control_ListContainer_AddItems(void *addonData, GUIHANDLE handle,GUIHANDLE listItems,GUIHANDLE items[],int size) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle || !items) + return; + + CFileItem **pItems = (CFileItem**) items; + CGUIListContainer *pListContainer = (CGUIListContainer*) handle; + CFileItemList *itemlist = (CFileItemList*) listItems; + for(int i = 0;i < size; i++) + itemlist->Add(CFileItemPtr(pItems[i])); + CGUIMessage msg(GUI_MSG_LABEL_BIND, pListContainer->GetParentID(), pListContainer->GetID(), 0, 0, itemlist); + msg.SetPointer(itemlist); + g_windowManager.SendThreadMessage(msg, pListContainer->GetParentID()); +} + +GUIHANDLE CAddonCallbacksGUI::Control_ListContainer_GetItem(void *addonData, GUIHANDLE handle,GUIHANDLE listItems,int index) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + CFileItem* pFileItem = NULL; + + CGUIListContainer *pListContainer = (CGUIListContainer*)handle; + + if(pListContainer->GetListItem(index,INFOFLAG_LISTITEM_POSITION)->IsFileItem()) + pFileItem = (CFileItem*)pListContainer->GetListItem(index,INFOFLAG_LISTITEM_POSITION).get(); + return pFileItem; +} + +int CAddonCallbacksGUI::Control_ListContainer_GetSelected(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return -1; + + CGUIListContainer *pListContainer = (CGUIListContainer*)handle; + + return pListContainer->GetSelectedItem(); +} + +void CAddonCallbacksGUI::Control_ListContainer_Reset(void *addonData, GUIHANDLE handle,GUIHANDLE listItems) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + CFileItemList *itemlist = (CFileItemList*) listItems; + CGUIListContainer *pListContainer = (CGUIListContainer*)handle; + CGUIMessage msg(GUI_MSG_LABEL_RESET, pListContainer->GetParentID(), pListContainer->GetID()); + g_windowManager.SendThreadMessage(msg, pListContainer->GetParentID()); + itemlist->Clear(); +} + +void CAddonCallbacksGUI::Control_RadioButton_SetVisible(void *addonData, GUIHANDLE handle, bool yesNo) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIRadioButtonControl *pRadioButton = (CGUIRadioButtonControl*)handle; + pRadioButton->SetVisible(yesNo); +} + +void CAddonCallbacksGUI::Control_RadioButton_SetText(void *addonData, GUIHANDLE handle, const char *label) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIRadioButtonControl *pRadioButton = (CGUIRadioButtonControl*)handle; + pRadioButton->SetLabel(label); +} + +void CAddonCallbacksGUI::Control_RadioButton_SetSelected(void *addonData, GUIHANDLE handle, bool yesNo) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIRadioButtonControl *pRadioButton = (CGUIRadioButtonControl*)handle; + pRadioButton->SetSelected(yesNo); +} + +bool CAddonCallbacksGUI::Control_RadioButton_IsSelected(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return false; + + CGUIRadioButtonControl *pRadioButton = (CGUIRadioButtonControl*)handle; + return pRadioButton->IsSelected(); +} + +void CAddonCallbacksGUI::Control_Progress_SetPercentage(void *addonData, GUIHANDLE handle, float fPercent) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIProgressControl *pControl = (CGUIProgressControl*)handle; + pControl->SetPercentage(fPercent); +} + +float CAddonCallbacksGUI::Control_Progress_GetPercentage(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return 0.0; + + CGUIProgressControl *pControl = (CGUIProgressControl*)handle; + return pControl->GetPercentage(); +} + +void CAddonCallbacksGUI::Control_Progress_SetInfo(void *addonData, GUIHANDLE handle, int iInfo) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + CGUIProgressControl *pControl = (CGUIProgressControl*)handle; + pControl->SetInfo(iInfo); +} + +int CAddonCallbacksGUI::Control_Progress_GetInfo(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return -1; + + CGUIProgressControl *pControl = (CGUIProgressControl*)handle; + return pControl->GetInfo(); +} + +const char* CAddonCallbacksGUI::Control_Progress_GetDescription(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + + CGUIProgressControl *pControl = (CGUIProgressControl*)handle; + CStdString string = pControl->GetDescription(); + + char *buffer = (char*) malloc (string.length()+1); + strcpy(buffer, string.c_str()); + return buffer; +} + +GUIHANDLE CAddonCallbacksGUI::ListItem_Create(void *addonData, const char *label, const char *label2, const char *iconImage, const char *thumbnailImage, const char *path) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper) + return NULL; + + // create CFileItem + CFileItem *pItem = new CFileItem(); + if (!pItem) + return NULL; + + if (label) + pItem->SetLabel(label); + if (label2) + pItem->SetLabel2(label2); + if (iconImage) + pItem->SetIconImage(iconImage); + if (thumbnailImage) + pItem->SetThumbnailImage(thumbnailImage); + if (path) + pItem->SetPath(path); + + return pItem; +} + +void CAddonCallbacksGUI::ListItem_Destroy(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + CFileItem *pItem = (CFileItem*) handle; + delete pItem; +} + +const char* CAddonCallbacksGUI::ListItem_GetLabel(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + + CStdString string = ((CFileItem*)handle)->GetLabel(); + char *buffer = (char*) malloc (string.length()+1); + strcpy(buffer, string.c_str()); + return buffer; +} + +void CAddonCallbacksGUI::ListItem_SetLabel(void *addonData, GUIHANDLE handle, const char *label) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + ((CFileItem*)handle)->SetLabel(label); +} + +const char* CAddonCallbacksGUI::ListItem_GetLabel2(void *addonData, GUIHANDLE handle) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + + CStdString string = ((CFileItem*)handle)->GetLabel2(); + + char *buffer = (char*) malloc (string.length()+1); + strcpy(buffer, string.c_str()); + return buffer; +} + +void CAddonCallbacksGUI::ListItem_SetLabel2(void *addonData, GUIHANDLE handle, const char *label) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + ((CFileItem*)handle)->SetLabel2(label); +} + +void CAddonCallbacksGUI::ListItem_SetIconImage(void *addonData, GUIHANDLE handle, const char *image) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + ((CFileItem*)handle)->SetIconImage(image); +} + +void CAddonCallbacksGUI::ListItem_SetThumbnailImage(void *addonData, GUIHANDLE handle, const char *image) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + ((CFileItem*)handle)->SetThumbnailImage(image); +} + +void CAddonCallbacksGUI::ListItem_SetInfo(void *addonData, GUIHANDLE handle, const char *info) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + +} + +void CAddonCallbacksGUI::ListItem_SetProperty(void *addonData, GUIHANDLE handle, const char *key, const char *value) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + ((CFileItem*)handle)->SetProperty(key, value); +} + +const char* CAddonCallbacksGUI::ListItem_GetProperty(void *addonData, GUIHANDLE handle, const char *key) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return NULL; + + string string = ((CFileItem*)handle)->GetProperty(key).asString(); + char *buffer = (char*) malloc (string.length()+1); + strcpy(buffer, string.c_str()); + return buffer; +} + +void CAddonCallbacksGUI::ListItem_SetPath(void *addonData, GUIHANDLE handle, const char *path) +{ + CAddonCallbacks* helper = (CAddonCallbacks*) addonData; + if (!helper || !handle) + return; + + ((CFileItem*)handle)->SetPath(path); +} + + + + + + + +CGUIAddonWindow::CGUIAddonWindow(int id, CStdString strXML, CAddon* addon) + : CGUIMediaWindow(id, strXML) + , m_iWindowId(id) + , m_iOldWindowId(0) + , m_bModal(false) + , m_bIsDialog(false) + , m_actionEvent(true) + , m_addon(addon) +{ + m_loadOnDemand = false; + CBOnInit = NULL; + CBOnFocus = NULL; + CBOnClick = NULL; + CBOnAction = NULL; + CBOnContextMenu = NULL; +} + +CGUIAddonWindow::~CGUIAddonWindow(void) +{ +} + +bool CGUIAddonWindow::OnAction(const CAction &action) +{ + // do the base class window first, and the call to python after this + bool ret = CGUIWindow::OnAction(action); // we don't currently want the mediawindow actions here + if (CBOnAction) + { + CBOnAction(m_clientHandle, action.GetID()); + } + return ret; +} + +bool CGUIAddonWindow::OnMessage(CGUIMessage& message) +{ + // TODO: We shouldn't be dropping down to CGUIWindow in any of this ideally. + // We have to make up our minds about what python should be doing and + // what this side of things should be doing + switch (message.GetMessage()) + { + case GUI_MSG_WINDOW_DEINIT: + { + return CGUIMediaWindow::OnMessage(message); + } + break; + + case GUI_MSG_WINDOW_INIT: + { + CGUIMediaWindow::OnMessage(message); + if (CBOnInit) + CBOnInit(m_clientHandle); + + return true; + } + break; + + case GUI_MSG_SETFOCUS: + { + if (m_viewControl.HasControl(message.GetControlId()) && m_viewControl.GetCurrentControl() != (int)message.GetControlId()) + { + m_viewControl.SetFocused(); + return true; + } + // check if our focused control is one of our category buttons + int iControl = message.GetControlId(); + if (CBOnFocus) + { + CBOnFocus(m_clientHandle, iControl); + } + } + break; + case GUI_MSG_CLICKED: + { + int iControl=message.GetSenderId(); + // Handle Sort/View internally. Scripters shouldn't use ID 2, 3 or 4. + if (iControl == CONTROL_BTNSORTASC) // sort asc + { + CLog::Log(LOGINFO, "WindowXML: Internal asc/dsc button not implemented"); + /*if (m_guiState.get()) + m_guiState->SetNextSortOrder(); + UpdateFileList();*/ + return true; + } + else if (iControl == CONTROL_BTNSORTBY) // sort by + { + CLog::Log(LOGINFO, "WindowXML: Internal sort button not implemented"); + /*if (m_guiState.get()) + m_guiState->SetNextSortMethod(); + UpdateFileList();*/ + return true; + } + + if (CBOnClick && iControl && iControl != (int)this->GetID()) + { + CGUIControl* controlClicked = (CGUIControl*)this->GetControl(iControl); + + // The old python way used to check list AND SELECITEM method or if its a button, checkmark. + // Its done this way for now to allow other controls without a python version like togglebutton to still raise a onAction event + if (controlClicked) // Will get problems if we the id is not on the window and we try to do GetControlType on it. So check to make sure it exists + { + if ((controlClicked->IsContainer() && (message.GetParam1() == ACTION_SELECT_ITEM || + message.GetParam1() == ACTION_MOUSE_LEFT_CLICK)) || + !controlClicked->IsContainer()) + { + CBOnClick(m_clientHandle, iControl); + } + else if (controlClicked->IsContainer() && message.GetParam1() == ACTION_MOUSE_RIGHT_CLICK && m_mContextButtons.count(iControl)) + { + iCurrentContextMenuControl = iControl; + int iItemSelected = SelectContainerItem( controlClicked, message.GetParam2(),true); + if(GetSelectedContainerItem(controlClicked, message.GetParam2())->HasProperty("ContextMenuOverride")) + iCurrentContextMenuControl = atoi(GetSelectedContainerItem(controlClicked, message.GetParam2())->GetProperty("ContextMenuOverride").asString("-1").c_str()); + bool retval = CGUIMediaWindow::OnPopupMenu(iItemSelected); + SelectContainerItem( controlClicked, message.GetParam2(),false); + return retval; +// PyXBMCAction* inf = new PyXBMCAction; +// inf->pObject = Action_FromAction(CAction(ACTION_CONTEXT_MENU)); +// inf->pCallbackWindow = pCallbackWindow; +// +// // aquire lock? +// PyXBMC_AddPendingCall(Py_XBMC_Event_OnAction, inf); +// PulseActionEvent(); + } + return true; + } + } + } + break; + } + + return CGUIMediaWindow::OnMessage(message); +} + +int CGUIAddonWindow::SelectContainerItem(CGUIControl* control, int offset,bool select) +{ + int iItemSelected = -1; + switch ( control->GetControlType() ) + { + case CGUIControl::GUICONTAINER_LIST: + iItemSelected = ((CGUIListContainer*)control)->GetSelectedItem(); + ((CGUIListContainer*)control)->GetListItem(offset)->Select(select); + break; + case CGUIControl::GUICONTAINER_EPGGRID: + iItemSelected = ((EPG::CGUIEPGGridContainer*)control)->GetSelectedItem(); + ((EPG::CGUIEPGGridContainer*)control)->GetListItem(offset)->Select(select); + break; + case CGUIControl::GUICONTAINER_FIXEDLIST: + iItemSelected = ((CGUIFixedListContainer*)control)->GetSelectedItem(); + ((CGUIFixedListContainer*)control)->GetListItem(offset)->Select(select); + break; + case CGUIControl::GUICONTAINER_PANEL: + iItemSelected = ((CGUIPanelContainer*)control)->GetSelectedItem(); + ((CGUIPanelContainer*)control)->GetListItem(offset)->Select(select); + break; + case CGUIControl::GUICONTAINER_WRAPLIST: + iItemSelected = ((CGUIWrappingListContainer*)control)->GetSelectedItem(); + ((CGUIWrappingListContainer*)control)->GetListItem(offset)->Select(select); + break; + } + return iItemSelected; +} + +CGUIListItemPtr CGUIAddonWindow::GetSelectedContainerItem(CGUIControl* control,int offset) +{ + switch ( control->GetControlType() ) + { + case CGUIControl::GUICONTAINER_LIST: + return ((CGUIListContainer*)control)->GetListItem(offset); + break; + case CGUIControl::GUICONTAINER_EPGGRID: + return ((EPG::CGUIEPGGridContainer*)control)->GetListItem(offset); + break; + case CGUIControl::GUICONTAINER_FIXEDLIST: + return ((CGUIFixedListContainer*)control)->GetListItem(offset); + break; + case CGUIControl::GUICONTAINER_PANEL: + return ((CGUIPanelContainer*)control)->GetListItem(offset); + break; + case CGUIControl::GUICONTAINER_WRAPLIST: + return ((CGUIWrappingListContainer*)control)->GetListItem(offset); + break; + } + return CGUIListItemPtr(); +} + + +void CGUIAddonWindow::AllocResources(bool forceLoad /*= FALSE */) +{ + CStdString tmpDir; + URIUtils::GetDirectory(GetProperty("xmlfile").asString(), tmpDir); + CStdString fallbackMediaPath; + URIUtils::GetParentPath(tmpDir, fallbackMediaPath); + URIUtils::RemoveSlashAtEnd(fallbackMediaPath); + m_mediaDir = fallbackMediaPath; + + //CLog::Log(LOGDEBUG, "CGUIPythonWindowXML::AllocResources called: %s", fallbackMediaPath.c_str()); + g_TextureManager.AddTexturePath(m_mediaDir); + CGUIMediaWindow::AllocResources(forceLoad); + g_TextureManager.RemoveTexturePath(m_mediaDir); +} + +void CGUIAddonWindow::FreeResources(bool forceUnLoad /*= FALSE */) +{ + // Unload temporary language strings + ClearAddonStrings(); + + CGUIMediaWindow::FreeResources(forceUnLoad); +} + +void CGUIAddonWindow::Render() +{ + g_TextureManager.AddTexturePath(m_mediaDir); + CGUIMediaWindow::Render(); + g_TextureManager.RemoveTexturePath(m_mediaDir); +} + +void CGUIAddonWindow::Update() +{ +} + +void CGUIAddonWindow::AddItem(CFileItemPtr fileItem, int itemPosition) +{ + if (itemPosition == -1 || itemPosition > m_vecItems->Size()) + { + m_vecItems->Add(fileItem); + } + else if (itemPosition < -1 && !(itemPosition-1 < m_vecItems->Size())) + { + m_vecItems->AddFront(fileItem,0); + } + else + { + m_vecItems->AddFront(fileItem,itemPosition); + } + m_viewControl.SetItems(*m_vecItems); + UpdateButtons(); +} + +void CGUIAddonWindow::RemoveItem(int itemPosition) +{ + m_vecItems->Remove(itemPosition); + m_viewControl.SetItems(*m_vecItems); + UpdateButtons(); +} + +int CGUIAddonWindow::GetCurrentListPosition() +{ + return m_viewControl.GetSelectedItem(); +} + +void CGUIAddonWindow::SetCurrentListPosition(int item) +{ + m_viewControl.SetSelectedItem(item); +} + +int CGUIAddonWindow::GetListSize() +{ + return m_vecItems->Size(); +} + +CFileItemPtr CGUIAddonWindow::GetListItem(int position) +{ + if (position < 0 || position >= m_vecItems->Size()) return CFileItemPtr(); + return m_vecItems->Get(position); +} + +void CGUIAddonWindow::ClearList() +{ + ClearFileItems(); + + m_viewControl.SetItems(*m_vecItems); + UpdateButtons(); +} + +void CGUIAddonWindow::AddContextMenuButton(int controlId,unsigned int contextButtonId,const char* label) +{ + if( !m_mContextButtons.count(controlId)) + m_mContextButtons[controlId] = CContextButtons(); + m_mContextButtons.at(controlId).Add(contextButtonId,label); +} + +void CGUIAddonWindow::GetContextButtons(int itemNumber, CContextButtons &buttons) +{ + if(m_mContextButtons.count(iCurrentContextMenuControl)) + buttons = m_mContextButtons.at(iCurrentContextMenuControl); + // maybe on day we can make an easy way to do this context menu + // with out this method overriding the MediaWindow version, it will display 'Add to Favorites' +} + +bool CGUIAddonWindow::OnContextButton(int itemNumber, CONTEXT_BUTTON button) +{ + if(CBOnContextMenu) + return CBOnContextMenu(m_clientHandle,iCurrentContextMenuControl,itemNumber,button); + return false; +} + +void CGUIAddonWindow::WaitForActionEvent(unsigned int timeout) +{ + m_actionEvent.WaitMSec(timeout); + m_actionEvent.Reset(); +} + +void CGUIAddonWindow::PulseActionEvent() +{ + m_actionEvent.Set(); +} + +void CGUIAddonWindow::ClearAddonStrings() +{ + // Unload temporary language strings + g_localizeStrings.ClearBlock(m_addon->Path()); +} + +bool CGUIAddonWindow::OnClick(int iItem) +{ + // Hook Over calling CGUIMediaWindow::OnClick(iItem) results in it trying to PLAY the file item + // which if its not media is BAD and 99 out of 100 times undesireable. + return false; +} + +// SetupShares(); +/* + CGUIMediaWindow::OnWindowLoaded() calls SetupShares() so override it +and just call UpdateButtons(); +*/ +void CGUIAddonWindow::SetupShares() +{ + UpdateButtons(); +} + + +CGUIAddonWindowDialog::CGUIAddonWindowDialog(int id, CStdString strXML, CAddon* addon) +: CGUIAddonWindow(id,strXML,addon) +{ + m_bRunning = false; + m_loadOnDemand = false; + m_bIsDialog = true; +} + +CGUIAddonWindowDialog::~CGUIAddonWindowDialog(void) +{ +} + +bool CGUIAddonWindowDialog::OnMessage(CGUIMessage &message) +{ + if (message.GetMessage() == GUI_MSG_WINDOW_DEINIT) + { + CGUIWindow *pWindow = g_windowManager.GetWindow(g_windowManager.GetActiveWindow()); + if (pWindow) + g_windowManager.ShowOverlay(pWindow->GetOverlayState()); + return CGUIWindow::OnMessage(message); + } + return CGUIAddonWindow::OnMessage(message); +} + +void CGUIAddonWindowDialog::Show(bool show /* = true */) +{ + unsigned int iCount = g_graphicsContext.exit(); + ThreadMessage tMsg = {TMSG_GUI_ADDON_DIALOG, 1, show ? 1 : 0}; + tMsg.lpVoid = this; + g_application.getApplicationMessenger().SendMessage(tMsg, true); + g_graphicsContext.restore(iCount); +} + +void CGUIAddonWindowDialog::Show_Internal(bool show /* = true */) +{ + if (show) + { + m_bModal = true; + m_bRunning = true; + g_windowManager.RouteToWindow(this); + + // active this window... + CGUIMessage msg(GUI_MSG_WINDOW_INIT, 0, 0, WINDOW_INVALID, m_iWindowId); + OnMessage(msg); + + while (m_bRunning && !g_application.m_bStop) + { + g_windowManager.Process(CTimeUtils::GetFrameTime()); + g_windowManager.ProcessRenderLoop(); + } + } + else // hide + { + m_bRunning = false; + + CGUIMessage msg(GUI_MSG_WINDOW_DEINIT,0,0); + OnMessage(msg); + + g_windowManager.RemoveDialog(GetID()); + } +} + +}; /* namespace ADDON */ diff --git a/xbmc/addons/AddonCallbacksGUI.h b/xbmc/addons/AddonCallbacksGUI.h new file mode 100644 index 0000000..f89cad5 --- /dev/null +++ b/xbmc/addons/AddonCallbacksGUI.h @@ -0,0 +1,225 @@ +#pragma once +/* + * Copyright (C) 2005-2010 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 "AddonCallbacks.h" +#include "windows/GUIMediaWindow.h" +#include "settings/GUIDialogSettings.h" +#include "threads/Event.h" + +class CGUISpinControlEx; +class CGUIButtonControl; +class CGUIRadioButtonControl; +class CGUISettingsSliderControl; +class CGUIEditControl; + +namespace ADDON +{ + +class CAddonCallbacksGUI +{ +public: + CAddonCallbacksGUI(CAddon* addon); + ~CAddonCallbacksGUI(); + + /**! \name General Functions */ + CB_GUILib *GetCallbacks() { return m_callbacks; } + + static void Lock(); + static void Unlock(); + static int GetScreenHeight(); + static int GetScreenWidth(); + static int GetVideoResolution(); + + static int Dialog_ShowYesNo(const char* heading, const char* line0, const char* line1, const char* line2, int* bCanceled, const char* noLabel, const char* yesLabel); + + static GUIHANDLE Window_New(void *addonData, const char *xmlFilename, const char *defaultSkin, bool forceFallback, bool asDialog); + static void Window_Delete(void *addonData, GUIHANDLE handle); + static void Window_SetCallbacks(void *addonData, GUIHANDLE handle, GUIHANDLE clienthandle, bool (*initCB)(GUIHANDLE), bool (*clickCB)(GUIHANDLE, int), bool (*focusCB)(GUIHANDLE, int), bool (*onActionCB)(GUIHANDLE handle, int),bool (*onContextMenuCB)(GUIHANDLE ,int ,int , unsigned int)); + static bool Window_Show(void *addonData, GUIHANDLE handle); + static bool Window_Close(void *addonData, GUIHANDLE handle); + static bool Window_DoModal(void *addonData, GUIHANDLE handle); + static bool Window_SetFocusId(void *addonData, GUIHANDLE handle, int iControlId); + static int Window_GetFocusId(void *addonData, GUIHANDLE handle); + static bool Window_SetCoordinateResolution(void *addonData, GUIHANDLE handle, int res); + static void Window_SetProperty(void *addonData, GUIHANDLE handle, const char *key, const char *value); + static void Window_SetPropertyInt(void *addonData, GUIHANDLE handle, const char *key, int value); + static void Window_SetPropertyBool(void *addonData, GUIHANDLE handle, const char *key, bool value); + static void Window_SetPropertyDouble(void *addonData, GUIHANDLE handle, const char *key, double value); + static const char * Window_GetProperty(void *addonData, GUIHANDLE handle, const char *key); + static int Window_GetPropertyInt(void *addonData, GUIHANDLE handle, const char *key); + static bool Window_GetPropertyBool(void *addonData, GUIHANDLE handle, const char *key); + static double Window_GetPropertyDouble(void *addonData, GUIHANDLE handle, const char *key); + static void Window_ClearProperties(void *addonData, GUIHANDLE handle); + static int Window_GetListSize(void *addonData, GUIHANDLE handle); + static void Window_ClearList(void *addonData, GUIHANDLE handle); + static GUIHANDLE Window_AddItem(void *addonData, GUIHANDLE handle, GUIHANDLE item, int itemPosition); + static GUIHANDLE Window_AddStringItem(void *addonData, GUIHANDLE handle, const char *itemName, int itemPosition); + static void Window_RemoveItem(void *addonData, GUIHANDLE handle, int itemPosition); + static GUIHANDLE Window_GetListItem(void *addonData, GUIHANDLE handle, int listPos); + static void Window_SetCurrentListPosition(void *addonData, GUIHANDLE handle, int listPos); + static int Window_GetCurrentListPosition(void *addonData, GUIHANDLE handle); + static void Window_AddContextMenuButton(void *addonData, GUIHANDLE handle,int controlId,unsigned int contextButtonId,const char* label); + static GUIHANDLE Window_GetControl_Spin(void *addonData, GUIHANDLE handle, int controlId); + static GUIHANDLE Window_GetControl_ListContainer(void *addonData, GUIHANDLE handle, int controlId,GUIHANDLE *listItems); + static void Window_ReleaseControl_ListContainer(GUIHANDLE listItems); + static GUIHANDLE Window_GetControl_Button(void *addonData, GUIHANDLE handle, int controlId); + static GUIHANDLE Window_GetControl_RadioButton(void *addonData, GUIHANDLE handle, int controlId); + static GUIHANDLE Window_GetControl_Edit(void *addonData, GUIHANDLE handle, int controlId); + static GUIHANDLE Window_GetControl_Progress(void *addonData, GUIHANDLE handle, int controlId); + static void Window_SetControlLabel(void *addonData, GUIHANDLE handle, int controlId, const char *label); + static void Control_Spin_SetVisible(void *addonData, GUIHANDLE spinhandle, bool yesNo); + static void Control_Spin_SetText(void *addonData, GUIHANDLE spinhandle, const char *label); + static void Control_Spin_Clear(void *addonData, GUIHANDLE spinhandle); + static void Control_Spin_AddLabel(void *addonData, GUIHANDLE spinhandle, const char *label, int iValue); + static int Control_Spin_GetValue(void *addonData, GUIHANDLE spinhandle); + static void Control_Spin_SetValue(void *addonData, GUIHANDLE spinhandle, int iValue); + static void Control_ListContainer_SetVisible(void *addonData, GUIHANDLE handle, bool yesNo); + static void Control_ListContainer_AddItems(void *addonData, GUIHANDLE handle,GUIHANDLE listItems,GUIHANDLE items[],int size); + static GUIHANDLE Control_ListContainer_GetItem(void *addonData, GUIHANDLE handle,GUIHANDLE listItems,int index); + static int Control_ListContainer_GetSelected(void *addonData, GUIHANDLE handle); + static void Control_ListContainer_Reset(void *addonData, GUIHANDLE handle,GUIHANDLE listItems); + static void Control_RadioButton_SetVisible(void *addonData, GUIHANDLE handle, bool yesNo); + static void Control_RadioButton_SetText(void *addonData, GUIHANDLE handle, const char *label); + static void Control_RadioButton_SetSelected(void *addonData, GUIHANDLE handle, bool yesNo); + static bool Control_RadioButton_IsSelected(void *addonData, GUIHANDLE handle); + static void Control_Progress_SetPercentage(void *addonData, GUIHANDLE handle, float fPercent); + static float Control_Progress_GetPercentage(void *addonData, GUIHANDLE handle); + static void Control_Progress_SetInfo(void *addonData, GUIHANDLE handle, int iInfo); + static int Control_Progress_GetInfo(void *addonData, GUIHANDLE handle); + static const char * Control_Progress_GetDescription(void *addonData, GUIHANDLE handle); + static GUIHANDLE ListItem_Create(void *addonData, const char *label, const char *label2, const char *iconImage, const char *thumbnailImage, const char *path); + static void ListItem_Destroy(void *addonData, GUIHANDLE handle); + static const char * ListItem_GetLabel(void *addonData, GUIHANDLE handle); + static void ListItem_SetLabel(void *addonData, GUIHANDLE handle, const char *label); + static const char * ListItem_GetLabel2(void *addonData, GUIHANDLE handle); + static void ListItem_SetLabel2(void *addonData, GUIHANDLE handle, const char *label); + static void ListItem_SetIconImage(void *addonData, GUIHANDLE handle, const char *image); + static void ListItem_SetThumbnailImage(void *addonData, GUIHANDLE handle, const char *image); + static void ListItem_SetInfo(void *addonData, GUIHANDLE handle, const char *info); + static void ListItem_SetProperty(void *addonData, GUIHANDLE handle, const char *key, const char *value); + static const char * ListItem_GetProperty(void *addonData, GUIHANDLE handle, const char *key); + static void ListItem_SetPath(void *addonData, GUIHANDLE handle, const char *path); + +private: + CB_GUILib *m_callbacks; + CAddon *m_addon; +}; + +class CGUIAddonWindow : public CGUIMediaWindow +{ +friend class CAddonCallbacksGUI; + +public: + CGUIAddonWindow(int id, CStdString strXML, CAddon* addon); + virtual ~CGUIAddonWindow(void); + + virtual bool OnMessage(CGUIMessage& message); + virtual bool OnAction(const CAction &action); + virtual void AllocResources(bool forceLoad = false); + virtual void FreeResources(bool forceUnLoad = false); + virtual void Render(); + void WaitForActionEvent(unsigned int timeout); + void PulseActionEvent(); + void AddItem(CFileItemPtr fileItem, int itemPosition); + void RemoveItem(int itemPosition); + void ClearList(); + CFileItemPtr GetListItem(int position); + int GetListSize(); + int GetCurrentListPosition(); + void SetCurrentListPosition(int item); + virtual bool OnClick(int iItem); + void AddContextMenuButton(int controlId,unsigned int contextButtonId,const char* label); + +protected: + virtual void Update(); + virtual void GetContextButtons(int itemNumber, CContextButtons &buttons); + virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button); + void ClearAddonStrings(); + void SetupShares(); + + bool (*CBOnInit)(GUIHANDLE cbhdl); + bool (*CBOnFocus)(GUIHANDLE cbhdl, int controlId); + bool (*CBOnClick)(GUIHANDLE cbhdl, int controlId); + bool (*CBOnAction)(GUIHANDLE cbhdl, int); + bool (*CBOnContextMenu)(GUIHANDLE chdl,int controlId,int itemNumber, unsigned int contextButtonId); + + GUIHANDLE m_clientHandle; + const int m_iWindowId; + int m_iOldWindowId; + bool m_bModal; + bool m_bIsDialog; + + std::map m_mContextButtons; + int iCurrentContextMenuControl; + +private: + CEvent m_actionEvent; + CAddon *m_addon; + CStdString m_mediaDir; + int SelectContainerItem(CGUIControl* control, int offset,bool select); + CGUIListItemPtr GetSelectedContainerItem(CGUIControl* control,int offset); +}; + +class CGUIAddonWindowDialog : public CGUIAddonWindow +{ +public: + CGUIAddonWindowDialog(int id, CStdString strXML, CAddon* addon); + virtual ~CGUIAddonWindowDialog(void); + + void Show(bool show = true); + virtual bool OnMessage(CGUIMessage &message); + virtual bool IsDialogRunning() const { return m_bRunning; } + virtual bool IsDialog() const { return true;}; + virtual bool IsModalDialog() const { return true; }; + virtual bool IsMediaWindow() const { return false; }; + + void Show_Internal(bool show = true); + +private: + bool m_bRunning; +}; + +// TODO: +//class CGUIAddonDialogSettings : public CGUIDialogSettings +//{ +//friend class CAddonCallbacksGUI; +// +//public: +// CGUIAddonDialogSettings(int id, const char *xmlFile); +// virtual ~CGUIDialogSettings(void){} +// virtual bool OnMessage(CGUIMessage &message);/*??*/ +// +// virtual void OnSliderChange(void *data, CGUISliderControl *slider);/*??*/ +//protected: +// virtual void OnOkay() {};/*callback*/ +// virtual void OnCancel() {};/*callback*/ +// virtual bool OnBack(int actionID);/*??*/ +// virtual void OnInitWindow();/*??*/ +// virtual void SetupPage();/*??*/ +// virtual void CreateSettings() {};/*callback*/ +// virtual void OnSettingChanged(SettingInfo &setting) {};/*callback*/ +// SettingInfo GetSetting(int n); +// }; +// +}; + /* namespace ADDON */ diff --git a/xbmc/addons/AddonCallbacksPVR.cpp b/xbmc/addons/AddonCallbacksPVR.cpp new file mode 100644 index 0000000..6f72add --- /dev/null +++ b/xbmc/addons/AddonCallbacksPVR.cpp @@ -0,0 +1,311 @@ +/* + * 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 "Application.h" +#include "AddonCallbacksPVR.h" +#include "settings/AdvancedSettings.h" +#include "utils/log.h" +#include "dialogs/GUIDialogKaiToast.h" + +#include "epg/Epg.h" +#include "pvr/PVRManager.h" +#include "pvr/channels/PVRChannelGroupsContainer.h" +#include "pvr/channels/PVRChannelGroupInternal.h" +#include "pvr/addons/PVRClient.h" +#include "pvr/recordings/PVRRecordings.h" +#include "pvr/timers/PVRTimers.h" +#include "pvr/timers/PVRTimerInfoTag.h" + +using namespace PVR; +using namespace EPG; + +namespace ADDON +{ + +CAddonCallbacksPVR::CAddonCallbacksPVR(CAddon* addon) +{ + m_addon = addon; + m_callbacks = new CB_PVRLib; + + /* write XBMC PVR specific add-on function addresses to callback table */ + m_callbacks->TransferEpgEntry = PVRTransferEpgEntry; + m_callbacks->TransferChannelEntry = PVRTransferChannelEntry; + m_callbacks->TransferTimerEntry = PVRTransferTimerEntry; + m_callbacks->TransferRecordingEntry = PVRTransferRecordingEntry; + m_callbacks->AddMenuHook = PVRAddMenuHook; + m_callbacks->Recording = PVRRecording; + m_callbacks->TriggerChannelUpdate = PVRTriggerChannelUpdate; + m_callbacks->TriggerChannelGroupsUpdate = PVRTriggerChannelGroupsUpdate; + m_callbacks->TriggerTimerUpdate = PVRTriggerTimerUpdate; + m_callbacks->TriggerRecordingUpdate = PVRTriggerRecordingUpdate; + m_callbacks->FreeDemuxPacket = PVRFreeDemuxPacket; + m_callbacks->AllocateDemuxPacket = PVRAllocateDemuxPacket; + m_callbacks->TransferChannelGroup = PVRTransferChannelGroup; + m_callbacks->TransferChannelGroupMember = PVRTransferChannelGroupMember; +} + +CAddonCallbacksPVR::~CAddonCallbacksPVR() +{ + /* delete the callback table */ + delete m_callbacks; +} + +void CAddonCallbacksPVR::PVRTransferChannelGroup(void *addonData, const PVR_HANDLE handle, const PVR_CHANNEL_GROUP *group) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL || handle == NULL || group == NULL || handle->dataAddress == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + if (strlen(group->strGroupName) == 0) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - empty group name", __FUNCTION__); + return; + } + + CPVRChannelGroups *xbmcGroups = (CPVRChannelGroups *) handle->dataAddress; + CPVRChannelGroup xbmcGroup(*group); + + /* transfer this entry to the groups container */ + xbmcGroups->UpdateFromClient(xbmcGroup); +} + +void CAddonCallbacksPVR::PVRTransferChannelGroupMember(void *addonData, const PVR_HANDLE handle, const PVR_CHANNEL_GROUP_MEMBER *member) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL || handle == NULL || member == NULL || handle->dataAddress == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + CPVRClient* client = (CPVRClient*) handle->callerAddress; + CPVRChannelGroup *group = (CPVRChannelGroup *) handle->dataAddress; + CPVRChannel *channel = (CPVRChannel *) g_PVRChannelGroups->GetByUniqueID(member->iChannelUniqueId, client->GetClientID()); + if (!group || !channel) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - cannot find group '%s' or channel '%d'", __FUNCTION__, member->strGroupName, member->iChannelUniqueId); + } + else if (group->IsRadio() == channel->IsRadio()) + { + /* transfer this entry to the group */ + group->AddToGroup(*channel, member->iChannelNumber, false); + } +} + +void CAddonCallbacksPVR::PVRTransferEpgEntry(void *addonData, const PVR_HANDLE handle, const EPG_TAG *epgentry) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL || handle == NULL || epgentry == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + CEpg *xbmcEpg = (CEpg*) handle->dataAddress; + + EPG_TAG *epgentry2 = (EPG_TAG*) epgentry; + bool bUpdateDatabase = handle->dataIdentifier == 1; + + /* transfer this entry to the epg */ + xbmcEpg->UpdateEntry(epgentry2, bUpdateDatabase); +} + +void CAddonCallbacksPVR::PVRTransferChannelEntry(void *addonData, const PVR_HANDLE handle, const PVR_CHANNEL *channel) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL || handle == NULL || channel == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + CPVRClient* client = (CPVRClient*) handle->callerAddress; + CPVRChannelGroupInternal *xbmcChannels = (CPVRChannelGroupInternal*) handle->dataAddress; + + CPVRChannel channelTag(*channel, client->GetClientID()); + + /* transfer this entry to the internal channels group */ + xbmcChannels->UpdateFromClient(channelTag); +} + +void CAddonCallbacksPVR::PVRTransferRecordingEntry(void *addonData, const PVR_HANDLE handle, const PVR_RECORDING *recording) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL || handle == NULL || recording == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + CPVRClient* client = (CPVRClient*) handle->callerAddress; + CPVRRecordings *xbmcRecordings = (CPVRRecordings*) handle->dataAddress; + + CPVRRecording tag(*recording, client->GetClientID()); + + /* transfer this entry to the recordings container */ + xbmcRecordings->UpdateFromClient(tag); +} + +void CAddonCallbacksPVR::PVRTransferTimerEntry(void *addonData, const PVR_HANDLE handle, const PVR_TIMER *timer) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL || handle == NULL || timer == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + CPVRTimers *xbmcTimers = (CPVRTimers*) handle->dataAddress; + CPVRClient* client = (CPVRClient*) handle->callerAddress; + CPVRChannel *channel = (CPVRChannel *) g_PVRChannelGroups->GetByUniqueID(timer->iClientChannelUid, client->GetClientID()); + + if (channel == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - cannot find channel %d on client %d", + __FUNCTION__, timer->iClientChannelUid, client->GetClientID()); + return; + } + + CPVRTimerInfoTag tag(*timer, channel, client->GetClientID()); + + /* transfer this entry to the timers container */ + xbmcTimers->UpdateFromClient(tag); +} + +void CAddonCallbacksPVR::PVRAddMenuHook(void *addonData, PVR_MENUHOOK *hook) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL || hook == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + CAddonCallbacksPVR* addonHelper = addon->GetHelperPVR(); + CPVRClient* client = (CPVRClient*) addonHelper->m_addon; + PVR_MENUHOOKS *hooks = client->GetMenuHooks(); + + PVR_MENUHOOK hookInt; + hookInt.iHookId = hook->iHookId; + hookInt.iLocalizedStringId = hook->iLocalizedStringId; + + /* add this new hook */ + hooks->push_back(hookInt); +} + +void CAddonCallbacksPVR::PVRRecording(void *addonData, const char *strName, const char *strFileName, bool bOnOff) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + CAddonCallbacksPVR* addonHelper = addon->GetHelperPVR(); + + CStdString strLine1; + if (bOnOff) + strLine1.Format(g_localizeStrings.Get(19197), addonHelper->m_addon->Name()); + else + strLine1.Format(g_localizeStrings.Get(19198), addonHelper->m_addon->Name()); + + CStdString strLine2; + if (strName) + strLine2 = strName; + else if (strFileName) + strLine2 = strFileName; + else + strLine2 = ""; + + /* display a notification for 5 seconds */ + CGUIDialogKaiToast::QueueNotification(CGUIDialogKaiToast::Info, strLine1, strLine2, 5000, false); + + CLog::Log(LOGDEBUG, "CAddonCallbacksPVR - %s - recording %s on client '%s'. name='%s' filename='%s'", + __FUNCTION__, bOnOff ? "started" : "finished", addonHelper->m_addon->Name().c_str(), strName, strFileName); +} + +void CAddonCallbacksPVR::PVRTriggerChannelUpdate(void *addonData) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + /* update the channels table in the next iteration of the pvrmanager's main loop */ + g_PVRManager.TriggerChannelsUpdate(); +} + +void CAddonCallbacksPVR::PVRTriggerTimerUpdate(void *addonData) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + /* update the timers table in the next iteration of the pvrmanager's main loop */ + g_PVRManager.TriggerTimersUpdate(); +} + +void CAddonCallbacksPVR::PVRTriggerRecordingUpdate(void *addonData) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + /* update the recordings table in the next iteration of the pvrmanager's main loop */ + g_PVRManager.TriggerRecordingsUpdate(); +} + +void CAddonCallbacksPVR::PVRTriggerChannelGroupsUpdate(void *addonData) +{ + CAddonCallbacks* addon = (CAddonCallbacks*) addonData; + if (addon == NULL) + { + CLog::Log(LOGERROR, "CAddonCallbacksPVR - %s - called with a null pointer", __FUNCTION__); + return; + } + + /* update all channel groups in the next iteration of the pvrmanager's main loop */ + g_PVRManager.TriggerChannelGroupsUpdate(); +} + +void CAddonCallbacksPVR::PVRFreeDemuxPacket(void *addonData, DemuxPacket* pPacket) +{ + CDVDDemuxUtils::FreeDemuxPacket(pPacket); +} + +DemuxPacket* CAddonCallbacksPVR::PVRAllocateDemuxPacket(void *addonData, int iDataSize) +{ + return CDVDDemuxUtils::AllocateDemuxPacket(iDataSize); +} + +}; /* namespace ADDON */ diff --git a/xbmc/addons/AddonCallbacksPVR.h b/xbmc/addons/AddonCallbacksPVR.h new file mode 100644 index 0000000..d9850bf --- /dev/null +++ b/xbmc/addons/AddonCallbacksPVR.h @@ -0,0 +1,153 @@ +#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 "AddonCallbacks.h" +#include "include/xbmc_pvr_types.h" + +namespace ADDON +{ + +/*! + * Callbacks for a PVR add-on to XBMC. + * + * Also translates the addon's C structures to XBMC's C++ structures. + */ +class CAddonCallbacksPVR +{ +public: + CAddonCallbacksPVR(CAddon* addon); + ~CAddonCallbacksPVR(void); + + /*! + * @return The callback table. + */ + CB_PVRLib *GetCallbacks() { return m_callbacks; } + + /*! + * @brief Transfer a channel group from the add-on to XBMC. The group will be created if it doesn't exist. + * @param addonData A pointer to the add-on. + * @param handle The handle that initiated this action. + * @param group The entry to transfer. + */ + static void PVRTransferChannelGroup(void *addonData, const PVR_HANDLE handle, const PVR_CHANNEL_GROUP *group); + + /*! + * @brief Transfer a channel group member from the add-on to XBMC. The channel will be added to the group if the group can be found. + * @param addonData A pointer to the add-on. + * @param handle The handle that initiated this action. + * @param member The entry to transfer. + */ + static void PVRTransferChannelGroupMember(void *addonData, const PVR_HANDLE handle, const PVR_CHANNEL_GROUP_MEMBER *member); + + /*! + * @brief Transfer an EPG entry from the add-on to XBMC. + * @param addonData A pointer to the add-on. + * @param handle The handle that initiated this action. + * @param epgentry The entry to transfer. + */ + static void PVRTransferEpgEntry(void *addonData, const PVR_HANDLE handle, const EPG_TAG *epgentry); + + /*! + * @brief Transfer a channel entry from the add-on to XBMC. + * @param addonData A pointer to the add-on. + * @param handle The handle that initiated this action. + * @param channel The entry to transfer. + */ + static void PVRTransferChannelEntry(void *addonData, const PVR_HANDLE handle, const PVR_CHANNEL *channel); + + /*! + * @brief Transfer a timer entry from the add-on to XBMC. + * @param addonData A pointer to the add-on. + * @param handle The handle that initiated this action. + * @param timer The entry to transfer. + */ + static void PVRTransferTimerEntry(void *addonData, const PVR_HANDLE handle, const PVR_TIMER *timer); + + /*! + * @brief Transfer a recording entry from the add-on to XBMC. + * @param addonData A pointer to the add-on. + * @param handle The handle that initiated this action. + * @param recording The entry to transfer. + */ + static void PVRTransferRecordingEntry(void *addonData, const PVR_HANDLE handle, const PVR_RECORDING *recording); + + /*! + * @brief Add a menu hook to this add-on table. + * @param addonData A pointer to the add-on. + * @param hook The hook to add. + */ + static void PVRAddMenuHook(void *addonData, PVR_MENUHOOK *hook); + + /*! + * @brief Notify XBMC that a recording has started or stoppped. + * @param addonData A pointer to the add-on. + * @param strName The name of the recording. + * @param strFileName The filename of the recording. + * @param bOnOff True if the recording started, false if it stopped. + */ + static void PVRRecording(void *addonData, const char *strName, const char *strFileName, bool bOnOff); + + /*! + * @brief Ask the PVRManager to refresh it's channels list. + * @param addonData A pointer to the add-on. + */ + static void PVRTriggerChannelUpdate(void *addonData); + + /*! + * @brief Ask the PVRManager to refresh it's timers list. + * @param addonData A pointer to the add-on. + */ + static void PVRTriggerTimerUpdate(void *addonData); + + /*! + * @brief Ask the PVRManager to refresh it's recordings list. + * @param addonData A pointer to the add-on. + */ + static void PVRTriggerRecordingUpdate(void *addonData); + + /*! + * @brief Ask the PVRManager to refresh it's channel groups list. + * @param addonData A pointer to the add-on. + */ + static void PVRTriggerChannelGroupsUpdate(void *addonData); + + /*! + * @brief Free an allocated demux packet. + * @param addonData A pointer to the add-on. + * @param pPacket The packet to free. + */ + static void PVRFreeDemuxPacket(void *addonData, DemuxPacket* pPacket); + + /*! + * @brief Allocate a new demux packet. + * @param addonData A pointer to the add-on. + * @param iDataSize The packet size. + * @return The allocated packet. + */ + static DemuxPacket* PVRAllocateDemuxPacket(void *addonData, int iDataSize = 0); + +private: + CB_PVRLib *m_callbacks; /*!< callback addresses */ + CAddon *m_addon; /*!< the addon */ +}; + +}; /* namespace ADDON */ diff --git a/xbmc/addons/AddonDatabase.cpp b/xbmc/addons/AddonDatabase.cpp index fe4e7b4..24276e1 100644 --- a/xbmc/addons/AddonDatabase.cpp +++ b/xbmc/addons/AddonDatabase.cpp @@ -658,6 +658,14 @@ bool CAddonDatabase::IsAddonDisabled(const CStdString &addonID) return false; } +bool CAddonDatabase::IsSystemPVRAddonEnabled(const CStdString &addonID) +{ + CStdString strWhereClause = PrepareSQL("addonID = '%s'", addonID.c_str()); + CStdString strEnabled = GetSingleValue("pvrenabled", "id", strWhereClause); + + return !strEnabled.IsEmpty(); +} + CStdString CAddonDatabase::IsAddonBroken(const CStdString &addonID) { try diff --git a/xbmc/addons/AddonDatabase.h b/xbmc/addons/AddonDatabase.h index 515fa98..34b8ed3 100644 --- a/xbmc/addons/AddonDatabase.h +++ b/xbmc/addons/AddonDatabase.h @@ -79,6 +79,10 @@ public: \sa DisableAddon, IsAddonDisabled */ bool HasDisabledAddons(); + /*! @deprecated only here to allow clean upgrades from earlier pvr versions + */ + bool IsSystemPVRAddonEnabled(const CStdString &addonID); + /*! \brief Mark an addon as broken Sets a flag that this addon has been marked as broken in the repository. \param addonID id of the addon to mark as broken diff --git a/xbmc/addons/AddonDll.h b/xbmc/addons/AddonDll.h index bda98e7..2db5d15 100644 --- a/xbmc/addons/AddonDll.h +++ b/xbmc/addons/AddonDll.h @@ -23,6 +23,7 @@ #include "DllAddon.h" #include "AddonManager.h" #include "AddonStatusHandler.h" +#include "AddonCallbacks.h" #include "settings/GUIDialogSettings.h" #include "utils/URIUtils.h" #include "filesystem/File.h" @@ -59,6 +60,7 @@ namespace ADDON virtual bool LoadSettings(); TheStruct* m_pStruct; TheProps* m_pInfo; + CAddonCallbacks* m_pHelpers; private: TheDll* m_pDll; @@ -109,6 +111,7 @@ CAddonDll::CAddonDll(const AddonProps &props) m_initialized = false; m_pDll = NULL; m_pInfo = NULL; + m_pHelpers = NULL; m_needsavedsettings = false; } @@ -186,9 +189,15 @@ bool CAddonDll::Create() if (!LoadDll()) return false; + /* Allocate the helper function class to allow crosstalk over + helper libraries */ + m_pHelpers = new CAddonCallbacks(this); + + /* Call Create to make connections, initializing data or whatever is + needed to become the AddOn running */ try { - ADDON_STATUS status = m_pDll->Create(NULL, m_pInfo); + ADDON_STATUS status = m_pDll->Create(m_pHelpers->GetCallbacks(), m_pInfo); if (status == ADDON_STATUS_OK) m_initialized = true; else if ((status == ADDON_STATUS_NEED_SETTINGS) || (status == ADDON_STATUS_NEED_SAVEDSETTINGS)) @@ -210,6 +219,9 @@ bool CAddonDll::Create() HandleException(e, "m_pDll->Create"); } + if (!m_initialized) + SAFE_DELETE(m_pHelpers); + return m_initialized; } @@ -258,6 +270,8 @@ void CAddonDll::Destroy() { HandleException(e, "m_pDll->Unload"); } + delete m_pHelpers; + m_pHelpers = NULL; free(m_pStruct); m_pStruct = NULL; delete m_pDll; diff --git a/xbmc/addons/AddonManager.cpp b/xbmc/addons/AddonManager.cpp index 4a61c7e..fa99ff1 100644 --- a/xbmc/addons/AddonManager.cpp +++ b/xbmc/addons/AddonManager.cpp @@ -39,6 +39,10 @@ #ifdef HAS_SCREENSAVER #include "ScreenSaver.h" #endif +#ifdef HAS_PVRCLIENTS +#include "DllPVRClient.h" +#include "pvr/addons/PVRClient.h" +#endif //#ifdef HAS_SCRAPERS #include "Scraper.h" //#endif @@ -46,8 +50,11 @@ #include "Repository.h" #include "Skin.h" #include "Service.h" +#include "pvr/PVRManager.h" +#include "pvr/addons/PVRClients.h" using namespace std; +using namespace PVR; namespace ADDON { @@ -109,6 +116,7 @@ AddonPtr CAddonMgr::Factory(const cp_extension_t *props) return AddonPtr(new CScraper(props)); case ADDON_VIZ: case ADDON_SCREENSAVER: + case ADDON_PVRDLL: { // begin temporary platform handling for Dlls // ideally platforms issues will be handled by C-Pluff // this is not an attempt at a solution @@ -136,6 +144,12 @@ AddonPtr CAddonMgr::Factory(const cp_extension_t *props) return AddonPtr(new CVisualisation(props)); #endif } + else if (type == ADDON_PVRDLL) + { +#ifdef HAS_PVRCLIENTS + return AddonPtr(new CPVRClient(props)); +#endif + } else return AddonPtr(new CScreenSaver(props)); } @@ -286,14 +300,14 @@ bool CAddonMgr::HasAddons(const TYPE &type, bool enabled /*= true*/) return GetAddons(type, addons, enabled); } -bool CAddonMgr::GetAllAddons(VECADDONS &addons, bool enabled /*= true*/, bool allowRepos /* = false */) +bool CAddonMgr::GetAllAddons(VECADDONS &addons, bool enabled /*= true*/, bool allowRepos /* = false */, bool bGetDisabledPVRAddons /* = true */) { for (int i = ADDON_UNKNOWN+1; i < ADDON_VIZ_LIBRARY; ++i) { if (!allowRepos && ADDON_REPOSITORY == (TYPE)i) continue; VECADDONS temp; - if (CAddonMgr::Get().GetAddons((TYPE)i, temp, enabled)) + if (CAddonMgr::Get().GetAddons((TYPE)i, temp, enabled, bGetDisabledPVRAddons)) addons.insert(addons.end(), temp.begin(), temp.end()); } return !addons.empty(); @@ -372,8 +386,9 @@ bool CAddonMgr::HasOutdatedAddons(bool enabled /*= true*/) return GetAllOutdatedAddons(dummy,enabled); } -bool CAddonMgr::GetAddons(const TYPE &type, VECADDONS &addons, bool enabled /* = true */) +bool CAddonMgr::GetAddons(const TYPE &type, VECADDONS &addons, bool enabled /* = true */, bool bGetDisabledPVRAddons /* = true */) { + CStdString xbmcPath = _P("special://xbmc/addons"); CSingleLock lock(m_critSection); addons.clear(); cp_status_t status; @@ -382,9 +397,25 @@ bool CAddonMgr::GetAddons(const TYPE &type, VECADDONS &addons, bool enabled /* = cp_extension_t **exts = m_cpluff->get_extensions_info(m_cp_context, ext_point.c_str(), &status, &num); for(int i=0; i ID()) != enabled) - addons.push_back(addon); + const cp_extension_t *props = exts[i]; + bool bIsPVRAddon(TranslateType(props->ext_point_id) == ADDON_PVRDLL); + + if (((bGetDisabledPVRAddons && bIsPVRAddon) || m_database.IsAddonDisabled(props->plugin->identifier) != enabled)) + { + if (bIsPVRAddon && g_PVRManager.IsStarted()) + { + AddonPtr pvrAddon; + if (g_PVRClients->GetClient(props->plugin->identifier, pvrAddon)) + { + addons.push_back(pvrAddon); + continue; + } + } + + AddonPtr addon(Factory(props)); + if (addon) + addons.push_back(addon); + } } m_cpluff->release_info(m_cp_context, exts); return addons.size() > 0; @@ -394,14 +425,26 @@ bool CAddonMgr::GetAddon(const CStdString &str, AddonPtr &addon, const TYPE &typ { CSingleLock lock(m_critSection); + CStdString xbmcPath = _P("special://xbmc/addons"); cp_status_t status; cp_plugin_info_t *cpaddon = m_cpluff->get_plugin_info(m_cp_context, str.c_str(), &status); if (status == CP_OK && cpaddon) { addon = GetAddonFromDescriptor(cpaddon); m_cpluff->release_info(m_cp_context, cpaddon); - if (addon.get() && enabledOnly && m_database.IsAddonDisabled(addon->ID())) - return false; + + if (addon && addon.get()) + { + if (enabledOnly && m_database.IsAddonDisabled(addon->ID())) + return false; + + if (addon->Type() == ADDON_PVRDLL && g_PVRManager.IsStarted()) + { + AddonPtr pvrAddon; + if (g_PVRClients->GetClient(addon->ID(), pvrAddon)) + addon = pvrAddon; + } + } return NULL != addon.get(); } if (cpaddon) @@ -489,15 +532,25 @@ CStdString CAddonMgr::GetString(const CStdString &id, const int number) void CAddonMgr::FindAddons() { - CSingleLock lock(m_critSection); - if (m_cpluff && m_cp_context) - m_cpluff->scan_plugins(m_cp_context, CP_SP_UPGRADE); + { + CSingleLock lock(m_critSection); + if (m_cpluff && m_cp_context) + { + m_cpluff->scan_plugins(m_cp_context, CP_SP_UPGRADE); + SetChanged(); + } + } + NotifyObservers("addons"); } void CAddonMgr::RemoveAddon(const CStdString& ID) { if (m_cpluff && m_cp_context) + { m_cpluff->uninstall_plugin(m_cp_context,ID.c_str()); + SetChanged(); + NotifyObservers("addons"); + } } const char *CAddonMgr::GetTranslatedString(const cp_cfg_element_t *root, const char *tag) @@ -554,6 +607,8 @@ AddonPtr CAddonMgr::AddonFromProps(AddonProps& addonProps) return AddonPtr(new CScreenSaver(addonProps)); case ADDON_VIZ_LIBRARY: return AddonPtr(new CAddonLibrary(addonProps)); + case ADDON_PVRDLL: + return AddonPtr(new CPVRClient(addonProps)); case ADDON_REPOSITORY: return AddonPtr(new CRepository(addonProps)); default: diff --git a/xbmc/addons/AddonManager.h b/xbmc/addons/AddonManager.h index 8166974..aaae599 100644 --- a/xbmc/addons/AddonManager.h +++ b/xbmc/addons/AddonManager.h @@ -22,6 +22,7 @@ #include "Addon.h" #include "threads/CriticalSection.h" #include "utils/StdString.h" +#include "utils/Observer.h" #include #include #include @@ -44,6 +45,7 @@ namespace ADDON const CStdString ADDON_PYTHON_EXT = "*.py"; const CStdString ADDON_SCRAPER_EXT = "*.xml"; const CStdString ADDON_SCREENSAVER_EXT = "*.xbs"; + const CStdString ADDON_PVRDLL_EXT = "*.pvr"; const CStdString ADDON_DSP_AUDIO_EXT = "*.adsp"; const CStdString ADDON_VERSION_RE = "(?\\d*)\\.?(?\\d*)?\\.?(?\\d*)?\\.?(?\\d*)?"; @@ -67,7 +69,7 @@ namespace ADDON * otherwise. Services the generic callbacks available * to all addon variants. */ - class CAddonMgr + class CAddonMgr : public Observable { public: static CAddonMgr &Get(); @@ -90,8 +92,8 @@ namespace ADDON */ bool GetAddon(const CStdString &id, AddonPtr &addon, const TYPE &type = ADDON_UNKNOWN, bool enabledOnly = true); bool HasAddons(const TYPE &type, bool enabled = true); - bool GetAddons(const TYPE &type, VECADDONS &addons, bool enabled = true); - bool GetAllAddons(VECADDONS &addons, bool enabled = true, bool allowRepos = false); + bool GetAddons(const TYPE &type, VECADDONS &addons, bool enabled = true, bool bGetDisabledPVRAddons = true); + bool GetAllAddons(VECADDONS &addons, bool enabled = true, bool allowRepos = false, bool bGetDisabledPVRAddons = true); void AddToUpdateableAddons(AddonPtr &pAddon); void RemoveFromUpdateableAddons(AddonPtr &pAddon); bool ReloadSettings(const CStdString &id); diff --git a/xbmc/addons/AddonStatusHandler.cpp b/xbmc/addons/AddonStatusHandler.cpp index f7397f9..0bba67d 100644 --- a/xbmc/addons/AddonStatusHandler.cpp +++ b/xbmc/addons/AddonStatusHandler.cpp @@ -84,7 +84,7 @@ void CAddonStatusHandler::Process() heading.Format("%s: %s", TranslateType(m_addon->Type(), true).c_str(), m_addon->Name().c_str()); /* AddOn lost connection to his backend (for ones that use Network) */ - if (m_status == ADDON_STATUS_LOST_CONNECTION) + if (m_status == ADDON_STATUS_LOST_CONNECTION && m_addon->Type() != ADDON_PVRDLL) // TODO display a proper message for pvr addons, but don't popup a dialog that requires user action { CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO); if (!pDialog) return; diff --git a/xbmc/addons/DllPVRClient.h b/xbmc/addons/DllPVRClient.h new file mode 100644 index 0000000..82bfcb5 --- /dev/null +++ b/xbmc/addons/DllPVRClient.h @@ -0,0 +1,30 @@ +#pragma once +/* + * Copyright (C) 2005-2009 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 "DllAddon.h" +#include "include/xbmc_pvr_types.h" + +class DllPVRClient : public DllAddon +{ + // this is populated via Macro calls in DllAddon.h +}; + diff --git a/xbmc/addons/GUIDialogAddonInfo.cpp b/xbmc/addons/GUIDialogAddonInfo.cpp index 0123aae..49ded35 100644 --- a/xbmc/addons/GUIDialogAddonInfo.cpp +++ b/xbmc/addons/GUIDialogAddonInfo.cpp @@ -37,6 +37,7 @@ #include "utils/StringUtils.h" #include "utils/URIUtils.h" #include "addons/AddonInstaller.h" +#include "Application.h" #define CONTROL_BTN_INSTALL 6 #define CONTROL_BTN_ENABLE 7 @@ -138,11 +139,13 @@ void CGUIDialogAddonInfo::UpdateControls() GrabRollbackVersions(); // TODO: System addons should be able to be disabled - bool canDisable = isInstalled && !isSystem && !m_localAddon->IsInUse(); + // TODO: the following line will have to be changed later, when the PVR add-ons are no longer part of our source tree + bool isPVR = isInstalled && m_localAddon->Type() == ADDON_PVRDLL; + bool canDisable = isInstalled && (!isSystem || isPVR) && !m_localAddon->IsInUse(); bool canInstall = !isInstalled && m_item->GetProperty("Addon.Broken").empty(); bool isRepo = (isInstalled && m_localAddon->Type() == ADDON_REPOSITORY) || (m_addon && m_addon->Type() == ADDON_REPOSITORY); - CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_INSTALL, canDisable || canInstall); + CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_INSTALL, (canDisable || canInstall) && !isPVR); SET_CONTROL_LABEL(CONTROL_BTN_INSTALL, isInstalled ? 24037 : 24038); CONTROL_ENABLE_ON_CONDITION(CONTROL_BTN_ENABLE, canDisable); @@ -208,9 +211,17 @@ void CGUIDialogAddonInfo::OnEnable(bool enable) if (!m_localAddon.get()) return; + CStdString xbmcPath = _P("special://xbmc/addons"); CAddonDatabase database; database.Open(); - database.DisableAddon(m_localAddon->ID(), !enable); +// if (m_localAddon->Type() == ADDON_PVRDLL && m_localAddon->Path().Left(xbmcPath.size()).Equals(xbmcPath)) +// database.EnableSystemPVRAddon(m_localAddon->ID(), enable); +// else + database.DisableAddon(m_localAddon->ID(), !enable); + + if (m_localAddon->Type() == ADDON_PVRDLL && enable) + g_application.StartPVRManager(); + SetItem(m_item); UpdateControls(); g_windowManager.SendMessage(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_UPDATE); diff --git a/xbmc/addons/Makefile b/xbmc/addons/Makefile index 8848788..952a267 100644 --- a/xbmc/addons/Makefile +++ b/xbmc/addons/Makefile @@ -1,4 +1,8 @@ SRCS=Addon.cpp \ + AddonCallbacks.cpp \ + AddonCallbacksAddon.cpp \ + AddonCallbacksGUI.cpp \ + AddonCallbacksPVR.cpp \ AddonDatabase.cpp \ AddonInstaller.cpp \ AddonManager.cpp \ diff --git a/xbmc/addons/Skin.cpp b/xbmc/addons/Skin.cpp index fd1b252..62745dc 100644 --- a/xbmc/addons/Skin.cpp +++ b/xbmc/addons/Skin.cpp @@ -202,6 +202,7 @@ bool CSkinInfo::LoadStartupWindows(const cp_extension_t *ext) { m_startupWindows.clear(); m_startupWindows.push_back(CStartupWindow(WINDOW_HOME, "513")); + m_startupWindows.push_back(CStartupWindow(WINDOW_PVR, "19180")); m_startupWindows.push_back(CStartupWindow(WINDOW_PROGRAMS, "0")); m_startupWindows.push_back(CStartupWindow(WINDOW_PICTURES, "1")); m_startupWindows.push_back(CStartupWindow(WINDOW_MUSIC, "2")); diff --git a/xbmc/addons/include/xbmc_pvr_dll.h b/xbmc/addons/include/xbmc_pvr_dll.h new file mode 100644 index 0000000..8c99416 --- /dev/null +++ b/xbmc/addons/include/xbmc_pvr_dll.h @@ -0,0 +1,441 @@ +/* + * 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 + * + */ + +#ifndef __XBMC_PVR_H__ +#define __XBMC_PVR_H__ + +#include "xbmc_addon_dll.h" +#include "xbmc_pvr_types.h" + +extern "C" +{ + // Functions that your PVR client must implement + + /** @name PVR server methods */ + //@{ + + /*! + * @brief Query this add-on's capabilities. + * @param pCapabilities The add-on properties. + * @return PVR_ERROR_NO_ERROR if the properties were fetched successfully. + */ + PVR_ERROR GetAddonCapabilities(PVR_ADDON_CAPABILITIES *pCapabilities); + + /*! + * @brief Get the stream properties of the stream that's currently being read. + * @param pProperties The properties. + * @return PVR_ERROR_NO_ERROR if the properties have been fetched successfully. + */ + PVR_ERROR GetStreamProperties(PVR_STREAM_PROPERTIES *pProperties); + + /*! + * @return The name reported by the backend. + */ + const char *GetBackendName(void); + + /*! + * @return The version string reported by the backend. + */ + const char *GetBackendVersion(void); + + /*! + * @return The connection string reported by the backend. + */ + const char *GetConnectionString(void); + + /*! + * @brief Get the disk space reported by the server. + * @param iTotal The total disk space. + * @param iUsed The used disk space. + * @return PVR_ERROR_NO_ERROR if the drive space has been fetched successfully. + */ + PVR_ERROR GetDriveSpace(long long *iTotal, long long *iUsed); + + /*! + * @brief Show the channel scan dialog. + * @return PVR_ERROR_NO_ERROR if the dialog was displayed successfully. + */ + PVR_ERROR DialogChannelScan(void); + + /*! + * @brief Call one of the menu hooks. + * @param menuhook The hook to call. + * @return PVR_ERROR_NO_ERROR if the hook was called successfully. + */ + PVR_ERROR CallMenuHook(const PVR_MENUHOOK &menuhook); + + //@} + /** @name PVR EPG methods */ + //@{ + + /*! + * @brief Request an EPG table for a channel from the client. + * @param handle Callback handle + * @param channel The channel to get the EPG table for. + * @param iStart The start time to use. + * @param iEnd The end time to use. + * @return PVR_ERROR_NO_ERROR if the table has been fetched successfully. + */ + PVR_ERROR GetEPGForChannel(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd); + + //@} + /** @name PVR channel group methods */ + //@{ + + /*! + * @return The total amount of channel groups on the server or -1 on error. + */ + int GetChannelGroupsAmount(void); + + /*! + * @brief Request the list of all channel groups from the backend. + * @param bRadio True to get the radio channel groups, false to get the TV channel groups. + * @return PVR_ERROR_NO_ERROR if the list has been fetched successfully. + */ + PVR_ERROR GetChannelGroups(PVR_HANDLE handle, bool bRadio); + + /*! + * @brief Request the list of all group members of a group. + * @param handle Callback. + * @param group The group to get the members for. + * @return PVR_ERROR_NO_ERROR if the list has been fetched successfully. + */ + PVR_ERROR GetChannelGroupMembers(PVR_HANDLE handle, const PVR_CHANNEL_GROUP &group); + + //@} + /** @name PVR channel methods */ + //@{ + + /*! + * @return The total amount of channels on the server or -1 on error. + */ + int GetChannelsAmount(void); + + /*! + * @brief Request the list of all channels from the backend. + * @param bRadio True to get the radio channels, false to get the TV channels. + * @return PVR_ERROR_NO_ERROR if the list has been fetched successfully. + */ + PVR_ERROR GetChannels(PVR_HANDLE handle, bool bRadio); + + /*! + * @brief Delete a channel. + * @param channel The channel to delete. + * @return PVR_ERROR_NO_ERROR if the channel has been deleted successfully. + */ + PVR_ERROR DeleteChannel(const PVR_CHANNEL &channel); + + /*! + * @brief Rename a channel. + * @param channel The channel to rename, containing the new channel name. + * @return PVR_ERROR_NO_ERROR if the channel has been renamed successfully. + */ + PVR_ERROR RenameChannel(const PVR_CHANNEL &channel); + + /*! + * @brief Move a channel to another channel number. + * @param channel The channel to move, containing the new channel number. + * @return PVR_ERROR_NO_ERROR if the channel has been moved successfully. + */ + PVR_ERROR MoveChannel(const PVR_CHANNEL &channel); + + /*! + * @brief Show the channel settings dialog. + * @param channel The channel to show the dialog for. + * @return PVR_ERROR_NO_ERROR if the dialog has been displayed successfully. + */ + PVR_ERROR DialogChannelSettings(const PVR_CHANNEL &channel); + + /*! + * @brief Show the dialog to add a channel on the backend. + * @param channel The channel to add. + * @return PVR_ERROR_NO_ERROR if the channel has been added successfully. + */ + PVR_ERROR DialogAddChannel(const PVR_CHANNEL &channel); + + //@} + /** @name PVR recording methods */ + //@{ + + /*! + * @return The total amount of channels on the server or -1 on error. + */ + int GetRecordingsAmount(void); + + /*! + * @brief Request the list of all recordings from the backend. + * @param handle The callback handle. + * @return PVR_ERROR_NO_ERROR if the recordings have been fetched successfully. + */ + PVR_ERROR GetRecordings(PVR_HANDLE handle); + + /*! + * @brief Delete a recording on the backend. + * @param recording The recording to delete. + * @return PVR_ERROR_NO_ERROR if the recording has been deleted successfully. + */ + PVR_ERROR DeleteRecording(const PVR_RECORDING &recording); + + /*! + * @brief Rename a recording on the backend. + * @param recording The recording to rename, containing the new name. + * @return PVR_ERROR_NO_ERROR if the recording has been renamed successfully. + */ + PVR_ERROR RenameRecording(const PVR_RECORDING &recording); + + //@} + /** @name PVR timer methods */ + //@{ + + /*! + * @return The total amount of timers on the backend or -1 on error. + */ + int GetTimersAmount(void); + + /*! + * @brief Request the list of all timers from the backend. + * @param handle The callback handle. + * @return PVR_ERROR_NO_ERROR if the list has been fetched successfully. + */ + PVR_ERROR GetTimers(PVR_HANDLE handle); + + /*! + * @brief Add a timer on the backend. + * @param timer The timer to add. + * @return PVR_ERROR_NO_ERROR if the timer has been added successfully. + */ + PVR_ERROR AddTimer(const PVR_TIMER &timer); + + /*! + * @brief Delete a timer on the backend. + * @param timer The timer to delete. + * @param bForceDelete Set to true to delete a timer that is currently recording a program. + * @return PVR_ERROR_NO_ERROR if the timer has been deleted successfully. + */ + PVR_ERROR DeleteTimer(const PVR_TIMER &timer, bool bForceDelete); + + /*! + * @brief Update the timer information on the server. + * @param timer The timer to update. + * @return PVR_ERROR_NO_ERROR if the timer has been updated successfully. + */ + PVR_ERROR UpdateTimer(const PVR_TIMER &timer); + + //@} + /** @name PVR live stream methods */ + //@{ + + /*! + * @brief Open a live stream on the server. + * @param channel The channel to stream. + * @return True if the stream opened successfully, false otherwise. + */ + bool OpenLiveStream(const PVR_CHANNEL &channel); + + /*! + * @brief Close an open live stream. + */ + void CloseLiveStream(void); + + /*! + * @brief Read from an open live stream. + * @param pBuffer The buffer to store the data in. + * @param iBufferSize The amount of bytes to read. + * @return The amount of bytes that were actually read from the stream. + */ + int ReadLiveStream(unsigned char *pBuffer, unsigned int iBufferSize); + + /*! + * @brief Seek in a live stream on a backend that supports timeshifting. + * @param iPosition The position to seek to. + * @param iWhence ? + * @return The new position. + */ + long long SeekLiveStream(long long iPosition, int iWhence = SEEK_SET); + + /*! + * @return The position in the stream that's currently being read. + */ + long long PositionLiveStream(void); + + /*! + * @return The total length of the stream that's currently being read. + */ + long long LengthLiveStream(void); + + /*! + * @return The channel number on the server of the live stream that's currently being read. + */ + int GetCurrentClientChannel(void); + + /*! + * @brief Switch to another channel. Only to be called when a live stream has already been opened. + * @param channel The channel to switch to. + * @return True if the switch was successful, false otherwise. + */ + bool SwitchChannel(const PVR_CHANNEL &channel); + + /*! + * @brief Get the signal status of the stream that's currently open. + * @param signalStatus The signal status. + * @return True if the signal status has been read successfully, false otherwise. + */ + PVR_ERROR SignalStatus(PVR_SIGNAL_STATUS &signalStatus); + + /*! + * @brief Get the stream URL for a channel from the server. Used by the MediaPortal add-on. + * @param channel The channel to get the stream URL for. + * @return The requested URL. + */ + const char *GetLiveStreamURL(const PVR_CHANNEL &channel); + + //@} + /** @name PVR recording stream methods */ + //@{ + + /*! + * @brief Open a recording on the server. + * @param recording The recording to open. + * @return True if the stream has been opened succesfully, false otherwise. + */ + bool OpenRecordedStream(const PVR_RECORDING &recording); + + /*! + * @brief Close an open stream from a recording. + */ + void CloseRecordedStream(void); + + /*! + * @brief Read from a recording. + * @param pBuffer The buffer to store the data in. + * @param iBufferSize The amount of bytes to read. + * @return The amount of bytes that were actually read from the stream. + */ + int ReadRecordedStream(unsigned char *pBuffer, unsigned int iBufferSize); + + /*! + * @brief Seek in a recorded stream. + * @param iPosition The position to seek to. + * @param iWhence ? + * @return The new position. + */ + long long SeekRecordedStream(long long iPosition, int iWhence = SEEK_SET); + + /*! + * @return The position in the stream that's currently being read. + */ + long long PositionRecordedStream(void); + + /*! + * @return The total length of the stream that's currently being read. + */ + long long LengthRecordedStream(void); + + //@} + /** @name PVR demultiplexer methods */ + //@{ + + /*! + * @brief Reset the demultiplexer in the add-on. + */ + void DemuxReset(void); + + /*! + * @brief Abort the demultiplexer thread in the add-on. + */ + void DemuxAbort(void); + + /*! + * @brief Flush all data that's currently in the demultiplexer buffer in the add-on. + */ + void DemuxFlush(void); + + /*! + * @brief Read a packet from the demultiplexer. + * @return The packet. + */ + DemuxPacket *DemuxRead(void); + + //@} + + // function to export the above structure to XBMC + void __declspec(dllexport) get_addon(struct PVRClient *pClient) + { + pClient->GetAddonCapabilities = GetAddonCapabilities; + pClient->GetStreamProperties = GetStreamProperties; + pClient->GetConnectionString = GetConnectionString; + pClient->GetBackendName = GetBackendName; + pClient->GetBackendVersion = GetBackendVersion; + pClient->GetDriveSpace = GetDriveSpace; + pClient->DialogChannelScan = DialogChannelScan; + pClient->MenuHook = CallMenuHook; + + pClient->GetEpg = GetEPGForChannel; + + pClient->GetChannelGroupsAmount = GetChannelGroupsAmount; + pClient->GetChannelGroups = GetChannelGroups; + pClient->GetChannelGroupMembers = GetChannelGroupMembers; + + pClient->GetChannelsAmount = GetChannelsAmount; + pClient->GetChannels = GetChannels; + pClient->DeleteChannel = DeleteChannel; + pClient->RenameChannel = RenameChannel; + pClient->MoveChannel = MoveChannel; + pClient->DialogChannelSettings = DialogChannelSettings; + pClient->DialogAddChannel = DialogAddChannel; + + pClient->GetRecordingsAmount = GetRecordingsAmount; + pClient->GetRecordings = GetRecordings; + pClient->DeleteRecording = DeleteRecording; + pClient->RenameRecording = RenameRecording; + + pClient->GetTimersAmount = GetTimersAmount; + pClient->GetTimers = GetTimers; + pClient->AddTimer = AddTimer; + pClient->DeleteTimer = DeleteTimer; + pClient->UpdateTimer = UpdateTimer; + + pClient->OpenLiveStream = OpenLiveStream; + pClient->CloseLiveStream = CloseLiveStream; + pClient->ReadLiveStream = ReadLiveStream; + pClient->SeekLiveStream = SeekLiveStream; + pClient->PositionLiveStream = PositionLiveStream; + pClient->LengthLiveStream = LengthLiveStream; + pClient->GetCurrentClientChannel = GetCurrentClientChannel; + pClient->SwitchChannel = SwitchChannel; + pClient->SignalStatus = SignalStatus; + pClient->GetLiveStreamURL = GetLiveStreamURL; + + pClient->OpenRecordedStream = OpenRecordedStream; + pClient->CloseRecordedStream = CloseRecordedStream; + pClient->ReadRecordedStream = ReadRecordedStream; + pClient->SeekRecordedStream = SeekRecordedStream; + pClient->PositionRecordedStream = PositionRecordedStream; + pClient->LengthRecordedStream = LengthRecordedStream; + + pClient->DemuxReset = DemuxReset; + pClient->DemuxAbort = DemuxAbort; + pClient->DemuxFlush = DemuxFlush; + pClient->DemuxRead = DemuxRead; + }; +}; + +#endif diff --git a/xbmc/addons/include/xbmc_pvr_types.h b/xbmc/addons/include/xbmc_pvr_types.h new file mode 100644 index 0000000..add0996 --- /dev/null +++ b/xbmc/addons/include/xbmc_pvr_types.h @@ -0,0 +1,412 @@ +#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 + * + */ + +#ifndef __PVRCLIENT_TYPES_H__ +#define __PVRCLIENT_TYPES_H__ + +#ifdef _WIN32 +#include +#else +#ifndef __cdecl +#define __cdecl +#endif +#ifndef __declspec +#define __declspec(X) +#endif +#endif +#include + +/*! @note Define "USE_DEMUX" on compile time if demuxing inside pvr + * addon is used. Also XBMC's "DVDDemuxPacket.h" file must be inside + * the include path of the pvr addon. + */ +#ifdef USE_DEMUX +#include "DVDDemuxPacket.h" +#else +struct DemuxPacket; +#endif + +#undef ATTRIBUTE_PACKED +#undef PRAGMA_PACK_BEGIN +#undef PRAGMA_PACK_END + +#if defined(__GNUC__) +#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ >= 95) +#define ATTRIBUTE_PACKED __attribute__ ((packed)) +#define PRAGMA_PACK 0 +#endif +#endif + +#if !defined(ATTRIBUTE_PACKED) +#define ATTRIBUTE_PACKED +#define PRAGMA_PACK 1 +#endif + +/*! @name PVR entry content event types */ +//@{ +/* These IDs come from the DVB-SI EIT table "content descriptor" + * Also known under the name "E-book genre assignments" + */ +#define EPG_EVENT_CONTENTMASK_UNDEFINED 0x00 +#define EPG_EVENT_CONTENTMASK_MOVIEDRAMA 0x10 +#define EPG_EVENT_CONTENTMASK_NEWSCURRENTAFFAIRS 0x20 +#define EPG_EVENT_CONTENTMASK_SHOW 0x30 +#define EPG_EVENT_CONTENTMASK_SPORTS 0x40 +#define EPG_EVENT_CONTENTMASK_CHILDRENYOUTH 0x50 +#define EPG_EVENT_CONTENTMASK_MUSICBALLETDANCE 0x60 +#define EPG_EVENT_CONTENTMASK_ARTSCULTURE 0x70 +#define EPG_EVENT_CONTENTMASK_SOCIALPOLITICALECONOMICS 0x80 +#define EPG_EVENT_CONTENTMASK_EDUCATIONALSCIENCE 0x90 +#define EPG_EVENT_CONTENTMASK_LEISUREHOBBIES 0xA0 +#define EPG_EVENT_CONTENTMASK_SPECIAL 0xB0 +#define EPG_EVENT_CONTENTMASK_USERDEFINED 0xF0 +//@} +/* Set EPGTAG.iGenreType to EPG_GENRE_USE_STRING to transfer genre strings to XBMC */ +#define EPG_GENRE_USE_STRING 0x100 + +/* using the default avformat's MAX_STREAMS value to be safe */ +#define PVR_STREAM_MAX_STREAMS 20 + +#ifdef __cplusplus +extern "C" { +#endif + + /*! + * @brief Handle used to return data from the PVR add-on to CPVRClient + */ + struct PVR_HANDLE_STRUCT + { + void *callerAddress; /*!< address of the caller */ + void *dataAddress; /*!< address to store data in */ + int dataIdentifier; /*!< parameter to pass back when calling the callback */ + }; + typedef PVR_HANDLE_STRUCT *PVR_HANDLE; + + /*! \brief PVR Client Error Codes + */ + typedef enum + { + PVR_ERROR_NO_ERROR = 0, + PVR_ERROR_UNKNOWN = -1, + PVR_ERROR_NOT_IMPLEMENTED = -2, + PVR_ERROR_SERVER_ERROR = -3, + PVR_ERROR_SERVER_TIMEOUT = -4, + PVR_ERROR_NOT_SYNC = -5, + PVR_ERROR_NOT_DELETED = -6, + PVR_ERROR_NOT_SAVED = -7, + PVR_ERROR_RECORDING_RUNNING = -8, + PVR_ERROR_ALREADY_PRESENT = -9, + PVR_ERROR_NOT_POSSIBLE = -10 + } PVR_ERROR; + + /*! + * @brief PVR timer states + */ + typedef enum + { + PVR_TIMER_STATE_INVALID = 0, + PVR_TIMER_STATE_SCHEDULED = 1, /*!< @brief the timer is scheduled for recording */ + PVR_TIMER_STATE_RECORDING = 2, /*!< @brief the timer is currently recordings */ + PVR_TIMER_STATE_COMPLETED = 3, /*!< @brief the recording completed successfully */ + PVR_TIMER_STATE_ABORTED = 4, /*!< @brief recording started, but was aborted */ + PVR_TIMER_STATE_CANCELLED = 5 /*!< @brief the timer was scheduled, but was cancelled */ + } PVR_TIMER_STATE; + + /*! + * @brief Properties passed to the Create() method of an add-on. + */ + typedef struct PVR_PROPERTIES + { + int iClientId; /*!< @brief (required) database ID of the client */ + const char *strUserPath; /*!< @brief (required) path to the user profile */ + const char *strClientPath; /*!< @brief (required) path to this add-on */ + } PVR_PROPERTIES; + + /*! + * @brief PVR add-on capabilities. All capabilities are set to "false" as default. + */ + typedef struct PVR_ADDON_CAPABILITIES + { + bool bSupportsChannelSettings; /*!< @brief (optional) true if this add-on supports changing channel settings on the backend */ + bool bSupportsTimeshift; /*!< @brief (optional) true if the backend will handle timeshift. false if XBMC should handle it. */ + bool bSupportsEPG; /*!< @brief (optional) true if the add-on provides EPG information */ + bool bSupportsTV; /*!< @brief (optional) true if this add-on provides TV channels */ + bool bSupportsRadio; /*!< @brief (optional) true if this add-on supports radio channels */ + bool bSupportsRecordings; /*!< @brief (optional) true if this add-on supports playback of recordings stored on the backend */ + bool bSupportsTimers; /*!< @brief (optional) true if this add-on supports the creation and editing of timers */ + bool bSupportsChannelGroups; /*!< @brief (optional) true if this add-on supports channel groups */ + bool bSupportsChannelScan; /*!< @brief (optional) true if this add-on support scanning for new channels on the backend */ + bool bHandlesInputStream; /*!< @brief (optional) true if this add-on provides an input stream. false if XBMC handles the stream. */ + bool bHandlesDemuxing; /*!< @brief (optional) true if this add-on demultiplexes packets. */ + bool bSupportsRecordingFolders; /*!< @brief (optional) true if the backend supports timers / recordings in folders. */ + } ATTRIBUTE_PACKED PVR_ADDON_CAPABILITIES; + + /*! + * @brief PVR stream properties + */ + typedef struct PVR_STREAM_PROPERTIES + { + unsigned int iStreamCount; + struct PVR_STREAM + { + unsigned int iStreamIndex; /*!< @brief (required) stream index */ + unsigned int iPhysicalId; /*!< @brief (required) physical index */ + unsigned int iCodecType; /*!< @brief (required) codec type id */ + unsigned int iCodecId; /*!< @brief (required) codec id */ + char strLanguage[4]; /*!< @brief (required) language id */ + unsigned int iIdentifier; /*!< @brief (required) stream id */ + unsigned int iFPSScale; /*!< @brief (required) scale of 1000 and a rate of 29970 will result in 29.97 fps */ + unsigned int iFPSRate; /*!< @brief (required) FPS rate */ + unsigned int iHeight; /*!< @brief (required) height of the stream reported by the demuxer */ + unsigned int iWidth; /*!< @brief (required) width of the stream reported by the demuxer */ + float fAspect; /*!< @brief (required) display aspect ratio of the stream */ + unsigned int iChannels; /*!< @brief (required) amount of channels */ + unsigned int iSampleRate; /*!< @brief (required) sample rate */ + unsigned int iBlockAlign; /*!< @brief (required) block alignment */ + unsigned int iBitRate; /*!< @brief (required) bit rate */ + unsigned int iBitsPerSample; /*!< @brief (required) bits per sample */ + } stream[PVR_STREAM_MAX_STREAMS]; /*!< @brief (required) the streams */ + } ATTRIBUTE_PACKED PVR_STREAM_PROPERTIES; + + /*! + * @brief Signal status information + */ + typedef struct PVR_SIGNAL_STATUS + { + char strAdapterName[1024]; /*!< @brief (optional) name of the adapter that's being used */ + char strAdapterStatus[1024]; /*!< @brief (optional) status of the adapter that's being used */ + int iSNR; /*!< @brief (optional) signal/noise ratio */ + int iSignal; /*!< @brief (optional) signal strength */ + long iBER; /*!< @brief (optional) bit error rate */ + long iUNC; /*!< @brief (optional) uncorrected blocks */ + double dVideoBitrate; /*!< @brief (optional) video bitrate */ + double dAudioBitrate; /*!< @brief (optional) audio bitrate */ + double dDolbyBitrate; /*!< @brief (optional) dolby bitrate */ + } ATTRIBUTE_PACKED PVR_SIGNAL_STATUS; + + /*! + * @brief Menu hooks that are available in the context menus while playing a stream via this add-on. + */ + typedef struct PVR_MENUHOOK + { + unsigned int iHookId; /*!< @brief (required) this hook's identifier */ + unsigned int iLocalizedStringId; /*!< @brief (required) the id of the label for this hook in g_localizeStrings */ + } ATTRIBUTE_PACKED PVR_MENUHOOK; + + /*! + * @brief Representation of a TV or radio channel. + */ + typedef struct PVR_CHANNEL + { + unsigned int iUniqueId; /*!< @brief (required) unique identifier for this channel */ + bool bIsRadio; /*!< @brief (required) true if this is a radio channel, false if it's a TV channel */ + unsigned int iChannelNumber; /*!< @brief (optional) channel number of this channel on the backend */ + const char * strChannelName; /*!< @brief (optional) channel name given to this channel */ + const char * strInputFormat; /*!< @brief (optional) input format type. types can be found in ffmpeg/libavformat/allformats.c + leave empty if unknown */ + const char * strStreamURL; /*!< @brief (optional) the URL to use to access this channel. + leave empty to use this add-on to access the stream. + set to a path that's supported by XBMC otherwise. */ + unsigned int iEncryptionSystem; /*!< @brief (optional) the encryption ID or CaID of this channel */ + const char * strIconPath; /*!< @brief (optional) path to the channel icon (if present) */ + bool bIsHidden; /*!< @brief (optional) true if this channel is marked as hidden */ + } ATTRIBUTE_PACKED PVR_CHANNEL; + + typedef struct PVR_CHANNEL_GROUP + { + const char * strGroupName; /*!< @brief (required) name of this channel group */ + bool bIsRadio; /*!< @brief (required) true if this is a radio channel group, false otherwise. */ + } ATTRIBUTE_PACKED PVR_CHANNEL_GROUP; + + typedef struct PVR_CHANNEL_GROUP_MEMBER + { + const char * strGroupName; /*!< @brief (required) name of the channel group to add the channel to */ + unsigned int iChannelUniqueId; /*!< @brief (required) unique id of the member */ + unsigned int iChannelNumber; /*!< @brief (optional) channel number within the group */ + } ATTRIBUTE_PACKED PVR_CHANNEL_GROUP_MEMBER; + + /*! + * @brief Representation of an EPG event. + */ + typedef struct EPG_TAG { + unsigned int iUniqueBroadcastId; /*!< @brief (required) identifier for this event */ + const char * strTitle; /*!< @brief (required) this event's title */ + unsigned int iChannelNumber; /*!< @brief (required) the number of the channel this event occurs on */ + time_t startTime; /*!< @brief (required) start time in UTC */ + time_t endTime; /*!< @brief (required) end time in UTC */ + const char * strPlotOutline; /*!< @brief (optional) plot outline */ + const char * strPlot; /*!< @brief (optional) plot */ + const char * strIconPath; /*!< @brief (optional) icon path */ + int iGenreType; /*!< @brief (optional) genre type */ + int iGenreSubType; /*!< @brief (optional) genre sub type */ + const char * strGenreDescription; /*!< @brief (optional) genre. Will be used only when iGenreType = EPG_GENRE_USE_STRING */ + time_t firstAired; /*!< @brief (optional) first aired in UTC */ + int iParentalRating; /*!< @brief (optional) parental rating */ + int iStarRating; /*!< @brief (optional) star rating */ + bool bNotify; /*!< @brief (optional) notify the user when this event starts */ + int iSeriesNumber; /*!< @brief (optional) series number */ + int iEpisodeNumber; /*!< @brief (optional) episode number */ + int iEpisodePartNumber; /*!< @brief (optional) episode part number */ + const char * strEpisodeName; /*!< @brief (optional) episode name */ + } ATTRIBUTE_PACKED EPG_TAG; + + /*! + * @brief Representation of a timer event. + */ + typedef struct PVR_TIMER { + unsigned int iClientIndex; /*!< @brief (required) the index of this timer given by the client */ + int iClientChannelUid; /*!< @brief (required) unique identifier of the channel to record on */ + time_t startTime; /*!< @brief (required) start time of the recording in UTC. instant timers that are sent to the add-on by xbmc will have this value set to 0 */ + time_t endTime; /*!< @brief (required) end time of the recording in UTC */ + PVR_TIMER_STATE state; /*!< @brief (required) the state of this timer */ + const char * strTitle; /*!< @brief (optional) title of this timer */ + const char * strDirectory; /*!< @brief (optional) the directory where the recording will be stored in */ + const char * strSummary; /*!< @brief (optional) the summary for this timer */ + int iPriority; /*!< @brief (optional) the priority of this timer */ + int iLifetime; /*!< @brief (optional) lifetimer of this timer in days */ + bool bIsRepeating; /*!< @brief (optional) true if this is a recurring timer */ + time_t firstDay; /*!< @brief (optional) the first day this recording is active in case of a repeating event */ + int iWeekdays; /*!< @brief (optional) weekday mask */ + int iEpgUid; /*!< @brief (optional) epg event id */ + unsigned int iMarginStart; /*!< @brief (optional) if set, the backend starts the recording iMarginStart minutes before startTime. */ + unsigned int iMarginEnd; /*!< @brief (optional) if set, the backend ends the recording iMarginEnd minutes after endTime. */ + int iGenreType; /*!< @brief (optional) genre type */ + int iGenreSubType; /*!< @brief (optional) genre sub type */ + } ATTRIBUTE_PACKED PVR_TIMER; + + /*! + * @brief Representation of a recording. + */ + typedef struct PVR_RECORDING { + const char * strRecordingId; /*!< @brief (required) unique id of the recording on the client. */ + const char * strTitle; /*!< @brief (required) the title of this recording */ + const char * strStreamURL; /*!< @brief (required) stream URL to access this recording */ + const char * strDirectory; /*!< @brief (optional) directory of this recording on the client */ + const char * strPlotOutline; /*!< @brief (optional) plot outline */ + const char * strPlot; /*!< @brief (optional) plot */ + const char * strChannelName; /*!< @brief (optional) channel name */ + time_t recordingTime; /*!< @brief (optional) start time of the recording */ + int iDuration; /*!< @brief (optional) duration of the recording in seconds */ + int iPriority; /*!< @brief (optional) priority of this recording (from 0 - 100) */ + int iLifetime; /*!< @brief (optional) life time in days of this recording */ + int iGenreType; /*!< @brief (optional) genre type */ + int iGenreSubType; /*!< @brief (optional) genre sub type */ + const char * strIconPath; /*!< @brief (optional) icon path */ + const char * strDefFanart; /*!< @brief (optional) fanart path */ + } ATTRIBUTE_PACKED PVR_RECORDING; + + /*! + * @brief Structure to transfer the PVR functions to XBMC + */ + typedef struct PVRClient + { + /** @name PVR server methods */ + //@{ + PVR_ERROR (__cdecl* GetAddonCapabilities)(PVR_ADDON_CAPABILITIES *pCapabilities); + PVR_ERROR (__cdecl* GetStreamProperties)(PVR_STREAM_PROPERTIES *pProperties); + const char * (__cdecl* GetBackendName)(void); + const char * (__cdecl* GetBackendVersion)(void); + const char * (__cdecl* GetConnectionString)(void); + PVR_ERROR (__cdecl* GetDriveSpace)(long long *iTotal, long long *iUsed); + PVR_ERROR (__cdecl* DialogChannelScan)(void); + PVR_ERROR (__cdecl* MenuHook)(const PVR_MENUHOOK &menuhook); + //@} + + /** @name PVR EPG methods */ + //@{ + PVR_ERROR (__cdecl* GetEpg)(PVR_HANDLE handle, const PVR_CHANNEL &channel, time_t iStart, time_t iEnd); + //@} + + /** @name PVR channel group methods */ + //@{ + int (__cdecl* GetChannelGroupsAmount)(void); + PVR_ERROR (__cdecl* GetChannelGroups)(PVR_HANDLE handle, bool bRadio); + PVR_ERROR (__cdecl* GetChannelGroupMembers)(PVR_HANDLE handle, const PVR_CHANNEL_GROUP &group); + //@} + + /** @name PVR channel methods */ + //@{ + int (__cdecl* GetChannelsAmount)(void); + PVR_ERROR (__cdecl* GetChannels)(PVR_HANDLE handle, bool bRadio); + PVR_ERROR (__cdecl* DeleteChannel)(const PVR_CHANNEL &channel); + PVR_ERROR (__cdecl* RenameChannel)(const PVR_CHANNEL &channel); + PVR_ERROR (__cdecl* MoveChannel)(const PVR_CHANNEL &channel); + PVR_ERROR (__cdecl* DialogChannelSettings)(const PVR_CHANNEL &channel); + PVR_ERROR (__cdecl* DialogAddChannel)(const PVR_CHANNEL &channel); + //@} + + /** @name PVR recording methods */ + //@{ + int (__cdecl* GetRecordingsAmount)(void); + PVR_ERROR (__cdecl* GetRecordings)(PVR_HANDLE handle); + PVR_ERROR (__cdecl* DeleteRecording)(const PVR_RECORDING &recording); + PVR_ERROR (__cdecl* RenameRecording)(const PVR_RECORDING &recording); + //@} + + /** @name PVR timer methods */ + //@{ + int (__cdecl* GetTimersAmount)(void); + PVR_ERROR (__cdecl* GetTimers)(PVR_HANDLE handle); + PVR_ERROR (__cdecl* AddTimer)(const PVR_TIMER &timer); + PVR_ERROR (__cdecl* DeleteTimer)(const PVR_TIMER &timer, bool bForceDelete); + PVR_ERROR (__cdecl* UpdateTimer)(const PVR_TIMER &timer); + //@} + + /** @name PVR live stream methods */ + //@{ + bool (__cdecl* OpenLiveStream)(const PVR_CHANNEL &channel); + void (__cdecl* CloseLiveStream)(void); + int (__cdecl* ReadLiveStream)(unsigned char *pBuffer, unsigned int iBufferSize); + long long (__cdecl* SeekLiveStream)(long long iPosition, int iWhence /* = SEEK_SET */); + long long (__cdecl* PositionLiveStream)(void); + long long (__cdecl* LengthLiveStream)(void); + int (__cdecl* GetCurrentClientChannel)(void); + bool (__cdecl* SwitchChannel)(const PVR_CHANNEL &channel); + PVR_ERROR (__cdecl* SignalStatus)(PVR_SIGNAL_STATUS &signalStatus); + const char* (__cdecl* GetLiveStreamURL)(const PVR_CHANNEL &channel); + //@} + + /** @name PVR recording stream methods */ + //@{ + bool (__cdecl* OpenRecordedStream)(const PVR_RECORDING &recording); + void (__cdecl* CloseRecordedStream)(void); + int (__cdecl* ReadRecordedStream)(unsigned char *pBuffer, unsigned int iBufferSize); + long long (__cdecl* SeekRecordedStream)(long long iPosition, int iWhence /* = SEEK_SET */); + long long (__cdecl* PositionRecordedStream)(void); + long long (__cdecl* LengthRecordedStream)(void); + //@} + + /** @name PVR demultiplexer methods */ + //@{ + void (__cdecl* DemuxReset)(void); + void (__cdecl* DemuxAbort)(void); + void (__cdecl* DemuxFlush)(void); + DemuxPacket* (__cdecl* DemuxRead)(void); + //@} + + } PVRClient; + +#ifdef __cplusplus +} +#endif + +#endif //__PVRCLIENT_TYPES_H__ diff --git a/xbmc/cores/DllLoader/DllLoaderContainer.cpp b/xbmc/cores/DllLoader/DllLoaderContainer.cpp index 3e02492..f70facc 100644 --- a/xbmc/cores/DllLoader/DllLoaderContainer.cpp +++ b/xbmc/cores/DllLoader/DllLoaderContainer.cpp @@ -231,7 +231,7 @@ LibraryLoader* DllLoaderContainer::LoadDll(const char* sName, bool bLoadSymbols) LibraryLoader* pLoader; #ifdef _LINUX if (strstr(sName, ".so") != NULL || strstr(sName, ".vis") != NULL || strstr(sName, ".xbs") != NULL - || strstr(sName, ".mvis") != NULL || strstr(sName, ".dylib") != NULL || strstr(sName, ".framework") != NULL) + || strstr(sName, ".mvis") != NULL || strstr(sName, ".dylib") != NULL || strstr(sName, ".framework") != NULL || strstr(sName, ".pvr") != NULL) pLoader = new SoLoader(sName, bLoadSymbols); else #elif defined(_WIN32) diff --git a/xbmc/cores/DllLoader/Win32DllLoader.cpp b/xbmc/cores/DllLoader/Win32DllLoader.cpp index a7af019..fd918e4 100644 --- a/xbmc/cores/DllLoader/Win32DllLoader.cpp +++ b/xbmc/cores/DllLoader/Win32DllLoader.cpp @@ -331,6 +331,9 @@ bool Win32DllLoader::NeedsHooking(const char *dllName) CStdStringW strdllNameW; g_charsetConverter.utf8ToW(_P(dllName), strdllNameW, false); HMODULE hModule = GetModuleHandleW(strdllNameW.c_str()); + if (hModule == NULL) + return false; + wchar_t filepathW[MAX_PATH]; GetModuleFileNameW(hModule, filepathW, MAX_PATH); CStdString dllPath; diff --git a/xbmc/cores/IPlayer.h b/xbmc/cores/IPlayer.h index 91655a5..b44f56b 100644 --- a/xbmc/cores/IPlayer.h +++ b/xbmc/cores/IPlayer.h @@ -30,6 +30,11 @@ class TiXmlElement; class CStreamDetails; class CAction; +namespace PVR +{ + class CPVRChannel; +} + class IPlayerCallback { public: @@ -170,6 +175,7 @@ public: virtual CStdString GetPlayingTitle() { return ""; }; + virtual bool SwitchChannel(const PVR::CPVRChannel &channel) { return false; } protected: IPlayerCallback& m_callback; }; diff --git a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp index ea1f0bd..0e67af3 100644 --- a/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp +++ b/xbmc/cores/dvdplayer/DVDCodecs/Video/VDPAU.cpp @@ -531,7 +531,8 @@ bool CVDPAU::Supports(VdpVideoMixerFeature feature) bool CVDPAU::Supports(EINTERLACEMETHOD method) { if(method == VS_INTERLACEMETHOD_VDPAU_BOB - || method == VS_INTERLACEMETHOD_AUTO) + || method == VS_INTERLACEMETHOD_AUTO + || method == VS_INTERLACEMETHOD_AUTO_ION) return true; for(SInterlaceMapping* p = g_interlace_mapping; p->method != VS_INTERLACEMETHOD_NONE; p++) @@ -657,8 +658,21 @@ void CVDPAU::SetDeinterlacing() } else { - if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL - || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF) + if (method == VS_INTERLACEMETHOD_AUTO_ION) + { + if (vid_height <= 576) + { + VdpBool enabled[]={1,1,0}; + vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled); + } + else if (vid_height > 576) + { + VdpBool enabled[]={1,0,0}; + vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled); + } + } + else if (method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL + || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF) { VdpBool enabled[]={1,0,0}; vdp_st = vdp_video_mixer_set_feature_enables(videoMixer, ARSIZE(feature), feature, enabled); @@ -1387,14 +1401,16 @@ int CVDPAU::Decode(AVCodecContext *avctx, AVFrame *pFrame) if (mode == VS_DEINTERLACEMODE_FORCE || (mode == VS_DEINTERLACEMODE_AUTO && m_DVDVideoPics.front().iFlags & DVP_FLAG_INTERLACED)) { - if((method == VS_INTERLACEMETHOD_VDPAU_BOB + if((method == VS_INTERLACEMETHOD_AUTO_ION + || method == VS_INTERLACEMETHOD_VDPAU_BOB || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF || method == VS_INTERLACEMETHOD_VDPAU_INVERSE_TELECINE )) { - if(method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF + if((method == VS_INTERLACEMETHOD_AUTO_ION && vid_height > 576) + || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_HALF || method == VS_INTERLACEMETHOD_VDPAU_TEMPORAL_SPATIAL_HALF || avctx->skip_frame == AVDISCARD_NONREF) m_mixerstep = 0; diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h index dd8d977..2642a81 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemux.h @@ -23,6 +23,7 @@ #include "utils/StdString.h" #include "system.h" +#include "DVDDemuxPacket.h" class CDVDInputStream; @@ -219,19 +220,6 @@ public: virtual void GetStreamInfo(std::string& strInfo); }; -typedef struct DemuxPacket -{ - BYTE* pData; // data - int iSize; // data size - int iStreamId; // integer representing the stream index - int iGroupId; // the group this data belongs to, used to group data from different streams together - - double pts; // pts in DVD_TIME_BASE - double dts; // dts in DVD_TIME_BASE - double duration; // duration in DVD_TIME_BASE if available -} DemuxPacket; - - class CDVDDemux { public: diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp index 46287a8..55138fa 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxFFmpeg.cpp @@ -34,6 +34,7 @@ #include "DVDInputStreams/DVDInputStream.h" #include "DVDInputStreams/DVDInputStreamNavigator.h" #include "DVDInputStreams/DVDInputStreamBluray.h" +#include "DVDInputStreams/DVDInputStreamPVRManager.h" #include "DVDDemuxUtils.h" #include "DVDClock.h" // for DVD_TIME_BASE #include "utils/Win32Exception.h" diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxHTSP.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxHTSP.cpp index 2737f19..38ca397 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxHTSP.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxHTSP.cpp @@ -284,6 +284,7 @@ void CDVDDemuxHTSP::SubscriptionStart (htsmsg_t *m) CDemuxStreamAudio* a; CDemuxStreamVideo* v; CDemuxStreamSubtitle* s; + CDemuxStreamTeletext* t; } st; CLog::Log(LOGDEBUG, "CDVDDemuxHTSP::SubscriptionStart - id: %d, type: %s", index, type); @@ -320,6 +321,9 @@ void CDVDDemuxHTSP::SubscriptionStart (htsmsg_t *m) } else if(!strcmp(type, "TEXTSUB")) { st.s = new CDemuxStreamSubtitle(); st.s->codec = CODEC_ID_TEXT; + } else if(!strcmp(type, "TELETEXT")) { + st.t = new CDemuxStreamTeletext(); + st.t->codec = CODEC_ID_DVB_TELETEXT; } else { continue; } diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp new file mode 100644 index 0000000..9a57eb1 --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.cpp @@ -0,0 +1,317 @@ +/* + * Copyright (C) 2005-2010 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 "DVDInputStreams/DVDInputStream.h" +#include "DVDDemuxPVRClient.h" +#include "DVDDemuxUtils.h" +#include "utils/log.h" +#include "pvr/PVRManager.h" +#include "pvr/addons/PVRClients.h" + +using namespace PVR; + +void CDemuxStreamVideoPVRClient::GetStreamInfo(std::string& strInfo) +{ + switch (codec) + { + case CODEC_ID_MPEG2VIDEO: + strInfo = "mpeg2video"; + break; + case CODEC_ID_H264: + strInfo = "h264"; + break; + default: + break; + } +} + +void CDemuxStreamAudioPVRClient::GetStreamInfo(std::string& strInfo) +{ + switch (codec) + { + case CODEC_ID_AC3: + strInfo = "ac3"; + break; + case CODEC_ID_EAC3: + strInfo = "eac3"; + break; + case CODEC_ID_MP2: + strInfo = "mpeg2audio"; + break; + case CODEC_ID_AAC: + strInfo = "aac"; + break; + case CODEC_ID_DTS: + strInfo = "dts"; + break; + default: + break; + } +} + +void CDemuxStreamSubtitlePVRClient::GetStreamInfo(std::string& strInfo) +{ +} + +CDVDDemuxPVRClient::CDVDDemuxPVRClient() : CDVDDemux() +{ + m_pInput = NULL; + for (int i = 0; i < MAX_STREAMS; i++) m_streams[i] = NULL; +} + +CDVDDemuxPVRClient::~CDVDDemuxPVRClient() +{ + Dispose(); +} + +bool CDVDDemuxPVRClient::Open(CDVDInputStream* pInput) +{ + Abort(); + m_pInput = pInput; + RequestStreams(); + return true; +} + +void CDVDDemuxPVRClient::Dispose() +{ + for (int i = 0; i < MAX_STREAMS; i++) + { + if (m_streams[i]) + { + if (m_streams[i]->ExtraData) + delete[] (BYTE*)(m_streams[i]->ExtraData); + delete m_streams[i]; + } + m_streams[i] = NULL; + } + m_pInput = NULL; +} + +void CDVDDemuxPVRClient::Reset() +{ + if(m_pInput && g_PVRManager.IsStarted()) + g_PVRClients->DemuxReset(); + + CDVDInputStream* pInputStream = m_pInput; + Dispose(); + Open(pInputStream); +} + +void CDVDDemuxPVRClient::Abort() +{ + if(m_pInput) + g_PVRClients->DemuxAbort(); +} + +void CDVDDemuxPVRClient::Flush() +{ + if(m_pInput && g_PVRManager.IsStarted()) + g_PVRClients->DemuxFlush(); +} + +DemuxPacket* CDVDDemuxPVRClient::Read() +{ + if (!g_PVRManager.IsStarted()) + return CDVDDemuxUtils::AllocateDemuxPacket(0); + + DemuxPacket* pPacket = g_PVRClients->ReadDemuxStream(); + if (!pPacket) + { + if (m_pInput) + m_pInput->Close(); + return NULL; + } + + if (pPacket->iStreamId == DMX_SPECIALID_STREAMINFO) + { + UpdateStreams((PVR_STREAM_PROPERTIES*)pPacket->pData); + CDVDDemuxUtils::FreeDemuxPacket(pPacket); + return CDVDDemuxUtils::AllocateDemuxPacket(0); + } + else if (pPacket->iStreamId == DMX_SPECIALID_STREAMCHANGE) + { + Reset(); + } + + return pPacket; +} + +CDemuxStream* CDVDDemuxPVRClient::GetStream(int iStreamId) +{ + if (iStreamId < 0 || iStreamId >= MAX_STREAMS) return NULL; + return m_streams[iStreamId]; +} + +void CDVDDemuxPVRClient::RequestStreams() +{ + if (!g_PVRManager.IsStarted()) + return; + + PVR_STREAM_PROPERTIES *props = g_PVRClients->GetCurrentStreamProperties(); + + for (unsigned int i = 0; i < props->iStreamCount; ++i) + { + if (props->stream[i].iCodecType == AVMEDIA_TYPE_AUDIO) + { + CDemuxStreamAudioPVRClient* st = new CDemuxStreamAudioPVRClient(this); + st->iChannels = props->stream[i].iChannels; + st->iSampleRate = props->stream[i].iSampleRate; + st->iBlockAlign = props->stream[i].iBlockAlign; + st->iBitRate = props->stream[i].iBitRate; + st->iBitsPerSample = props->stream[i].iBitsPerSample; + m_streams[props->stream[i].iStreamIndex] = st; + } + else if (props->stream[i].iCodecType == AVMEDIA_TYPE_VIDEO) + { + CDemuxStreamVideoPVRClient* st = new CDemuxStreamVideoPVRClient(this); + st->iFpsScale = props->stream[i].iFPSScale; + st->iFpsRate = props->stream[i].iFPSRate; + st->iHeight = props->stream[i].iHeight; + st->iWidth = props->stream[i].iWidth; + st->fAspect = props->stream[i].fAspect; + m_streams[props->stream[i].iStreamIndex] = st; + } + else if (props->stream[i].iCodecId == CODEC_ID_DVB_TELETEXT) + { + m_streams[props->stream[i].iStreamIndex] = new CDemuxStreamTeletext(); + } + else if (props->stream[i].iCodecType == AVMEDIA_TYPE_SUBTITLE) + { + CDemuxStreamSubtitlePVRClient* st = new CDemuxStreamSubtitlePVRClient(this); + st->identifier = props->stream[i].iIdentifier; + m_streams[props->stream[i].iStreamIndex] = st; + } + else + m_streams[props->stream[i].iStreamIndex] = new CDemuxStream(); + + m_streams[props->stream[i].iStreamIndex]->codec = (CodecID)props->stream[i].iCodecId; + m_streams[props->stream[i].iStreamIndex]->iId = props->stream[i].iStreamIndex; + m_streams[props->stream[i].iStreamIndex]->iPhysicalId = props->stream[i].iPhysicalId; + m_streams[props->stream[i].iStreamIndex]->language[0] = props->stream[i].strLanguage[0]; + m_streams[props->stream[i].iStreamIndex]->language[1] = props->stream[i].strLanguage[1]; + m_streams[props->stream[i].iStreamIndex]->language[2] = props->stream[i].strLanguage[2]; + m_streams[props->stream[i].iStreamIndex]->language[3] = props->stream[i].strLanguage[3]; + + CLog::Log(LOGDEBUG,"CDVDDemuxPVRClient::RequestStreams(): added stream %d:%d with codec_id %d", + m_streams[props->stream[i].iStreamIndex]->iId, + m_streams[props->stream[i].iStreamIndex]->iPhysicalId, + m_streams[props->stream[i].iStreamIndex]->codec); + } +} + +void CDVDDemuxPVRClient::UpdateStreams(PVR_STREAM_PROPERTIES *props) +{ + bool bGotVideoStream(false); + + for (unsigned int i = 0; i < props->iStreamCount; ++i) + { + if (m_streams[props->stream[i].iStreamIndex] == NULL || + m_streams[props->stream[i].iStreamIndex]->codec != (CodecID)props->stream[i].iCodecId) + { + CLog::Log(LOGERROR,"Invalid stream inside UpdateStreams"); + continue; + } + + if (m_streams[props->stream[i].iStreamIndex]->type == STREAM_AUDIO) + { + CDemuxStreamAudioPVRClient* st = (CDemuxStreamAudioPVRClient*) m_streams[props->stream[i].iStreamIndex]; + st->iChannels = props->stream[i].iChannels; + st->iSampleRate = props->stream[i].iSampleRate; + st->iBlockAlign = props->stream[i].iBlockAlign; + st->iBitRate = props->stream[i].iBitRate; + st->iBitsPerSample = props->stream[i].iBitsPerSample; + } + else if (m_streams[props->stream[i].iStreamIndex]->type == STREAM_VIDEO) + { + if (bGotVideoStream) + { + CLog::Log(LOGDEBUG, "CDVDDemuxPVRClient - %s - skip video stream", __FUNCTION__); + continue; + } + + CDemuxStreamVideoPVRClient* st = (CDemuxStreamVideoPVRClient*) m_streams[props->stream[i].iStreamIndex]; + if (st->iWidth <= 0 || st->iHeight <= 0) + { + CLog::Log(LOGWARNING, "CDVDDemuxPVRClient - %s - invalid stream data", __FUNCTION__); + continue; + } + + st->iFpsScale = props->stream[i].iFPSScale; + st->iFpsRate = props->stream[i].iFPSRate; + st->iHeight = props->stream[i].iHeight; + st->iWidth = props->stream[i].iWidth; + st->fAspect = props->stream[i].fAspect; + bGotVideoStream = true; + } + else if (m_streams[props->stream[i].iStreamIndex]->type == STREAM_SUBTITLE) + { + CDemuxStreamSubtitlePVRClient* st = (CDemuxStreamSubtitlePVRClient*) m_streams[props->stream[i].iStreamIndex]; + st->identifier = props->stream[i].iIdentifier; + } + + m_streams[props->stream[i].iStreamIndex]->language[0] = props->stream[i].strLanguage[0]; + m_streams[props->stream[i].iStreamIndex]->language[1] = props->stream[i].strLanguage[1]; + m_streams[props->stream[i].iStreamIndex]->language[2] = props->stream[i].strLanguage[2]; + m_streams[props->stream[i].iStreamIndex]->language[3] = props->stream[i].strLanguage[3]; + + CLog::Log(LOGDEBUG,"CDVDDemuxPVRClient::UpdateStreams(): update stream %d:%d with codec_id %d", + m_streams[props->stream[i].iStreamIndex]->iId, + m_streams[props->stream[i].iStreamIndex]->iPhysicalId, + m_streams[props->stream[i].iStreamIndex]->codec); + } +} + +int CDVDDemuxPVRClient::GetNrOfStreams() +{ + int i = 0; + while (i < MAX_STREAMS && m_streams[i]) i++; + return i; +} + +std::string CDVDDemuxPVRClient::GetFileName() +{ + if(m_pInput) + return m_pInput->GetFileName(); + else + return ""; +} + +void CDVDDemuxPVRClient::GetStreamCodecName(int iStreamId, CStdString &strName) +{ + CDemuxStream *stream = GetStream(iStreamId); + if (stream) + { + if (stream->codec == CODEC_ID_AC3) + strName = "ac3"; + else if (stream->codec == CODEC_ID_MP2) + strName = "mp2"; + else if (stream->codec == CODEC_ID_AAC) + strName = "aac"; + else if (stream->codec == CODEC_ID_DTS) + strName = "dca"; + else if (stream->codec == CODEC_ID_MPEG2VIDEO) + strName = "mpeg2video"; + else if (stream->codec == CODEC_ID_H264) + strName = "h264"; + else if (stream->codec == CODEC_ID_EAC3) + strName = "eac3"; + } +} diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.h new file mode 100644 index 0000000..ec0fbd5 --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPVRClient.h @@ -0,0 +1,108 @@ +#pragma once +/* + * Copyright (C) 2005-2010 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 "DVDDemux.h" +#include + +#ifndef _LINUX +#include +#else +extern "C" { +#if (defined USE_EXTERNAL_FFMPEG) + #if (defined HAVE_LIBAVFORMAT_AVFORMAT_H) + #include + #elif (defined HAVE_FFMPEG_AVFORMAT_H) + #include + #endif +#else + #include "libavformat/avformat.h" +#endif +} +#endif + +class CDVDDemuxPVRClient; +struct PVR_STREAM_PROPERTIES; + +class CDemuxStreamVideoPVRClient : public CDemuxStreamVideo +{ + CDVDDemuxPVRClient *m_parent; +public: + CDemuxStreamVideoPVRClient(CDVDDemuxPVRClient *parent) + : m_parent(parent) + {} + virtual void GetStreamInfo(std::string& strInfo); +}; + +class CDemuxStreamAudioPVRClient : public CDemuxStreamAudio +{ + CDVDDemuxPVRClient *m_parent; +public: + CDemuxStreamAudioPVRClient(CDVDDemuxPVRClient *parent) + : m_parent(parent) + {} + virtual void GetStreamInfo(std::string& strInfo); +}; + +class CDemuxStreamSubtitlePVRClient : public CDemuxStreamSubtitle +{ + CDVDDemuxPVRClient *m_parent; +public: + CDemuxStreamSubtitlePVRClient(CDVDDemuxPVRClient *parent) + : m_parent(parent) + {} + virtual void GetStreamInfo(std::string& strInfo); +}; + + +class CDVDDemuxPVRClient : public CDVDDemux +{ +public: + + CDVDDemuxPVRClient(); + ~CDVDDemuxPVRClient(); + + bool Open(CDVDInputStream* pInput); + void Dispose(); + void Reset(); + void Abort(); + void Flush(); + DemuxPacket* Read(); + bool SeekTime(int time, bool backwords = false, double* startpts = NULL) { return false; } + void SetSpeed(int iSpeed) {}; + int GetStreamLength() { return 0; } + CDemuxStream* GetStream(int iStreamId); + int GetNrOfStreams(); + std::string GetFileName(); + virtual void GetStreamCodecName(int iStreamId, CStdString &strName); + +protected: + CDVDInputStream* m_pInput; +#ifndef MAX_STREAMS + #define MAX_STREAMS 100 +#endif + CDemuxStream* m_streams[MAX_STREAMS]; // maximum number of streams that ffmpeg can handle + +private: + void RequestStreams(); + void UpdateStreams(PVR_STREAM_PROPERTIES *props); +}; + diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h new file mode 100644 index 0000000..beadfcd --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxPacket.h @@ -0,0 +1,37 @@ +#pragma once + +/* + * Copyright (C) 2005-2010 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 + * + */ + +#define DMX_SPECIALID_STREAMINFO -10 +#define DMX_SPECIALID_STREAMCHANGE -11 + + typedef struct DemuxPacket +{ + unsigned char* pData; // data + int iSize; // data size + int iStreamId; // integer representing the stream index + int iGroupId; // the group this data belongs to, used to group data from different streams together + + double pts; // pts in DVD_TIME_BASE + double dts; // dts in DVD_TIME_BASE + double duration; // duration in DVD_TIME_BASE if available +} DemuxPacket; diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.h b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.h index e7d5f41..5d28810 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.h +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDDemuxUtils.h @@ -21,7 +21,7 @@ * */ -#include "DVDDemux.h" +#include "DVDDemuxPacket.h" class CDVDDemuxUtils { diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp index 7021661..c2ff089 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp +++ b/xbmc/cores/dvdplayer/DVDDemuxers/DVDFactoryDemuxer.cpp @@ -24,14 +24,18 @@ #include "DVDInputStreams/DVDInputStream.h" #include "DVDInputStreams/DVDInputStreamHttp.h" +#include "DVDInputStreams/DVDInputStreamPVRManager.h" #include "DVDDemuxFFmpeg.h" #include "DVDDemuxShoutcast.h" #ifdef HAS_FILESYSTEM_HTSP #include "DVDDemuxHTSP.h" #endif +#include "DVDDemuxPVRClient.h" +#include "pvr/PVRManager.h" using namespace std; +using namespace PVR; CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) { @@ -62,6 +66,38 @@ CDVDDemux* CDVDFactoryDemuxer::CreateDemuxer(CDVDInputStream* pInputStream) } #endif + if (pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) + { + CDVDInputStreamPVRManager* pInputStreamPVR = (CDVDInputStreamPVRManager*)pInputStream; + CDVDInputStream* pOtherStream = pInputStreamPVR->GetOtherStream(); + if(pOtherStream) + { + /* Used for MediaPortal PVR addon (uses PVR otherstream for playback of rtsp streams) */ + if (pOtherStream->IsStreamType(DVDSTREAM_TYPE_FFMPEG)) + { + auto_ptr demuxer(new CDVDDemuxFFmpeg()); + if(demuxer->Open(pOtherStream)) + return demuxer.release(); + else + return NULL; + } + } + + std::string filename = pInputStream->GetFileName(); + /* Use PVR demuxer only for live streams */ + if (filename.substr(0, 14) == "pvr://channels") + { + if (g_PVRManager.GetCurrentAddonCapabilities().bHandlesDemuxing) + { + auto_ptr demuxer(new CDVDDemuxPVRClient()); + if(demuxer->Open(pInputStream)) + return demuxer.release(); + else + return NULL; + } + } + } + auto_ptr demuxer(new CDVDDemuxFFmpeg()); if(demuxer->Open(pInputStream)) return demuxer.release(); diff --git a/xbmc/cores/dvdplayer/DVDDemuxers/Makefile.in b/xbmc/cores/dvdplayer/DVDDemuxers/Makefile.in index dc6f959..be2e392 100644 --- a/xbmc/cores/dvdplayer/DVDDemuxers/Makefile.in +++ b/xbmc/cores/dvdplayer/DVDDemuxers/Makefile.in @@ -3,6 +3,7 @@ INCLUDES+=-I@abs_top_srcdir@/xbmc/cores/dvdplayer SRCS= DVDDemux.cpp \ DVDDemuxFFmpeg.cpp \ DVDDemuxHTSP.cpp \ + DVDDemuxPVRClient.cpp \ DVDDemuxShoutcast.cpp \ DVDDemuxUtils.cpp \ DVDDemuxVobsub.cpp \ diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp index e4e7065..151daeb 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDFactoryInputStream.cpp @@ -26,6 +26,7 @@ #include "DVDInputStreamNavigator.h" #include "DVDInputStreamHttp.h" #include "DVDInputStreamFFmpeg.h" +#include "DVDInputStreamPVRManager.h" #include "DVDInputStreamTV.h" #include "DVDInputStreamRTMP.h" #ifdef HAVE_LIBBLURAY @@ -52,6 +53,8 @@ CDVDInputStream* CDVDFactoryInputStream::CreateInputStream(IDVDPlayer* pPlayer, { return (new CDVDInputStreamNavigator(pPlayer)); } + else if(file.substr(0, 6) == "pvr://") + return new CDVDInputStreamPVRManager(pPlayer); #ifdef HAVE_LIBBLURAY else if (item.IsType(".bdmv") || item.IsType(".mpls") || content == "bluray/iso") return new CDVDInputStreamBluray(); diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStream.h b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStream.h index 5cd64ea..d07fc22 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStream.h +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStream.h @@ -39,6 +39,7 @@ enum DVDStreamType DVDSTREAM_TYPE_HTSP = 8, DVDSTREAM_TYPE_MPLS = 10, DVDSTREAM_TYPE_BLURAY = 11, + DVDSTREAM_TYPE_PVRMANAGER = 12, }; #define SEEK_POSSIBLE 0x10 // flag used to check if protocol allows seeks @@ -53,10 +54,17 @@ public: { public: virtual ~IChannel() {}; - virtual bool NextChannel() = 0; - virtual bool PrevChannel() = 0; - virtual bool SelectChannel(unsigned int channel) = 0; + virtual bool NextChannel(bool preview = false) = 0; + virtual bool PrevChannel(bool preview = false) = 0; + virtual bool SelectChannelByNumber(unsigned int channel) = 0; + virtual bool SelectChannel(const PVR::CPVRChannel &channel) { return false; }; + virtual bool GetSelectedChannel(PVR::CPVRChannel *) { return false; }; + virtual int GetTotalTime() = 0; + virtual int GetStartTime() = 0; virtual bool UpdateItem(CFileItem& item) = 0; + virtual bool CanRecord() = 0; + virtual bool IsRecording() = 0; + virtual bool Record(bool bOnOff) = 0; }; class IDisplayTime diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.cpp index 80d2abe..5ae7737 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.cpp @@ -195,7 +195,7 @@ bool CDVDInputStreamHTSP::GetChannels(SChannelV &channels, SChannelV::iterator & return false; } -bool CDVDInputStreamHTSP::NextChannel() +bool CDVDInputStreamHTSP::NextChannel(bool preview/* = false*/) { SChannelV channels; SChannelV::iterator it; @@ -209,7 +209,7 @@ bool CDVDInputStreamHTSP::NextChannel() return SetChannel(circ->id); } -bool CDVDInputStreamHTSP::PrevChannel() +bool CDVDInputStreamHTSP::PrevChannel(bool preview/* = false*/) { SChannelV channels; SChannelV::iterator it; @@ -223,7 +223,7 @@ bool CDVDInputStreamHTSP::PrevChannel() return SetChannel(circ->id); } -bool CDVDInputStreamHTSP::SelectChannel(unsigned int channel) +bool CDVDInputStreamHTSP::SelectChannelByNumber(unsigned int channel) { return SetChannel(channel); } @@ -256,6 +256,33 @@ int CDVDInputStreamHTSP::GetTotalTime() { if(m_event.id == 0) return 0; + + long duration = (time_t)m_event.stop - (time_t)m_event.start; + CDateTimeSpan time = CDateTimeSpan(0, 0, duration / 60, duration % 60); + + return time.GetDays() * 1000 * 60 * 60 * 24 + + time.GetHours() * 1000 * 60 * 60 + + time.GetMinutes() * 1000 * 60 + + time.GetSeconds() * 1000; +} + +int CDVDInputStreamHTSP::GetStartTime() +{ + if(m_event.id == 0) + return 0; + + time_t time_c; + + CDateTime::GetCurrentDateTime().GetAsTime(time_c); + + return (m_event.start - time_c) * 1000; +} + +/* +int CDVDInputStreamHTSP::GetTotalTime() +{ + if(m_event.id == 0) + return 0; return (m_event.stop - m_event.start) * 1000; } @@ -270,6 +297,7 @@ int CDVDInputStreamHTSP::GetTime() + time.GetMinutes() * 1000 * 60 + time.GetSeconds() * 1000; } +*/ void CDVDInputStreamHTSP::Abort() { diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.h b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.h index 287c8ac..83012e7 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.h +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamHTSP.h @@ -26,7 +26,6 @@ class CDVDInputStreamHTSP : public CDVDInputStream , public CDVDInputStream::IChannel - , public CDVDInputStream::IDisplayTime { public: CDVDInputStreamHTSP(); @@ -43,13 +42,19 @@ public: virtual void Abort(); - bool NextChannel(); - bool PrevChannel(); - bool SelectChannel(unsigned int channel); + bool NextChannel(bool preview = false); + bool PrevChannel(bool preview = false); + bool SelectChannelByNumber(unsigned int channel); + bool SelectChannel(const PVR::CPVRChannel &channel) { return false; } + bool GetSelectedChannel(PVR::CPVRChannel *channel) {return false; } bool UpdateItem(CFileItem& item); + bool CanRecord() { return false; } + bool IsRecording() { return false; } + bool Record(bool bOnOff) { return false; } + int GetTotalTime(); - int GetTime(); + int GetStartTime(); htsmsg_t* ReadStream(); diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamPVRManager.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamPVRManager.cpp new file mode 100644 index 0000000..a1d61ad --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamPVRManager.cpp @@ -0,0 +1,294 @@ +/* + * Copyright (C) 2005-2009 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 "DVDFactoryInputStream.h" +#include "DVDInputStreamPVRManager.h" +#include "filesystem/PVRFile.h" +#include "URL.h" +#include "pvr/PVRManager.h" +#include "pvr/channels/PVRChannel.h" +#include "utils/log.h" +#include "utils/StringUtils.h" +#include "pvr/addons/PVRClients.h" + +using namespace XFILE; +using namespace PVR; + +/************************************************************************ + * Description: Class constructor, initialize member variables + * public class is CDVDInputStream + */ +CDVDInputStreamPVRManager::CDVDInputStreamPVRManager(IDVDPlayer* pPlayer) : CDVDInputStream(DVDSTREAM_TYPE_PVRMANAGER) +{ + m_pPlayer = pPlayer; + m_pFile = NULL; + m_pRecordable = NULL; + m_pLiveTV = NULL; + m_pOtherStream = NULL; + m_eof = true; +} + +/************************************************************************ + * Description: Class destructor + */ +CDVDInputStreamPVRManager::~CDVDInputStreamPVRManager() +{ + Close(); +} + +bool CDVDInputStreamPVRManager::IsEOF() +{ + if (m_pOtherStream) + return m_pOtherStream->IsEOF(); + else + return !m_pFile || m_eof; +} + +bool CDVDInputStreamPVRManager::Open(const char* strFile, const std::string& content) +{ + /* Open PVR File for both cases, to have access to ILiveTVInterface and + * IRecordable + */ + m_pFile = new CPVRFile(); + m_pLiveTV = ((CPVRFile*)m_pFile)->GetLiveTV(); + m_pRecordable = ((CPVRFile*)m_pFile)->GetRecordable(); + + CURL url(strFile); + if (!CDVDInputStream::Open(strFile, content)) return false; + if (!m_pFile->Open(url)) + { + delete m_pFile; + m_pFile = NULL; + return false; + } + m_eof = false; + + /* + * Translate the "pvr://....." entry. + * The PVR Client can use http or whatever else is supported by DVDPlayer. + * to access streams. + * If after translation the file protocol is still "pvr://" use this class + * to read the stream data over the CPVRFile class and the PVR Library itself. + * Otherwise call CreateInputStream again with the translated filename and looks again + * for the right protocol stream handler and swap every call to this input stream + * handler. + */ + std::string transFile = XFILE::CPVRFile::TranslatePVRFilename(strFile); + if(transFile.substr(0, 6) != "pvr://") + { + m_pOtherStream = CDVDFactoryInputStream::CreateInputStream(m_pPlayer, transFile, content); + if (!m_pOtherStream) + { + CLog::Log(LOGERROR, "CDVDInputStreamPVRManager::Open - unable to create input stream for [%s]", transFile.c_str()); + return false; + } + else + m_pOtherStream->SetFileItem(m_item); + + if (!m_pOtherStream->Open(transFile.c_str(), content)) + { + CLog::Log(LOGERROR, "CDVDInputStreamPVRManager::Open - error opening [%s]", transFile.c_str()); + delete m_pFile; + m_pFile = NULL; + delete m_pOtherStream; + m_pOtherStream = NULL; + return false; + } + } + + return true; +} + +// close file and reset everyting +void CDVDInputStreamPVRManager::Close() +{ + if (m_pOtherStream) + { + m_pOtherStream->Close(); + delete m_pOtherStream; + } + + if (m_pFile) + { + m_pFile->Close(); + delete m_pFile; + } + + CDVDInputStream::Close(); + + m_pPlayer = NULL; + m_pFile = NULL; + m_pLiveTV = NULL; + m_pRecordable = NULL; + m_pOtherStream = NULL; + m_eof = true; +} + +int CDVDInputStreamPVRManager::Read(BYTE* buf, int buf_size) +{ + if(!m_pFile) return -1; + + if (m_pOtherStream) + { + return m_pOtherStream->Read(buf, buf_size); + } + else + { + unsigned int ret = m_pFile->Read(buf, buf_size); + + /* we currently don't support non completing reads */ + if( ret <= 0 ) m_eof = true; + + return (int)(ret & 0xFFFFFFFF); + } +} + +__int64 CDVDInputStreamPVRManager::Seek(__int64 offset, int whence) +{ + if (!m_pFile) + return -1; + + if (whence == SEEK_POSSIBLE) + return m_pFile->IoControl(IOCTRL_SEEK_POSSIBLE, NULL); + + if (m_pOtherStream) + { + return m_pOtherStream->Seek(offset, whence); + } + else + { + __int64 ret = m_pFile->Seek(offset, whence); + + /* if we succeed, we are not eof anymore */ + if( ret >= 0 ) m_eof = false; + + return ret; + } +} + +__int64 CDVDInputStreamPVRManager::GetLength() +{ + if(!m_pFile) return -1; + + if (m_pOtherStream) + return m_pOtherStream->GetLength(); + else + return m_pFile->GetLength(); +} + +int CDVDInputStreamPVRManager::GetTotalTime() +{ + if (m_pLiveTV) + return m_pLiveTV->GetTotalTime(); + return 0; +} + +int CDVDInputStreamPVRManager::GetStartTime() +{ + if (m_pLiveTV) + return m_pLiveTV->GetStartTime(); + return 0; +} + +bool CDVDInputStreamPVRManager::NextChannel(bool preview/* = false*/) +{ + if (m_pLiveTV) + return m_pLiveTV->NextChannel(preview); + return false; +} + +bool CDVDInputStreamPVRManager::PrevChannel(bool preview/* = false*/) +{ + if (m_pLiveTV) + return m_pLiveTV->PrevChannel(preview); + return false; +} + +bool CDVDInputStreamPVRManager::SelectChannelByNumber(unsigned int channel) +{ + if (m_pLiveTV) + return m_pLiveTV->SelectChannel(channel); + return false; +} + +bool CDVDInputStreamPVRManager::SelectChannel(const CPVRChannel &channel) +{ + if (m_pLiveTV) + return m_pLiveTV->SelectChannel(channel.ChannelNumber()); + return false; +} + +bool CDVDInputStreamPVRManager::GetSelectedChannel(CPVRChannel &channel) const +{ + return g_PVRManager.GetCurrentChannel(channel); +} + +bool CDVDInputStreamPVRManager::UpdateItem(CFileItem& item) +{ + if (m_pLiveTV) + return m_pLiveTV->UpdateItem(item); + return false; +} + +bool CDVDInputStreamPVRManager::NextStream() +{ + if(!m_pFile) return false; + + if (m_pOtherStream) + return m_pOtherStream->NextStream(); + else + { + if(m_pFile->SkipNext()) + { + m_eof = false; + return true; + } + } + return false; +} + +bool CDVDInputStreamPVRManager::CanRecord() +{ + if (m_pRecordable) + return m_pRecordable->CanRecord(); + return false; +} + +bool CDVDInputStreamPVRManager::IsRecording() +{ + if (m_pRecordable) + return m_pRecordable->IsRecording(); + return false; +} + +bool CDVDInputStreamPVRManager::Record(bool bOnOff) +{ + if (m_pRecordable) + return m_pRecordable->Record(bOnOff); + return false; +} + +CStdString CDVDInputStreamPVRManager::GetInputFormat() +{ + if (!m_pOtherStream && g_PVRManager.IsStarted()) + return g_PVRClients->GetCurrentInputFormat(); + return StringUtils::EmptyString; +} diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamPVRManager.h b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamPVRManager.h new file mode 100644 index 0000000..6a3688e --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamPVRManager.h @@ -0,0 +1,107 @@ +#pragma once + +/* + * 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 + * + */ + +/* +* for DESCRIPTION see 'DVDInputStreamPVRManager.cpp' +*/ + +#include "DVDInputStream.h" +#include "FileItem.h" + +namespace XFILE { +class IFile; +class ILiveTVInterface; +class IRecordable; +} + +class IDVDPlayer; + +class CDVDInputStreamPVRManager + : public CDVDInputStream + , public CDVDInputStream::IChannel +{ +public: + CDVDInputStreamPVRManager(IDVDPlayer* pPlayer); + virtual ~CDVDInputStreamPVRManager(); + virtual bool Open(const char* strFile, const std::string &content); + virtual void Close(); + virtual int Read(BYTE* buf, int buf_size); + virtual __int64 Seek(__int64 offset, int whence); + virtual bool Pause(double dTime) { return false; } + virtual bool IsEOF(); + virtual __int64 GetLength(); + + virtual bool NextStream(); + + bool SelectChannelByNumber(unsigned int iChannel); + bool SelectChannel(const PVR::CPVRChannel &channel); + bool NextChannel(bool preview = false); + bool PrevChannel(bool preview = false); + bool GetSelectedChannel(PVR::CPVRChannel &channel) const; + + int GetTotalTime(); + int GetStartTime(); + + bool CanRecord(); + bool IsRecording(); + bool Record(bool bOnOff); + + bool UpdateItem(CFileItem& item); + + /* overloaded is streamtype to support m_pOtherStream */ + bool IsStreamType(DVDStreamType type) const; + + /*! \brief Get the input format from the Backend + If it is empty ffmpeg scanning the stream to find the right input format. + See "xbmc/cores/dvdplayer/Codecs/ffmpeg/libavformat/allformats.c" for a + list of the input formats. + \return The name of the input format + */ + CStdString GetInputFormat(); + + /* returns m_pOtherStream */ + CDVDInputStream* GetOtherStream(); + +protected: + IDVDPlayer* m_pPlayer; + CDVDInputStream* m_pOtherStream; + XFILE::IFile* m_pFile; + XFILE::ILiveTVInterface* m_pLiveTV; + XFILE::IRecordable* m_pRecordable; + bool m_eof; +}; + + +inline bool CDVDInputStreamPVRManager::IsStreamType(DVDStreamType type) const +{ + if (m_pOtherStream) + return m_pOtherStream->IsStreamType(type); + + return m_streamType == type; +} + +inline CDVDInputStream* CDVDInputStreamPVRManager::GetOtherStream() +{ + return m_pOtherStream; +}; + diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamTV.cpp b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamTV.cpp index 5ed50a9..606e78b 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamTV.cpp +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamTV.cpp @@ -21,8 +21,9 @@ #include "DVDInputStreamTV.h" #include "filesystem/MythFile.h" -#include "filesystem/VTPFile.h" #include "filesystem/Slingbox.h" +#include "filesystem/VTPFile.h" +#include "pvr/channels/PVRChannel.h" #include "URL.h" using namespace XFILE; @@ -137,19 +138,19 @@ int CDVDInputStreamTV::GetStartTime() return m_pLiveTV->GetStartTime(); } -bool CDVDInputStreamTV::NextChannel() +bool CDVDInputStreamTV::NextChannel(bool preview/* = false*/) { if(!m_pLiveTV) return false; return m_pLiveTV->NextChannel(); } -bool CDVDInputStreamTV::PrevChannel() +bool CDVDInputStreamTV::PrevChannel(bool preview/* = false*/) { if(!m_pLiveTV) return false; return m_pLiveTV->PrevChannel(); } -bool CDVDInputStreamTV::SelectChannel(unsigned int channel) +bool CDVDInputStreamTV::SelectChannelByNumber(unsigned int channel) { if(!m_pLiveTV) return false; return m_pLiveTV->SelectChannel(channel); diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamTV.h b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamTV.h index f19244a..f2db586 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamTV.h +++ b/xbmc/cores/dvdplayer/DVDInputStreams/DVDInputStreamTV.h @@ -47,10 +47,9 @@ public: virtual bool NextStream(); virtual int GetBlockSize(); - - bool NextChannel(); - bool PrevChannel(); - bool SelectChannel(unsigned int channel); + bool NextChannel(bool preview = false); + bool PrevChannel(bool preview = false); + bool SelectChannelByNumber(unsigned int channel); int GetTotalTime(); int GetStartTime(); diff --git a/xbmc/cores/dvdplayer/DVDInputStreams/Makefile b/xbmc/cores/dvdplayer/DVDInputStreams/Makefile index b522e05..4607ed3 100644 --- a/xbmc/cores/dvdplayer/DVDInputStreams/Makefile +++ b/xbmc/cores/dvdplayer/DVDInputStreams/Makefile @@ -11,6 +11,7 @@ SRCS= DVDFactoryInputStream.cpp \ DVDInputStreamMemory.cpp \ DVDInputStreamNavigator.cpp \ DVDInputStreamRTMP.cpp \ + DVDInputStreamPVRManager.cpp \ DVDInputStreamStack.cpp \ DVDInputStreamTV.cpp \ DVDStateSerializer.cpp \ diff --git a/xbmc/cores/dvdplayer/DVDMessage.h b/xbmc/cores/dvdplayer/DVDMessage.h index 706e09e..bd54732 100644 --- a/xbmc/cores/dvdplayer/DVDMessage.h +++ b/xbmc/cores/dvdplayer/DVDMessage.h @@ -70,7 +70,8 @@ public: PLAYER_CHANNEL_NEXT, // switches to next playback channel PLAYER_CHANNEL_PREV, // switches to previous playback channel - PLAYER_CHANNEL_SELECT, // switches to given playback channel + PLAYER_CHANNEL_SELECT_NUMBER, // switches to the channel with the provided channel number + PLAYER_CHANNEL_SELECT, // switches to the provided channel PLAYER_STARTED, // sent whenever a sub player has finished it's first frame after open // demuxer related messages diff --git a/xbmc/cores/dvdplayer/DVDPlayer.cpp b/xbmc/cores/dvdplayer/DVDPlayer.cpp index b9b271e..65cf071 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.cpp +++ b/xbmc/cores/dvdplayer/DVDPlayer.cpp @@ -28,6 +28,7 @@ #include "DVDInputStreams/DVDFactoryInputStream.h" #include "DVDInputStreams/DVDInputStreamNavigator.h" #include "DVDInputStreams/DVDInputStreamTV.h" +#include "DVDInputStreams/DVDInputStreamPVRManager.h" #include "DVDDemuxers/DVDDemux.h" #include "DVDDemuxers/DVDDemuxUtils.h" @@ -67,6 +68,11 @@ #include "utils/log.h" #include "utils/TimeUtils.h" #include "utils/StreamDetails.h" +#include "pvr/PVRManager.h" +#include "pvr/channels/PVRChannel.h" +#include "pvr/windows/GUIWindowPVR.h" +#include "filesystem/PVRFile.h" +#include "video/dialogs/GUIDialogFullScreenInfo.h" #include "utils/StreamUtils.h" #include "utils/Variant.h" #include "storage/MediaManager.h" @@ -76,6 +82,7 @@ #include "Util.h" using namespace std; +using namespace PVR; void CSelectionStreams::Clear(StreamType type, StreamSource source) { @@ -354,6 +361,7 @@ bool CDVDPlayer::OpenFile(const CFileItem& file, const CPlayerOptions &options) m_item = file; m_mimetype = file.GetMimeType(); m_filename = file.GetPath(); + m_scanStart = 0; m_ready.Reset(); @@ -482,6 +490,7 @@ retry: // find any available external subtitles for non dvd files if (!m_pInputStream->IsStreamType(DVDSTREAM_TYPE_DVD) + && !m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER) && !m_pInputStream->IsStreamType(DVDSTREAM_TYPE_TV) && !m_pInputStream->IsStreamType(DVDSTREAM_TYPE_HTSP)) { @@ -520,6 +529,7 @@ retry: m_clock.Reset(); m_dvd.Clear(); m_errorCount = 0; + m_iChannelEntryTimeOut = 0; return true; } @@ -533,11 +543,15 @@ bool CDVDPlayer::OpenDemuxStream() try { - int attempts = 10; + int attempts = m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER) ? 1000 : 10; while(!m_bStop && attempts-- > 0) { m_pDemuxer = CDVDFactoryDemuxer::CreateDemuxer(m_pInputStream); - if(!m_pDemuxer && m_pInputStream->NextStream()) + if(!m_pDemuxer && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) + { + continue; + } + else if(!m_pDemuxer && m_pInputStream->NextStream()) { CLog::Log(LOGDEBUG, "%s - New stream available from input, retry open", __FUNCTION__); continue; @@ -736,7 +750,6 @@ void CDVDPlayer::OpenDefaultStreams() m_dvdPlayerVideo.EnableSubtitle(true); else m_dvdPlayerVideo.EnableSubtitle(false); - // open teletext data stream count = m_SelectionStreams.Count(STREAM_TELETEXT); valid = false; @@ -761,6 +774,15 @@ bool CDVDPlayer::ReadPacket(DemuxPacket*& packet, CDemuxStream*& stream) if(packet) { + if(packet->iStreamId == DMX_SPECIALID_STREAMCHANGE) + { + // reset the caching state for pvr streams + if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) + SetCaching(CACHESTATE_PVR); + CDVDDemuxUtils::FreeDemuxPacket(packet); + return true; + } + if(packet->iStreamId < 0) return true; @@ -877,6 +899,30 @@ bool CDVDPlayer::IsBetterStream(CCurrentStream& current, CDemuxStream* stream) if(current.type == STREAM_VIDEO && current.id < 0) return true; } + else if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) + { + if(stream->source == current.source && + stream->iId == current.id) + return false; + + if(stream->disabled) + return false; + + if(stream->type != current.type) + return false; + + if(current.type == STREAM_AUDIO && stream->iPhysicalId == m_dvd.iSelectedAudioStream) + return true; + + if(current.type == STREAM_SUBTITLE && stream->iPhysicalId == m_dvd.iSelectedSPUStream) + return true; + + if(current.type == STREAM_TELETEXT) + return true; + + if(current.id < 0) + return true; + } else { if(stream->source == current.source @@ -1000,6 +1046,10 @@ void CDVDPlayer::Process() } } + // make sure all selected stream have data on startup + if (CachePVRStream()) + SetCaching(CACHESTATE_PVR); + // make sure application know our info UpdateApplication(0); UpdatePlayState(0); @@ -1010,7 +1060,8 @@ void CDVDPlayer::Process() // we are done initializing now, set the readyevent m_ready.Set(); - SetCaching(CACHESTATE_FLUSH); + if (!CachePVRStream()) + SetCaching(CACHESTATE_FLUSH); while (!m_bAbortRequest) { @@ -1046,6 +1097,10 @@ void CDVDPlayer::Process() } OpenDefaultStreams(); + + if (CachePVRStream()) + SetCaching(CACHESTATE_PVR); + UpdateApplication(0); UpdatePlayState(0); } @@ -1059,9 +1114,12 @@ void CDVDPlayer::Process() // update application with our state UpdateApplication(1000); + if (CheckDelayedChannelEntry()) + continue; + // if the queues are full, no need to read more - if ((!m_dvdPlayerAudio.AcceptsData() && m_CurrentAudio.id >= 0) - || (!m_dvdPlayerVideo.AcceptsData() && m_CurrentVideo.id >= 0)) + if ((!m_dvdPlayerAudio.AcceptsData() && m_CurrentAudio.id >= 0) || + (!m_dvdPlayerVideo.AcceptsData() && m_CurrentVideo.id >= 0)) { Sleep(10); continue; @@ -1132,6 +1190,23 @@ void CDVDPlayer::Process() Sleep(100); continue; } + else if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) + { + CDVDInputStreamPVRManager* pStream = static_cast(m_pInputStream); + unsigned int iTimeout = (unsigned int) g_guiSettings.GetInt("pvrplayback.scantime"); + if (m_scanStart && XbmcThreads::SystemClockMillis() - m_scanStart >= iTimeout*1000) + { + CLog::Log(LOGERROR,"CDVDPlayer - %s - no video or audio data available after %i seconds, playback stopped", + __FUNCTION__, iTimeout); + break; + } + + if (pStream->IsEOF()) + break; + + Sleep(100); + continue; + } // make sure we tell all players to finish it's data if(m_CurrentAudio.inited) @@ -1191,6 +1266,23 @@ void CDVDPlayer::Process() } } +bool CDVDPlayer::CheckDelayedChannelEntry(void) +{ + bool bReturn(false); + + if (m_iChannelEntryTimeOut > 0 && XbmcThreads::SystemClockMillis() >= m_iChannelEntryTimeOut) + { + CFileItem currentFile(g_application.CurrentFileItem()); + CPVRChannel *currentChannel = currentFile.GetPVRChannelInfoTag(); + SwitchChannel(*currentChannel); + + bReturn = true; + m_iChannelEntryTimeOut = 0; + } + + return bReturn; +} + void CDVDPlayer::ProcessPacket(CDemuxStream* pStream, DemuxPacket* pPacket) { /* process packet if it belongs to selected stream. for dvd's don't allow automatic opening of streams*/ @@ -1436,6 +1528,42 @@ void CDVDPlayer::HandlePlaySpeed() } } + if (caching == CACHESTATE_PVR) + { + bool bGotAudio(m_pDemuxer->GetNrOfAudioStreams() > 0); + bool bGotVideo(m_pDemuxer->GetNrOfVideoStreams() > 0); + bool bAudioLevelOk(m_dvdPlayerAudio.m_messageQueue.GetLevel() > g_advancedSettings.m_iPVRMinAudioCacheLevel); + bool bVideoLevelOk(m_dvdPlayerVideo.m_messageQueue.GetLevel() > g_advancedSettings.m_iPVRMinVideoCacheLevel); + bool bAudioFull(!m_dvdPlayerAudio.AcceptsData()); + bool bVideoFull(!m_dvdPlayerVideo.AcceptsData()); + + if (/* if all streams got at least g_advancedSettings.m_iPVRMinCacheLevel in their buffers, we're done */ + ((bGotVideo || bGotAudio) && (!bGotAudio || bAudioLevelOk) && (!bGotVideo || bVideoLevelOk)) || + /* or if one of the buffers is full */ + (bAudioFull || bVideoFull)) + { + CLog::Log(LOGDEBUG, "set caching from pvr to done. audio (%d) = %d. video (%d) = %d", + bGotAudio, m_dvdPlayerAudio.m_messageQueue.GetLevel(), + bGotVideo, m_dvdPlayerVideo.m_messageQueue.GetLevel()); + + CFileItem currentItem(g_application.CurrentFileItem()); + if (currentItem.HasPVRChannelInfoTag()) + g_PVRManager.LoadCurrentChannelSettings(); + + caching = CACHESTATE_DONE; + SAFE_RELEASE(m_CurrentAudio.startsync); + SAFE_RELEASE(m_CurrentVideo.startsync); + } + else + { + /* ensure that automatically started players are stopped while caching */ + if (m_CurrentAudio.started) + m_dvdPlayerAudio.SetSpeed(DVD_PLAYSPEED_PAUSE); + if (m_CurrentVideo.started) + m_dvdPlayerVideo.SetSpeed(DVD_PLAYSPEED_PAUSE); + } + } + if(caching == CACHESTATE_PLAY) { // if all enabled streams have started playing we are done @@ -1499,21 +1627,26 @@ bool CDVDPlayer::CheckStartCaching(CCurrentStream& current) if((current.type == STREAM_AUDIO && m_dvdPlayerAudio.IsStalled()) || (current.type == STREAM_VIDEO && m_dvdPlayerVideo.IsStalled())) { + if (CachePVRStream()) + { + if ((current.type == STREAM_AUDIO && current.started && m_dvdPlayerAudio.m_messageQueue.GetLevel() == 0) || + (current.type == STREAM_VIDEO && current.started && m_dvdPlayerVideo.m_messageQueue.GetLevel() == 0)) + { + CLog::Log(LOGDEBUG, "%s stream stalled. start buffering", current.type == STREAM_AUDIO ? "audio" : "video"); + SetCaching(CACHESTATE_PVR); + } + return true; + } + // don't start caching if it's only a single stream that has run dry - if(m_dvdPlayerAudio.m_messageQueue.GetLevel() > 50 - || m_dvdPlayerVideo.m_messageQueue.GetLevel() > 50) + if(m_dvdPlayerAudio.m_messageQueue.GetLevel() > 50 || + m_dvdPlayerVideo.m_messageQueue.GetLevel() > 50) return false; - if(m_pInputStream->IsStreamType(DVDSTREAM_TYPE_HTSP) - || m_pInputStream->IsStreamType(DVDSTREAM_TYPE_TV)) - SetCaching(CACHESTATE_INIT); + if(current.inited) + SetCaching(CACHESTATE_FULL); else - { - if(current.inited) - SetCaching(CACHESTATE_FULL); - else - SetCaching(CACHESTATE_INIT); - } + SetCaching(CACHESTATE_INIT); return true; } return false; @@ -1621,7 +1754,7 @@ void CDVDPlayer::CheckContinuity(CCurrentStream& current, DemuxPacket* pPacket) #if 0 // these checks seem to cause more harm, than good // looping stillframes are not common in normal files - // and a better fix for this behaviour would be to + // and a better fix for this behaviour would be to // correct the timestamps with some offset if (current.type == STREAM_VIDEO @@ -1697,6 +1830,7 @@ void CDVDPlayer::CheckContinuity(CCurrentStream& current, DemuxPacket* pPacket) /* normally don't need to sync players since video player will keep playing at normal fps */ /* after a discontinuity */ //SynchronizePlayers(dts, pts, MSGWAIT_ALL); + m_CurrentAudio.inited = false; m_CurrentVideo.inited = false; m_CurrentSubtitle.inited = false; @@ -2101,8 +2235,9 @@ void CDVDPlayer::HandleMessages() } else if (pMsg->IsType(CDVDMsg::PLAYER_SET_RECORD)) { - if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_TV)) - static_cast(m_pInputStream)->Record(*(CDVDMsgBool*)pMsg); + CDVDInputStream::IChannel* input = dynamic_cast(m_pInputStream); + if(input) + input->Record(*(CDVDMsgBool*)pMsg); } else if (pMsg->IsType(CDVDMsg::GENERAL_FLUSH)) { @@ -2144,30 +2279,71 @@ void CDVDPlayer::HandleMessages() if(m_pDemuxer) m_pDemuxer->SetSpeed(speed); } - else if (pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_NEXT) || - pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_PREV) || - (pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_SELECT) && m_messenger.GetPacketCount(CDVDMsg::PLAYER_CHANNEL_SELECT) == 0)) + else if (pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_SELECT_NUMBER) && m_messenger.GetPacketCount(CDVDMsg::PLAYER_CHANNEL_SELECT_NUMBER) == 0) + { + FlushBuffers(false); + CDVDInputStream::IChannel* input = dynamic_cast(m_pInputStream); + if(input && input->SelectChannelByNumber(static_cast(pMsg)->m_value)) + { + SAFE_DELETE(m_pDemuxer); + }else + { + CLog::Log(LOGWARNING, "%s - failed to switch channel. playback stopped", __FUNCTION__); + g_application.getApplicationMessenger().MediaStop(false); + } + } + else if (pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_SELECT) && m_messenger.GetPacketCount(CDVDMsg::PLAYER_CHANNEL_SELECT) == 0) + { + FlushBuffers(false); + CDVDInputStream::IChannel* input = dynamic_cast(m_pInputStream); + if(input && input->SelectChannel(static_cast *>(pMsg)->m_value)) + { + SAFE_DELETE(m_pDemuxer); + }else + { + CLog::Log(LOGWARNING, "%s - failed to switch channel. playback stopped", __FUNCTION__); + g_application.getApplicationMessenger().MediaStop(false); + } + } + else if (pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_NEXT) || pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_PREV)) { CDVDInputStream::IChannel* input = dynamic_cast(m_pInputStream); if(input) { - g_infoManager.SetDisplayAfterSeek(100000); + bool bSwitchSuccessful(false); + bool bShowPreview(g_guiSettings.GetInt("pvrplayback.channelentrytimeout") > 0); - bool result; - if (pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_SELECT)) - result = input->SelectChannel(static_cast(pMsg)->m_value); - else if(pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_NEXT)) - result = input->NextChannel(); - else - result = input->PrevChannel(); - - if(result) + if (!bShowPreview) { + g_infoManager.SetDisplayAfterSeek(100000); FlushBuffers(false); - SAFE_DELETE(m_pDemuxer); } - g_infoManager.SetDisplayAfterSeek(); + if(pMsg->IsType(CDVDMsg::PLAYER_CHANNEL_NEXT)) + bSwitchSuccessful = input->NextChannel(bShowPreview); + else + bSwitchSuccessful = input->PrevChannel(bShowPreview); + + if(bSwitchSuccessful) + { + if (bShowPreview) + { + UpdateApplication(0); + m_iChannelEntryTimeOut = XbmcThreads::SystemClockMillis() + g_guiSettings.GetInt("pvrplayback.channelentrytimeout"); + } + else + { + m_iChannelEntryTimeOut = 0; + SAFE_DELETE(m_pDemuxer); + + g_infoManager.SetDisplayAfterSeek(); + } + } + else + { + CLog::Log(LOGWARNING, "%s - failed to switch channel. playback stopped", __FUNCTION__); + g_application.getApplicationMessenger().MediaStop(false); + } } } else if (pMsg->IsType(CDVDMsg::GENERAL_GUI_ACTION)) @@ -2208,13 +2384,17 @@ void CDVDPlayer::SetCaching(ECacheState state) CLog::Log(LOGDEBUG, "CDVDPlayer::SetCaching - caching state %d", state); if(state == CACHESTATE_FULL - || state == CACHESTATE_INIT) + || state == CACHESTATE_INIT + || state == CACHESTATE_PVR) { m_clock.SetSpeed(DVD_PLAYSPEED_PAUSE); m_dvdPlayerAudio.SetSpeed(DVD_PLAYSPEED_PAUSE); m_dvdPlayerAudio.SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1); m_dvdPlayerVideo.SetSpeed(DVD_PLAYSPEED_PAUSE); m_dvdPlayerVideo.SendMessage(new CDVDMsg(CDVDMsg::PLAYER_STARTED), 1); + + if (state == CACHESTATE_PVR) + m_scanStart = XbmcThreads::SystemClockMillis(); } if(state == CACHESTATE_PLAY @@ -2223,6 +2403,7 @@ void CDVDPlayer::SetCaching(ECacheState state) m_clock.SetSpeed(m_playSpeed); m_dvdPlayerAudio.SetSpeed(m_playSpeed); m_dvdPlayerVideo.SetSpeed(m_playSpeed); + m_scanStart = 0; } m_caching = state; } @@ -2237,7 +2418,7 @@ void CDVDPlayer::SetPlaySpeed(int speed) void CDVDPlayer::Pause() { - if(m_playSpeed != DVD_PLAYSPEED_PAUSE && m_caching == CACHESTATE_FULL) + if(m_playSpeed != DVD_PLAYSPEED_PAUSE && (m_caching == CACHESTATE_FULL || m_caching == CACHESTATE_PVR)) { SetCaching(CACHESTATE_DONE); return; @@ -2258,7 +2439,7 @@ void CDVDPlayer::Pause() bool CDVDPlayer::IsPaused() const { - return (m_playSpeed == DVD_PLAYSPEED_PAUSE) || m_caching == CACHESTATE_FULL; + return m_playSpeed == DVD_PLAYSPEED_PAUSE || m_caching == CACHESTATE_FULL || m_caching == CACHESTATE_PVR; } bool CDVDPlayer::HasVideo() const @@ -3231,6 +3412,21 @@ int CDVDPlayer::OnDVDNavResult(void* pData, int iMessage) return NAVRESULT_NOP; } +bool CDVDPlayer::ShowPVRChannelInfo(void) +{ + bool bReturn(false); + + if (g_guiSettings.GetBool("pvrmenu.infoswitch")) + { + int iTimeout = g_guiSettings.GetBool("pvrmenu.infotimeout") ? g_guiSettings.GetInt("pvrmenu.infotime") : 0; + g_PVRManager.ShowPlayerInfo(iTimeout); + + bReturn = true; + } + + return bReturn; +} + bool CDVDPlayer::OnAction(const CAction &action) { #define THREAD_ACTION(action) \ @@ -3416,17 +3612,21 @@ bool CDVDPlayer::OnAction(const CAction &action) { switch (action.GetID()) { + case ACTION_MOVE_UP: case ACTION_NEXT_ITEM: case ACTION_PAGE_UP: m_messenger.Put(new CDVDMsg(CDVDMsg::PLAYER_CHANNEL_NEXT)); g_infoManager.SetDisplayAfterSeek(); + ShowPVRChannelInfo(); return true; break; + case ACTION_MOVE_DOWN: case ACTION_PREV_ITEM: case ACTION_PAGE_DOWN: m_messenger.Put(new CDVDMsg(CDVDMsg::PLAYER_CHANNEL_PREV)); g_infoManager.SetDisplayAfterSeek(); + ShowPVRChannelInfo(); return true; break; @@ -3434,8 +3634,9 @@ bool CDVDPlayer::OnAction(const CAction &action) { // Offset from key codes back to button number int channel = action.GetAmount(); - m_messenger.Put(new CDVDMsgInt(CDVDMsg::PLAYER_CHANNEL_SELECT, channel)); + m_messenger.Put(new CDVDMsgInt(CDVDMsg::PLAYER_CHANNEL_SELECT_NUMBER, channel)); g_infoManager.SetDisplayAfterSeek(); + ShowPVRChannelInfo(); return true; } break; @@ -3668,6 +3869,11 @@ void CDVDPlayer::UpdatePlayState(double timeout) state.canrecord = static_cast(m_pInputStream)->CanRecord(); state.recording = static_cast(m_pInputStream)->IsRecording(); } + else if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) + { + state.canrecord = static_cast(m_pInputStream)->CanRecord(); + state.recording = static_cast(m_pInputStream)->IsRecording(); + } CDVDInputStream::IDisplayTime* pDisplayTime = dynamic_cast(m_pInputStream); if (pDisplayTime) @@ -3690,7 +3896,6 @@ void CDVDPlayer::UpdatePlayState(double timeout) else state.player_state = ""; - if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_TV)) { if(((CDVDInputStreamTV*)m_pInputStream)->GetTotalTime() > 0) @@ -3699,6 +3904,15 @@ void CDVDPlayer::UpdatePlayState(double timeout) state.time_total = ((CDVDInputStreamTV*)m_pInputStream)->GetTotalTime(); } } + else if (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) + { + if(((CDVDInputStreamPVRManager*)m_pInputStream)->GetTotalTime() > 0 && + ((CDVDInputStreamPVRManager*)m_pInputStream)->GetStartTime() > 0) + { + state.time = ((CDVDInputStreamPVRManager*)m_pInputStream)->GetStartTime(); + state.time_total = ((CDVDInputStreamPVRManager*)m_pInputStream)->GetTotalTime(); + } + } } if (m_Edl.HasCut()) @@ -3792,7 +4006,8 @@ bool CDVDPlayer::IsRecording() bool CDVDPlayer::Record(bool bOnOff) { - if (m_pInputStream && m_pInputStream->IsStreamType(DVDSTREAM_TYPE_TV)) + if (m_pInputStream && (m_pInputStream->IsStreamType(DVDSTREAM_TYPE_TV) || + m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER)) ) { m_messenger.Put(new CDVDMsgBool(CDVDMsg::PLAYER_SET_RECORD, bOnOff)); return true; @@ -3874,3 +4089,30 @@ CStdString CDVDPlayer::GetPlayingTitle() return ""; } + +bool CDVDPlayer::SwitchChannel(const CPVRChannel &channel) +{ + /* set GUI info */ + if (!g_PVRManager.PerformChannelSwitch(channel, true)) + return false; + + UpdateApplication(0); + UpdatePlayState(0); + + /* make sure the pvr window is updated */ + CGUIWindowPVR *pWindow = (CGUIWindowPVR *) g_windowManager.GetWindow(WINDOW_PVR); + if (pWindow) + pWindow->SetInvalid(); + + /* select the new channel */ + m_messenger.Put(new CDVDMsgType(CDVDMsg::PLAYER_CHANNEL_SELECT, channel)); + + return true; +} + +bool CDVDPlayer::CachePVRStream(void) const +{ + return m_pInputStream->IsStreamType(DVDSTREAM_TYPE_PVRMANAGER) && + !g_PVRManager.IsPlayingRecording() && + g_advancedSettings.m_bPVRCacheInDvdPlayer; +} diff --git a/xbmc/cores/dvdplayer/DVDPlayer.h b/xbmc/cores/dvdplayer/DVDPlayer.h index 4afb5e2..2424ee3 100644 --- a/xbmc/cores/dvdplayer/DVDPlayer.h +++ b/xbmc/cores/dvdplayer/DVDPlayer.h @@ -49,6 +49,11 @@ class CDemuxStreamVideo; class CDemuxStreamAudio; class CStreamInfo; +namespace PVR +{ + class CPVRChannel; +} + #define DVDSTATE_NORMAL 0x00000001 // normal dvd state #define DVDSTATE_STILL 0x00000002 // currently displaying a still frame #define DVDSTATE_WAIT 0x00000003 // waiting for demuxer read error @@ -223,15 +228,19 @@ public: virtual CStdString GetPlayingTitle(); + virtual bool SwitchChannel(const PVR::CPVRChannel &channel); + virtual bool CachePVRStream(void) const; + enum ECacheState { CACHESTATE_DONE = 0 , CACHESTATE_FULL // player is filling up the demux queue + , CACHESTATE_PVR // player is waiting for some data in each buffer , CACHESTATE_INIT // player is waiting for first packet of each stream , CACHESTATE_PLAY // player is waiting for players to not be stalled , CACHESTATE_FLUSH // temporary state player will choose startup between init or full }; - virtual bool IsCaching() const { return m_caching == CACHESTATE_FULL; } + virtual bool IsCaching() const { return m_caching == CACHESTATE_FULL || m_caching == CACHESTATE_PVR; } virtual int GetCacheLevel() const ; virtual int OnDVDNavResult(void* pData, int iMessage); @@ -263,6 +272,8 @@ protected: void ProcessSubData(CDemuxStream* pStream, DemuxPacket* pPacket); void ProcessTeletextData(CDemuxStream* pStream, DemuxPacket* pPacket); + bool ShowPVRChannelInfo(); + int AddSubtitleFile(const std::string& filename, const std::string& subfilename = "", CDemuxStream::EFlags flags = CDemuxStream::FLAG_NONE); /** @@ -297,6 +308,7 @@ protected: bool ReadPacket(DemuxPacket*& packet, CDemuxStream*& stream); bool IsValidStream(CCurrentStream& stream); bool IsBetterStream(CCurrentStream& current, CDemuxStream* stream); + bool CheckDelayedChannelEntry(void); bool OpenInputStream(); bool OpenDemuxStream(); @@ -308,10 +320,12 @@ protected: bool m_bAbortRequest; - std::string m_filename; // holds the actual filename - std::string m_mimetype; // hold a hint to what content file contains (mime type) - ECacheState m_caching; - CFileItem m_item; + std::string m_filename; // holds the actual filename + std::string m_mimetype; // hold a hint to what content file contains (mime type) + ECacheState m_caching; + CFileItem m_item; + unsigned int m_scanStart; + unsigned int m_iChannelEntryTimeOut; CCurrentStream m_CurrentAudio; diff --git a/xbmc/cores/dvdplayer/DVDSubtitles/SamiTagConvertor.cpp b/xbmc/cores/dvdplayer/DVDSubtitles/SamiTagConvertor.cpp new file mode 100644 index 0000000..6199aaa --- /dev/null +++ b/xbmc/cores/dvdplayer/DVDSubtitles/SamiTagConvertor.cpp @@ -0,0 +1,242 @@ +/* + * 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 "SamiTagConvertor.h" +#include "DVDSubtitleStream.h" +#include "DVDCodecs/Overlay/DVDOverlayText.h" +#include "utils/RegExp.h" + +SamiTagConvertor::~SamiTagConvertor() +{ + delete m_tags; + delete m_tagOptions; +} + +bool SamiTagConvertor::Init() +{ + m_tags = new CRegExp(true); + if (!m_tags->RegComp("(<[^>]*>)")) + return false; + + m_tagOptions = new CRegExp(true); + if (!m_tagOptions->RegComp("([a-z]+)[ \t]*=[ \t]*(?:[\"'])?([^\"'> ]+)(?:[\"'])?(?:>)?")) + return false; + + return true; +} + +void SamiTagConvertor::ConvertLine(CDVDOverlayText* pOverlay, const char* line, int len, const char* lang) +{ + CStdStringA strUTF8; + strUTF8.assign(line, len); + + int pos = 0; + int del_start = 0; + while ((pos=m_tags->RegFind(strUTF8.c_str(), pos)) >= 0) + { + // Parse Tags + CStdString fullTag = m_tags->GetMatch(0); + fullTag.ToLower(); + strUTF8.erase(pos, fullTag.length()); + if (fullTag == "") + { + tag_flag[FLAG_BOLD] = true; + strUTF8.insert(pos, "[B]"); + pos += 3; + } + else if (fullTag == "" && tag_flag[FLAG_BOLD]) + { + tag_flag[FLAG_BOLD] = false; + strUTF8.insert(pos, "[/B]"); + pos += 4; + } + else if (fullTag == "") + { + tag_flag[FLAG_ITALIC] = true; + strUTF8.insert(pos, "[I]"); + pos += 3; + } + else if (fullTag == "" && tag_flag[FLAG_ITALIC]) + { + tag_flag[FLAG_ITALIC] = false; + strUTF8.insert(pos, "[/I]"); + pos += 4; + } + else if (fullTag == "" && tag_flag[FLAG_COLOR]) + { + tag_flag[FLAG_COLOR] = false; + strUTF8.insert(pos, "[/COLOR]"); + pos += 8; + } + else if (fullTag.Left(5) == "RegFind(fullTag.c_str(), pos2)) >= 0) + { + CStdString tagOptionName = m_tagOptions->GetMatch(1); + CStdString tagOptionValue = m_tagOptions->GetMatch(2); + pos2 += tagOptionName.length() + tagOptionValue.length(); + if (tagOptionName == "color") + { + tag_flag[FLAG_COLOR] = true; + CStdString tempColorTag = "[COLOR "; + if (tagOptionValue[0] == '#') + { + tagOptionValue.erase(0, 1); + tempColorTag += "FF"; + } + else if( tagOptionValue.size() == 6 ) + { + bool bHex = true; + for( int i=0 ; i<6 ; i++ ) + { + char temp = tagOptionValue[i]; + if( !(('0' <= temp && temp <= '9') || + ('a' <= temp && temp <= 'f') || + ('A' <= temp && temp <= 'F') )) + { + bHex = false; + break; + } + } + if( bHex ) tempColorTag += "FF"; + } + tempColorTag += tagOptionValue; + tempColorTag += "]"; + strUTF8.insert(pos, tempColorTag); + pos += tempColorTag.length(); + } + } + } + else if (lang && (fullTag.Left(3) == "

RegFind(fullTag.c_str(), pos2)) >= 0) + { + CStdString tagOptionName = m_tagOptions->GetMatch(1); + CStdString tagOptionValue = m_tagOptions->GetMatch(2); + pos2 += tagOptionName.length() + tagOptionValue.length(); + if (tagOptionName == "class") + { + if (tag_flag[FLAG_LANGUAGE]) + { + strUTF8.erase(del_start, pos - del_start); + pos = del_start; + } + if (!tagOptionValue.Compare(lang)) + { + tag_flag[FLAG_LANGUAGE] = false; + } + else + { + tag_flag[FLAG_LANGUAGE] = true; + del_start = pos; + } + break; + } + } + } + else if (fullTag == "

" && tag_flag[FLAG_LANGUAGE]) + { + strUTF8.erase(del_start, pos - del_start); + pos = del_start; + tag_flag[FLAG_LANGUAGE] = false; + } + else if (fullTag == "
" && !strUTF8.IsEmpty()) + { + strUTF8.Insert(pos, "\n"); + pos += 1; + } + } + + if(tag_flag[FLAG_LANGUAGE]) + strUTF8.erase(del_start); + + if (strUTF8.IsEmpty()) + return; + + if( strUTF8[strUTF8.size()-1] == '\n' ) + strUTF8.Delete(strUTF8.size()-1); + + // add a new text element to our container + pOverlay->AddElement(new CDVDOverlayText::CElementText(strUTF8.c_str())); +} + +void SamiTagConvertor::CloseTag(CDVDOverlayText* pOverlay) +{ + if (tag_flag[FLAG_BOLD]) + { + pOverlay->AddElement(new CDVDOverlayText::CElementText("[/B]")); + tag_flag[FLAG_BOLD] = false; + } + if (tag_flag[FLAG_ITALIC]) + { + pOverlay->AddElement(new CDVDOverlayText::CElementText("[/I]")); + tag_flag[FLAG_ITALIC] = false; + } + if (tag_flag[FLAG_COLOR]) + { + pOverlay->AddElement(new CDVDOverlayText::CElementText("[/COLOR]")); + tag_flag[FLAG_COLOR] = false; + } + tag_flag[FLAG_LANGUAGE] = false; +} + +void SamiTagConvertor::LoadHead(CDVDSubtitleStream* samiStream) +{ + char line[1024]; + bool inSTYLE = false; + CRegExp reg(true); + if (!reg.RegComp("\\.([a-z]+)[ \t]*\\{[ \t]*name:([^;]*?);[ \t]*lang:([^;]*?);[ \t]*SAMIType:([^;]*?);[ \t]*\\}")) + return; + + while (samiStream->ReadLine(line, sizeof(line))) + { + if (!strnicmp(line, "", 6)) + break; + if (inSTYLE) + { + if (!strnicmp(line, "", 8)) + break; + else + { + if (reg.RegFind(line) > -1) + { + SLangclass lc; + lc.ID = reg.GetMatch(1); + lc.Name = reg.GetMatch(2); + lc.Lang = reg.GetMatch(3); + lc.SAMIType = reg.GetMatch(4); + lc.Name.Trim(); + lc.Lang.Trim(); + lc.SAMIType.Trim(); + m_Langclass.push_back(lc); + } + } + } + else + { + if (!strnicmp(line, "