diff options
46 files changed, 378 insertions, 6978 deletions
@@ -1,6 +1,21 @@ VDR Plugin 'upnp' Revision History ---------------------------------- +2009-01-24: Version 0.0.2-alpha0 + + - New: Added record streaming support for SDTV + HDTV is not working yet, as it requires different DLNA profiles + - Bug: Improved live-tv streaming quality, which will hopefully fix the + problem with the buffer strategy and channels with bad bandwidth + - New: Rearranged folder structure to meet future features + - New: Added german translation + - New: support for DLNA compatible devices. For those devices a special + patch is required which must be applied to libupnp-1.6.6. + See README for more information + - New: Added new command line option to specify the destination folder + for the metadata database and the webfolder. + See README for more information + 2009-11-19: Version 0.0.1-alpha4 - New: Added options for verbosity level and autodetect settings. @@ -27,15 +27,10 @@ VDRDIR = ../../.. LIBDIR = ../../lib TMPDIR = /tmp -WEBDIR = $(shell grep '\#define UPNP_DIR_PRESENTATION*' $(COMMON) | awk '{ print $$3 }' | sed -e 's/["/]//g') - ### Allow user defined options to overwrite defaults: -include $(VDRDIR)/Make.config -#DESDIR = /var/lib/vdrdevel/plugins/$(PLUGIN) -DESDIR = $(CONFDIR)/plugins/$(PLUGIN) - ### The version number of VDR's plugin API (taken from VDR's "config.h"): APIVERSION = $(shell sed -ne '/define APIVERSION/s/^.*"\(.*\)".*$$/\1/p' $(VDRDIR)/config.h) @@ -49,13 +44,44 @@ PACKAGE = vdr-$(ARCHIVE) LIBS += -lupnp -lixml -lsqlite3 -lavformat -lavcodec -INCLUDES += -I$(VDRDIR)/include -I/usr/include \ +INCLUDES += -I$(VDRDIR)/include -I/usr/include -Iinc \ DEFINES += -D_GNU_SOURCE -DPLUGIN_NAME_I18N='"$(PLUGIN)"' DEFINES += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -D_LARGEFILE64_SOURCE +ifdef WITH_WINDOWS_MEDIA + DEFINES += -DWITH_WINDOWS_MEDIA +endif + +DEFINES += -DWITHOUT_AUDIO -DWITHOUT_CUSTOM_VIDEOS + ### The object files (add further files here): +# DLNA Profiles +DLNA_PROFILES = dlna/profiles/aac.o \ + dlna/profiles/ac3.o \ + dlna/profiles/amr.o \ + dlna/profiles/atrac3plus.o \ + dlna/profiles/jpeg.o \ + dlna/profiles/lpcm.o \ + dlna/profiles/mpa.o \ + dlna/profiles/mpeg1.o \ + dlna/profiles/mpeg2.o \ + dlna/profiles/mpeg4_p2.o \ + dlna/profiles/mpeg4_p10.o \ + dlna/profiles/png.o \ + dlna/profiles/container.o + +# Windows Media Formats +ifdef WITH_WINDOWS_MEDIA + DLNA_PROFILES += dlna/profiles/wma.o \ + dlna/profiles/wmv9.o +endif + +DLNA_OBJS = dlna/dlna.o \ + dlna/avdetector.o \ + $(DLNA_PROFILES) + # Root folder OBJS = $(PLUGIN).o \ common.o \ @@ -63,20 +89,18 @@ OBJS = $(PLUGIN).o \ misc/util.o \ misc/config.o \ misc/search.o \ - misc/avdetector.o \ database/database.o \ database/metadata.o \ database/object.o \ database/resources.o \ server/server.o \ - upnpcomponents/dlna.o \ - upnpcomponents/upnpwebserver.o \ - upnpcomponents/upnpservice.o \ - upnpcomponents/connectionmanager.o \ - upnpcomponents/contentdirectory.o \ + server/webserver.o \ + upnp/service.o \ + upnp/connectionmanager.o \ + upnp/contentdirectory.o \ receiver/livereceiver.o \ receiver/recplayer.o \ - receiver/filehandle.o \ + $(DLNA_OBJS) ### The main target: @@ -109,7 +133,7 @@ I18Npot = $(PODIR)/$(PLUGIN).pot msgfmt -c -o $@ $< $(I18Npot): $(wildcard *.cpp) - xgettext -C -cTRANSLATORS --no-wrap --no-location -k -ktr -ktrNOOP --msgid-bugs-address='<see README>' -o $@ $^ + xgettext -C -cTRANSLATORS --no-wrap --no-location -k -k_ -ktr -ktrNOOP --msgid-bugs-address='<see README>' -o $@ $(OBJS:%.o=%.cpp) %.po: $(I18Npot) msgmerge -U --no-wrap --no-location --backup=none -q $@ $< @@ -127,15 +151,12 @@ i18n: $(I18Nmsgs) $(I18Npot) libvdr-$(PLUGIN).so: $(OBJS) $(CXX) $(CXXFLAGS) $(LIBS) -shared $(OBJS) -o $@ -lc @cp --remove-destination $@ $(LIBDIR)/$@.$(APIVERSION) - @-rm -rf $(DESDIR)/$(WEBDIR) - @mkdir -p $(DESDIR)/$(WEBDIR) - @cp --remove-destination -r $(WEBDIR)/* $(DESDIR)/$(WEBDIR) dist: clean @-rm -rf $(TMPDIR)/$(ARCHIVE) @mkdir $(TMPDIR)/$(ARCHIVE) @cp -a * $(TMPDIR)/$(ARCHIVE) - @tar czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE) + @tar --exclude="doc" -czf $(PACKAGE).tgz -C $(TMPDIR) $(ARCHIVE) @-rm -rf $(TMPDIR)/$(ARCHIVE) @echo Distribution package created as $(PACKAGE).tgz @@ -25,6 +25,7 @@ http://www.hft-leipzig.de All rights reserved. + Description: UPnP/DLNA Plugin for Video Disk Recorder @@ -41,25 +42,29 @@ options or by editing the setup via the VDRs setup page. The command line options have a higher priority and substitute the menu settings. The command line settings are: - -i <interface> --int=<interface> The server network - interface - e.g: eth0, wlan1 etc. - If given option '-a' must - be absent. - -a <address> --address=<address> The server IPv4 address. - If given option '-i' must - be absent. - -p <port> --port=<port> The server port - Supported ports: - 0 (auto detect) - 49152-65535 (user defined) - -d --autodetect Force auto detection - Use this option to - overwrite the setup menu - options. - -v --verbose Increase verbosity level - The more v options the - higher the output level + -i <interface> --int=<interface> The server network + interface + e.g: eth0, wlan1 etc. + If given option '-a' must + be absent. + -a <address> --address=<address> The server IPv4 address. + If given option '-i' must + be absent. + -p <port> --port=<port> The server port + Supported ports: + 0 (auto detect) + 49152-65535 (user defined) + -d --autodetect Force auto detection + Use this option to + overwrite the setup menu + options. + -v --verbose Increase verbosity level + The more v options the + higher the output level + --dbdir=<directory> The directory in which the + metadata database is stored + --httpdir=<directory> The directory where the + http documents are located The verbose option can be more than once. With each option the verbosity level will be increased. The maximum level is 5. Further options are silently ignored. @@ -87,6 +92,7 @@ devices. If not, please report this as a bug on the project homepage or send an email to the developers of this plugin with the full device description and, if applicable, the errors thrown by the media player device and/or the server. + Dependencies: This plugin is tested with and requires the following libraries to work: @@ -114,3 +120,10 @@ are explained. I appreciate, if you help making the plugin better. If you find any project related errors or missing features, please open a new ticket at the plugin website with a detailed description of what you want or what happened. + + +Patching the libupnp: + +If you have a DLNA compliant device such as TVs or streaming clients, you may +require a patched version of libupnp. You can download the patch on the project +website.
\ No newline at end of file @@ -7,18 +7,7 @@ #include <stdarg.h> #include "common.h" -#include "misc/config.h" - -DLNAProfile DLNA_PROFILE_MPEG_TS_SD_EU = { "MPEG_TS_SD_EU", "video/vnd.dlna.mpeg-tts" }; -DLNAProfile DLNA_PROFILE_AVC_TS_HD_EU = { "AVC_TS_HD_EU", "video/vnd.dlna.mpeg-tts" }; -DLNAProfile DLNA_PROFILE_MPEG_TS_SD_EU_ISO = { "MPEG_TS_SD_EU_ISO", "video/mpeg" }; -DLNAProfile DLNA_PROFILE_AVC_TS_HD_EU_ISO = { "AVC_TS_HD_EU_ISO", "video/mpeg" }; -DLNAProfile DLNA_PROFILE_MPEG1_L3 = { "MP3", "audio/mpeg" }; - -DLNAIconProfile DLNA_ICON_JPEG_SM_24 = { "image/jpeg", 48, 48, 24 }; -DLNAIconProfile DLNA_ICON_JPEG_LRG_24 = { "image/jpeg", 120, 120, 24 }; -DLNAIconProfile DLNA_ICON_PNG_SM_24A = { "image/png", 48, 48, 24 }; -DLNAIconProfile DLNA_ICON_PNG_LRG_24A = { "image/png", 120, 120, 24 }; +#include "config.h" #define MESSAGE_SIZE 256 @@ -8,7 +8,7 @@ #ifndef _COMMON_H #define _COMMON_H -#include "misc/util.h" +#include "util.h" #include <libintl.h> #include <string.h> #include <vdr/tools.h> @@ -65,9 +65,6 @@ #define OUT #define INOUT -//#define DEBUG -//#define WITH_WINDOWS_MEDIA - #define TOSTRING(s) #s #define FALSE 0 @@ -79,7 +76,7 @@ * Translation with gettext() */ #ifndef _ -#define _(s) tr(s) +#define _(s) gettext(s) #endif #define KB(i) i*1024 @@ -92,6 +89,17 @@ #define att(s) strchr(s,'@')!=NULL?strchr(s,'@')+1:NULL #define prop(s) substr(s, 0, strchr(s,'@')-s) +#ifdef WITHOUT_AUDIO + #define WITHOUT_RADIO + #define WITHOUT_CUSTOM_AUDIO +#endif + +#ifdef WITHOUT_VIDEO + #define WITHOUT_TV + #define WITHOUT_RECORDS + #define WITHOUT_CUSTOM_VIDEO +#endif + void message(int level, const char* File, int Line, const char* Format, ...) __attribute__ ((format (printf, 4, 5))); /**************************************************** @@ -100,10 +108,11 @@ void message(int level, const char* File, int Line, const char* Format, ...) __a * ****************************************************/ -#define VDR_RECORDFILE_PATTERN_PES "%s/%03d.vdr" -#define VDR_RECORDFILE_PATTERN_TS "%s/%05d.ts" -#define VDR_MAX_FILES_PER_RECORDING 65535 -#define VDR_FILENAME_BUFSIZE 2048 +//#define VDR_RECORDFILE_PATTERN_PES "%s/%03d.vdr" +//#define VDR_RECORDFILE_PATTERN_TS "%s/%05d.ts" +#define VDR_MAX_FILES_PER_TSRECORDING 65535 +#define VDR_MAX_FILES_PER_PESRECORDING 255 +//#define VDR_FILENAME_BUFSIZE 2048 /**************************************************** * @@ -119,7 +128,7 @@ void message(int level, const char* File, int Line, const char* Format, ...) __a * string in the main file "upnp.c" as well to avoid errors with the makefile */ #define PLUGIN_VERSION_MAJOR 0 #define PLUGIN_VERSION_MINOR 0 -#define PLUGIN_VERSION_MICRO 1 +#define PLUGIN_VERSION_MICRO 2 /* The plugin version as dot-separated string */ #define PLUGIN_VERSION VERSION_STR(PLUGIN_VERSION_MAJOR, \ PLUGIN_VERSION_MINOR, \ @@ -189,10 +198,10 @@ void message(int level, const char* File, int Line, const char* Format, ...) __a #define VERBOSE_EPG_UPDATES 3 ///< show information on EPG changes #define VERBOSE_WEBSERVER 2 ///< print actions done by the webserver #define VERBOSE_MODIFICATIONS 2 ///< show modifications to objects or anything else -#define VERBOSE_METADATA 3 ///< print additional metadata information +#define VERBOSE_METADATA 4 ///< print additional metadata information #define VERBOSE_CUSTOM_OUTPUT 5 ///< everything else... #define VERBOSE_PARSERS 5 ///< print the parsers output -#define VERBOSE_BUFFERS 5 ///< print the buffer output +#define VERBOSE_BUFFERS 4 ///< print the buffer output #define VERBOSE_CDS 2 ///< print messages from the content directory #define VERBOSE_CMS 2 ///< print messages from the connection manager #define VERBOSE_OBJECTS 3 ///< print messages related to objects @@ -222,11 +231,13 @@ void message(int level, const char* File, int Line, const char* Format, ...) __a * ****************************************************/ -#define SETUP_SERVER_ENABLED "ServerEnabled" -#define SETUP_SERVER_INT "ServerInt" -#define SETUP_SERVER_PORT "ServerPort" -#define SETUP_SERVER_AUTO "ServerAutoDetect" -#define SETUP_SERVER_ADDRESS "ServerAddress" +#define SETUP_SERVER_ENABLED "Server.Enabled" +#define SETUP_SERVER_INT "Server.Int" +#define SETUP_SERVER_PORT "Server.Port" +#define SETUP_SERVER_AUTO "Server.AutoDetect" +#define SETUP_SERVER_ADDRESS "Server.Address" +#define SETUP_WEBSERVER_DIR "Webserver.Directory" +#define SETUP_DATABASE_DIR "Database.Directory" /* The server port range where the server interacts with clients */ #define SERVER_MIN_PORT 49152 @@ -269,7 +280,7 @@ enum UPNP_RESOURCE_TYPES { ****************************************************/ #define UPNP_XMLNS_UPNP "urn:schemas-upnp-org:metadata-1-0/upnp/" -#define UPNP_XMLNS_DIDL "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite" +#define UPNP_XMLNS_DIDL "urn:schemas-upnp-org:metadata-1-0/DIDL-Lite/" #define UPNP_XMLNS_DLNA_META "urn:schemas-dlna-org:metadata-1-0/" #define UPNP_XMLNS_UPNP_DEV "urn:schemas-upnp-org:device-1-0" #define UPNP_XMLNS_DLNA_DEV "urn:schemas-dlna-org:device-1-0" @@ -290,7 +301,7 @@ enum UPNP_RESOURCE_TYPES { #define UPNP_DIR_EVENT "/event" #define UPNP_DIR_XML "/xml" #define UPNP_DIR_SHARES "/shares" -#define UPNP_DIR_PRESENTATION "/web" +#define UPNP_DIR_PRESENTATION "/http" #define UPNP_DIR_ICONS "/icons" /**************************************************** @@ -410,10 +421,11 @@ enum UPNP_WEB_METHODS { #define UPNP_PROP_DLNA_CONTAINERTYPE "dlna:container" #define UPNP_DIDL_SKELETON "<DIDL-Lite "\ + "xmlns=\"" UPNP_XMLNS_DIDL "\" "\ "xmlns:dc=\"" UPNP_XMLNS_DUBLINCORE "\" "\ "xmlns:upnp=\"" UPNP_XMLNS_UPNP "\" "\ - "xmlns:dlna=\"" UPNP_XMLNS_DLNA_META "\" "\ - "xmlns=\"" UPNP_XMLNS_DIDL "\"></DIDL-Lite>" + "xmlns:dlna=\"" UPNP_XMLNS_DLNA_META "\">"\ + "</DIDL-Lite>" /**************************************************** * @@ -723,7 +735,7 @@ enum UPnPWriteStatus { #define DLNA_FLAG_CLEARTEXT_BYTE_FULL_SEEK 1 << 15 ///< (Link Protection) currently not used #define DLNA_FLAG_CLEARTEXT_LIMITED_SEEK 1 << 14 ///< (Link Protection) currently not used -#define DLNA_FLAGS_PLUGIN_SUPPORT DLNA_FLAG_BYTE_BASED_SEEK | \ +#define DLNA_SUPPORTED_FLAGS DLNA_FLAG_BYTE_BASED_SEEK | \ DLNA_FLAG_SN_INCREASE | \ DLNA_FLAG_STREAMING_TRANSFER | \ DLNA_FLAG_BACKGROUND_TRANSFER | \ diff --git a/database/database.cpp b/database/database.cpp index e47dcbf..c58294d 100644 --- a/database/database.cpp +++ b/database/database.cpp @@ -12,6 +12,7 @@ #include "../common.h" #include "object.h" #include "../upnp.h" +#include "config.h" cSQLiteDatabase* cSQLiteDatabase::mInstance = NULL; @@ -160,7 +161,8 @@ bool cRow::fetchColumn(char** Column, char** Value){ int cSQLiteDatabase::initialize(){ int ret; - cString File = cString::sprintf("%s/%s", cPluginUpnp::getConfigDirectory(), SQLITE_DB_FILE); + const char* dbdir = (cUPnPConfig::get()->mDatabaseFolder) ? cUPnPConfig::get()->mDatabaseFolder : cPluginUpnp::getConfigDirectory(); + cString File = cString::sprintf("%s/%s", dbdir, SQLITE_DB_FILE); if((ret = sqlite3_open(File, &this->mDatabase))){ ERROR("Unable to open database file %s (Error code: %d)!", *File, ret); sqlite3_close(this->mDatabase); diff --git a/database/database.h b/database/database.h deleted file mode 100644 index 5bb595f..0000000 --- a/database/database.h +++ /dev/null @@ -1,1024 +0,0 @@ -/* - * File: database.h - * Author: savop - * - * Created on 3. September 2009, 22:20 - */ - -#ifndef _DATABASE_H -#define _DATABASE_H - -#include <sqlite3.h> -#include <vdr/tools.h> -#include "../common.h" - -#define SQLITE_CASCADE_DELETES - -#define PK_OBJECTS TOSTRING(1) -#define PK_RESOURCES TOSTRING(2) -#define PK_SEARCHCLASSES TOSTRING(3) - -#define SQLITE_FIRST_CUSTOMID TOSTRING(100) - -#define SQLITE_COLUMN_NAME_LENGTH 64 - -#define SQLITE_TABLE_RESOURCES "Resources" -#define SQLITE_TABLE_OBJECTS "Objects" -#define SQLITE_TABLE_ITEMS "Items" -#define SQLITE_TABLE_CONTAINERS "Containers" -#define SQLITE_TABLE_VIDEOITEMS "VideoItems" -#define SQLITE_TABLE_AUDIOITEMS "AudioItems" -#define SQLITE_TABLE_IMAGEITEMS "ImageItems" -#define SQLITE_TABLE_VIDEOBROADCASTS "VideoBroadcasts" -#define SQLITE_TABLE_AUDIOBROADCASTS "AudioBroadcasts" -#define SQLITE_TABLE_MOVIES "Movies" -#define SQLITE_TABLE_PHOTOS "Photos" -#define SQLITE_TABLE_ALBUMS "Albums" -#define SQLITE_TABLE_PLAYLISTS "Playlists" -#define SQLITE_TABLE_SEARCHCLASS "SearchClass" -#define SQLITE_TABLE_PRIMARY_KEYS "PrimaryKeys" -#define SQLITE_TABLE_SYSTEM "System" -#define SQLITE_TABLE_ITEMFINDER "ItemFinder" - -#define SQLITE_TYPE_TEXT "TEXT" -#define SQLITE_TYPE_INTEGER "INTEGER" -#define SQLITE_TYPE_BOOL SQLITE_TYPE_INTEGER -#define SQLITE_TYPE_DATE SQLITE_TYPE_TEXT -#define SQLITE_TYPE_ULONG SQLITE_TYPE_INTEGER -#define SQLITE_TYPE_LONG SQLITE_TYPE_INTEGER -#define SQLITE_TYPE_UINTEGER SQLITE_TYPE_INTEGER - -#define SQLITE_TRANSACTION_BEGIN "BEGIN IMMEDIATE TRANSACTION " -#define SQLITE_TRANSACTION_END "COMMIT TRANSACTION" -#define SQLITE_TRANSACTION_TYPE "ROLLBACK" - -#define SQLITE_CONFLICT_CLAUSE "ON CONFLICT " SQLITE_TRANSACTION_TYPE -#define SQLITE_PRIMARY_KEY SQLITE_TYPE_INTEGER " PRIMARY KEY" -#define SQLITE_NOT_NULL "NOT NULL" -#define SQLITE_UNIQUE "UNIQUE" - -#define SQLITE_COL_OBJECTID "ObjectID" -#define SQLITE_COL_PARENTID "ParentID" -#define SQLITE_COL_TITLE "Title" -#define SQLITE_COL_CREATOR "Creator" -#define SQLITE_COL_CLASS "Class" -#define SQLITE_COL_RESTRICTED "Restricted" -#define SQLITE_COL_WRITESTATUS "WriteStatus" -#define SQLITE_COL_REFERENCEID "RefID" -#define SQLITE_COL_CLASSDERIVED "IncludeDerived" -#define SQLITE_COL_SEARCHABLE "Searchable" -#define SQLITE_COL_CONTAINER_UID "UpdateID" -#define SQLITE_COL_RESOURCEID "ResourceID" -#define SQLITE_COL_PROTOCOLINFO "ProtocolInfo" -#define SQLITE_COL_CONTENTTYPE "ContentType" -#define SQLITE_COL_RESOURCETYPE "ResourceType" -#define SQLITE_COL_RESOURCE "Resource" -#define SQLITE_COL_SIZE "Size" -#define SQLITE_COL_DURATION "Duration" -#define SQLITE_COL_BITRATE "Bitrate" -#define SQLITE_COL_SAMPLEFREQUENCE "SampleFreq" -#define SQLITE_COL_BITSPERSAMPLE "BitsPerSample" -#define SQLITE_COL_NOAUDIOCHANNELS "NoAudioChannels" -#define SQLITE_COL_COLORDEPTH "ColorDepth" -#define SQLITE_COL_RESOLUTION "Resolution" -#define SQLITE_COL_GENRE "Genre" -#define SQLITE_COL_LONGDESCRIPTION "LongDescription" -#define SQLITE_COL_PRODUCER "Producer" -#define SQLITE_COL_RATING "Rating" -#define SQLITE_COL_ACTOR "Actor" -#define SQLITE_COL_DIRECTOR "Director" -#define SQLITE_COL_DESCRIPTION "Description" -#define SQLITE_COL_PUBLISHER "Publisher" -#define SQLITE_COL_LANGUAGE "Language" -#define SQLITE_COL_RELATION "Relation" -#define SQLITE_COL_STORAGEMEDIUM "StorageMedium" -#define SQLITE_COL_DVDREGIONCODE "DVDRegionCode" -#define SQLITE_COL_CHANNELNAME "Channelname" -#define SQLITE_COL_SCHEDULEDSTARTTIME "ScheduledStartTime" -#define SQLITE_COL_SCHEDULEDENDTIME "ScheduledEndTime" -#define SQLITE_COL_ICON "Icon" -#define SQLITE_COL_REGION "Region" -#define SQLITE_COL_CHANNELNR "ChannelNr" -#define SQLITE_COL_RIGHTS "Rights" -#define SQLITE_COL_RADIOCALLSIGN "CallSign" -#define SQLITE_COL_RADIOSTATIONID "StationID" -#define SQLITE_COL_RADIOBAND "Band" -#define SQLITE_COL_CONTRIBUTOR "Contributor" -#define SQLITE_COL_DATE "Date" -#define SQLITE_COL_ALBUM "Album" -#define SQLITE_COL_ARTIST "Artist" -#define SQLITE_COL_DLNA_CONTAINERTYPE "DLNAContainer" -#define SQLITE_COL_CHILDCOUNT "ChildCount" -#define SQLITE_COL_ITEMFINDER "ItemFastID" - -#define SQLITE_UPNP_OBJECTID SQLITE_COL_OBJECTID " " SQLITE_TYPE_INTEGER " " SQLITE_NOT_NULL " " SQLITE_CONFLICT_CLAUSE " "\ - SQLITE_UNIQUE " " SQLITE_CONFLICT_CLAUSE - -#define SQLITE_INSERT_TRIGGER(TableA,TableB,Class) "CREATE TRIGGER IF NOT EXISTS "\ - TableA "_I_" TableB " "\ - "BEFORE INSERT ON "\ - TableB " "\ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ("\ - "((SELECT " SQLITE_COL_OBJECTID " FROM " TableA " "\ - "WHERE " SQLITE_COL_OBJECTID "=NEW." SQLITE_COL_OBJECTID " "\ - ") IS NULL) "\ - "OR "\ - "((SELECT " SQLITE_COL_OBJECTID " FROM " SQLITE_TABLE_OBJECTS " "\ - "WHERE " SQLITE_COL_OBJECTID "=NEW." SQLITE_COL_OBJECTID " "\ - "AND " SQLITE_COL_CLASS " LIKE '" Class "%%') IS NULL) "\ - ") THEN "\ - "RAISE(" SQLITE_TRANSACTION_TYPE ", "\ - "'INSERT on table " TableB " failed due constraint violation "\ - "on foreign key " SQLITE_COL_OBJECTID "'"\ - ") "\ - "END; END;" - -#define SQLITE_UPDATE_TRIGGER(TableA,TableB,Class) "CREATE TRIGGER IF NOT EXISTS "\ - TableA "_U_" TableB " "\ - "BEFORE UPDATE ON "\ - TableB " "\ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ("\ - "((SELECT " SQLITE_COL_OBJECTID " FROM " SQLITE_TABLE_OBJECTS " "\ - "WHERE " SQLITE_COL_OBJECTID "=NEW." SQLITE_COL_OBJECTID " "\ - "AND " SQLITE_COL_CLASS " LIKE '" Class "%%') IS NULL)"\ - ") THEN "\ - "RAISE(" SQLITE_TRANSACTION_TYPE ", "\ - "'UPDATE on table " TableB " failed due constraint violation "\ - "on foreign key " SQLITE_COL_OBJECTID "'"\ - ") "\ - "END; END;" - -#define SQLITE_INSERT_REFERENCE_TRIGGER(Table,Column) "CREATE TRIGGER IF NOT EXISTS "\ - Table "_I_" Table " "\ - "BEFORE INSERT ON " \ - Table " " \ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ( "\ - "((SELECT " SQLITE_COL_OBJECTID " FROM " Table " "\ - "WHERE " SQLITE_COL_OBJECTID " = NEW." Column ") IS NULL) "\ - "AND "\ - "(NEW." Column "!=-1)"\ - ")THEN "\ - "RAISE(" SQLITE_TRANSACTION_TYPE ", 'INSERT on table " Table " "\ - "violates foreign key \"" Column "\"') "\ - "END; END;" - -#define SQLITE_UPDATE_REFERENCE_TRIGGER(Table,Column) "CREATE TRIGGER IF NOT EXISTS "\ - Table "_U_" Table " "\ - "BEFORE INSERT ON " \ - Table " " \ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ( "\ - "((SELECT " SQLITE_COL_OBJECTID " FROM " Table " "\ - "WHERE " SQLITE_COL_OBJECTID " = NEW." Column ") IS NULL) "\ - "AND "\ - "(NEW." Column "!=-1)"\ - ")THEN "\ - "RAISE(" SQLITE_TRANSACTION_TYPE ", 'UPDATE on table " Table " "\ - "violates foreign key \"" Column "\"') "\ - "END; END;" - -#define SQLITE_DELETE_REFERENCE_TRIGGER(Table,Column) "CREATE TRIGGER IF NOT EXISTS "\ - Table "_D_" Table " " \ - "BEFORE DELETE ON " \ - Table " " \ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ("\ - "(SELECT " Column " FROM " Table " "\ - "WHERE " Column " = OLD." SQLITE_COL_OBJECTID ") IS NOT NULL"\ - ")THEN "\ - "RAISE(" SQLITE_TRANSACTION_TYPE ", 'DELETE on table " Table " "\ - "violates foreign key \"" Column "\"') "\ - "END; END;" - -#ifdef SQLITE_CASCADE_DELETES -#define SQLITE_DELETE_TRIGGER(TableA,TableB) "CREATE TRIGGER IF NOT EXISTS "\ - TableA "_D_" TableB " "\ - "BEFORE DELETE ON "\ - TableA " "\ - "FOR EACH ROW BEGIN "\ - "DELETE FROM " TableB " "\ - "WHERE " SQLITE_COL_OBJECTID "=OLD." SQLITE_COL_OBJECTID "; "\ - "END;" - -#define SQLITE_DELETE_PARENT_TRIGGER "CREATE TRIGGER IF NOT EXISTS "\ - SQLITE_TABLE_OBJECTS "_D_" SQLITE_TABLE_OBJECTS " " \ - "BEFORE DELETE ON " \ - SQLITE_TABLE_OBJECTS " " \ - "FOR EACH ROW BEGIN "\ - "DELETE FROM " SQLITE_TABLE_OBJECTS " "\ - "WHERE " SQLITE_COL_PARENTID "=OLD." SQLITE_COL_OBJECTID "; "\ - "END;" -#else -#define SQLITE_DELETE_TRIGGER(TableA,TableB) "CREATE TRIGGER IF NOT EXISTS "\ - TableA "_D_" TableB " "\ - "BEFORE DELETE ON "\ - TableA " "\ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ("\ - "(SELECT " SQLITE_COL_OBJECTID " FROM " TableB " "\ - "WHERE " SQLITE_COL_OBJECTID "=OLD." SQLITE_COL_OBJECTID ") IS NOT NULL"\ - ") THEN "\ - "RAISE(" SQLITE_TRANSACTION_TYPE ", "\ - "'DELETE on table " TableA " failed due constraint violation "\ - "on foreign key " SQLITE_COL_OBJECTID "'"\ - ") "\ - "END; END;" - -#define SQLITE_DELETE_PARENT_TRIGGER SQLITE_DELETE_REFERENCE_TRIGGER(SQLITE_TABLE_OBJECTS, SQLITE_COL_PARENTID) -#endif - -/**********************************************\ -* * -* Primary keys * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_PRIMARY_KEYS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_PRIMARY_KEYS \ - "("\ - "KeyID " SQLITE_PRIMARY_KEY " " SQLITE_NOT_NULL ","\ - "Key " SQLITE_TYPE_INTEGER " " SQLITE_NOT_NULL\ - ");"\ - "INSERT OR IGNORE INTO "\ - SQLITE_TABLE_PRIMARY_KEYS \ - "(KeyID, Key) VALUES ("\ - PK_OBJECTS "," SQLITE_FIRST_CUSTOMID\ - ");"\ - "INSERT OR IGNORE INTO "\ - SQLITE_TABLE_PRIMARY_KEYS \ - "(KeyID, Key) VALUES ("\ - PK_RESOURCES ",0"\ - ");"\ - "INSERT OR IGNORE INTO "\ - SQLITE_TABLE_PRIMARY_KEYS \ - "(KeyID, Key) VALUES ("\ - PK_SEARCHCLASSES ",0"\ - ");" - -#define SQLITE_TRIGGER_UPDATE_OBJECTID "CREATE TRIGGER IF NOT EXISTS "\ - SQLITE_TABLE_OBJECTS "_PK_UPDATE "\ - "AFTER INSERT ON "\ - SQLITE_TABLE_OBJECTS " "\ - "BEGIN "\ - "UPDATE " SQLITE_TABLE_PRIMARY_KEYS " SET Key=Key+1 WHERE KeyID=" PK_OBJECTS "; "\ - "END;" - -/**********************************************\ -* * -* System settings * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_SYSTEM "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_SYSTEM " "\ - "("\ - "Key " SQLITE_TYPE_TEXT " " SQLITE_NOT_NULL " " SQLITE_UNIQUE ","\ - "Value " SQLITE_TYPE_TEXT " "\ - ");" - -#define SQLITE_TRIGGER_UPDATE_SYSTEM "CREATE TRIGGER IF NOT EXISTS "\ - SQLITE_TABLE_SYSTEM "_VALUE_UPDATE "\ - "BEFORE UPDATE "\ - "ON " SQLITE_TABLE_SYSTEM " "\ - "WHEN ((SELECT Key FROM " SQLITE_TABLE_SYSTEM " WHERE Key=NEW.Key) IS NULL) "\ - "BEGIN INSERT INTO " SQLITE_TABLE_SYSTEM " (Key) VALUES (NEW.Key); END;" - -/**********************************************\ -* * -* Fast item finder * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_ITEMFINDER "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_ITEMFINDER " "\ - "("\ - SQLITE_UPNP_OBJECTID ","\ - SQLITE_COL_ITEMFINDER " " SQLITE_TYPE_TEXT " " SQLITE_NOT_NULL " " SQLITE_UNIQUE \ - ");" - -#define SQLITE_TRIGGER_D_OBJECTS_ITEMFINDER SQLITE_DELETE_TRIGGER(SQLITE_TABLE_OBJECTS,\ - SQLITE_TABLE_ITEMFINDER) - -/**********************************************\ -* * -* Objects * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_OBJECTS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_OBJECTS \ - "(" \ - SQLITE_COL_OBJECTID " " SQLITE_PRIMARY_KEY " " SQLITE_NOT_NULL " " SQLITE_CONFLICT_CLAUSE "," \ - SQLITE_COL_PARENTID " " SQLITE_TYPE_INTEGER " " SQLITE_NOT_NULL " " SQLITE_CONFLICT_CLAUSE "," \ - SQLITE_COL_TITLE " " SQLITE_TYPE_TEXT " " SQLITE_NOT_NULL "," \ - SQLITE_COL_CREATOR " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_CLASS " " SQLITE_TYPE_TEXT " " SQLITE_NOT_NULL "," \ - SQLITE_COL_RESTRICTED " " SQLITE_TYPE_BOOL " " SQLITE_NOT_NULL "," \ - SQLITE_COL_WRITESTATUS " " SQLITE_TYPE_INTEGER \ - ");" - -// Trigger for foreign key ParentID - -#define SQLITE_TRIGGER_D_OBJECTS_OBJECTS SQLITE_DELETE_PARENT_TRIGGER - -#define SQLITE_TRIGGER_I_OBJECTS_OBJECTS SQLITE_INSERT_REFERENCE_TRIGGER(SQLITE_TABLE_OBJECTS, SQLITE_COL_PARENTID)\ - "CREATE TRIGGER IF NOT EXISTS "\ - SQLITE_TABLE_OBJECTS "_PI_" SQLITE_TABLE_OBJECTS " "\ - "BEFORE INSERT ON "\ - SQLITE_TABLE_OBJECTS " " \ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ("\ - "((SELECT " SQLITE_COL_PARENTID " FROM " SQLITE_TABLE_OBJECTS " "\ - "WHERE " SQLITE_COL_PARENTID "=-1) IS NOT NULL) "\ - "AND "\ - "(NEW." SQLITE_COL_PARENTID "=-1)"\ - ") THEN "\ - "RAISE(" SQLITE_TRANSACTION_TYPE ","\ - "'INSERT on table " SQLITE_TABLE_OBJECTS " violates constraint. "\ - SQLITE_COL_PARENTID " must uniquely be -1') "\ - "END; END;" - -#define SQLITE_TRIGGER_U_OBJECTS_OBJECTS SQLITE_UPDATE_REFERENCE_TRIGGER(SQLITE_TABLE_OBJECTS, SQLITE_COL_PARENTID)\ - "CREATE TRIGGER IF NOT EXISTS "\ - SQLITE_TABLE_OBJECTS "_PU_" SQLITE_TABLE_OBJECTS " "\ - "BEFORE UPDATE ON "\ - SQLITE_TABLE_OBJECTS " " \ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ("\ - "((SELECT " SQLITE_COL_PARENTID " FROM " SQLITE_TABLE_OBJECTS " "\ - "WHERE " SQLITE_COL_PARENTID "=-1 "\ - "AND " SQLITE_COL_OBJECTID "!=NEW." SQLITE_COL_OBJECTID " ) IS NOT NULL) "\ - "AND "\ - "(NEW." SQLITE_COL_PARENTID "=-1) AND (OLD." SQLITE_COL_PARENTID "!=-1) "\ - ") THEN "\ - "RAISE(" SQLITE_TRANSACTION_TYPE ","\ - "'UPDATE on table " SQLITE_TABLE_OBJECTS " violates constraint. "\ - SQLITE_COL_PARENTID " must uniquely be -1') "\ - "END; END;" - -/**********************************************\ -* * -* Items * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_ITEMS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_ITEMS \ - "(" \ - SQLITE_UPNP_OBJECTID "," \ - SQLITE_COL_REFERENCEID " " SQLITE_TYPE_INTEGER " DEFAULT -1" \ - ");" - -// Trigger for foreign key ObjectID - -#define SQLITE_TRIGGER_D_OBJECT_ITEMS SQLITE_DELETE_TRIGGER(SQLITE_TABLE_OBJECTS,\ - SQLITE_TABLE_ITEMS) - -#define SQLITE_TRIGGER_I_OBJECT_ITEMS SQLITE_INSERT_TRIGGER(SQLITE_TABLE_OBJECTS,\ - SQLITE_TABLE_ITEMS,\ - UPNP_CLASS_ITEM) - -#define SQLITE_TRIGGER_U_OBJECT_ITEMS SQLITE_UPDATE_TRIGGER(SQLITE_TABLE_OBJECTS,\ - SQLITE_TABLE_ITEMS,\ - UPNP_CLASS_ITEM) - -// Trigger for Reference items - -#define SQLITE_TRIGGER_I_ITEMS_ITEMS SQLITE_INSERT_REFERENCE_TRIGGER(SQLITE_TABLE_ITEMS, SQLITE_COL_REFERENCEID) - -#define SQLITE_TRIGGER_U_ITEMS_ITEMS SQLITE_UPDATE_REFERENCE_TRIGGER(SQLITE_TABLE_ITEMS, SQLITE_COL_REFERENCEID) - -#define SQLITE_TRIGGER_D_ITEMS_ITEMS SQLITE_DELETE_REFERENCE_TRIGGER(SQLITE_TABLE_ITEMS, SQLITE_COL_REFERENCEID) - -/**********************************************\ -* * -* Containers * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_CONTAINER "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_CONTAINERS \ - "(" \ - SQLITE_UPNP_OBJECTID "," \ - SQLITE_COL_SEARCHABLE " " SQLITE_TYPE_INTEGER ","\ - SQLITE_COL_CONTAINER_UID " " SQLITE_TYPE_INTEGER " " SQLITE_NOT_NULL ","\ - SQLITE_COL_DLNA_CONTAINERTYPE " " SQLITE_TYPE_TEXT \ - ");" - -#define SQLITE_TRIGGER_D_OBJECT_CONTAINERS SQLITE_DELETE_TRIGGER(SQLITE_TABLE_OBJECTS,\ - SQLITE_TABLE_CONTAINERS) - -#define SQLITE_TRIGGER_I_OBJECT_CONTAINERS SQLITE_INSERT_TRIGGER(SQLITE_TABLE_OBJECTS,\ - SQLITE_TABLE_CONTAINERS,\ - UPNP_CLASS_CONTAINER) - -#define SQLITE_TRIGGER_U_OBJECT_CONTAINERS SQLITE_UPDATE_TRIGGER(SQLITE_TABLE_OBJECTS,\ - SQLITE_TABLE_CONTAINERS,\ - UPNP_CLASS_CONTAINER) - -/**********************************************\ -* * -* Video items * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_VIDEOITEMS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_VIDEOITEMS \ - "(" \ - SQLITE_UPNP_OBJECTID "," \ - SQLITE_COL_GENRE " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_LONGDESCRIPTION " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_PRODUCER " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_RATING " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_ACTOR " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_DIRECTOR " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_DESCRIPTION " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_PUBLISHER " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_LANGUAGE " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_RELATION " " SQLITE_TYPE_TEXT \ - ");" - -#define SQLITE_TRIGGER_D_ITEMS_VIDEOITEMS SQLITE_DELETE_TRIGGER(SQLITE_TABLE_ITEMS, SQLITE_TABLE_VIDEOITEMS) - -#define SQLITE_TRIGGER_U_ITEMS_VIDEOITEMS SQLITE_UPDATE_TRIGGER(SQLITE_TABLE_ITEMS, \ - SQLITE_TABLE_VIDEOITEMS, \ - UPNP_CLASS_VIDEO) - -#define SQLITE_TRIGGER_I_ITEMS_VIDEOITEMS SQLITE_INSERT_TRIGGER(SQLITE_TABLE_ITEMS, \ - SQLITE_TABLE_VIDEOITEMS, \ - UPNP_CLASS_VIDEO) - -/**********************************************\ -* * -* Audio items * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_AUDIOITEMS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_AUDIOITEMS \ - "(" \ - SQLITE_UPNP_OBJECTID "," \ - SQLITE_COL_GENRE " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_LONGDESCRIPTION " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_DESCRIPTION " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_PUBLISHER " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_RELATION " " SQLITE_TYPE_TEXT \ - ");" - -#define SQLITE_TRIGGER_D_ITEMS_AUDIOITEMS SQLITE_DELETE_TRIGGER(SQLITE_TABLE_ITEMS, SQLITE_TABLE_AUDIOITEMS) - -#define SQLITE_TRIGGER_U_ITEMS_AUDIOITEMS SQLITE_UPDATE_TRIGGER(SQLITE_TABLE_ITEMS, \ - SQLITE_TABLE_AUDIOITEMS, \ - UPNP_CLASS_AUDIO) - -#define SQLITE_TRIGGER_I_ITEMS_AUDIOITEMS SQLITE_INSERT_TRIGGER(SQLITE_TABLE_ITEMS, \ - SQLITE_TABLE_AUDIOITEMS, \ - UPNP_CLASS_AUDIO) - -/**********************************************\ -* * -* Image items * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_IMAGEITEMS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_IMAGEITEMS \ - "("\ - SQLITE_UPNP_OBJECTID "," \ - SQLITE_COL_LONGDESCRIPTION " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_DESCRIPTION " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_PUBLISHER " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_STORAGEMEDIUM " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_RATING " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_DATE " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_RIGHTS " " SQLITE_TYPE_TEXT\ - ");" - -#define SQLITE_TRIGGER_D_ITEMS_IMAGEITEMS SQLITE_DELETE_TRIGGER(SQLITE_TABLE_ITEMS, SQLITE_TABLE_IMAGEITEMS) - -#define SQLITE_TRIGGER_U_ITEMS_IMAGEITEMS SQLITE_UPDATE_TRIGGER(SQLITE_TABLE_ITEMS, \ - SQLITE_TABLE_IMAGEITEMS, \ - UPNP_CLASS_IMAGE) - -#define SQLITE_TRIGGER_I_ITEMS_IMAGEITEMS SQLITE_INSERT_TRIGGER(SQLITE_TABLE_ITEMS, \ - SQLITE_TABLE_IMAGEITEMS, \ - UPNP_CLASS_IMAGE) - -/**********************************************\ -* * -* Video broadcasts * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_VIDEOBROADCASTS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_VIDEOBROADCASTS \ - "("\ - SQLITE_UPNP_OBJECTID "," \ - SQLITE_COL_ICON " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_REGION " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_CHANNELNR " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_CHANNELNAME " " SQLITE_TYPE_TEXT " " SQLITE_UNIQUE \ - ");" - -#define SQLITE_TRIGGER_D_VIDEOITEMS_VIDEOBROADCASTS SQLITE_DELETE_TRIGGER(SQLITE_TABLE_VIDEOITEMS, SQLITE_TABLE_VIDEOBROADCASTS) - -#define SQLITE_TRIGGER_U_VIDEOITEMS_VIDEOBROADCASTS SQLITE_UPDATE_TRIGGER(SQLITE_TABLE_VIDEOITEMS,\ - SQLITE_TABLE_VIDEOBROADCASTS,\ - UPNP_CLASS_VIDEOBC) - -#define SQLITE_TRIGGER_I_VIDEOITEMS_VIDEOBROADCASTS SQLITE_INSERT_TRIGGER(SQLITE_TABLE_VIDEOITEMS,\ - SQLITE_TABLE_VIDEOBROADCASTS,\ - UPNP_CLASS_VIDEOBC) - -/**********************************************\ -* * -* Audio broadcasts * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_AUDIOBROADCASTS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_AUDIOBROADCASTS \ - "("\ - SQLITE_UPNP_OBJECTID "," \ - SQLITE_COL_REGION " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_RADIOCALLSIGN " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_RADIOSTATIONID " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_RADIOBAND " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_CHANNELNR " " SQLITE_TYPE_INTEGER \ - ");" - -#define SQLITE_TRIGGER_D_AUDIOITEMS_AUDIOBROADCASTS SQLITE_DELETE_TRIGGER(SQLITE_TABLE_AUDIOITEMS, SQLITE_TABLE_AUDIOBROADCASTS) - -#define SQLITE_TRIGGER_I_AUDIOITEMS_AUDIOBROADCASTS SQLITE_INSERT_TRIGGER(SQLITE_TABLE_AUDIOITEMS,\ - SQLITE_TABLE_AUDIOBROADCASTS,\ - UPNP_CLASS_AUDIOBC) - -#define SQLITE_TRIGGER_U_AUDIOITEMS_AUDIOBROADCASTS SQLITE_UPDATE_TRIGGER(SQLITE_TABLE_AUDIOITEMS,\ - SQLITE_TABLE_AUDIOBROADCASTS,\ - UPNP_CLASS_AUDIOBC) - -/**********************************************\ -* * -* Movies * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_MOVIES "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_MOVIES \ - "("\ - SQLITE_UPNP_OBJECTID "," \ - SQLITE_COL_STORAGEMEDIUM " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_DVDREGIONCODE " " SQLITE_TYPE_INTEGER "," \ - SQLITE_COL_CHANNELNAME " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_SCHEDULEDSTARTTIME " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_SCHEDULEDENDTIME " " SQLITE_TYPE_TEXT\ - ");" - -#define SQLITE_TRIGGER_D_VIDEOITEMS_MOVIES SQLITE_DELETE_TRIGGER(SQLITE_TABLE_VIDEOITEMS, SQLITE_TABLE_MOVIES) - - -#define SQLITE_TRIGGER_I_VIDEOITEMS_MOVIES SQLITE_INSERT_TRIGGER(SQLITE_TABLE_VIDEOITEMS,\ - SQLITE_TABLE_MOVIES,\ - UPNP_CLASS_MOVIE) - -#define SQLITE_TRIGGER_U_VIDEOITEMS_MOVIES SQLITE_UPDATE_TRIGGER(SQLITE_TABLE_VIDEOITEMS,\ - SQLITE_TABLE_MOVIES,\ - UPNP_CLASS_MOVIE) - -/**********************************************\ -* * -* Photos * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_PHOTOS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_PHOTOS \ - "("\ - SQLITE_UPNP_OBJECTID "," \ - SQLITE_COL_ALBUM " " SQLITE_TYPE_TEXT\ - ");" - -#define SQLITE_TRIGGER_D_IMAGEITEMS_PHOTOS SQLITE_DELETE_TRIGGER(SQLITE_TABLE_IMAGEITEMS, SQLITE_TABLE_PHOTOS) - -#define SQLITE_TRIGGER_I_IMAGEITEMS_PHOTOS SQLITE_INSERT_TRIGGER(SQLITE_TABLE_IMAGEITEMS,\ - SQLITE_TABLE_PHOTOS,\ - UPNP_CLASS_PHOTO) - -#define SQLITE_TRIGGER_U_IMAGEITEMS_PHOTOS SQLITE_UPDATE_TRIGGER(SQLITE_TABLE_IMAGEITEMS,\ - SQLITE_TABLE_PHOTOS,\ - UPNP_CLASS_PHOTO) - -/**********************************************\ -* * -* Albums * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_ALBUMS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_ALBUMS \ - "("\ - SQLITE_UPNP_OBJECTID "," \ - SQLITE_COL_STORAGEMEDIUM " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_LONGDESCRIPTION " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_DESCRIPTION " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_PUBLISHER " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_CONTRIBUTOR " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_DATE " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_RELATION " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_RIGHTS " " SQLITE_TYPE_TEXT \ - ");" - -#define SQLITE_TRIGGER_D_CONTAINERS_ALBUMS SQLITE_DELETE_TRIGGER(SQLITE_TABLE_CONTAINERS, SQLITE_TABLE_ALBUMS) - -#define SQLITE_TRIGGER_U_CONTAINERS_ALBUMS SQLITE_UPDATE_TRIGGER(SQLITE_TABLE_CONTAINERS,\ - SQLITE_TABLE_ALBUMS,\ - UPNP_CLASS_ALBUM) - -#define SQLITE_TRIGGER_I_CONTAINERS_ALBUMS SQLITE_INSERT_TRIGGER(SQLITE_TABLE_CONTAINERS,\ - SQLITE_TABLE_ALBUMS,\ - UPNP_CLASS_ALBUM) - -/**********************************************\ -* * -* Playlists * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_PLAYLISTS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_PLAYLISTS \ - "(" \ - SQLITE_UPNP_OBJECTID "," \ - SQLITE_COL_ARTIST " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_GENRE " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_LONGDESCRIPTION " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_DESCRIPTION " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_PRODUCER " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_STORAGEMEDIUM " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_CONTRIBUTOR " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_DATE " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_LANGUAGE " " SQLITE_TYPE_TEXT ","\ - SQLITE_COL_RIGHTS " " SQLITE_TYPE_TEXT\ - ");" - -#define SQLITE_TRIGGER_D_CONTAINERS_PLAYLISTS SQLITE_DELETE_TRIGGER(SQLITE_TABLE_CONTAINERS, SQLITE_TABLE_PLAYLISTS) - -#define SQLITE_TRIGGER_I_CONTAINERS_PLAYLISTS SQLITE_INSERT_TRIGGER(SQLITE_TABLE_CONTAINERS,\ - SQLITE_TABLE_PLAYLISTS,\ - UPNP_CLASS_PLAYLISTCONT) - -#define SQLITE_TRIGGER_U_CONTAINERS_PLAYLISTS SQLITE_UPDATE_TRIGGER(SQLITE_TABLE_CONTAINERS,\ - SQLITE_TABLE_PLAYLISTS,\ - UPNP_CLASS_PLAYLISTCONT) - -/**********************************************\ -* * -* Search classes * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_SEARCHCLASS "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_SEARCHCLASS \ - "(" \ - SQLITE_COL_OBJECTID " " SQLITE_TYPE_INTEGER " " SQLITE_NOT_NULL "," \ - SQLITE_COL_CLASS " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_CLASSDERIVED " " SQLITE_TYPE_BOOL \ - ");" - -#define SQLITE_TRIGGER_D_CONTAINERS_SEARCHCLASSES "CREATE TRIGGER IF NOT EXISTS " \ - SQLITE_TABLE_CONTAINERS "_D_" SQLITE_TABLE_SEARCHCLASS " " \ - "BEFORE DELETE ON " \ - SQLITE_TABLE_CONTAINERS " " \ - "FOR EACH ROW BEGIN "\ - "DELETE FROM " SQLITE_TABLE_SEARCHCLASS " "\ - "WHERE " SQLITE_COL_OBJECTID "= OLD." SQLITE_COL_OBJECTID "; " \ - "END;" - -#define SQLITE_TRIGGER_U_CONTAINERS_SEARCHCLASSES "CREATE TRIGGER IF NOT EXISTS " \ - SQLITE_TABLE_CONTAINERS "_U_" SQLITE_TABLE_SEARCHCLASS " " \ - "BEFORE UPDATE ON " \ - SQLITE_TABLE_SEARCHCLASS " " \ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ("\ - "(SELECT " SQLITE_COL_OBJECTID " FROM " SQLITE_TABLE_CONTAINERS " "\ - "WHERE " SQLITE_COL_OBJECTID "=NEW." SQLITE_COL_OBJECTID ") IS NULL "\ - ") THEN "\ - "RAISE (" SQLITE_TRANSACTION_TYPE ", 'UPDATE on table " SQLITE_TABLE_SEARCHCLASS " "\ - "violates foreign key constraint \"" SQLITE_COL_OBJECTID "\"') " \ - "END; END;" - -#define SQLITE_TRIGGER_I_CONTAINERS_SEARCHCLASSES "CREATE TRIGGER IF NOT EXISTS " \ - SQLITE_TABLE_CONTAINERS "_I_" SQLITE_TABLE_SEARCHCLASS " " \ - "BEFORE INSERT ON " \ - SQLITE_TABLE_SEARCHCLASS " " \ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ("\ - "(SELECT " SQLITE_COL_OBJECTID " FROM " SQLITE_TABLE_CONTAINERS " "\ - "WHERE " SQLITE_COL_OBJECTID "=NEW." SQLITE_COL_OBJECTID ") IS NULL "\ - ") THEN "\ - "RAISE (" SQLITE_TRANSACTION_TYPE ", 'INSERT on table " SQLITE_TABLE_SEARCHCLASS " "\ - "violates foreign key constraint \"" SQLITE_COL_OBJECTID "\"') " \ - "END; END;" - -/**********************************************\ -* * -* Resources * -* * -\**********************************************/ - -#define SQLITE_CREATE_TABLE_RESOURCES "CREATE TABLE IF NOT EXISTS "\ - SQLITE_TABLE_RESOURCES \ - "(" \ - SQLITE_COL_RESOURCEID " " SQLITE_PRIMARY_KEY " " SQLITE_NOT_NULL "," \ - SQLITE_COL_OBJECTID " " SQLITE_TYPE_INTEGER " " SQLITE_NOT_NULL "," \ - SQLITE_COL_PROTOCOLINFO " " SQLITE_TYPE_TEXT " " SQLITE_NOT_NULL "," \ - SQLITE_COL_CONTENTTYPE " " SQLITE_TYPE_TEXT " " SQLITE_NOT_NULL "," \ - SQLITE_COL_RESOURCETYPE " " SQLITE_TYPE_INTEGER " " SQLITE_NOT_NULL "," \ - SQLITE_COL_RESOURCE " " SQLITE_TYPE_TEXT " " SQLITE_NOT_NULL "," \ - SQLITE_COL_SIZE " " SQLITE_TYPE_ULONG "," \ - SQLITE_COL_DURATION " " SQLITE_TYPE_TEXT "," \ - SQLITE_COL_BITRATE " " SQLITE_TYPE_UINTEGER "," \ - SQLITE_COL_SAMPLEFREQUENCE " " SQLITE_TYPE_UINTEGER "," \ - SQLITE_COL_BITSPERSAMPLE " " SQLITE_TYPE_UINTEGER "," \ - SQLITE_COL_NOAUDIOCHANNELS " " SQLITE_TYPE_UINTEGER "," \ - SQLITE_COL_COLORDEPTH " " SQLITE_TYPE_UINTEGER "," \ - SQLITE_COL_RESOLUTION " " SQLITE_TYPE_TEXT \ - ");" - -#define SQLITE_TRIGGER_D_OBJECT_RESOURCES "CREATE TRIGGER IF NOT EXISTS " \ - SQLITE_TABLE_OBJECTS "_D_" SQLITE_TABLE_RESOURCES " " \ - "BEFORE DELETE ON " \ - SQLITE_TABLE_OBJECTS " " \ - "FOR EACH ROW BEGIN "\ - "DELETE FROM " SQLITE_TABLE_RESOURCES " "\ - "WHERE " SQLITE_COL_OBJECTID "= OLD." SQLITE_COL_OBJECTID "; " \ - "END;" - -#define SQLITE_TRIGGER_I_OBJECT_RESOURCES "CREATE TRIGGER IF NOT EXISTS " \ - SQLITE_TABLE_OBJECTS "_I_" SQLITE_TABLE_RESOURCES " " \ - "BEFORE INSERT ON " \ - SQLITE_TABLE_RESOURCES " " \ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ("\ - "(SELECT " SQLITE_COL_OBJECTID " FROM " SQLITE_TABLE_OBJECTS " "\ - "WHERE " SQLITE_COL_OBJECTID "=NEW." SQLITE_COL_OBJECTID ") IS NULL"\ - ") THEN "\ - "RAISE (" SQLITE_TRANSACTION_TYPE ", 'INSERT on table " SQLITE_TABLE_RESOURCES " "\ - "violates foreign key constraint \"" SQLITE_COL_OBJECTID "\"') " \ - "END; END;" - -#define SQLITE_TRIGGER_U_OBJECT_RESOURCES "CREATE TRIGGER IF NOT EXISTS " \ - SQLITE_TABLE_OBJECTS "_U_" SQLITE_TABLE_RESOURCES " " \ - "BEFORE UPDATE ON " \ - SQLITE_TABLE_RESOURCES " " \ - "FOR EACH ROW BEGIN "\ - "SELECT CASE "\ - "WHEN ("\ - "(SELECT " SQLITE_COL_OBJECTID " FROM " SQLITE_TABLE_OBJECTS " "\ - "WHERE " SQLITE_COL_OBJECTID "=NEW." SQLITE_COL_OBJECTID ") IS NULL"\ - ") THEN "\ - "RAISE (" SQLITE_TRANSACTION_TYPE ", 'INSERT on table " SQLITE_TABLE_RESOURCES " "\ - "violates foreign key constraint \"" SQLITE_COL_OBJECTID "\"') " \ - "END; END;" - -class cSQLiteDatabase; - -/** - * Result row of a SQL SELECT request - * - * This is a single row of a {\c SQL SELECT} request. - * - * @see cRows - */ -class cRow : public cListObject { - friend class cSQLiteDatabase; -private: - int currentCol; - int ColCount; - char** Columns; - char** Values; - cRow(); -public: - virtual ~cRow(); - /** - * Number of columns in this row - * - * @return the number of rows - */ - int Count(){ return this->ColCount; } - /** - * Fetches a Column - * - * This will fetch a column of this row and stores the name of the column - * in the first parameter and the value in the second parameter. - * - * @return returns - * - \bc true, if more columns to come - * - \bc false, if the column is its last in this row. - */ - bool fetchColumn( - cString* Column, /**< The name of the current column */ - cString* Value /**< The value of the current value */ - ); - - /** - * Fetches a Column - * - * This will fetch a column of this row and stores the name of the column - * in the first parameter and the value in the second parameter. - * - * @return returns - * - \bc true, if more columns to come - * - \bc false, if the column is its last in this row. - */ - bool fetchColumn( - char** Column, /**< The name of the current column */ - char** Value /**< The value of the current column */ - ); -}; - -/** - * Result rows of a SQL SELECT request - * - * Contains the rows of a SQL SELECT request - * - * @see cRow - */ -class cRows : public cList<cRow> { - friend class cSQLiteDatabase; -private: - cRow* mLastRow; - cRows(); -public: - virtual ~cRows(); - /** - * Fetches a row from the result - * - * This fetches the next row in the resultset by storing the contents of - * that row in the first parameter. - * - * @return returns - * - \bc true, if more rows to come - * - \bc false, if the row is its last in this resultset. - */ - bool fetchRow( - cRow** Row /**< The Pointer of the row */ - ); -}; - -/** - * SQLite Database - * - * This is a wrapper class for a SQLite3 database connection - * It supports simple execution functions. - * - * On requests with returns any results a instance of \c cRows* will be created. - */ -class cSQLiteDatabase { - friend class cStatement; -private: - bool mAutoCommit; - bool mActiveTransaction; - cRow* mLastRow; - cRows* mRows; - sqlite3* mDatabase; - static cSQLiteDatabase* mInstance; - cSQLiteDatabase(); - int initialize(); - int initializeTables(); - int initializeTriggers(); - static int getResultRow(void* DB, int NumCols, char** Values, char** ColNames); - int exec(const char* Statement); -public: - /** - * Prints a SQLite escaped text - * - * Returns a formated text with special characters to escape SQLite special - * characters like "'". Additionally to the well known characters of \a printf - * the following are allowed: - * - * - \bc q, like s, escapes single quotes in strings - * - \bc Q, like q, surrounds the escaped string with additional - * single quotes - * - \bc z, frees the string after reading and coping it - * - * @see sprintf() - * @return the formated string - */ - static const char* sprintf( - const char* Format, /**< The format string */ - ... /**< optional properties which will be passed to sprintf */ - ); - virtual ~cSQLiteDatabase(); - /** - * Returns the instance of the database - * - * Returns the instance of the SQLite database. This will create a single - * instance of none is existing on the very first call. A subsequent call - * will return the same instance. - * - * @return the database instance - */ - static cSQLiteDatabase* getInstance(); - /** - * Row count of the last result - * - * Returns the row count of the last {\c SQL SELECT} request. - * - * @see cRows - * @return the result row count - */ - int getResultCount() const { return this->mRows->Count(); } - /** - * The last \c INSERT RowID - * - * Returns the primary key of the last inserted row. - * This will only work if there are no successive calls to the database. - * - * @return the last insert RowID - */ - long getLastInsertRowID() const; - /** - * Result set of the last request - * - * Returns the result rows of the SQL SELECT request. - * This might be NULL, if the last statement was not a SELECT. - * - * @see cRows - * @return the result rows of the last \c SELECT statement. - */ - cRows* getResultRows() const { return this->mRows; } - /** - * Executes a SQL statement - * - * This will execute the statement in the first parameter. If it is followed - * by any optional parameters it will be formated using the same function as - * in \c cSQLiteDatabase::sprintf(). - * - * \sa cSQLiteDatabase::sprintf(). - * - * @return returns an integer representing - * - \bc -1, in case of an error - * - \bc 0, when the statement was executed successfuly - */ - int execStatement( - const char* Statement , /**< Statement to be executed */ - ... /**< optional parameters passed to the format string */ - ); - /** - * Starts a transaction - * - * This starts a new transaction and commits or rolls back a previous. - * - * @see cSQLiteDatabase::setAutoCommit - * @see cSQLiteDatabase::commitTransaction - */ - void startTransaction(); - /** - * Commits a transaction - * - * This function commits the transaction and writes all changes to the - * database - * - * @see cSQLiteDatabase::startTransaction - */ - void commitTransaction(); - /** - * Performs a rollback on a transaction - * - * This function performs a rollback. No changes will be made to the - * database - * - * @see cSQLiteDatabase::rollbackTransaction - */ - void rollbackTransaction(); - /** - * Set the commit behavior - * - * This function sets the auto commit behavior on new transactions with - * \sa cSQLiteDatabase::startTransaction. - * - * - \bc true, commits the last transaction before starting a - * new one - * - \bc false, performs a rollback on the old transaction - * - */ - void setAutoCommit( - bool Commit=true /**< Switches the behavior of auto commit */ - ){ this->mAutoCommit = Commit; } -}; - -#endif /* _DATABASE_H */
\ No newline at end of file diff --git a/database/metadata.cpp b/database/metadata.cpp index 91c512f..2bfa2d1 100644 --- a/database/metadata.cpp +++ b/database/metadata.cpp @@ -12,7 +12,7 @@ #include "resources.h" #include "metadata.h" #include "../common.h" -#include "../misc/search.h" +#include "search.h" #include <vdr/channels.h> #include <vdr/epg.h> #include <upnp/upnp.h> @@ -49,14 +49,18 @@ bool cMediaDatabase::init(){ ERROR("Initializing of database failed."); return false; } +#ifndef WITHOUT_TV if(this->loadChannels()){ ERROR("Loading channels failed"); return false; } +#endif +#ifndef WITHOUT_RECORDS if(this->loadRecordings()){ ERROR("Loading records failed"); return false; } +#endif return true; } @@ -195,58 +199,65 @@ int cMediaDatabase::prepareDatabase(){ cUPnPClassContainer* Root = (cUPnPClassContainer*)this->mFactory->createObject(UPNP_CLASS_CONTAINER, _(PLUGIN_SHORT_NAME)); Root->setID(0); if(this->mFactory->saveObject(Root)) return -1; - - cClass VideoClass = { UPNP_CLASS_VIDEO, true }; - cClass AudioClass = { UPNP_CLASS_AUDIO, true }; - cClass VideoBCClass = { UPNP_CLASS_VIDEOBC, true }; - cClass AudioBCClass = { UPNP_CLASS_AUDIOBC, true }; - + +#ifndef WITHOUT_VIDEO cUPnPClassContainer* Video = (cUPnPClassContainer*)this->mFactory->createObject(UPNP_CLASS_CONTAINER, _("Video")); Video->setID(1); Root->addObject(Video); + cClass VideoClass = { UPNP_CLASS_VIDEO, true }; Video->addSearchClass(VideoClass); Video->setSearchable(true); if(this->mFactory->saveObject(Video)) return -1; - +#endif +#ifndef WITHOUT_AUDIO cUPnPClassContainer* Audio = (cUPnPClassContainer*)this->mFactory->createObject(UPNP_CLASS_CONTAINER, _("Audio")); Audio->setID(2); Root->addObject(Audio); + cClass AudioClass = { UPNP_CLASS_AUDIO, true }; Audio->addSearchClass(AudioClass); Audio->setSearchable(true); if(this->mFactory->saveObject(Audio)) return -1; - +#endif +#ifndef WITHOUT_TV cUPnPClassContainer* TV = (cUPnPClassContainer*)this->mFactory->createObject(UPNP_CLASS_CONTAINER, _("TV")); TV->setID(3); TV->setContainerType(DLNA_CONTAINER_TUNER); TV->setSearchable(true); + cClass VideoBCClass = { UPNP_CLASS_VIDEOBC, true }; TV->addSearchClass(VideoBCClass); Video->addObject(TV); if(this->mFactory->saveObject(TV)) return -1; - +#endif +#ifndef WITHOUT_RECORDS cUPnPClassContainer* Records = (cUPnPClassContainer*)this->mFactory->createObject(UPNP_CLASS_CONTAINER, _("Records")); Records->setID(4); Video->addObject(Records); Records->addSearchClass(VideoClass); Records->setSearchable(true); if(this->mFactory->saveObject(Records)) return -1; - +#endif +#ifndef WITHOUT_RADIO cUPnPClassContainer* Radio = (cUPnPClassContainer*)this->mFactory->createObject(UPNP_CLASS_CONTAINER, _("Radio")); Radio->setID(5); Audio->addObject(Radio); + cClass AudioBCClass = { UPNP_CLASS_AUDIOBC, true }; Radio->addSearchClass(AudioBCClass); Radio->setSearchable(true); if(this->mFactory->saveObject(Radio)) return -1; - +#endif +#ifndef WITHOUT_CUSTOM_VIDEOS cUPnPClassContainer* CustomVideos = (cUPnPClassContainer*)this->mFactory->createObject(UPNP_CLASS_CONTAINER, _("User videos")); CustomVideos->setID(6); Video->addObject(CustomVideos); CustomVideos->addSearchClass(VideoClass); CustomVideos->setSearchable(true); if(this->mFactory->saveObject(CustomVideos)) return -1; +#endif } return 0; } +#ifndef WITHOUT_TV int cMediaDatabase::loadChannels(){ MESSAGE(VERBOSE_LIVE_TV ,"Loading channels"); cUPnPClassContainer* TV = (cUPnPClassContainer*)this->getObjectByID(3); @@ -317,6 +328,70 @@ int cMediaDatabase::loadChannels(){ return 0; } +void cMediaDatabase::updateChannelEPG(){ + cUPnPClassContainer* TV = (cUPnPClassContainer*)this->getObjectByID(3); + if(TV){ + // Iterating channels + MESSAGE(VERBOSE_EPG_UPDATES, "Getting schedule..."); + cSchedulesLock SchedulesLock; + const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock); + + cList<cUPnPClassObject>* List = TV->getObjectList(); + MESSAGE(VERBOSE_EPG_UPDATES, "TV folder has %d items", List->Count()); + for(cUPnPClassVideoBroadcast* ChannelItem = (cUPnPClassVideoBroadcast*)List->First(); + ChannelItem; + ChannelItem = (cUPnPClassVideoBroadcast*)List->Next(ChannelItem) + ){ + MESSAGE(VERBOSE_EPG_UPDATES, "Find channel by number %d", ChannelItem->getChannelNr()); + cChannel* Channel = Channels.GetByNumber(ChannelItem->getChannelNr()); + + if(!Channel){ + continue; + } + else { + MESSAGE(VERBOSE_EPG_UPDATES, "Found channel with ID %s", *Channel->GetChannelID().ToString()); + + const cSchedule* Schedule = Schedules->GetSchedule(Channel); + const cEvent* Event = Schedule?Schedule->GetPresentEvent():NULL; + if(Event){ + + time_t LastEPGChange = Event->StartTime(); + time_t LastObjectChange = ChannelItem->modified(); + + MESSAGE(VERBOSE_EPG_UPDATES, "Last event start: %s", ctime(&LastEPGChange)); + MESSAGE(VERBOSE_EPG_UPDATES, "Last object modification: %s", ctime(&LastObjectChange)); + if(LastEPGChange >= LastObjectChange){ + MESSAGE(VERBOSE_EPG_UPDATES, "Updating details"); + + if(Event){ + ChannelItem->setTitle(Event->Title()?Event->Title():Channel->Name()); + ChannelItem->setLongDescription(Event->Description()); + ChannelItem->setDescription(Event->ShortText()); + } + else { + ChannelItem->setTitle(Channel->Name()); + ChannelItem->setLongDescription(NULL); + ChannelItem->setDescription(NULL); + } + + this->mFactory->saveObject(ChannelItem); + } + else { + MESSAGE(VERBOSE_EPG_UPDATES, "Channel did not change"); + } + } + else { + MESSAGE(VERBOSE_EPG_UPDATES, "No EPG data"); + ChannelItem->setTitle(Channel->Name()); + ChannelItem->setLongDescription(NULL); + ChannelItem->setDescription(NULL); + } + } + } + } +} +#endif +#ifndef WITHOUT_RECORDS int cMediaDatabase::loadRecordings(){ MESSAGE(VERBOSE_RECORDS, "Loading recordings"); cUPnPClassContainer* Records = (cUPnPClassContainer*)this->getObjectByID(4); @@ -344,7 +419,7 @@ int cMediaDatabase::loadRecordings(){ MESSAGE(VERBOSE_RECORDS, "Adding movie '%s' File name:%s", RecInfo->Title(), Recording->FileName()); - MovieItem = (cUPnPClassMovie*)this->mFactory->createObject(UPNP_CLASS_MOVIE, RecInfo->Title()); + MovieItem = (cUPnPClassMovie*)this->mFactory->createObject(UPNP_CLASS_MOVIE, RecInfo->Title()?RecInfo->Title():Recording->Name()); MovieItem->setDescription(RecInfo->ShortText()); MovieItem->setLongDescription(RecInfo->Description()); MovieItem->setStorageMedium(UPNP_STORAGE_HDD); @@ -380,6 +455,7 @@ int cMediaDatabase::loadRecordings(){ } return 0; } +#endif void cMediaDatabase::Action(){ time_t LastEPGUpdate = 0; @@ -395,63 +471,6 @@ void cMediaDatabase::Action(){ } } -void cMediaDatabase::updateChannelEPG(){ - cUPnPClassContainer* TV = (cUPnPClassContainer*)this->getObjectByID(3); - if(TV){ - // Iterating channels - MESSAGE(VERBOSE_EPG_UPDATES, "Getting schedule..."); - cSchedulesLock SchedulesLock; - const cSchedules *Schedules = cSchedules::Schedules(SchedulesLock); - - cList<cUPnPClassObject>* List = TV->getObjectList(); - MESSAGE(VERBOSE_EPG_UPDATES, "TV folder has %d items", List->Count()); - for(cUPnPClassVideoBroadcast* ChannelItem = (cUPnPClassVideoBroadcast*)List->First(); - ChannelItem; - ChannelItem = (cUPnPClassVideoBroadcast*)List->Next(ChannelItem) - ){ - MESSAGE(VERBOSE_EPG_UPDATES, "Find channel by number %d", ChannelItem->getChannelNr()); - cChannel* Channel = Channels.GetByNumber(ChannelItem->getChannelNr()); - MESSAGE(VERBOSE_EPG_UPDATES, "Found channel with ID %s", *Channel->GetChannelID().ToString()); - - const cSchedule* Schedule = Schedules->GetSchedule(Channel); - const cEvent* Event = Schedule?Schedule->GetPresentEvent():NULL; - if(Event){ - - time_t LastEPGChange = Event->StartTime(); - time_t LastObjectChange = ChannelItem->modified(); - - MESSAGE(VERBOSE_EPG_UPDATES, "Last event start: %s", ctime(&LastEPGChange)); - MESSAGE(VERBOSE_EPG_UPDATES, "Last object modification: %s", ctime(&LastObjectChange)); - if(LastEPGChange >= LastObjectChange){ - MESSAGE(VERBOSE_EPG_UPDATES, "Updating details"); - - if(Event){ - ChannelItem->setTitle(Event->Title()?Event->Title():Channel->Name()); - ChannelItem->setLongDescription(Event->Description()); - ChannelItem->setDescription(Event->ShortText()); - } - else { - ChannelItem->setTitle(Channel->Name()); - ChannelItem->setLongDescription(NULL); - ChannelItem->setDescription(NULL); - } - - this->mFactory->saveObject(ChannelItem); - } - else { - MESSAGE(VERBOSE_EPG_UPDATES, "Channel did not change"); - } - } - else { - MESSAGE(VERBOSE_EPG_UPDATES, "No EPG data"); - ChannelItem->setTitle(Channel->Name()); - ChannelItem->setLongDescription(NULL); - ChannelItem->setDescription(NULL); - } - } - } -} - int cMediaDatabase::browse( OUT cUPnPResultSet** Results, IN const char* ID, diff --git a/database/metadata.h b/database/metadata.h deleted file mode 100644 index 4868231..0000000 --- a/database/metadata.h +++ /dev/null @@ -1,185 +0,0 @@ -/* - * File: metadata.h - * Author: savop - * - * Created on 28. Mai 2009, 21:14 - */ - -#ifndef _METADATA_H -#define _METADATA_H - -#include <vdr/tools.h> -#include <vdr/channels.h> -#include <vdr/recording.h> -#include "../common.h" -#include "database.h" -#include "object.h" -#include "resources.h" - -/** - * The result set of a request - * - * This contains the results of a previous \e Browse or \e Search request. - */ -struct cUPnPResultSet { - int mNumberReturned; ///< The number of returned matches - int mTotalMatches; ///< The total amount of matches - const char* mResult; ///< The DIDL-Lite fragment -}; - -/** - * The media database - * - * This class is the global object manager. It holds every object in a local cache. - * Only this class is allowed to create new objects. - * - * @see cUPnPClassObject - */ -class cMediaDatabase : public cThread { - friend class cUPnPServer; - friend class cUPnPObjectMediator; -private: - unsigned int mSystemUpdateID; - cUPnPObjectFactory* mFactory; - cHash<cUPnPClassObject>* mObjects; - cSQLiteDatabase* mDatabase; - cUPnPObjectID mLastInsertObjectID; - cUPnPObjectID getNextObjectID(); - void cacheObject(cUPnPClassObject* Object); - int prepareDatabase(); - int loadChannels(); - int loadRecordings(); - void updateChannelEPG(); - void updateRecordings(); - bool init(); - void updateSystemID(); - virtual void Action(); -public: - /** - * Returns the SystemUpdateID - * - * This returns the \e SystemUpdateID. This changes whenever anything changed - * within the content directory. This value will be sent through the UPnP - * network every 2 seconds. - * - * @return the SystemUpdateID - */ - unsigned int getSystemUpdateID(); - /** - * Returns a CSV list with ContainerUpdateIDs - * - * This list contains an unordered list of ordered pairs of ContainerID and - * its ContainerUpdateID. It contains only recent changes which are not yet - * beeing evented. This means that evented updates will be removed from list. - * - * @return CSV list of ContainerUpdateIDs - */ - const char* getContainerUpdateIDs(); - /** - * Constructor - * - * This creates an instance of the media database. - */ - cMediaDatabase(); - virtual ~cMediaDatabase(); - /** - * Add a Fastfind - * - * This creates a \e Fastfind entry. It is a string which can be used to - * relocate a objectID. Usually this is a file name or another ID with which - * the related object can be found. - * - * @return returns - * - \bc -1, if the creation was successful - * - \bc 0, otherwise - */ - int addFastFind( - cUPnPClassObject* Object, ///< the object, which should be registered - const char* FastFind ///< the string with which the object shall be - ///< relocated - ); - /** - * Finds a object by Fastfind - * - * This returns the object via the \e Fastfind string. The object must be - * previosly registered via \c cMediaDatabase::addFastFind(). - * - * It tries to find the object in the internal object cache. If this fails, - * the object will be loaded from the database. - * - * @see cMediaDatabase::addFastFind - * @return The object associated with FastFind - */ - cUPnPClassObject* getObjectByFastFind( - const char* FastFind ///< the string with which the object shall be - ///< relocated - ); - /** - * Finds a object by its ObjectID - * - * This returns the object via its \e ObjectID. - * - * It tries to find the object in the internal object cache. If this fails, - * the object will be loaded from the database. - * - * @return The object associated with FastFind - */ - cUPnPClassObject* getObjectByID( - cUPnPObjectID ID ///< The ObjectID of the requested object - ); - /** - * Performs a browse on the database - * - * This performs a browse request on the database and returns a structure - * containing the matching count and DIDL-Lite fragement which is sent to - * the control point. - * - * @return returns an integer representing one of the following: - * - \bc UPNP_CDS_E_INVALID_SORT_CRITERIA, when the sort criteria is malformed - * - \bc UPNP_CDS_E_CANT_PROCESS_REQUEST, when there is an internal error while - * processing the request - * - \bc UPNP_CDS_E_NO_SUCH_OBJECT, when the requested ObjectID does not exist - * - \bc UPNP_SOAP_E_ACTION_FAILED, when the action failed due any reasons - * - \bc UPNP_E_SUCCESS, if the request was successful - */ - int browse( - OUT cUPnPResultSet** Results, ///< the result of the request - IN const char* ID, ///< the objectID of the request - IN bool BrowseMetadata, ///< \b true to browse metadata, \b false otherwise - IN const char* Filter = "*", ///< the filter applied to the returned metadata - IN unsigned int Offset = 0, ///< the starting offset - IN unsigned int Count = 0, ///< maximum count returned - IN const char* SortCriteria = "" ///< sorts the results before returning them - ); - /** - * Performs a search on the database - * - * This performs a search request on the database and returns a structure - * containing the matching count and DIDL-Lite fragement which is sent to - * the control point. - * - * @note - * The submitted ID must be a ContainerID. Searches are performed only - * in this container. - * - * @return returns an integer representing one of the following: - * - \bc UPNP_CDS_E_INVALID_SORT_CRITERIA, when the sort criteria is malformed - * - \bc UPNP_CDS_E_CANT_PROCESS_REQUEST, when there is an internal error while - * processing the request - * - \bc UPNP_CDS_E_NO_SUCH_OBJECT, when the requested ObjectID does not exist - * - \bc UPNP_SOAP_E_ACTION_FAILED, when the action failed due any reasons - * - \bc UPNP_E_SUCCESS, if the request was successful - */ - int search( - OUT cUPnPResultSet** Results, ///< the result of the request - IN const char* ID, ///< the ContainerID - IN const char* Search, ///< the search string - IN const char* Filter = "*", ///< the filter applied to the returned metadata - IN unsigned int Offset = 0, ///< the starting offset - IN unsigned int Count = 0, ///< maximum count returned - IN const char* SortCriteria = "" ///< sorts the results before returning them - ); -}; - -#endif /* _METADATA_H */ - diff --git a/database/object.cpp b/database/object.cpp index 5ab355d..71dfe63 100644 --- a/database/object.cpp +++ b/database/object.cpp @@ -18,46 +18,6 @@ #include "../common.h" #include "resources.h" -cUPnPResource::cUPnPResource(){ - this->mBitrate = 0; - this->mBitsPerSample = 0; - this->mColorDepth = 0; - this->mDuration = NULL; - this->mImportURI = NULL; - this->mNrAudioChannels = 0; - this->mObjectID = 0; - this->mProtocolInfo = NULL; - this->mResolution = NULL; - this->mResource = NULL; - this->mResourceID = 0; - this->mSampleFrequency = 0; - this->mSize = 0; - this->mContentType = NULL; -} - -time_t cUPnPResource::getLastModification() const { - time_t Time; - const cRecording* Recording; - const cEvent* Event; - switch(this->mResourceType){ - case UPNP_RESOURCE_CHANNEL: - case UPNP_RESOURCE_URL: - Time = time(NULL); - break; - case UPNP_RESOURCE_RECORDING: - Recording = Recordings.GetByName(this->mResource); - Event = (Recording)?Recording->Info()->GetEvent():NULL; - Time = (Event)?Event->EndTime():time(NULL); - break; - case UPNP_RESOURCE_FILE: - //break; - default: - ERROR("Invalid resource type. This resource might be broken"); - Time = -1; - } - return Time; -} - static int CompareUPnPObjects(const void *a, const void *b){ const cUPnPClassObject *la = *(const cUPnPClassObject **)a; const cUPnPClassObject *lb = *(const cUPnPClassObject **)b; diff --git a/database/object.h b/database/object.h deleted file mode 100644 index 9c2c133..0000000 --- a/database/object.h +++ /dev/null @@ -1,1728 +0,0 @@ -/* - * File: object.h - * Author: savop - * - * Created on 11. September 2009, 20:39 - */ - -#ifndef _OBJECT_H -#define _OBJECT_H - -#include "database.h" -#include "../common.h" -#include "../misc/util.h" -#include <string.h> -#include <vdr/tools.h> -#include <map> -#include <vector> -#include <upnp/ixml.h> - -/** - * UPnP Object ID - * - * This is a UPnP Object ID representation. - */ -struct cUPnPObjectID { - int _ID; ///< The UPnP Object ID - /** - * Constructor - * - * Creates invalid ID - */ - cUPnPObjectID():_ID(-1){} - /** - * Constructor - * - * Creates from long integer - */ - cUPnPObjectID( - long ID ///< new ID - ){ _ID = (int)ID; } - /** - * Constructor - * - * Creates from integer - */ - cUPnPObjectID( - int ID ///< new ID - ){ _ID = ID; } - /** Set the object ID */ - cUPnPObjectID &operator=( - long ID ///< new ID - ){ _ID = ID; return *this; } - /** @overload cUPnPObjectID &operator=(long ID) */ - cUPnPObjectID &operator=( - int ID ///< new ID - ){ _ID = ID; return *this; } - /** @overload cUPnPObjectID &operator=(long ID) */ - cUPnPObjectID &operator=( - const cUPnPObjectID& ID ///< new ID - ){ if(this != &ID){ _ID = ID._ID; } return *this; } - /** Pre increment the ID */ - cUPnPObjectID &operator++(){ _ID++; return *this; } - /** Post increment the ID */ - cUPnPObjectID operator++(int){ cUPnPObjectID old = *this; _ID++; return old; } - /** Post decrement the ID */ - cUPnPObjectID operator--(int){ cUPnPObjectID old = *this; _ID--; return old; } - /** Pre decrement the ID */ - cUPnPObjectID &operator--(){ _ID--; return *this; } - /** Not equal */ - bool operator!=( - long ID ///< compare with this ID - ){ return _ID != ID; } - /** Equal */ - bool operator==( - long ID ///< compare with this ID - ){ return _ID == ID; } - /** @overload bool operator!=(long ID) */ - bool operator!=( - int ID ///< compare with this ID - ){ return _ID != ID; } - /** @overload bool operator==(long ID) */ - bool operator==( - int ID ///< compare with this ID - ){ return _ID == ID; } - /** @overload bool operator!=(long ID) */ - bool operator!=( - const cUPnPObjectID& ID ///< compare with this ID - ){ return *this == ID; } - /** @overload bool operator==(long ID) */ - bool operator==( - const cUPnPObjectID& ID ///< compare with this ID - ){ return *this == ID; } - /** Casts to unsigned int */ - operator unsigned int(){ return (unsigned int)_ID; } - /** Casts to int */ - operator int(){ return _ID; } - /** Casts to long */ - operator long(){ return (long)_ID; } - /** Casts to string */ - const char* operator*(){ char* buf; return asprintf(&buf,"%d",_ID)?buf:NULL; } -}; - -/** - * Structure of a UPnP Class - * - * This represents a UPnP Class - */ -struct cClass { - cString ID; ///< The upnp class ID - bool includeDerived; ///< flag, to indicate if derived classes are allowed - /** - * Compares two classes - * - * @param cmp the other class to compare with - */ - bool operator==(const cClass &cmp){ return (!strcasecmp(cmp.ID,ID) && includeDerived==cmp.includeDerived); } - /*! @copydoc operator==(const cClass &cmp) */ - bool operator!=(const cClass &cmp){ return !(*this==cmp); } -}; - -/** - * UPnP Resource - * - * This contains all details about a resource - */ -class cUPnPResource : public cListObject { - friend class cUPnPResourceMediator; - friend class cUPnPResources; - friend class cAudioVideoDetector; -private: - unsigned int mResourceID; - cUPnPObjectID mObjectID; - int mResourceType; - cString mResource; - cString mDuration; - cString mResolution; - cString mProtocolInfo; - cString mContentType; - cString mImportURI; - off64_t mSize; - unsigned int mBitrate; - unsigned int mSampleFrequency; - unsigned int mBitsPerSample; - unsigned int mNrAudioChannels; - unsigned int mColorDepth; - cUPnPResource(); -public: - /** - * Get resource ID - * - * Gets the resource ID - * - * @return the resource ID - */ - unsigned int getID() const { return this->mResourceID; } - /** - * Get the resources - * - * Returns the resource. This is in most cases the file name or resource locator - * where to find the resource - * - * @return the resource string - */ - const char* getResource() const { return this->mResource; } - /** - * Get the duration - * - * Returns a date time string with the duration of the resource - * - * @return the duration of the resource - */ - const char* getDuration() const { return this->mDuration; } - /** - * Get the resolution - * - * Returns the resolution string with the pattern width x height in pixels - * - * @return the resolution of the resource - */ - const char* getResolution() const { return this->mResolution; } - /** - * Get the protocol info - * - * This returns the protocol info field of a resource - * - * @return the protocol info string - */ - const char* getProtocolInfo() const { return this->mProtocolInfo; } - /** - * Get the content type - * - * Returns the mime type of the content of the resource - * - * @return the content type of the resource - */ - const char* getContentType() const { return this->mContentType; } - /** - * Get the import URI - * - * This returns the import URI where the resource was located before importing - * it - * - * @return the import URI - */ - const char* getImportURI() const { return this->mImportURI; } - /** - * Get the resource type - * - * This returns the resource type of the resource. - * - * @return the resource type - */ - int getResourceType() const { return this->mResourceType; } - /** - * Get the file size - * - * Returns the file size in bytes of the resource or 0 if its unknown or a - * stream - * - * @return the file size - */ - off64_t getFileSize() const { return this->mSize; }; - /** - * Get the last modification - * - * This returns the timestamp of the last modification to the file. If it - * is a stream, then its the current time. - * - * @return the timestamp with the last modification of the resource - */ - time_t getLastModification() const; - /** - * Get the bitrate - * - * This returns the bitrate of the resource in bits per second. - * - * @return the bitrate of the resource - */ - unsigned int getBitrate() const { return this->mBitrate; } - /** - * Get the sample frequency - * - * Returns the sample frequency in samples per second. - * - * @return the sample frequency of the resource - */ - unsigned int getSampleFrequency() const { return this->mSampleFrequency; } - /** - * Get the bits per sample - * - * Returns the number of bits per sample. - * - * @return the bits per sample of the resource - */ - unsigned int getBitsPerSample() const { return this->mBitsPerSample; } - /** - * Get number of audio channels - * - * Returns the number of audio channels of the audio stream in a video - * - * @return the number of audio channels - */ - unsigned int getNrAudioChannels() const { return this->mNrAudioChannels; } - /** - * Get the color depth - * - * Returns the color depth of the resource in pits per pixel - * - * @return the color depth of the resource - */ - unsigned int getColorDepth() const { return this->mColorDepth; } -}; - -class cUPnPClassObject; -class cUPnPObjectMediator; -class cUPnPContainerMediator; -class cUPnPClassContainer; - -/** - * List of UPnP Objects - * - * This is a cList of UPnP Objects - * The list can be sorted by using a specific property - */ -class cUPnPObjects : public cList<cUPnPClassObject> { -public: - cUPnPObjects(); - virtual ~cUPnPObjects(); - /** - * Sorts the list - * - * This sorts the list by a specific property and a certain direction - */ - void SortBy( - const char* Property, ///< the property used for sorting - bool Descending = false ///< the direction of the sort - ); -}; - -/** - * The UPnP class Object - * - * This is a UPnP class Object representation with all its properties. - */ -class cUPnPClassObject : public cListObject { - friend class cMediaDatabase; - friend class cUPnPObjectMediator; - friend class cUPnPClassContainer; -private: - cUPnPObjectID mLastID; - bool mDeleted; // is this Objected marked as deleted, NOT used yet. -protected: - time_t mLastModified; ///< The last modification of this property - cUPnPObjectID mID; ///< The object ID - cUPnPClassObject* mParent; ///< The parent object - cString mClass; ///< Class (Who am I?) - cString mTitle; ///< Object title - cString mCreator; ///< Creator of this object - bool mRestricted; ///< Ability of changing metadata? - int mWriteStatus; ///< Ability of writing resources? - cList<cUPnPResource>* mResources; ///< The resources of this object - cHash<cUPnPResource>* mResourcesID; ///< The resources of this object as hashmap - IXML_Document* mDIDLFragment; ///< The DIDL fragment of the object - cString mSortCriteria; ///< The sort criteria to sort with - bool mSortDescending; ///< The direction of the sort - cUPnPClassObject(); - /** - * Set the Object ID - * - * This is only allowed by mediators and the media database. Manually editing - * the object ID may result in unpredictable behavior. - * - * @param ID the ObjectID of this object - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - */ - int setID(cUPnPObjectID ID); - /** - * Set the Parent Object - * - * This is only allowed by mediators and the media database. Manually editing - * the parent may result in unpredictable behavior. - * - * @param Parent the parent of this object - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - */ - int setParent(cUPnPClassContainer* Parent); - /** - * Set the object class - * - * This is only allowed by mediators and the media database. Manually editing - * the object class may result in unpredictable behavior. - * - * @param Class the class of this object - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - */ - int setClass(const char* Class); - /** - * Set the modification time - * - * This sets the last modification time to the current timestamp. This is - * used to indicate when the object was updated the last time. - */ - void setModified(void){ this->mLastModified = time(NULL); } -public: - /** - * Last modified - * - * Returns when the object was modified the last time. - * - * @return last modification timestamp - */ - time_t modified() const { return this->mLastModified; } - virtual ~cUPnPClassObject(); - /** - * Compares a object - * - * This compares a given object with this object - * It uses the SortCriteria to compare them. - * - * @return returns - * - \bc >0, if the object comes after this one - * - \bc 0, if the objects have the same property - * - \bc <0, if the object comes before this one - * @param ListObject the object to compare with - */ - virtual int Compare(const cListObject& ListObject) const; - /** - * Get the properties of the object - * - * This returns a property list with all the properties which can be obtained - * or set with \c getProperty or \c setProperty. - * - * @return a stringlist with the properties - */ - virtual cStringList* getPropertyList(); - /** - * Gets a property - * - * Returns the value of a specified property. The value is converted into a - * string. - * - * @return returns - * - \bc true, if the property exists - * - \bc false, otherwise - * @param Property the property which should be returned - * @param Value the value of that property - */ - virtual bool getProperty(const char* Property, char** Value) const ; - /** - * Sets a property - * - * Sets the value of a specified property. The value is converted from string - * into the propper data type - * - * @return returns - * - \bc true, if the property exists - * - \bc false, otherwise - * @param Property the property which should be set - * @param Value the value of that property - */ - virtual bool setProperty(const char* Property, const char* Value); - /** - * Converts to container - * - * This will convert the object into a container if it is one. If not, it - * returns \bc NULL. - * - * @return returns - * - \bc NULL, if it is not a container - * - a container representation of this object - */ - virtual cUPnPClassContainer* getContainer(){ return NULL; } - /** - * Create the DIDL fragment - * - * This creates the DIDL-Lite fragment of the object. The DIDL is written to the - * specified \em IXML document. The details of the output can be controlled via - * the filter stringlist - * - * @return the DIDL fragment of the object - * @param Document the IXML document where to write the contents - * @param Filter the string list with the filter criteria - */ - virtual IXML_Node* createDIDLFragment(IXML_Document* Document, cStringList* Filter) = 0; - /** - * Is this a container? - * - * Returns if this object is a container or not - * - * @return returns - * - \bc true, if it is a container - * - \bc false, otherwise - */ - bool isContainer(){ return this->getContainer()==NULL?false:true; } - /** - * Set the sort criteria - * - * This sets a certain criteria which the object can be compared with. - * - * @param Property the property to sort after - * @param Descending sort the objects in descending order - */ - void setSortCriteria(const char* Property, bool Descending = false); - /** - * Clears the sort criteria - * - * Clears the property of the sort criteria and sets the descending flag to - * false. - */ - void clearSortCriteria(); - /******* Setter *******/ - /** - * Set the title - * - * This sets the title of the object. It is a required metadata information. - * It must not be \bc NULL or an empty string. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Title the title of the object - */ - int setTitle(const char* Title); - /** - * Set the creator - * - * The creator of an object is primarily the creator or owner of the object - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Creator the creator of the object - */ - int setCreator(const char* Creator); - /** - * Set the restriction - * - * This sets the restriction flag. If the object is restricted, no modifications - * to its metadata by the user are allowed. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Restricted \bc true, to disallow modification, \bc false to allow it - */ - int setRestricted(bool Restricted); - /** - * Set the write status - * - * This sets the write status of a resource. With this indicator, you can set - * the modifiabilty of resources by a control point. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Status the write status - */ - int setWriteStatus(int Status); - /** - * Set the resources - * - * This sets the list of resources of an object. The list usally contain a - * single resource. However, multiple resources a also very common. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Resources the resource list of this object - */ - int setResources(cList<cUPnPResource>* Resources); - /** - * Add resource to list - * - * This adds the specified resource to the resource list of the object - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Resource the resource to be added - */ - int addResource(cUPnPResource* Resource); - /** - * Remove resource from list - * - * This removes the specified resource from the resource list of the object - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Resource the resource to be removed - */ - int removeResource(cUPnPResource* Resource); - /******* Getter *******/ - /** - * Get the object ID - * - * This returns the object ID of the object. - * - * @return the object ID - */ - cUPnPObjectID getID() const { return this->mID; } - /** - * Get the parent ID - * - * This returns the ID of the parent container object, associated with this object. - * It is \bc -1, if the object is the root object. - * - * @return the parent ID - */ - cUPnPObjectID getParentID() const { return this->mParent?this->mParent->getID():cUPnPObjectID(-1); } - /** - * Get the parent object - * - * This returns the parent container object, associated with this object. It is - * \bc NULL, if the object is the root object. - * - * @return the parent object - */ - cUPnPClassContainer* getParent() const { return (cUPnPClassContainer*)this->mParent; } - /** - * Get the title - * - * This returns the title of the object. This may be the title of an item or - * the folder name in case of a container. - * - * @return the title of the object - */ - const char* getTitle() const { return this->mTitle; } - /** - * Get the object class - * - * This returns the object class of the object. The classes are defined by - * the UPnP Working Committee. However, custom classes which are derived from - * a standardized class are also possible. - * - * @return the class of the object - */ - const char* getClass() const { return this->mClass; } - /** - * Get the creator - * - * This returns the creator of the object. Usually, this is the primary - * content creator or the owner of the object - * - * @return the creator of the object - */ - const char* getCreator() const { return this->mCreator; } - /** - * Is the resource restricted? - * - * Returns \bc true, if the object is restricted or \bc false, otherwise. - * When the object is restricted, then modifications to the metadata of the - * object are disallowed. - * - * @return returns - * - \bc true, if the object is restricted - * - \bc false, otherwise - */ - bool isRestricted() const { return this->mRestricted; } - /** - * Get write status - * - * This returns the write status of the object. It gives information, if the - * resource is modifiable. - * - * @return the write status - */ - int getWriteStatus() const { return this->mWriteStatus; } - /** - * Get a resource by its ID - * - * Returns the resource with the specified resource ID. - * - * @return the resource by ID - * @param ResourceID the resource ID of the demanded resource - */ - cUPnPResource* getResource(unsigned int ResourceID) const { return this->mResourcesID->Get(ResourceID); } - /** - * Get the resources - * - * This returns a list with resources associated with this object. - * - * @return the resources of this object - */ - cList<cUPnPResource>* getResources() const { return this->mResources; } -}; - -/** - * The UPnP class Item - * - * This is a UPnP class Item representation with all its properties. - */ -class cUPnPClassItem : public cUPnPClassObject { - friend class cMediaDatabase; - friend class cUPnPObjectMediator; - friend class cUPnPItemMediator; -protected: -// cUPnPObjectID mReferenceID; - cUPnPClassItem* mReference; ///< The reference item - /** - * Constructor of an item - * - * This creates a new instance of an item - */ - cUPnPClassItem(); -public: - virtual ~cUPnPClassItem(){}; - virtual cStringList* getPropertyList(); - virtual IXML_Node* createDIDLFragment(IXML_Document* Document, cStringList* Filter); - virtual bool setProperty(const char* Property, const char* Value); - virtual bool getProperty(const char* Property, char** Value) const; - /******** Setter ********/ - /** - * Set a reference item - * - * This sets a reference item. Its comparable with symlinks in *nix systems - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Reference the reference item - */ - int setReference(cUPnPClassItem* Reference); - /******** Getter ********/ - /** - * Get the referenced item - * - * This returns the referenced item of this item - * - * @return the referenced item - */ - cUPnPClassItem* getReference() const { return this->mReference; } - /** - * Get the reference ID - * - * This returns the object ID of the referenced item or \b -1, if - * no reference exists. - * - * @return the reference ID - */ - cUPnPObjectID getReferenceID() const { return this->mReference?this->mReference->getID():cUPnPObjectID(-1); } -}; - -typedef std::vector<cClass> tClassVector; - -/** - * The UPnP class Container - * - * This is a UPnP class Container representation with all its properties. - */ -class cUPnPClassContainer : public cUPnPClassObject { - friend class cMediaDatabase; - friend class cUPnPObjectMediator; - friend class cUPnPContainerMediator; -protected: - cString mContainerType; ///< DLNA container type - tClassVector mSearchClasses; ///< Classes which are searchable - tClassVector mCreateClasses; ///< Classes which are creatable - bool mSearchable; ///< Is the Container searchable? - unsigned int mUpdateID; ///< The containerUpdateID - cUPnPObjects* mChildren; ///< List of children - cHash<cUPnPClassObject>* mChildrenID; ///< List of children as hash map - /** - * Update the container - * - * This performs an update, which acutally increases the containerUpdateID. - */ - void update(); - /** - * Sets the containerUpdateID - * - * This method should only be used when the containerUpdateID is loaded from - * the database. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param UID the containerUpdateID - */ - int setUpdateID(unsigned int UID); - /** - * Constructor of a container - * - * This creates a new instance of a container - */ - cUPnPClassContainer(); -public: - virtual ~cUPnPClassContainer(); - virtual cStringList* getPropertyList(); - virtual IXML_Node* createDIDLFragment(IXML_Document* Document, cStringList* Filter); - virtual bool setProperty(const char* Property, const char* Value); - virtual bool getProperty(const char* Property, char** Value) const; - virtual cUPnPClassContainer* getContainer(){ return this; } - /** - * Add a child - * - * This adds the specified child to this container. The parent container of the - * child will be set to this container. - * - * @param Object the child to be added - */ - void addObject(cUPnPClassObject* Object); - /** - * Remove a child - * - * This removes the specified child from the list of children. The child will - * also loose its parent container, so that there is no link between left. - * - * @param Object the child to be removed - */ - void removeObject(cUPnPClassObject* Object); - /** - * Get a child by ID - * - * Returns the child, which is specified by the \c ObjectID. - * - * @return the child with the specified ID - * @param ID the \c ObjectID of the child - */ - cUPnPClassObject* getObject(cUPnPObjectID ID) const; - /** - * Get the list of children - * - * This returns a list of the children of the container. - * - * @return the list of children - */ - cUPnPObjects* getObjectList() const { return this->mChildren; } - /** - * Add a search class - * - * This adds a search class to the search classes vector - * - * @return returns - * - \bc 0, if adding was successful - * - \bc <0, otherwise - * @param SearchClass the new class to be added - */ - int addSearchClass(cClass SearchClass); - /** - * Remove a search class - * - * This removes a search class from the search classes vector - * - * @return returns - * - \bc 0, if deleting was successful - * - \bc <0, otherwise - * @param SearchClass the class to be deleted - */ - int delSearchClass(cClass SearchClass); - /** - * Add a create class - * - * This adds a create class to the create classes vector - * - * @return returns - * - \bc 0, if adding was successful - * - \bc <0, otherwise - * @param CreateClass the new class to be added - */ - int addCreateClass(cClass CreateClass); - /** - * Remove a create class - * - * This removes a create class from the create classes vector - * - * @return returns - * - \bc 0, if deleting was successful - * - \bc <0, otherwise - * @param CreateClass the class to be deleted - */ - int delCreateClass(cClass CreateClass); - /******** Setter ********/ - /** - * Set the DLNA container type - * - * This sets the DLNA container type. It must be a valid container type value. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Type the DLNA container type - */ - int setContainerType(const char* Type); - /** - * Sets the search classes - * - * This sets the search classes, which allows the user to search only for - * these classes in the current container and its children. If the vector - * is empty the search can return any match. If the additional flag \bc - * derived is set, then also any derived classes are matched. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param SearchClasses a vector container the allowed search classes - */ - int setSearchClasses(std::vector<cClass> SearchClasses); - /** - * Sets the create classes - * - * This sets the create classes, which allows the user to create new objects - * in this container, if \em restricted is \bc false. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param CreateClasses a vector containing the create classes - */ - int setCreateClasses(std::vector<cClass> CreateClasses); - /** - * Sets the searchable flag - * - * This sets the searchable flag, which allows or disallows search on this - * container. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Searchable \bc true, to enable or \bc false, to disable searching - */ - int setSearchable(bool Searchable); - /******** Getter ********/ - /** - * Get the DLNA container type - * - * This returns the DLNA container type. Currently there are only these possible - * values beside \bc NULL: - * - \bc TUNER_1_0 - * - * @return the DLNA container type - */ - const char* getContainerType() const { return this->mContainerType; } - /** - * Get the search classes - * - * This returns a vector container all possible search classes. This are classes, - * which can be used for searching in this container. - * - * @return a vector with all search classes - */ - const std::vector<cClass>* getSearchClasses() const { return &(this->mSearchClasses); } - /** - * Get the create classes - * - * This returns a vector containing all possible create classes. This are classes, - * which can be created in this container. For instance a TV container can only create - * items of the class VideoBroadcast. The vector is empty when creation of new items - * by the user is not allowed. - * - * @return a vector with create classes - */ - const std::vector<cClass>* getCreateClasses() const { return &(this->mCreateClasses); } - /** - * Is this container searchable - * - * This returns \bc true, if the container can be search via \em Search or - * \bc false, otherwise. - * - * @return returns - * - \bc true, if the container is searchable - * - \bc false, otherwise - */ - bool isSearchable() const { return this->mSearchable; } - /** - * Get the number of children - * - * This returns the total number of children of this container - * - * @return the number of childen - */ - unsigned int getChildCount() const { return this->mChildren->Count(); } - /** - * Get the containerUpdateID - * - * This returns the containerUpdateID - * - * @return the containerUpdateID of this container - */ - unsigned int getUpdateID() const { return this->mUpdateID; } - /** - * Has the container been updated? - * - * This returns \bc true, if the container was recently updated or - * \bc false, otherwise - * - * @return returns - * - \bc true, if the container was updated - * - \bc false, otherwise - */ - bool isUpdated(); -}; - -/** - * The UPnP class VideoItem - * - * This is a UPnP class VideoItem representation with all its properties. - */ -class cUPnPClassVideoItem : public cUPnPClassItem { - friend class cMediaDatabase; - friend class cUPnPObjectMediator; - friend class cUPnPVideoItemMediator; -protected: - cString mGenre; ///< Genre of the video - cString mDescription; ///< Description - cString mLongDescription; ///< a longer description - cString mPublishers; ///< CSV of Publishers - cString mLanguage; ///< RFC 1766 Language code - cString mRelations; ///< Relation to other contents - cString mProducers; ///< CSV of Producers - cString mRating; ///< Rating (for parential control) - cString mActors; ///< CSV of Actors - cString mDirectors; ///< CSV of Directors - /** - * Constructor of a video item - * - * This creates a new instance of a video item - */ - cUPnPClassVideoItem(); -public: - virtual ~cUPnPClassVideoItem(); - //virtual cString createDIDLFragment(cStringList* Filter); - virtual cStringList* getPropertyList(); - virtual bool setProperty(const char* Property, const char* Value); - virtual bool getProperty(const char* Property, char** Value) const; - /******** Setter ********/ - /** - * Set a long description - * - * A long description may hold information about the content or the story - * of a video - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param LongDescription the content or story of a video - */ - int setLongDescription(const char* LongDescription); - /** - * Set a description - * - * A description may hold short information about the content or the story - * of a video. Unlike a long description, this contains just a very short - * brief like a subtitle or the episode title. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Description the description of a video - */ - int setDescription(const char* Description); - /** - * Set the publishers - * - * This is a CSV list of publishers, who distributes the video. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Publishers a CSV list of publishers - */ - int setPublishers(const char* Publishers); - /** - * Set a genre - * - * This is a CSV list of genre of a video. This may be something like - * "Western" or "SciFi". Actually, there is no standardized rule for - * a genre name, which results in an ambiguous definition of certain - * genre, like Thriller and Horror. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Genre a CSV list of genre - */ - int setGenre(const char* Genre); - /** - * Set the language - * - * This sets the language of a video. It is defined by RFC 1766. - * A valid language definition is \em "de-DE" or \em "en-US". - * - * @see http://www.ietf.org/rfc/rfc1766.txt - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Language the language (RFC 1766) - */ - int setLanguage(const char* Language); - /** - * Sets a relation URL - * - * This sets a CSV list of relation URLs, where to find additional - * information about the movie. The URLs may not contain commas and they - * must be properly escaped as in RFC 2396 - * - * @see http://www.ietf.org/rfc/rfc2396.txt - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Relations a CSV list with relations - */ - int setRelations(const char* Relations); - /** - * Sets the directors - * - * This sets a CSV list of directors. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Directors a CSV list of directors - */ - int setDirectors(const char* Directors); - /** - * Sets the actors - * - * This sets a CSV list of actors in a video. This usually contain the main actors. - * However, also other actors appearing in the video can be mentioned here. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Actors a CSV list of actors - */ - int setActors(const char* Actors); - /** - * Sets the producers - * - * This sets a CSV list of producers of a video. These are the people who are - * involed in the production of a video - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Producers a CSV list of producers - */ - int setProducers(const char* Producers); - /** - * Sets the rating - * - * This is a rating, which can be used for parential control issues. - * - * @see http://en.wikipedia.org/wiki/Motion_picture_rating_system - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Rating the rating of a video - */ - int setRating(const char* Rating); - /******** Getter ********/ - /** - * Get the genres - * - * This returns a CSV list of genre - * - * @return the genre of a video - */ - const char* getGenre() const { return this->mGenre; } - /** - * Get the long description - * - * This returns the long description of a video - * - * @return the long description of a video - */ - const char* getLongDescription() const { return this->mLongDescription; } - /** - * Get the description - * - * This returns the description of a video - * - * @return the description of a video - */ - const char* getDescription() const { return this->mDescription; } - /** - * Get the publishers - * - * This returns a CSV list of publishers of the video - * - * @return a CSV list of publishers - */ - const char* getPublishers() const { return this->mPublishers; } - /** - * Get the language - * - * This returns the language of the video - * - * @return the language - */ - const char* getLanguage() const { return this->mLanguage; } - /** - * Get the relations - * - * This returns a CSV list of relation URLs. - * - * @return a CSV list of relation URLs - */ - const char* getRelations() const { return this->mRelations; } - /** - * Get the actors - * - * This returns a CSV list of actors in the video - * - * @return a CSV list of actors - */ - const char* getActors() const { return this->mActors; } - /** - * Get the producers - * - * This returns a CSV list of producers of a video - * - * @return a CSV list of producers - */ - const char* getProducers() const { return this->mProducers; } - /** - * Get the directors - * - * This returns a CSV list of directors - * - * @return a CSV list of directors - */ - const char* getDirectors() const { return this->mDirectors; } - /** - * Get the rating - * - * This returns the rating used for parental control. - * - * @return the rating of a video - */ - const char* getRating() const { return this->mRating; } -}; - -/** - * The UPnP class Movie - * - * This is a UPnP class Movie representation with all its properties. - */ -class cUPnPClassMovie : public cUPnPClassVideoItem { - friend class cMediaDatabase; - friend class cUPnPObjectMediator; - friend class cUPnPMovieMediator; -protected: - int mDVDRegionCode; ///< The Region code of the movie (0 - 8) - cString mStorageMedium; ///< The storage medium where the movie is stored - /** - * Constructor of a movie - * - * This creates a new instance of a movie - */ - cUPnPClassMovie(); -public: - virtual ~cUPnPClassMovie(); - //virtual cString createDIDLFragment(cStringList* Filter); - virtual cStringList* getPropertyList(); - virtual bool setProperty(const char* Property, const char* Value); - virtual bool getProperty(const char* Property, char** Value) const; - /******** Setter ********/ - /** - * Sets the DVD region code - * - * For more information on this, see http://en.wikipedia.org/wiki/DVD_region_code - * - * The integer representation for \em ALL is 9. - * - * @see http://en.wikipedia.org/wiki/DVD_region_code - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param RegionCode the region code of this movie - */ - int setDVDRegionCode(int RegionCode); - /** - * Sets the storage medium - * - * This will set the storage medium, where the movie resides. Valid media - * are defined in \link common.h \endlink - * - * @see common.h - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param StorageMedium the medium where the movie is located - */ - int setStorageMedium(const char* StorageMedium); - /******** Getter ********/ - /** - * Get the DVD region code - * - * This returns the DVD region code. For more information, - * see http://en.wikipedia.org/wiki/DVD_region_code - * - * The integer representation for \em ALL is 9. - * - * @see http://en.wikipedia.org/wiki/DVD_region_code - * @return the DVD region code - */ - int getDVDRegionCode() const { return this->mDVDRegionCode; } - /** - * Get the storage medium - * - * This returns the storage medium, where the movie resides. - * - * @return the storage medium - */ - const char* getStorageMedium() const { return this->mStorageMedium; } -}; - -/** - * The UPnP class VideoBroadcast - * - * This is a UPnP class VideoBroadcast representation with all its properties. - */ -class cUPnPClassVideoBroadcast : public cUPnPClassVideoItem { - friend class cMediaDatabase; - friend class cUPnPObjectMediator; - friend class cUPnPVideoBroadcastMediator; -protected: - cString mIcon; ///< The channel icon of the channel - cString mRegion; ///< The region where the channel can be received - int mChannelNr; ///< The channel number - cString mChannelName; ///< The channel name or provider name - /** - * Constructor of a video broadcast - * - * This creates a new instance of a video broadcast - */ - cUPnPClassVideoBroadcast(); -public: - virtual ~cUPnPClassVideoBroadcast(); - //virtual cString createDIDLFragment(cStringList* Filter); - virtual cStringList* getPropertyList(); - virtual bool setProperty(const char* Property, const char* Value); - virtual bool getProperty(const char* Property, char** Value) const; - /******** Setter ********/ - /** - * Set the channel icon - * - * This sets the channel icon of this channel. The resource must be a valid - * URI which can be obtained via the internal webserver - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param IconURI the URI to the icon file - */ - int setIcon(const char* IconURI); - /** - * Set the channel region - * - * This sets the region of a channel, where it can be received - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param Region the location where the channel can be received - */ - int setRegion(const char* Region); - /** - * Set channel number - * - * This sets the channel number, so that it can be used for directly navigation - * or channel up and down navigation respectively. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param ChannelNr the channel number - */ - int setChannelNr(int ChannelNr); - /** - * Set the channel name - * - * This sets the channel name or the provider of the channel. - * - * @return returns - * - \bc 0, if setting was successful - * - \bc <0, otherwise - * @param ChannelName the channel name - */ - int setChannelName(const char* ChannelName); - /******** Getter ********/ - /** - * Get the channel icon - * - * This returns the channel icon of the channel. - * - * @return the channel icon - */ - const char* getIcon() const { return this->mIcon; } - /** - * Get the region - * - * This returns the region, where the channel can be received - * - * @return the channel region - */ - const char* getRegion() const { return this->mRegion; } - /** - * Get the channel number - * - * This returns the channel number - * - * @return the channel number - */ - int getChannelNr() const { return this->mChannelNr; } - /** - * Get the channel name - * - * This returns the channel name or provider name respectively - * - * @return the channel name - */ - const char* getChannelName() const { return this->mChannelName; } -}; - -/** - * Mediator interface - * - * This is an interface for mediators used to communicate with the database. - * A mediator is applied to get, create, save or delete an UPnP object. - */ -class cMediatorInterface { -public: - virtual ~cMediatorInterface(){}; - /** - * Creates an object - * - * This creates a new UPnP object with the specific title and the restriction. - * - * @return the newly created object - * @param Title the title of that object - * @param Restricted the restriction of the object - */ - virtual cUPnPClassObject* createObject(const char* Title, bool Restricted) = 0; - /** - * Get an object - * - * Retrieves a UPnP object from the database and stores its information in the - * object. The object is obtained via its object ID. - * - * @return the object, found in the database - * @param ID the object ID - */ - virtual cUPnPClassObject* getObject(cUPnPObjectID ID) = 0; - /** - * Saves the object - * - * This saves the object in the database by updating the values in the database - * with those in the object. - * - * @return returns - * - \bc <0, in case of an error - * - \bc 0, otherwise - * @param Object the object to be saved - */ - virtual int saveObject(cUPnPClassObject* Object) = 0; - /** - * Deletes the object - * - * This deletes the object in the database by removing all its children and then - * deleting the contents from the database - * - * @return returns - * - \bc <0, in case of an error - * - \bc 0, otherwise - * @param Object the object to be deleted - */ - virtual int deleteObject(cUPnPClassObject* Object) = 0; - /** - * Clears the object - * - * This clears the object, i.e. all its children will be removed and deleted - * from the database - * - * @return returns - * - \bc <0, in case of an error - * - \bc 0, otherwise - * @param Object the object to be cleared - */ - virtual int clearObject(cUPnPClassObject* Object) = 0; -}; - -typedef std::map<const char*, cMediatorInterface*, strCmp> tMediatorMap; - -/** - * The object factory - * - * This factory can create, delete, clear or save UPnP objects. It uses mediators - * to communicate with the persistance database to load or persist the objects. - * - * If a new type of object shall be stored in the database an according mediator - * is needed, which knows the internal database structure. It must implement the - * cMediatorInterface class to work with this factory. - */ -class cUPnPObjectFactory { -private: - static cUPnPObjectFactory* mInstance; - cSQLiteDatabase* mDatabase; - tMediatorMap mMediators; - cMediatorInterface* findMediatorByID(cUPnPObjectID ID); - cMediatorInterface* findMediatorByClass(const char* Class); - cUPnPObjectFactory(); -public: - /** - * Return the instance of the factory - * - * This returns the instance of the factory. When the media database is - * initialized successfully, it usally has all known mediators already - * registered. - * - * @return the instance of the factory - */ - static cUPnPObjectFactory* getInstance(); - /** - * Register a mediator - * - * This registers a new mediator by the associated class. The mediator - * must implement the cMediatorInterface class to be used with this - * factory. - * - * @param UPnPClass the class of which the mediator is associated to - * @param Mediator the mediator itself - */ - void registerMediator(const char* UPnPClass, cMediatorInterface* Mediator); - /** - * Unregisters a mediator - * - * This unregisters a mediator if it is not needed anylonger. If the optional - * parameter \c freeMediator is set, the object instance will be free'd after - * removing it from the list. - * - * @param UPnPClass the class of the associated mediator - * @param freeMediator flag to indicate if the mediator shall be free'd after removing - */ - void unregisterMediator(const char* UPnPClass, bool freeMediator=true); - /** - * @copydoc cMediatorInterface::createObject(const char* Title, bool Restricted) - * - * @param UPnPClass the class of the new object - */ - cUPnPClassObject* createObject(const char* UPnPClass, const char* Title, bool Restricted=true); - /*! @copydoc cMediatorInterface::getObject(cUPnPObjectID ID) */ - cUPnPClassObject* getObject(cUPnPObjectID ID); - /*! @copydoc cMediatorInterface::saveObject(cUPnPClassObject* Object) */ - int saveObject(cUPnPClassObject* Object); - /*! @copydoc cMediatorInterface::deleteObject(cUPnPClassObject* Object) */ - int deleteObject(cUPnPClassObject* Object); - /*! @copydoc cMediatorInterface::clearObject(cUPnPClassObject* Object) */ - int clearObject(cUPnPClassObject* Object); -}; - -class cMediaDatabase; - -/** - * Object Mediator - * - * This is the interface between the objects and the database. It is possible to - * create new objects, stores objects in the database as well as removing them from - * it. - */ -class cUPnPObjectMediator : public cMediatorInterface { -protected: - cSQLiteDatabase* mDatabase; ///< the SQLite 3 database wrapper - cMediaDatabase* mMediaDatabase; ///< the media database - /** - * Constructor of object mediator - * - * This constructs a new object mediator. This is actually not allowed because - * it is prohibited to create instances of the UPnP class Object - */ - cUPnPObjectMediator( - cMediaDatabase* MediaDatabase ///< the media database - ); - /** - * Initializes an object - * - * This initializes an object, which means, that it will be created in the database with - * the required details. - * - * @return returns - * - \bc <0, in case of an error - * - \bc 0, otherwise - */ - virtual int initializeObject( - cUPnPClassObject* Object, ///< the object to be initialized - const char* Class, ///< the class of the object - const char* Title, ///< the title of the object - bool Restricted ///< restriction of the object - ); - /** - * Store the object in the database - * - * This stores the information of an object in the database - * - * @return returns - * - \bc <0, in case of an error - * - \bc 0, otherwise - * @param Object the object to be saved - */ - virtual int objectToDatabase(cUPnPClassObject* Object); - /** - * Loads an object from database - * - * This loads an object from the database - * - * @return returns - * - \bc <0, in case of an error - * - \bc 0, otherwise - * @param Object the object to be loaded - * @param ID the object ID of that object - */ - virtual int databaseToObject(cUPnPClassObject* Object, cUPnPObjectID ID); -public: - virtual ~cUPnPObjectMediator(); - /*! @copydoc cMediatorInterface::createObject(const char* Title, bool Restricted) */ - virtual cUPnPClassObject* createObject(const char* Title, bool Restricted); - /*! @copydoc cMediatorInterface::getObject(cUPnPObjectID ID) */ - virtual cUPnPClassObject* getObject(cUPnPObjectID ID); - /*! @copydoc cMediatorInterface::saveObject(cUPnPClassObject* Object) */ - virtual int saveObject(cUPnPClassObject* Object); - /*! @copydoc cMediatorInterface::deleteObject(cUPnPClassObject* Object) */ - virtual int deleteObject(cUPnPClassObject* Object); - /*! @copydoc cMediatorInterface::clearObject(cUPnPClassObject* Object) */ - virtual int clearObject(cUPnPClassObject* Object); -}; - -/** - * Item Mediator - * - * This is the interface between the objects and the database. It is possible to - * create new objects, stores objects in the database as well as removing them from - * it. - */ -class cUPnPItemMediator : public cUPnPObjectMediator { -protected: - /*! @copydoc cUPnPObjectMediator::objectToDatabase(cUPnPClassObject* Object) */ - virtual int objectToDatabase(cUPnPClassObject* Object); - /*! @copydoc cUPnPObjectMediator::databaseToObject(cUPnPClassObject* Object, cUPnPObjectID ID) */ - virtual int databaseToObject(cUPnPClassObject* Object, cUPnPObjectID ID); -public: - /** - * Constructor of item mediator - * - * This creates a new item mediator with which it is possible to create new - * instances of Item objects. - * - * @param MediaDatabase the media database - */ - cUPnPItemMediator(cMediaDatabase* MediaDatabase); - virtual ~cUPnPItemMediator(){}; - /*! @copydoc cUPnPObjectMediator::createObject(const char* Title, bool Restricted) */ - virtual cUPnPClassItem* createObject(const char* Title, bool Restricted); - /*! @copydoc cUPnPObjectMediator::getObject(cUPnPObjectID ID) */ - virtual cUPnPClassItem* getObject(cUPnPObjectID ID); -}; - -/** - * VideoItem Mediator - * - * This is the interface between the objects and the database. It is possible to - * create new objects, stores objects in the database as well as removing them from - * it. - */ -class cUPnPVideoItemMediator : public cUPnPItemMediator { -protected: - virtual int objectToDatabase(cUPnPClassObject* Object); - virtual int databaseToObject(cUPnPClassObject* Object, cUPnPObjectID ID); -public: - /** - * Constructor of videoitem mediator - * - * This creates a new videoitem mediator with which it is possible to create new - * instances of VideoItem objects. - * - * @param MediaDatabase the media database - */ - cUPnPVideoItemMediator(cMediaDatabase* MediaDatabase); - virtual ~cUPnPVideoItemMediator(){}; - virtual cUPnPClassVideoItem* createObject(const char* Title, bool Restricted); - virtual cUPnPClassVideoItem* getObject(cUPnPObjectID ID); -}; - -/** - * VideoBroadcast Mediator - * - * This is the interface between the objects and the database. It is possible to - * create new objects, stores objects in the database as well as removing them from - * it. - */ -class cUPnPVideoBroadcastMediator : public cUPnPVideoItemMediator { -protected: - virtual int objectToDatabase(cUPnPClassObject* Object); - virtual int databaseToObject(cUPnPClassObject* Object, cUPnPObjectID ID); -public: - /** - * Constructor of video broadcast mediator - * - * This creates a new video broadcast mediator with which it is possible to create new - * instances of VideoBroadcast objects. - * - * @param MediaDatabase the media database - */ - cUPnPVideoBroadcastMediator(cMediaDatabase* MediaDatabase); - virtual ~cUPnPVideoBroadcastMediator(){}; - virtual cUPnPClassVideoBroadcast* createObject(const char* Title, bool Restricted); - virtual cUPnPClassVideoBroadcast* getObject(cUPnPObjectID ID); -}; - -/** - * Movie Mediator - * - * This is the interface between the objects and the database. It is possible to - * create new objects, stores objects in the database as well as removing them from - * it. - */ -class cUPnPMovieMediator : public cUPnPVideoItemMediator { -protected: - virtual int objectToDatabase(cUPnPClassObject* Object); - virtual int databaseToObject(cUPnPClassObject* Object, cUPnPObjectID ID); -public: - /** - * Constructor of movie mediator - * - * This creates a new movie mediator with which it is possible to create new - * instances of Movie objects. - * - * @param MediaDatabase the media database - */ - cUPnPMovieMediator(cMediaDatabase* MediaDatabase); - virtual ~cUPnPMovieMediator(){}; - virtual cUPnPClassMovie* createObject(const char* Title, bool Restricted); - virtual cUPnPClassMovie* getObject(cUPnPObjectID ID); -}; - -/** - * Container Mediator - * - * This is the interface between the objects and the database. It is possible to - * create new objects, stores objects in the database as well as removing them from - * it. - */ -class cUPnPContainerMediator : public cUPnPObjectMediator { -protected: - virtual int objectToDatabase(cUPnPClassObject* Object); - virtual int databaseToObject(cUPnPClassObject* Object, cUPnPObjectID ID); -public: - /** - * Constructor of container mediator - * - * This creates a new container mediator with which it is possible to create new - * instances of Container objects. - * - * @param MediaDatabase the media database - */ - cUPnPContainerMediator(cMediaDatabase* MediaDatabase); - virtual ~cUPnPContainerMediator(){}; - virtual cUPnPClassContainer* createObject(const char* Title, bool Restricted); - virtual cUPnPClassContainer* getObject(cUPnPObjectID ID); -}; - -#endif /* _OBJECT_H */ - diff --git a/database/resources.cpp b/database/resources.cpp index 646560a..d0ca481 100644 --- a/database/resources.cpp +++ b/database/resources.cpp @@ -7,10 +7,49 @@ #include <string.h> #include <vdr/channels.h> -#include "../upnpcomponents/dlna.h" +#include "upnp/dlna.h" #include <vdr/tools.h> #include "resources.h" -#include "../misc/avdetector.h" +#include "avdetector.h" + +cUPnPResource::cUPnPResource(){ + this->mBitrate = 0; + this->mBitsPerSample = 0; + this->mColorDepth = 0; + this->mDuration = NULL; + this->mImportURI = NULL; + this->mNrAudioChannels = 0; + this->mProtocolInfo = NULL; + this->mResolution = NULL; + this->mResource = NULL; + this->mResourceID = 0; + this->mSampleFrequency = 0; + this->mSize = 0; + this->mContentType = NULL; +} + +time_t cUPnPResource::getLastModification() const { + time_t Time; + const cRecording* Recording; + const cEvent* Event; + switch(this->mResourceType){ + case UPNP_RESOURCE_CHANNEL: + case UPNP_RESOURCE_URL: + Time = time(NULL); + break; + case UPNP_RESOURCE_RECORDING: + Recording = Recordings.GetByName(this->mResource); + Event = (Recording)?Recording->Info()->GetEvent():NULL; + Time = (Event)?Event->EndTime():time(NULL); + break; + case UPNP_RESOURCE_FILE: + //break; + default: + ERROR("Invalid resource type. This resource might be broken"); + Time = -1; + } + return Time; +} cUPnPResources* cUPnPResources::mInstance = NULL; @@ -125,7 +164,7 @@ int cUPnPResources::createFromRecording(cUPnPClassVideoItem* Object, cRecording* Resource->mImportURI = NULL; Resource->mColorDepth = 0; Object->addResource(Resource); - this->mMediator->saveResource(Resource); + this->mMediator->saveResource(Object, Resource); this->mResources->Add(Resource, Resource->getID()); delete Detector; @@ -178,7 +217,7 @@ int cUPnPResources::createFromChannel(cUPnPClassVideoBroadcast* Object, cChannel Resource->mImportURI = NULL; Resource->mColorDepth = 0; Object->addResource(Resource); - this->mMediator->saveResource(Resource); + this->mMediator->saveResource(Object, Resource); this->mResources->Add(Resource, Resource->getID()); delete Detector; @@ -208,10 +247,7 @@ cUPnPResource* cUPnPResourceMediator::getResource(unsigned int ResourceID){ } cString Column = NULL, Value = NULL; while(Row->fetchColumn(&Column, &Value)){ - if(!strcasecmp(SQLITE_COL_OBJECTID, Column)){ - Resource->mObjectID = *Value?atoi(Value):-1; - } - else if(!strcasecmp(SQLITE_COL_PROTOCOLINFO, Column)){ + if(!strcasecmp(SQLITE_COL_PROTOCOLINFO, Column)){ Resource->mProtocolInfo = Value; } else if(!strcasecmp(SQLITE_COL_RESOURCE, Column)){ @@ -251,7 +287,7 @@ cUPnPResource* cUPnPResourceMediator::getResource(unsigned int ResourceID){ return Resource; } -int cUPnPResourceMediator::saveResource(cUPnPResource* Resource){ +int cUPnPResourceMediator::saveResource(cUPnPClassObject* Object, cUPnPResource* Resource){ cString Format = "UPDATE %s SET %s=%Q," "%s=%Q," @@ -270,7 +306,7 @@ int cUPnPResourceMediator::saveResource(cUPnPResource* Resource){ if(this->mDatabase->execStatement(Format, SQLITE_TABLE_RESOURCES, - SQLITE_COL_OBJECTID, *Resource->mObjectID, + SQLITE_COL_OBJECTID, *Object->getID(), SQLITE_COL_PROTOCOLINFO, *Resource->mProtocolInfo, SQLITE_COL_RESOURCE, *Resource->mResource, SQLITE_COL_SIZE, Resource->mSize, @@ -310,7 +346,6 @@ cUPnPResource* cUPnPResourceMediator::newResource(cUPnPClassObject* Object, int return NULL; } Resource->mResourceID = (unsigned int)this->mDatabase->getLastInsertRowID(); - Resource->mObjectID = Object->getID(); Resource->mResource = ResourceFile; Resource->mProtocolInfo = ProtocolInfo; Resource->mContentType = ContentType; diff --git a/database/resources.h b/database/resources.h deleted file mode 100644 index 8f7fa86..0000000 --- a/database/resources.h +++ /dev/null @@ -1,162 +0,0 @@ -/* - * File: resources.h - * Author: savop - * - * Created on 30. September 2009, 15:17 - */ - -#ifndef _RESOURCES_H -#define _RESOURCES_H - -#include "database.h" -#include "object.h" -#include <vdr/channels.h> -#include <vdr/recording.h> - -class cUPnPResourceMediator; -class cMediaDatabase; - -/** - * The resource manager - * - * This manages the resources in an internal cache. It may create a new resource - * from a channel, a recording or a custom file. - */ -class cUPnPResources { -private: - cHash<cUPnPResource>* mResources; - static cUPnPResources* mInstance; - cUPnPResourceMediator* mMediator; - cSQLiteDatabase* mDatabase; - cUPnPResources(); -public: - /** - * Fill object with its resources - * - * This will load all the resources from the database, which are associated - * to the given object - * - * @param Object the object, which shall be filled - * @return returns - * - \bc 0, if loading was successful - * - \bc <0, otherwise - */ - int getResourcesOfObject(cUPnPClassObject* Object); - /** - * Loads all resources from database - * - * This loads all resources from the database into the internal cache. - * - * @return returns - * - \bc 0, if loading was successful - * - \bc <0, otherwise - */ - int loadResources(); - /*! @copydoc cUPnPResourceMediator::getResource */ - cUPnPResource* getResource(unsigned int ResourceID); - virtual ~cUPnPResources(); - /** - * Get the instance of the resource manager - * - * This returns the instance of the resource manager. - * - * @return the instance of the manager - */ - static cUPnPResources* getInstance(); - /** - * Create resource from channel - * - * This creates a new resource from the given channel. It determines what - * kind of video stream it is and further details if available. It stores - * the resource in the database after creating it. - * - * @param Object the videoBroadcast item which holds the resource - * @param Channel the VDR TV channel - * @return returns - * - \bc 0, if loading was successful - * - \bc <0, otherwise - */ - int createFromChannel(cUPnPClassVideoBroadcast* Object, cChannel* Channel); - /** - * Create resource from recording - * - * This creates a new resource from the given recording. It determines what - * kind of video stream it is and further details if available. It stores - * the resource in the database after creating it. - * - * @param Object the videoItem item which holds the resource - * @param Recording the VDR TV recording - * @return returns - * - \bc 0, if loading was successful - * - \bc <0, otherwise - */ - int createFromRecording(cUPnPClassVideoItem* Object, cRecording* Recording); - /** - * Create resource from file - * - * This creates a new resource from the given file. It determines all available - * information about the resource by analizing the content. It stores - * the resource in the database after creating it. - * - * @param Object the item which holds the resource - * @param File the file name - * @return returns - * - \bc 0, if loading was successful - * - \bc <0, otherwise - */ - int createFromFile(cUPnPClassItem* Object, cString File); -}; - -/** - * The resource mediator - * - * This is another mediator which communicates with the database. It manages the - * resources in the database - */ -class cUPnPResourceMediator { - friend class cUPnPResources; -private: - cSQLiteDatabase* mDatabase; - cUPnPResourceMediator(); - unsigned int getNextResourceID(); -public: - virtual ~cUPnPResourceMediator(); - /** - * Get a resource by ID - * - * This returns a resource by its resource ID - * - * @param ResourceID the resource ID of the demanded resource - * @return the requested resource - */ - cUPnPResource* getResource(unsigned int ResourceID); - /** - * Saves the resource - * - * This updates the information in the database with those in the resource - * object - * - * @param Resource the resource which shall be saved - * @return returns - * - \bc 0, if saving was successful - * - \bc <0, if an error occured - */ - int saveResource(cUPnPResource* Resource); - /** - * Create new resource - * - * This creates a new resource and stores the skeleton in the database. The - * newly created resource will only contain all required information. - * - * @param Object the Object which will hold the resource - * @param ResourceType the type of the resource - * @param ResourceFile the file or URL, where the resource can be located - * @param ContentType the mime type of the content - * @param ProtocolInfo the protocol information of the resource - * @return the newly created resource - */ - cUPnPResource* newResource(cUPnPClassObject* Object, int ResourceType, cString ResourceFile, cString ContentType, cString ProtocolInfo); -}; - -#endif /* _RESOURCES_H */ - diff --git a/misc/avdetector.cpp b/misc/avdetector.cpp deleted file mode 100644 index bb1c9c8..0000000 --- a/misc/avdetector.cpp +++ /dev/null @@ -1,270 +0,0 @@ -/* - * File: avdetector.cpp - * Author: savop - * - * Created on 26. Oktober 2009, 13:01 - */ - -#include "avdetector.h" -#include <sys/stat.h> - -cAudioVideoDetector::cAudioVideoDetector(const char* Filename) : mResourceType(UPNP_RESOURCE_FILE) { - this->mResource.Filename = Filename; - this->init(); -} - -cAudioVideoDetector::cAudioVideoDetector(const cChannel* Channel) : mResourceType(UPNP_RESOURCE_CHANNEL) { - this->mResource.Channel = Channel; - this->init(); -} - -cAudioVideoDetector::cAudioVideoDetector(const cRecording* Recording) : mResourceType(UPNP_RESOURCE_RECORDING) { - this->mResource.Recording = Recording; - this->init(); -} - -cAudioVideoDetector::~cAudioVideoDetector(){ - this->uninit(); -} - -void cAudioVideoDetector::init(){ - this->mBitrate = 0; - this->mBitsPerSample = 0; - this->mColorDepth = 0; - this->mDLNAProfile = NULL; - this->mDuration = 0; - this->mHeight = 0; - this->mNrAudioChannels = 0; - this->mSampleFrequency = 0; - this->mSize = 0; - this->mWidth = 0; -} - -void cAudioVideoDetector::uninit(){ - this->init(); -} - -int cAudioVideoDetector::detectProperties(){ - int ret = 0; - switch(this->mResourceType){ - case UPNP_RESOURCE_CHANNEL: - ret = this->detectChannelProperties(); - break; - case UPNP_RESOURCE_RECORDING: - ret = this->detectRecordingProperties(); - break; - case UPNP_RESOURCE_FILE: - ret = this->detectFileProperties(); - break; - default: - WARNING("This resource type is not yet implemented."); - ret = -1; - break; - } - - return ret; -} - -int cAudioVideoDetector::detectChannelProperties(){ - this->mBitrate = 0; - this->mBitsPerSample = 0; - this->mColorDepth = 0; - this->mDuration = 0; - this->mHeight = 0; - this->mNrAudioChannels = 0; - this->mSampleFrequency = 0; - this->mSize = (off64_t)-1; - this->mWidth = 0; - - switch(this->mResource.Channel->Vtype()){ - case 0x02: - // MPEG2 Video - this->mDLNAProfile = &DLNA_PROFILE_MPEG_TS_SD_EU_ISO; - break; - case 0x1B: - this->mDLNAProfile = &DLNA_PROFILE_AVC_TS_HD_EU_ISO; - break; - default: - ERROR("Unknown video type %d for channel %s!", this->mResource.Channel->Vtype(), this->mResource.Channel->Name()); - this->mDLNAProfile = NULL; - return -1; - } - - return 0; -} - -int cAudioVideoDetector::detectRecordingProperties(){ - - if(this->mResource.Recording->IsPesRecording()){ - ERROR("Sorry, PES Recordings are not supported"); - return -1; - } - - int ret = 0; - AVFormatContext *FormatCtx = NULL; - - cIndexFile* Index = new cIndexFile(this->mResource.Recording->FileName(), false, this->mResource.Recording->IsPesRecording()); - cFileName* RecFile = new cFileName(this->mResource.Recording->FileName(), false, false, this->mResource.Recording->IsPesRecording()); - if(Index && Index->Ok()){ - this->mDuration = (off64_t) (Index->Last() * AVDETECTOR_TIME_BASE / SecondsToFrames(1, this->mResource.Recording->FramesPerSecond())); - MESSAGE(VERBOSE_METADATA,"Record length: %llds", this->mDuration); - - uint16_t FileNumber = 0; - off_t FileOffset = 0; - - if(Index->Get(Index->Last()-1, &FileNumber, &FileOffset)) - for(int i = 0; i < FileNumber; i++){ - struct stat Stats; - RecFile->SetOffset(i+1); - stat(RecFile->Name(),&Stats); - this->mSize += (off64_t) Stats.st_size; - } - - av_register_all(); - - if(!(ret = av_open_input_file(&FormatCtx, RecFile->Name(), NULL, 0, NULL))){ - if((ret = av_find_stream_info(FormatCtx))<0){ - ERROR("AVDetector: Cannot find the stream information"); - } - else { - if((ret = this->analyseVideo(FormatCtx))<0){ - ERROR("AVDetector: Error while analysing video"); - } - if((ret = this->analyseAudio(FormatCtx))<0){ - ERROR("AVDetector: Error while analysing audio"); - } - } - } - } - else { - ret = -1; - } - - if(ret != 0){ - ERROR("Error occured while detecting properties"); - } - - delete RecFile; - delete Index; - av_free(FormatCtx); - - return ret; -} - -int cAudioVideoDetector::detectFileProperties(){ - av_register_all(); - - int ret = 0; - - AVFormatContext *FormatCtx = NULL; - - if(av_open_input_file(&FormatCtx, this->mResource.Filename, NULL, 0, NULL)){ - ERROR("AVDetector: Error while opening file %s", this->mResource.Filename); - return -1; - } - else { - if(av_find_stream_info(FormatCtx)<0){ - ERROR("AVDetector: Cannot find the stream information"); - return -1; - } - else { - - if((ret = this->analyseFormat(FormatCtx))<0){ - ERROR("AVDetector: Error while analysing format"); - return ret; - } - if((ret = this->analyseVideo(FormatCtx))<0){ - ERROR("AVDetector: Error while analysing video"); - return ret; - } - if((ret = this->analyseAudio(FormatCtx))<0){ - ERROR("AVDetector: Error while analysing audio"); - return ret; - } - - return 0; - } - } -} - -int cAudioVideoDetector::analyseFormat(AVFormatContext* FormatCtx){ - if(!FormatCtx) return -1; - - this->mSize = FormatCtx->file_size; - this->mDuration = FormatCtx->duration; - - MESSAGE(VERBOSE_METADATA, "Format properties: %lld and %lld Bytes", this->mDuration, this->mSize); - - AVMetadataTag* Tag = NULL; - - while((Tag=av_metadata_get(FormatCtx->metadata,"",Tag,AV_METADATA_IGNORE_SUFFIX))){ - MESSAGE(VERBOSE_METADATA, "%s: %s", Tag->key, Tag->value); - } - - return 0; -} - -int cAudioVideoDetector::analyseVideo(AVFormatContext* FormatCtx) -{ -// // Register avformat - - unsigned int i; int videoStream = -1; - - AVCodecContext *CodecCtx = NULL; - for(i = 0; i < FormatCtx->nb_streams; i++){ - if(FormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_VIDEO){ - videoStream = i; - break; - } - } - if(videoStream == -1){ - ERROR("AVDetector: No video stream found"); - return 1; - } - - CodecCtx = FormatCtx->streams[videoStream]->codec; - - AVCodec* Codec = avcodec_find_decoder(CodecCtx->codec_id); - - this->mWidth = CodecCtx->width; - this->mHeight = CodecCtx->height; - this->mBitrate = CodecCtx->bit_rate; - this->mSampleFrequency = CodecCtx->sample_rate; - this->mBitsPerSample = CodecCtx->bits_per_raw_sample; - - // TODO: what's the color depth of the stream - - const char* codecName = (Codec)?Codec->name:"unknown"; - - MESSAGE(VERBOSE_METADATA, "AVDetector: %s-stream %dx%d at %d bit/s", codecName, this->mWidth, this->mHeight, this->mBitrate); - return 0; -} - -int cAudioVideoDetector::analyseAudio(AVFormatContext* FormatCtx){ - - unsigned int i; int audioStream = -1; - - AVCodecContext *CodecCtx = NULL; - for(i = 0; i < FormatCtx->nb_streams; i++){ - if(FormatCtx->streams[i]->codec->codec_type == CODEC_TYPE_AUDIO){ - audioStream = i; - break; - } - } - if(audioStream == -1){ - ERROR("AVDetector: No audio stream found"); - return 1; - } - - CodecCtx = FormatCtx->streams[audioStream]->codec; - AVCodec* Codec = avcodec_find_decoder(CodecCtx->codec_id); - - this->mNrAudioChannels = CodecCtx->channels; - - const char* codecName = (Codec)?Codec->name:"unknown"; - - MESSAGE(VERBOSE_METADATA, "AVDetector: %s-stream at %d bit/s", codecName, CodecCtx->bit_rate); - return 0; - -} - diff --git a/misc/avdetector.h b/misc/avdetector.h deleted file mode 100644 index 33b3298..0000000 --- a/misc/avdetector.h +++ /dev/null @@ -1,105 +0,0 @@ -/* - * File: avdetector.h - * Author: savop - * - * Created on 26. Oktober 2009, 13:02 - */ - -#ifndef _AVDETECTOR_H -#define _AVDETECTOR_H - -#include "../database/object.h" -#include <vdr/recording.h> -#include <vdr/channels.h> - -extern "C" { -#include <libavcodec/avcodec.h> -#include <libavformat/avformat.h> -} - -/** - * The audio/video detector - * - * This is the audio video detector, which analizes the audio and video stream - * of a file to gather more information about the resource. This is also - * required for determination of a suitable DLNA profile. - */ -class cAudioVideoDetector { -private: - void init(); - void uninit(); - int detectChannelProperties(); - int detectFileProperties(); - int detectRecordingProperties(); - /** - * Detect video properties - * - * This detects video properties of a video stream - * - * @return returns - * - \bc 0, if the detection was successful - * - \bc <0, otherwise - */ - int analyseVideo(AVFormatContext* FormatCtx); - /** - * Detect audio properties - * - * This detects audio properties of a video or audio stream - * - * @return returns - * - \bc 0, if the detection was successful - * - \bc <0, otherwise - */ - int analyseAudio(AVFormatContext* FormatCtx); - int analyseFormat(AVFormatContext* FormatCtx); - int detectDLNAProfile(); - UPNP_RESOURCE_TYPES mResourceType; - union { - const cChannel* Channel; - const cRecording* Recording; - const char* Filename; - } mResource; - int mWidth; - int mHeight; - int mBitrate; - int mBitsPerSample; - int mColorDepth; - off64_t mDuration; - off64_t mSize; - int mSampleFrequency; - int mNrAudioChannels; - DLNAProfile* mDLNAProfile; -public: - cAudioVideoDetector(const char* Filename); - cAudioVideoDetector(const cChannel* Channel); - cAudioVideoDetector(const cRecording* Recording); - virtual ~cAudioVideoDetector(); - /** - * Detect resource properties of the file - * - * This detects the resource properties of a file. If the returned value - * is 0, no erros occured while detection and the properties are properly - * set. Otherwise, in case of an error, the properties may have - * unpredictable values. - * - * @return returns - * - \bc 0, if the detection was successful - * - \bc <0, otherwise - */ - int detectProperties(); - DLNAProfile* getDLNAProfile() const { return this->mDLNAProfile; } - const char* getContentType() const { return (this->mDLNAProfile) ? this->mDLNAProfile->mime : NULL; } - const char* getProtocolInfo() const; - int getWidth() const { return this->mWidth; } - int getHeight() const { return this->mHeight; } - int getBitrate() const { return this->mBitrate; } - int getBitsPerSample() const { return this->mBitsPerSample; } - int getSampleFrequency() const { return this->mSampleFrequency; } - int getNumberOfAudioChannels() const { return this->mNrAudioChannels; } - int getColorDepth() const { return this->mColorDepth; } - off64_t getFileSize() const { return this->mSize; } - off64_t getDuration() const { return this->mDuration; } -}; - -#endif /* _AVDETECTOR_H */ - diff --git a/misc/config.cpp b/misc/config.cpp index 1fa0ccb..10ed166 100644 --- a/misc/config.cpp +++ b/misc/config.cpp @@ -10,8 +10,11 @@ #include <getopt.h> #include "config.h" #include "../common.h" +#include "../upnp.h" cUPnPConfig::cUPnPConfig(){ + this->mDatabaseFolder = NULL; + this->mHTTPFolder = NULL; this->mParsedArgs = NULL; this->mInterface = NULL; this->mAddress = NULL; @@ -42,10 +45,13 @@ bool cUPnPConfig::processArgs(int argc, char* argv[]){ {"port", required_argument, NULL, 'p'}, {"autodetect", no_argument, NULL, 'd'}, {"verbose", no_argument, NULL, 'v'}, + {"httpdir", required_argument, NULL, 0}, + {"dbdir", required_argument, NULL, 0}, {0, 0, 0, 0} }; - int c = 0; + int c = 0; int index = -1; + struct option* opt = NULL; // Check if anything went wrong by setting 'success' to false // As there are multiple tests you may get a faulty behavior @@ -60,7 +66,7 @@ bool cUPnPConfig::processArgs(int argc, char* argv[]){ bool addExcistent = false; static int verbose = 0; - while((c = getopt_long(argc, argv, "i:a:p:dv",long_options, NULL)) != -1){ + while((c = getopt_long(argc, argv, "i:a:p:dv",long_options, &index)) != -1){ switch(c){ case 'i': if(addExcistent) { ERROR("Address given but must be absent!"); return false; } @@ -86,7 +92,15 @@ bool cUPnPConfig::processArgs(int argc, char* argv[]){ case 'v': cUPnPConfig::verbosity++; verbose++; - WARNING("Verbosity level: %i ", verbose); + break; + case 0: + opt = &long_options[index]; + if(!strcasecmp("httpdir", opt->name)){ + success = this->parseSetup(SETUP_WEBSERVER_DIR, optarg) && success; + } + else if(!strcasecmp("dbdir", opt->name)){ + success = this->parseSetup(SETUP_DATABASE_DIR, optarg) && success; + } break; default: return false; @@ -111,6 +125,8 @@ bool cUPnPConfig::parseSetup(const char *Name, const char *Value) else if (!strcasecmp(Name, SETUP_SERVER_INT)) this->mInterface = strdup0(Value); // (Value) ? strn0cpy(this->mInterface, Value, strlen(this->mInterface)) : NULL; else if (!strcasecmp(Name, SETUP_SERVER_ADDRESS)) this->mAddress = strdup0(Value); //(Value) ? strn0cpy(this->mAddress, Value, strlen(this->mAddress)) : NULL; else if (!strcasecmp(Name, SETUP_SERVER_PORT)) this->mPort = atoi(Value); + else if (!strcasecmp(Name, SETUP_WEBSERVER_DIR)) this->mHTTPFolder = strdup0(Value); + else if (!strcasecmp(Name, SETUP_DATABASE_DIR)) this->mDatabaseFolder = strdup0(Value); else return false; this->mParsedArgs = cString::sprintf("%s%s",*this->mParsedArgs,Name); diff --git a/misc/config.h b/misc/config.h deleted file mode 100644 index 40ae6f7..0000000 --- a/misc/config.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * File: config.h - * Author: savop - * - * Created on 15. August 2009, 13:03 - */ - -#ifndef _CONFIG_H -#define _CONFIG_H - -#include <vdr/tools.h> -#include "../common.h" - -/** - * The configuration settings - * - * This holds the configurations for the server. It holds information about the - * network settings as well as some status flags. - */ -class cUPnPConfig { -private: - static cUPnPConfig* mInstance; - cString mParsedArgs; - cUPnPConfig(); -public: - static int verbosity; ///< the verbosity of the plugin, the higher the more messages - ///< are printed. - char* mInterface; ///< the network interface, which the server is bound to - char* mAddress; ///< the IP address which is used by the server - int mPort; ///< the port which the server is listening on - int mEnable; ///< indicates, if the server is enabled or not - int mAutoSetup; ///< indicates, if the settings are automatically detected -public: - virtual ~cUPnPConfig(); - /** - * Get the configuration - * - * This returns the instance of the current configuration settings. - * - * @return the configuration object - */ - static cUPnPConfig* get(); - /** - * Parse setup variable - * - * This parses the setup variable with the according value. The value is a - * string representation and must be converted into the according data type. - * - * @return returns - * - \bc true, if parsing was successful - * - \bc false, otherwise - * @param Name the name of the variable - * @param Value the according value of the variable - */ - bool parseSetup(const char* Name, const char* Value); - /** - * Processes the commandline arguments - * - * This processes the commandline arguments which the user specified at the - * start of the plugin. - * - * @return returns - * - \bc true, if processing was successful - * - \bc false, otherwise - * @param argc the number of arguments in the list - * @param argv the arguments as a char array - */ - bool processArgs(int argc, char* argv[]); -}; - -#endif /* _CONFIG_H */ - diff --git a/misc/menusetup.h b/misc/menusetup.h deleted file mode 100644 index 4e32efc..0000000 --- a/misc/menusetup.h +++ /dev/null @@ -1,103 +0,0 @@ -/* - * File: menusetup.h - * Author: savop - * - * Created on 19. April 2009, 16:50 - */ - -#ifndef _CMENUSETUPUPNP_H -#define _CMENUSETUPUPNP_H - -#include <vdr/plugin.h> -#include "../server/server.h" -#include "config.h" - -/** - * The VDR setup page - * - * This class shows and manages the settings within the VDR setup OSD - * - */ -class cMenuSetupUPnP : public cMenuSetupPage { -public: - cMenuSetupUPnP(); -// virtual ~cMenuSetupUPnP(); - /** - * Processes a keystroke - * - * This processes a keystroke which is done by the user and updates the - * menu accordingly - * - * It returns the current state of the VDR after pressing a key - * - * @return The current state of the VDR - */ - virtual eOSState ProcessKey( - eKeys Key ///< Key, pressed by the user - ); -protected: - /** - * Stores the setup information - * - * This stores the setup information in the configuration file - */ - virtual void Store(void); - /** - * Update the menu - * - * This updates the menu osd and refreshes the screen. - */ - void Update(void); - /** - * Loads the setup information - * - * This loads the setup information from the configuration file - */ - void Load(void); -private: - const char* const* getInterfaceList(int *count); - int getInterfaceIndex(const char* Interface); - const char* getInterface(int Index); - cOsdItem *mCtrlBind; - cOsdItem *mCtrlEnabled; - cOsdItem *mCtrlPort; - cOsdItem *mCtrlAutoMode; - cUPnPServer* mUpnpServer; - /** - * Is the server enabled or not - * - * The server can be switched on or off. If it is turned off, the server - * will close open transmissions and ports - * - */ - int mEnable; - int mAutoSetup; - /** - * The port to listen to (Default: 0 autodetect) - * - * The port the server is bound to. The default setting is 0. - * So, the server will determine automatically a free random port between - * 49152 and 65535. If a server should use a specific port it can be set - * to one out of that range. - * - */ - int mPort; - int mDetectPort; - /** - * The Interface the server is bound to - * - * If multiple interfaces exist the server can be bound to a specific - * one - * - */ - int mInterfaceIndex; - /** - * The socket address of the server - * - * The IP address and the port of the server - */ - char *mAddress; -}; - -#endif /* _CMENUSETUPUPNP_H */ - diff --git a/misc/search.h b/misc/search.h deleted file mode 100644 index ef162b1..0000000 --- a/misc/search.h +++ /dev/null @@ -1,156 +0,0 @@ -/* - * File: search.h - * Author: savop - * - * Created on 27. August 2009, 21:21 - */ - -#ifndef _SEARCH_H -#define _SEARCH_H - -#include <map> -#include <vdr/tools.h> -#include "util.h" - -/** - * Sort criteria - * - * This is a structure for sorting objects. It has a certain property and - * a direction flag. - */ -struct cSortCrit : public cListObject { - const char* Property; ///< the Property, which shall be sorted - bool SortDescending; ///< sort the objects in descending order -}; - -typedef std::map<const char*, const char*, strCmp> propertyMap; - -/** - * Web path parser - * - * Parses paths which came from the webserver. It splits the path into - * a section, a certain method and its properties. - * - * This can be used to easily determine which file was requested by a client - */ -class cPathParser { -private: - cString mKey; - propertyMap mProperties; - int mSection; - int mMethod; - bool parsePath(const char* Path, int* Section, int* Method, propertyMap* Properties); - void pushPropertyKey(const char* Start, const char* End); - void pushPropertyValue(const char* Start, const char* End); - void pushMethod(int Method); - void pushSection(int Section); - cPathParser(); -public: - virtual ~cPathParser(); - /** - * Parses the path - * - * This will parse the path and stores the result in the pointers given. - * - * @return returns - * - \bc true, if the parsing was successful - * - \bc false, otherwise - */ - static bool parse( - const char* Path, ///< the path which is parsed - int* Section, ///< the number of the registered section - int* Method, ///< the number of the registered method - propertyMap* Properties ///< the properties found in the path - ); -}; - -/** - * Creates a list with sort criteria - * - * This parser creates a list of sort criteria. It parses the sort criteria string - * from a \em Browse or \em Search request and stores the information in a \c cSortCrit - * structure. - */ -class cSortCriteria { -private: - cSortCrit* mCurrentCrit; - cList<cSortCrit>* mCriteriaList; - bool parseSort(const char* Sort); - void pushProperty(const char* Property); - void pushDirection(const char Direction); - cList<cSortCrit>* getSortList() const { return this->mCriteriaList; } - cSortCriteria(); -public: - virtual ~cSortCriteria(); - /** - * Parses the sort criteria - * - * This parses the sort criteria and returns a list with valid criterias - * - * @return returns - * - a list with valid sort criterias - * - \bc null, otherwise - */ - static cList<cSortCrit>* parse( - const char* Sort ///< the string container the sort criteria - ); -}; - -/** - * Parses the filter criteria - * - * This parses the filter criteria which comes from a \em Browse or \em Search - * request. - */ -class cFilterCriteria { -private: - cStringList* mFilterList; - cFilterCriteria(); - bool parseFilter(const char* Filter); - void pushProperty(const char* Property); - void pushAsterisk(const char Asterisk); - cStringList* getFilterList() const { return this->mFilterList; } -public: - virtual ~cFilterCriteria(); - /** - * Parses the filter criteria - * - * This parses the filter criteria. It may be a empty string list, a \bc NULL - * pointer or a list with properties which shall be shown in the \em DIDL-Lite fragment. - * - * @return the stringlist containing the filter - */ - static cStringList* parse( - const char* Filter ///< the filter string - ); -}; - -/** - * @private - * @todo This is implemented very soon - */ -class cSearch { -private: - char* SQLWhereStmt; - const char* CurrentProperty; - const char* CurrentOperator; - const char* CurrentValue; - static cSearch* mInstance; - cSearch(); - bool parseCriteria(const char* Search); - void pushExistance (const char* Exists); - void pushProperty (const char* Property); - void pushOperator (const char* Operator); - void pushConcatOp (const char* Operator); - void pushStartBrackedExp(const char); - void pushEndBrackedExp(const char); - void pushValue (const char* Start, const char* End); - void pushExpression(const char* Start, const char* End); -public: - virtual ~cSearch(); - static const char* parse(const char* Search); -}; - - -#endif /* _SEARCH_H */ - diff --git a/misc/util.h b/misc/util.h deleted file mode 100644 index e5bc061..0000000 --- a/misc/util.h +++ /dev/null @@ -1,144 +0,0 @@ -/* - * File: util.h - * Author: savop - * - * Created on 21. Mai 2009, 21:25 - */ - -#ifndef _UTIL_H -#define _UTIL_H - -#include <vdr/tools.h> -#include <vdr/plugin.h> -#include <upnp/ixml.h> - -#ifdef __cplusplus -extern "C" { -#if 0 -} -#endif -/** - * Compares two strings - * - * This struct compares two strings and returns true on equality or false otherwise - * It is used in conjuction with hashmaps - */ -struct strCmp { - /** - * Compares two strings - * @return returns - * - \bc true, in case of equality - * - \bc false, otherwise - * @param s1 the first string - * @param s2 the second string - */ - bool operator()(const char* s1, const char* s2) const { return (strcmp(s1,s2) < 0); } -}; -/** - * Gets the IP address - * - * Returns the IP address of a given interface. The interface must be a valid interface - * identifier like eth0 or wlan1. - * - * @return a structure containing the IP address - * @param Interface to obtain the IP from - */ -const sockaddr_in* getIPFromInterface(const char* Interface); -/** - * Gets the MAC address - * - * Returns a string representation of the MAC address of a given interface. The interface - * must be a valid interface identifier like eth0 or wlan1. - * - * The pattern of the address is sixth byte hex number separated with ":" - * - * @return a string containing the MAC - * @param Interface to obtain the MAC from - */ -const char* getMACFromInterface(const char* Interface); -/** - * List with interfaces - * - * Returns an array with interfaces found on the system. The number of items - * in the array is stored in the parameter \c count. - * - * @return array list of interfaces - * @param count number of interfaces in the array - */ -char** getNetworkInterfaces(int *count); -/** - * First occurance of item - * - * Finds the first occurance of a specified item in a given \bc IXML document and returns its value. - * If an error occures, its code is stored in the last parameter \c 'error'. - * - * @return the value of the item - * @param doc the \c IXML document to be parsed - * @param item the item which shall be found - * @param error the error code in case of an error - */ -char* ixmlGetFirstDocumentItem( IN IXML_Document * doc, IN const char *item, int* error ); -/** - * Adds a property - * - * This adds a UPnP property to an \bc IXML document. - * The property must have the pattern "namespace:property@attribute". - * - * @return returns - * - \bc <0, in case of an error - * - \bc 0, otherwise - * @param document the \c IXML document to put the parameter in - * @param node the specific node where to put the parameter - * @param upnpproperty the upnp property - * @param value the value of the upnp property - */ -int ixmlAddProperty(IN IXML_Document* document, IN IXML_Element* node, const char* upnpproperty, const char* value ); -/** - * creates a part of a string - * - * This creates a substring of a string which begins at the given offset and has the - * specified lenght. - * - * @return the new string - * @param str the full string - * @param offset the starting index - * @param length the length of the new string - */ -char* substr(const char* str, unsigned int offset, unsigned int length); - -char* duration(off64_t duration, unsigned int timeBase = 1); -#if 0 -{ -#endif -} -#endif - -/** - * Escapes XML special characters - * - * This function escapes XML special characters, which must be transformed before - * inserting it into another XML document. - * - * @return the escaped document - * @param Data the data to escape - * @param Buf the pointer where the escaped document shall be stored - */ -const char* escapeXMLCharacters(const char* Data, char** Buf); - -/** @private */ -class cMenuEditIpItem: public cMenuEditItem { -private: - char *value; - int curNum; - int pos; - bool step; -protected: - virtual void Set(void); -public: - cMenuEditIpItem(const char *Name, char *Value); // Value must be 16 bytes - ~cMenuEditIpItem(); - virtual eOSState ProcessKey(eKeys Key); -}; - -#endif /* _UTIL_H */ - diff --git a/receiver/filehandle.cpp b/receiver/filehandle.cpp deleted file mode 100644 index bc24f53..0000000 --- a/receiver/filehandle.cpp +++ /dev/null @@ -1,8 +0,0 @@ -/* - * File: filehandle.cpp - * Author: savop - * - * Created on 15. Oktober 2009, 10:49 - */ - -#include "filehandle.h"
\ No newline at end of file diff --git a/receiver/filehandle.h b/receiver/filehandle.h deleted file mode 100644 index 1dc57bf..0000000 --- a/receiver/filehandle.h +++ /dev/null @@ -1,108 +0,0 @@ -/* - * File: filehandle.h - * Author: savop - * - * Created on 15. Oktober 2009, 10:49 - */ - -#ifndef _FILEHANDLE_H -#define _FILEHANDLE_H - -#include <upnp/upnp.h> -#include "../common.h" - -/** - * Interface for File Handles - * - * This class is a pure virtual class to act as an interface for file handles - * used by the webserver. - */ -class cFileHandle { -public: - /** - * Opens the file - * - * Opens the file at the given mode. These can be: - * - \b UPNP_READ, to read from the file - * - \b UPNP_WRITE, to write to the file - * - * @param mode The file mode, i.e. one of the following - * - \b UPNP_READ - * - \b UPNP_WRITE - */ - virtual void open( - UpnpOpenFileMode mode ///< The file mode, i.e. one of the following - ///< - \b UPNP_READ - ///< - \b UPNP_WRITE - ) = 0; - /** - * Reads from the file - * - * Reads from the file a certain amount of bytes and stores them in a buffer - * - * @return returns - * - \b <0, in case of an error - * - \b 0, when reading was successful - * - * @param buf The char buffer - * @param buflen The size of the buffer - */ - virtual int read( - char* buf, ///< The char buffer - size_t buflen ///< The size of the buffer - ) = 0; - /** - * Writes to the file - * - * Writes to the file a certain amount of bytes which are stored in a buffer - * - * @return returns - * - \b <0, in case of an error - * - \b 0, when reading was successful - * - * @param buf The char buffer - * @param buflen The size of the buffer - */ - virtual int write( - char* buf, ///< The char buffer - size_t buflen ///< The size of the buffer - ) = 0; - /** - * Seeks in the file - * - * Seeks in the file where the offset is the relativ position depending on - * the second parameter. This means, in case of - * - * - \b SEEK_SET, the offset is relative to the beginning of the file - * - \b SEEK_CUR, it is relative to the current position or - * - \b SEEK_END, relative to the end of the file. - * - * @return returns - * - \b <0, in case of an error - * - \b 0, when reading was successful - * - * @param offset The byte offset in the file - * @param whence one of the following - * - \b SEEK_SET, - * - \b SEEK_CUR, - * - \b SEEK_END - */ - virtual int seek( - off_t offset, ///< The byte offset in the file - int whence ///< one of the following - ///< - \b SEEK_SET, - ///< - \b SEEK_CUR, - ///< - \b SEEK_END - ) = 0; - /** - * Closes the open file - * - * This will close open file handles and frees the memory obtained by it. - */ - virtual void close() = 0; - virtual ~cFileHandle(){}; -private: -}; - -#endif /* _FILEHANDLE_H */ - diff --git a/receiver/livereceiver.cpp b/receiver/livereceiver.cpp index 8ca560f..a43d197 100644 --- a/receiver/livereceiver.cpp +++ b/receiver/livereceiver.cpp @@ -125,14 +125,18 @@ void cLiveReceiver::Action(void){ } int cLiveReceiver::read(char* buf, size_t buflen){ - int bytesRead; + int bytesRead = 0; if(!this->IsAttached()) bytesRead = -1; else { int WaitTimeout = RECEIVER_WAIT_ON_NODATA_TIMEOUT; // Wait until the buffer size is at least half the requested buffer length - while((unsigned)this->mOutputBuffer->Available() < (buflen / 2) ){ + + double MinBufSize = buflen * RECEIVER_MIN_BUFFER_FILLAGE/100; + int Available = 0; + while((double)(Available = this->mOutputBuffer->Available()) < MinBufSize){ WARNING("Too few data, waiting..."); + WARNING("Only %d bytes available, need %10f more bytes.", Available, (double)(MinBufSize-Available)); cCondWait::SleepMs(RECEIVER_WAIT_ON_NODATA); if(!this->IsAttached()){ MESSAGE(VERBOSE_LIVE_TV, "Lost device..."); diff --git a/receiver/livereceiver.h b/receiver/livereceiver.h deleted file mode 100644 index 92fe140..0000000 --- a/receiver/livereceiver.h +++ /dev/null @@ -1,104 +0,0 @@ -/* - * File: livereceiver.h - * Author: savop - * - * Created on 4. Juni 2009, 13:28 - */ - -#ifndef _LIVERECEIVER_H -#define _LIVERECEIVER_H - -#include "../common.h" -#include "filehandle.h" -#include <vdr/thread.h> -#include <vdr/receiver.h> -#include <vdr/ringbuffer.h> - -#define RECEIVER_WAIT_ON_NODATA 50 // 50 ms -#define RECEIVER_WAIT_ON_NODATA_TIMEOUT 1000 * 2 // 2s - -/** - * A receiver for live TV - * - * This is a receiver object which is attached to a VDR tv card device. - * It is receiving transport stream packages and generates a single MPEG2 - * transport stream which can be distributed through the network. - * - */ -class cLiveReceiver : public cReceiver, public cThread, public cFileHandle { -public: - /** - * Creates a new receiver instance - * - * This will create a new instance of a live receiver for the specified - * channel at the specified priority level. - * - * A negativ priority means that the receiver may being detached from a - * device. - * - * The receiver must be free'd with delete after it is not used anylonger. - * - * @return returns a new liveReceiver instance - */ - static cLiveReceiver* newInstance( - cChannel *Channel, ///< the channel which shall be tuned - int Priority ///< the priority level - ); - virtual ~cLiveReceiver(void); - /*! @copydoc cFileHandle::open(UpnpOpenFileMode) */ - virtual void open(UpnpOpenFileMode mode); - /*! @copydoc cFileHandle::read(char*,size_t) */ - virtual int read(char* buf, size_t buflen); - /*! @copydoc cFileHandle::write(char*,size_t) */ - virtual int write(char* buf, size_t buflen); - /*! @copydoc cFileHandle::seek(off_t,int) */ - virtual int seek(off_t offset, int whence); - /*! @copydoc cFileHandle::close() */ - virtual void close(); -protected: - /** - * Receives data from VDR - * - * This is the interface for receiving packet data from the VDR. It buffers - * the incoming transport stream packets in a linear ringbuffer and returns - * immediatelly - */ - virtual void Receive( - uchar *Data, ///< The data received from VDR - int Length ///< The length of the data packet, usually 188 bytes - ); - /** - * Activates the receiver - * - * This activates the receiver which initializes internal data structures to - * be prepared for receiving data from the VDR - * - * If the parameter is \bc true, the receiver will be activated. If it is - * \bc false, the receiver will be deactivated and stops its threads. - */ - virtual void Activate( - bool On ///< Activates the receiver thread - ); - /** - * The receiver thread action - * - * This actually is the receiver thread, which runs consequitivelly and - * buffers any received video data from the interal incoming buffer to the - * internal outgoing buffer. - * - * While doing so, it tries to syncronize with the stream and creates new - * MPEG2-TS PATs and PMTs for a single MPEG2-TS stream - */ - virtual void Action(void); -private: - cLiveReceiver(cChannel *Channel, cDevice *Device); - cDevice *mDevice; - cChannel *mChannel; - cRingBufferLinear *mLiveBuffer; - cRingBufferLinear *mOutputBuffer; - cFrameDetector *mFrameDetector; - cPatPmtGenerator mPatPmtGenerator; -}; - -#endif /* _LIVERECEIVER_H */ - diff --git a/receiver/recplayer.cpp b/receiver/recplayer.cpp index 954c9c8..8bf73d4 100644 --- a/receiver/recplayer.cpp +++ b/receiver/recplayer.cpp @@ -21,27 +21,31 @@ cRecordingPlayer *cRecordingPlayer::newInstance(cRecording* Recording){ return Player; } cRecordingPlayer::~cRecordingPlayer() { - delete this->mOffsets; + delete this->mRecordingFile; + delete [] this->mLastOffsets; } -cRecordingPlayer::cRecordingPlayer(cRecording *Recording) { +cRecordingPlayer::cRecordingPlayer(cRecording *Recording) : mRecording(Recording) { MESSAGE(VERBOSE_SDK, "Created Recplayer"); - this->mFile = NULL; - this->mTotalLenght = 0; - this->mRecording = Recording; - this->mOffsets = new off_t[VDR_MAX_FILES_PER_RECORDING]; - this->mOffset = 0; - this->mIndex = 1; - + + this->mRecordingFile = new cFileName(this->mRecording->FileName(), false, false, this->mRecording->IsPesRecording()); + this->mLastOffsets = new off_t[((this->mRecording->IsPesRecording())?VDR_MAX_FILES_PER_PESRECORDING:VDR_MAX_FILES_PER_TSRECORDING)+1]; + this->scanLastOffsets(); } void cRecordingPlayer::open(UpnpOpenFileMode){ - this->Scan(); + // Open() does not work?! + this->mCurrentFile = this->mRecordingFile->SetOffset(1); + if(this->mCurrentFile){ + MESSAGE(VERBOSE_RECORDS, "Record player opened"); + } + else { + ERROR("Error while opening record player file"); + } } void cRecordingPlayer::close(){ - delete [] this->mOffsets; - if(this->mFile) fclose(this->mFile); + this->mRecordingFile->Close(); } int cRecordingPlayer::write(char*, size_t){ @@ -50,122 +54,70 @@ int cRecordingPlayer::write(char*, size_t){ } int cRecordingPlayer::read(char* buf, size_t buflen){ - FILE *File; - off_t fileEndOffset = this->mOffsets[this->mIndex]; - if(this->mOffset > fileEndOffset){ - File = this->NextFile(); + if(!this->mCurrentFile){ + ERROR("Current part of record is not open"); + return -1; } - else { - File = this->GetFile(); + MESSAGE(VERBOSE_RECORDS, "Reading %d from record", buflen); + int bytesread = 0; + while((bytesread = this->mCurrentFile->Read(buf, buflen)) == 0){ // EOF, try next file + if(!(this->mCurrentFile = this->mRecordingFile->NextFile())){ + // no more files to read... finished! + break; + } } - // do not read more bytes than the actual file has - size_t bytesToRead = ((fileEndOffset - this->mOffset) < (off_t)buflen)? fileEndOffset - this->mOffset : buflen; - size_t bytesRead = fread((char*)buf, sizeof(char), bytesToRead, File); - - this->mOffset += (off_t)bytesRead; - - return (int)bytesRead; + return bytesread; } int cRecordingPlayer::seek(off_t offset, int origin){ - // Calculate the new offset + if(!this->mCurrentFile){ + ERROR("Current part of record is not open"); + return -1; + } + + MESSAGE(VERBOSE_RECORDS, "Seeking..."); + + off_t relativeOffset; + off_t curpos = this->mCurrentFile->Seek(0, SEEK_CUR); // this should not change anything + int index; + // recalculate the absolute position in the record switch(origin){ - case SEEK_CUR: - if(this->mOffset + offset > this->mTotalLenght){ - ERROR("Can't read behind end of file!"); - return -1; - } - this->mOffset += (off_t)offset; - break; case SEEK_END: - if(offset > 0){ - ERROR("Can't read behind end of file!"); - return -1; - } - this->mOffset = this->mTotalLenght + offset; + offset = this->mLastOffsets[this->mLastFileNumber] + offset; + break; + case SEEK_CUR: + offset = this->mLastOffsets[this->mRecordingFile->Number()-1] + curpos + offset; break; case SEEK_SET: - if(offset > this->mTotalLenght){ - ERROR("Can't read behind end of file!"); - return -1; - } - this->mOffset = (off_t)offset; + // Nothing to change break; default: - ERROR("Unknown seek mode (%d)!", origin); + ERROR("Seek operation invalid"); return -1; } - // Seek to the very first file; - this->SeekInFile(1,0); - off_t fileEndOffset = this->mOffsets[this->mIndex]; - // Spin until the new offset is in range of a specific file - while(this->mOffset > (fileEndOffset = this->mOffsets[this->mIndex])){ - // If its not possible to switch to next file, there was an error - if(!this->NextFile()){ - ERROR("Offset %lld not in the range of a file!", offset); - return -1; + // finally, we can seek + // TODO: binary search + for(index = 1; this->mLastOffsets[index]; index++){ + if(this->mLastOffsets[index-1] <= offset && offset <= this->mLastOffsets[index]){ + relativeOffset = offset - this->mLastOffsets[index-1]; + break; } } - off_t relativeOffset = - this->mOffset - (this->mOffsets[this->mIndex-1]) - ? this->mOffsets[this->mIndex-1] - : 0; - if(!this->SeekInFile(this->mIndex, relativeOffset)){ - ERROR("Cannot set offset!"); + if(!(this->mCurrentFile = this->mRecordingFile->SetOffset(index, relativeOffset))){ + // seeking failed!!! should never happen. + this->mCurrentFile = this->mRecordingFile->SetOffset(1); return -1; } - return 0; -} -void cRecordingPlayer::Scan(){ - MESSAGE(VERBOSE_RECORDS, "Scanning video files..."); - // Reset the offsets - int i = 1; - while(this->mOffsets[i++]) this->mOffsets[i] = 0; - MESSAGE(VERBOSE_RECORDS, "Offsets reseted."); - - i = 0; - FILE *File; - while((File = this->GetFile(i))){ - if(VDR_MAX_FILES_PER_RECORDING < i+1){ - ERROR("Maximum file offsets exceeded!"); - break; - } - fseek(File, 0, SEEK_END); - off_t offset = ftell(File); - MESSAGE(VERBOSE_RECORDS, "File %d has its last offset at %lld", i, offset); - this->mOffsets[i+1] = this->mOffsets[i] + offset; - this->mTotalLenght = this->mOffsets[i+1]; - i++; - } + return 0; } -FILE *cRecordingPlayer::GetFile(int Index){ - // No Index given: set current index - if(Index == 0) Index = this->mIndex; - // Index not changed: return current file - if(this->mIndex == Index && this->mFile) return this->mFile; - - // Index changed: close open file and open new file - if(this->mFile) fclose(this->mFile); - char *filename = new char[VDR_FILENAME_BUFSIZE]; - snprintf(filename, VDR_FILENAME_BUFSIZE, VDR_RECORDFILE_PATTERN_TS, this->mRecording->FileName(), Index ); - MESSAGE(VERBOSE_BUFFERS, "Filename: %s", filename); - this->mFile = NULL; - if(this->mFile = fopen(filename, "r")){ - this->mIndex = Index; - return this->mFile; +void cRecordingPlayer::scanLastOffsets(){ + // rewind + this->mCurrentFile = this->mRecordingFile->SetOffset(1); + for(int i = 1; (this->mCurrentFile = this->mRecordingFile->NextFile()); i++){ + this->mLastOffsets[i] = this->mLastOffsets[i-1] + this->mCurrentFile->Seek(0, SEEK_END); + this->mLastFileNumber = this->mRecordingFile->Number(); } - return NULL; -} - -FILE *cRecordingPlayer::NextFile(void){ - return this->GetFile(this->mIndex++); -} - -int cRecordingPlayer::SeekInFile(int Index, off_t Offset){ - FILE *File = this->GetFile(Index); - fseek(File, Offset, SEEK_SET); - return ftell(File); } diff --git a/receiver/recplayer.h b/receiver/recplayer.h deleted file mode 100644 index a2e69ac..0000000 --- a/receiver/recplayer.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * File: recplayer.h - * Author: savop - * - * Created on 8. Juni 2009, 11:57 - */ - -#ifndef _RECPLAYER_H -#define _RECPLAYER_H - -#include "../common.h" -#include "filehandle.h" -#include <vdr/recording.h> - -/** - * The recording player - * - * This class provides the ability to play VDR records. The difference between - * usual files and VDR recording files is, that recordings are possibly splitted - * into multiple files. The class will scan those files and tries to dynamically - * navigate in them like it would do, if it is a single file. - * - */ -class cRecordingPlayer : cFileHandle { -public: - /** - * Get a new instance of a recording player - * - * This returns a new instance of a recording player which plays the - * specified VDR recording. - * - * @param Recording the recording to play - * @return the new instance of the recording player - */ - static cRecordingPlayer *newInstance(cRecording *Recording); - virtual ~cRecordingPlayer(); - virtual void open(UpnpOpenFileMode mode); - virtual int read(char* buf, size_t buflen); - virtual int write(char* buf, size_t buflen); - virtual int seek(off_t offset, int origin); - virtual void close(); -private: - void Scan(void); - cRecordingPlayer(cRecording *Recording); - FILE* GetFile(int Index = 0); - FILE* NextFile(void); - int SeekInFile(int Index, off_t Offset); - cRecording *mRecording; - off_t* mOffsets; - off_t mOffset; - off_t mTotalLenght; - int mIndex; - FILE *mFile; -}; - -#endif /* _RECPLAYER_H */ - diff --git a/server/server.cpp b/server/server.cpp index d98c78b..56bf442 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -11,11 +11,11 @@ #include <arpa/inet.h> #include <upnp/upnp.h> #include "server.h" -#include "../misc/util.h" -#include "../misc/config.h" +#include "util.h" +#include "config.h" #include "../common.h" -#include "../upnpcomponents/dlna.h" -#include "../database/object.h" +#include "upnp/dlna.h" +#include "object.h" /**************************************************** * @@ -104,8 +104,9 @@ bool cUPnPServer::init(void){ MESSAGE(VERBOSE_CUSTOM_OUTPUT, "Setting maximum packet size for SOAP requests"); UpnpSetMaxContentLength(UPNP_SOAP_MAX_LEN); + const char* httpdir = (cUPnPConfig::get()->mHTTPFolder) ? cUPnPConfig::get()->mHTTPFolder : cPluginUpnp::getConfigDirectory(); //set the root directory of the webserver - cString WebserverRootDir = cString::sprintf("%s%s", cPluginUpnp::getConfigDirectory(), UPNP_WEB_SERVER_ROOT_DIR); + cString WebserverRootDir = cString::sprintf("%s%s", httpdir, UPNP_WEB_SERVER_ROOT_DIR); MESSAGE(VERBOSE_SDK, "Set web server root dir: %s", *WebserverRootDir ); this->mWebServer = cUPnPWebServer::getInstance(WebserverRootDir); diff --git a/server/server.h b/server/server.h deleted file mode 100644 index c2a0e9a..0000000 --- a/server/server.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * File: server.h - * Author: savop - * - * Created on 19. April 2009, 17:42 - */ - -#ifndef _SERVER_H -#define _SERVER_H - -#include <netinet/in.h> -#include <vdr/recording.h> -#include <vdr/thread.h> -#include <upnp/upnp.h> -#include "../misc/util.h" -#include "../common.h" -#include "../upnpcomponents/upnpwebserver.h" -#include "../database/metadata.h" -#include "../upnpcomponents/connectionmanager.h" -#include "../upnpcomponents/contentdirectory.h" -#include "../upnp.h" - -/** - * The UPnP Server - * - * This is the core of the UPnP server. This handles all the components which - * are needed for a UPnP media server. Incoming messages are passed through it - * and it determines what to do. - */ -class cUPnPServer { - friend class cPluginUpnp; -public: - /** - * Constructor - * - * This will create a new server and initializes the main functionalities - * The server has to be started manually by invoking cUPnPServer::start(). - */ - cUPnPServer(); - /** - * Destructor - * - * This will destroy the server object. Open ports and connections will be - * closed. - */ - virtual ~cUPnPServer(); - /** - * Enable the server - * - * This switch indicates if the server is startable or not - * - * If it is set to false, any invocation of start() will do nothing. - * - * @param enabled if \bc true, the server will be enabled. If \bc false it is - * disabled. - */ - void enable(bool enabled); - /** - * Start the UPnP server - * - * This will start the UPnP server activities as a background task. - * - * @return returns - * - \bc true, when the server started successfully - * - \bc false, otherwise - */ - bool start(void); - /** - * Restart the server - * - * When the server is not operating properly it can be restarted. - * It will stop the server functionalities, clear everything and - * start it again. - * - * @return returns - * - \bc true, when the server restarted successfully - * - \bc false, otherwise - */ - bool restart(void); - /** - * Stop the server - * - * This will stop the server. This means that open connections to - * any clients and open ports will be closed. - */ - void stop(void); - /** - * Automatically detect settings - * - * This will automatically detect the network settings if the autodetection - * is turned on. - * - * @return returns - * - \bc true, if autoDetection was successful - * - \bc false, otherwise - */ - bool autoDetectSettings(void); - /** - * Get the server address - * - * Returns a server address structure including IP address and port - * - * @return The server socket address - */ - sockaddr_in* getServerAddress(void); - /** - * Get the interface the server listens to - * - * @return the network interface - */ - const char* getInterface(void) const { return this->mInterface; } - /** - * Set the server port - * - * The port must be in the scope of user definied ports (49152 - 65535). If - * the port is 0, it is autoassigned. You can retrieve the actual port by - * calling getServerAddress(), which will give you a structure with the port - * in it. - * - * The server must be restarted if the IP or port changes. - * - * Returns 1 when the port is valid, 0 otherwise - * - * @param port The port of the server - * @return returns - * - \bc true, if the new server port is set - * - \bc false, otherwise - */ - bool setServerPort(unsigned short port); - /** - * The Interface to listen on - * - * Sets the listener interface, for instance 'eth1' or 'wlan0' - * - * @param Interface The interface of the server - * @return returns - * - \bc true, if the new server address is set - * - \bc false, otherwise - */ - bool setInterface(const char* Interface); - /** - * Set the server address - * - * Specifies the servers IP address. The server needs to restart - * when the IP is changed. However, it's not possible to detect - * changes through the system. - * - * This method should only be used in cases of fixed IP addresses - * for example when no DHCP server is available. - * - * @param Address The address of the server - * @return returns - * - \bc true, if the new server address is set - * - \bc false, otherwise - */ - bool setAddress(const char* Address); - /** - * Enables oder Disables auto detection mode - * - * If this is set to true, the setup will get it's information via - * auto detection - * - * @param enable \bc true enables and \bc false disables the auto detection - * @return returns - * - \bc true, if the new server address is set - * - \bc false, otherwise - */ - bool setAutoDetection(bool enable); - /** - * Checks if the server is enabled - * - * This indicates if the server is currently enabled. - * - * @return returns - * - \bc true, if the server is enabled - * - \bc false, otherwise - */ - bool isEnabled(void) const { return this->mIsEnabled; } - /** - * Checks if the server is running - * - * If the server is enabled, this indicates if it is running. - * - * @return returns - * - \bc true if the server is running - * - \bc false, otherwise - */ - bool isRunning(void) const { return this->mIsRunning; } - /** - * Is auto detection enabled or not - * - * Returns true or false if auto detection is enabled or not - * - * @return returns - * - \bc true, if autodetection is enabled - * - \bc false, otherwise - */ - bool isAutoDetectionEnabled() { return this->mIsAutoDetectionEnabled; } -protected: -private: - /** - * Inits the server - * - * This method initializes all member variables with default values - */ - bool init(void); - bool uninit(void); - static int upnpActionCallback(Upnp_EventType eventtype, void *event, void *cookie); - bool mIsRunning; - bool mIsEnabled; - sockaddr_in* mServerAddr; - cString mInterface; - bool mIsAutoDetectionEnabled; - cString mDeviceDescription; - cUPnPWebServer* mWebServer; - cMediaDatabase* mMediaDatabase; - UpnpDevice_Handle mDeviceHandle; - static cConnectionManager* mConnectionManager; - static cContentDirectory* mContentDirectory; -}; -#endif /* _SERVER_H */
\ No newline at end of file @@ -8,12 +8,12 @@ #include <stdio.h> #include "upnp.h" -#include "misc/menusetup.h" -#include "misc/config.h" +#include "menusetup.h" +#include "config.h" cCondWait DatabaseLocker; -static const char *VERSION = "0.0.1"; +static const char *VERSION = "0.0.2"; static const char *DESCRIPTION = PLUGIN_DESCRIPTION; const char* cPluginUpnp::mConfigDirectory = NULL; @@ -49,30 +49,34 @@ const char *cPluginUpnp::CommandLineHelp(void) // Return a string that describes all known command line options. cString cmdHelp; - cmdHelp = cString::sprintf( + cmdHelp = cString::sprintf(_( " The server can automatically detect both IP address and an\n" " appropriate port, assuming that the first network interface\n" " is connected to the internal network. However, it is possible\n" " to specify alternative settings with the following options:\n\n" - " -i <interface> --int=<interface> The server network\n" - " interface\n" - " e.g: eth0, wlan1 etc.\n" - " If given option '-a' must\n" - " be absent.\n" - " -a <address> --address=<address> The server IPv4 address.\n" - " If given option '-i' must\n" - " be absent.\n" - " -p <port> --port=<port> The server port\n" - " Supported ports:\n" - " %5d (auto detect)\n" - " %5d-%5d (user defined)\n" - " -d --autodetect Force auto detection\n" - " Use this option to\n" - " overwrite the setup menu\n" - " options.\n" - " -v --verbose Increase verbosity level\n" - " The more v options the\n" - " higher the output level\n", + " -i <interface> --int=<interface> The server network\n" + " interface\n" + " e.g: eth0, wlan1 etc.\n" + " If given option '-a' must\n" + " be absent.\n" + " -a <address> --address=<address> The server IPv4 address.\n" + " If given option '-i' must\n" + " be absent.\n" + " -p <port> --port=<port> The server port\n" + " Supported ports:\n" + " %5d (auto detect)\n" + " %5d-%5d (user defined)\n" + " -d --autodetect Force auto detection\n" + " Use this option to\n" + " overwrite the setup menu\n" + " options.\n" + " -v --verbose Increase verbosity level\n" + " The more v options the\n" + " higher the output level\n" + " --dbdir=<directory> The directory in which the\n" + " metadata database is stored\n" + " --httpdir=<directory> The directory where the\n" + " http documents are located\n"), 0, SERVER_MIN_PORT, SERVER_MAX_PORT @@ -11,7 +11,7 @@ #include <vdr/thread.h> #include <vdr/plugin.h> #include "common.h" -#include "server/server.h" +#include "server.h" class cUPnPServer; diff --git a/upnpcomponents/connectionmanager.cpp b/upnpcomponents/connectionmanager.cpp deleted file mode 100644 index e0d9203..0000000 --- a/upnpcomponents/connectionmanager.cpp +++ /dev/null @@ -1,393 +0,0 @@ -/* - * File: connectionmanager.cpp - * Author: savop - * - * Created on 21. August 2009, 18:35 - */ - -#include "upnpservice.h" -#include <string.h> -#include <upnp/ixml.h> -#include <upnp/upnptools.h> -#include <vdr/tools.h> -#include "connectionmanager.h" -#include "dlna.h" - -cVirtualConnection::cVirtualConnection() : mRcsID(-1) {} - -cConnectionManager::cConnectionManager(UpnpDevice_Handle DeviceHandle) : cUpnpService(DeviceHandle) { - this->mVirtualConnections = new cList<cVirtualConnection>; - this->mDefaultConnection = this->createVirtualConnection(); - this->mSupportedProtocols = cDlna::getInstance()->getSupportedProtocols(); -} - -cConnectionManager::~cConnectionManager() { - delete this->mDefaultConnection; - delete this->mVirtualConnections; -} - -int cConnectionManager::subscribe(Upnp_Subscription_Request* Request){ - IXML_Document* PropertySet = NULL; - /* The protocol infos which this server supports */ - UpnpAddToPropertySet(&PropertySet, "SourceProtocolInfo", this->mSupportedProtocols); - /* Not set, this field is only used by Media Renderers */ - UpnpAddToPropertySet(&PropertySet, "SinkProtocolInfo", ""); - /* The current connection IDs of all virtual connections */ - const char* IDs = this->getConnectionIDsCVS(); - if(!IDs){ - return UPNP_E_INTERNAL_ERROR; - } - UpnpAddToPropertySet(&PropertySet, "CurrentConnectionIDs", IDs); - // Accept subscription - int ret = UpnpAcceptSubscriptionExt(this->mDeviceHandle, Request->UDN, Request->ServiceId, PropertySet, Request->Sid); - - if(ret != UPNP_E_SUCCESS){ - ERROR("Subscription failed (Error code: %d)", ret); - } - - ixmlDocument_free(PropertySet); - return ret; -} - -int cConnectionManager::execute(Upnp_Action_Request* Request){ - if (Request == NULL) { - ERROR("CMS Action Handler - request is null"); - return UPNP_E_BAD_REQUEST; - } - - if(!strcmp(Request->ActionName, UPNP_CMS_ACTION_GETPROTOCOLINFO)) - return this->getProtocolInfo(Request); - if(!strcmp(Request->ActionName, UPNP_CMS_ACTION_GETCURRENTCONNECTIONIDS)) - return this->getCurrentConnectionIDs(Request); - if(!strcmp(Request->ActionName, UPNP_CMS_ACTION_GETCURRENTCONNECTIONINFO)) - return this->getCurrentConnectionInfo(Request); - if(!strcmp(Request->ActionName, UPNP_CMS_ACTION_PREPAREFORCONNECTION)) - return this->prepareForConnection(Request); - if(!strcmp(Request->ActionName, UPNP_CMS_ACTION_CONNECTIONCOMPLETE)) - return this->connectionComplete(Request); - - return UPNP_E_BAD_REQUEST; -} - -int cConnectionManager::getProtocolInfo(Upnp_Action_Request* Request){ - MESSAGE(VERBOSE_CMS, "Protocol info requested by %s.", inet_ntoa(Request->CtrlPtIPAddr)); - cString Result = cString::sprintf( - "<u:%sResponse xmlns:u=\"%s\"> \ - <Source>%s</Source> \ - <Sink></Sink> \ - </u:%sResponse>", - Request->ActionName, - UPNP_CMS_SERVICE_TYPE, - *this->mSupportedProtocols, - Request->ActionName - ); - Request->ActionResult = ixmlParseBuffer(Result); - Request->ErrCode = UPNP_E_SUCCESS; - return Request->ErrCode; -} - -int cConnectionManager::getCurrentConnectionIDs(Upnp_Action_Request* Request){ - MESSAGE(VERBOSE_CMS, "Current connection IDs requested by %s.", inet_ntoa(Request->CtrlPtIPAddr)); - cString Result; - const char* IDs = this->getConnectionIDsCVS(); - if(!IDs){ - Request->ErrCode = UPNP_E_INTERNAL_ERROR; - return Request->ErrCode; - } - Result = cString::sprintf( - "<u:%sResponse xmlns:u=\"%s\"> \ - <ConnectionIDs>%s</ConnectionIDs> \ - </u:%sResponse>", - Request->ActionName, - UPNP_CMS_SERVICE_TYPE, - IDs, - Request->ActionName - ); - Request->ActionResult = ixmlParseBuffer(Result); - Request->ErrCode = UPNP_E_SUCCESS; - return Request->ErrCode; -} - -int cConnectionManager::getCurrentConnectionInfo(Upnp_Action_Request* Request){ - MESSAGE(VERBOSE_CMS, "Current connection info requested by %s.", inet_ntoa(Request->CtrlPtIPAddr)); - int ConnectionID; - - if(this->parseIntegerValue(Request->ActionRequest, "ConnectionID", &ConnectionID) != 0){ - ERROR("Invalid arguments. ConnectionID missing or wrong"); - this->setError(Request, 402); - return Request->ErrCode; - } - - cVirtualConnection* Connection; - for(Connection = this->mVirtualConnections->First(); Connection && Connection->mConnectionID != ConnectionID; Connection = this->mVirtualConnections->Next(Connection)){} - - if(Connection){ - cString Result = cString::sprintf( - "<u:%sResponse xmlns:u=\"%s\">\ - <ProtocolInfo>%s</ProtocolInfo>\ - <PeerConnectionManager>%s</PeerConnectionManager>\ - <PeerConnectionID>%d</PeerConnectionID>\ - <Direction>%s</Direction>\ - <RcsID>%d</RcsID>\ - <AVTransportID>%d</AVTransportID>\ - <Status>%s</Status>\ - </u:%sResponse>", - Request->ActionName, - UPNP_CMS_SERVICE_TYPE, - *Connection->mRemoteProtocolInfo, - *Connection->mRemoteConnectionManager, - -1, - cVirtualConnection::getDirectionString(OUTPUT), - Connection->mRcsID, - Connection->mAVTransportID, - cVirtualConnection::getStatusString(Connection->mStatus), - Request->ActionName - ); - Request->ActionResult = ixmlParseBuffer(Result); - Request->ErrCode = UPNP_E_SUCCESS; - } - else { - ERROR("No valid connection found with given ID=%d!", ConnectionID); - this->setError(Request, 706); - } - - return Request->ErrCode; - -} - -int cConnectionManager::prepareForConnection(Upnp_Action_Request* Request){ - MESSAGE(VERBOSE_CMS, "Request for a new connection by %s.", inet_ntoa(Request->CtrlPtIPAddr)); - //char* Result = NULL; - char* RemoteProtocolInfo = NULL; - char* PeerConnectionManager = NULL; - int PeerConnectionID = 0; - char* DirectionStr = NULL; - int Direction; - - if(this->parseStringValue(Request->ActionRequest, "RemoteProtocolInfo", &RemoteProtocolInfo) != 0){ - ERROR("Invalid argument RemoteProtocolInfo: Missing or wrong"); - this->setError(Request, 402); - return Request->ErrCode; - } - - if(this->parseStringValue(Request->ActionRequest, "PeerConnectionManager", &PeerConnectionManager) != 0){ - ERROR("Invalid argument PeerConnectionManager: Missing or wrong"); - this->setError(Request, 402); - return Request->ErrCode; - } - - if(this->parseStringValue(Request->ActionRequest, "Direction", &DirectionStr) != 0 && (Direction = cVirtualConnection::getDirection(DirectionStr)) == -1){ - ERROR("Invalid argument Direction: Missing or wrong"); - this->setError(Request, 402); - return Request->ErrCode; - } - - if(this->parseIntegerValue(Request->ActionRequest, "PeerConnectionID", &PeerConnectionID) != 0){ - ERROR("Invalid argument PeerConnectionID: Missing or wrong"); - this->setError(Request, 402); - return Request->ErrCode; - } - - - /* TODO: - Create Connection - Notify AVTransport that a new connection was established - Send back the response */ - this->setError(Request, UPNP_SOAP_E_ACTION_NOT_IMPLEMENTED); - return Request->ErrCode; -} - -int cConnectionManager::connectionComplete(Upnp_Action_Request* Request){ - MESSAGE(VERBOSE_CMS, "Request for closing an open connection by %s.", inet_ntoa(Request->CtrlPtIPAddr)); - //char* Result = NULL; - int ConnectionID; - - if(this->parseIntegerValue(Request->ActionRequest, "ConnectionID", &ConnectionID) != 0){ - ERROR("Invalid argument ConnectionID: Missing or wrong"); - this->setError(Request, 402); - return Request->ErrCode; - } - - // TODO: - // Close and clear any open resources - // Close and delete the connection - // Free other resources left - this->setError(Request, UPNP_SOAP_E_ACTION_NOT_IMPLEMENTED); - return Request->ErrCode; -} - -//bool cConnectionManager::setProtocolInfo(const char* ProtocolInfo){ -// if(strcmp(this->mSupportedProtocols, ProtocolInfo)){ -// // ProtocolInfo changed, save and invoke a event notification -// this->mSupportedProtocols = ProtocolInfo; -// -// IXML_Document* PropertySet = NULL; -// UpnpAddToPropertySet(&PropertySet, "SourceProtocolInfo", this->mSupportedProtocols); -// int ret = UpnpNotifyExt(this->mDeviceHandle, UPNP_DEVICE_UDN, UPNP_CMS_SERVICE_ID, PropertySet); -// ixmlDocument_free(PropertySet); -// -// if(ret != UPNP_E_SUCCESS){ -// ERROR("State change notification failed (Error code: %d)",ret); -// return false; -// } -// } -// return true; -//} - -cVirtualConnection* cConnectionManager::createVirtualConnection(const char* RemoteProtocolInfo, const char* RemoteConnectionManager, int RemoteConnectionID, eDirection Direction){ - static int lastConnectionID = 0; - MESSAGE(VERBOSE_CMS, "Create virtual connection"); - if(lastConnectionID == 2147483647) lastConnectionID = 1; - cVirtualConnection* Connection = new cVirtualConnection; - // AVT is available - Connection->mAVTransportID = 0; - // The ProtocolInfo of the remote device (i.e. Media Renderer) - Connection->mRemoteProtocolInfo = RemoteProtocolInfo; - // The responsible connection manager - Connection->mRemoteConnectionManager = RemoteConnectionManager; - // The virtual connection direction is output - Connection->mDirection = Direction; - // The remote connection ID, -1 says ID is unknown - Connection->mRemoteConnectionID = RemoteConnectionID; - // Connection status, assume that its ok. - Connection->mStatus = OK; - // new assigned ConnectionID - Connection->mConnectionID = lastConnectionID++; - - // Notify the subscribers - IXML_Document* PropertySet = NULL; - const char* IDs = this->getConnectionIDsCVS(); - if(!IDs){ - return NULL; - } - UpnpAddToPropertySet(&PropertySet, "CurrentConnectionIDs", IDs); - int ret = UpnpNotifyExt(this->mDeviceHandle, UPNP_DEVICE_UDN, UPNP_CMS_SERVICE_ID, PropertySet); - ixmlDocument_free(PropertySet); - - if(ret != UPNP_E_SUCCESS){ - ERROR("State change notification failed (Error code: %d)",ret); - return NULL; - } - MESSAGE(VERBOSE_CMS, "Notification of connection creation sent"); - this->mVirtualConnections->Add(Connection); - return Connection; -} - -bool cConnectionManager::destroyVirtualConnection(int ConnectionID){ - if(ConnectionID == 0){ - ERROR("Cannot delete default connection with ID 0!"); - return false; - } - - cVirtualConnection* Connection; - for(Connection = this->mVirtualConnections->First(); Connection && Connection->mConnectionID != ConnectionID; Connection = this->mVirtualConnections->Next(Connection)){} - - if(Connection){ - this->mVirtualConnections->Del(Connection); - // Notify the subscribers - IXML_Document* PropertySet = NULL; - const char* IDs = this->getConnectionIDsCVS(); - if(!IDs){ - return false; - } - UpnpAddToPropertySet(&PropertySet, "CurrentConnectionIDs", IDs); - int ret = UpnpNotifyExt(this->mDeviceHandle, UPNP_DEVICE_UDN, UPNP_CMS_SERVICE_ID, PropertySet); - ixmlDocument_free(PropertySet); - - if(ret != UPNP_E_SUCCESS){ - ERROR("State change notification failed (Error code: %d)",ret); - return false; - } - return true; - } - ERROR("No connection with ID=%d found!", ConnectionID); - return false; -} - -const char* cConnectionManager::getConnectionIDsCVS(){ - cString IDs; - for(cVirtualConnection* Connection = this->mVirtualConnections->First(); Connection; Connection = this->mVirtualConnections->Next(Connection)){ - IDs = cString::sprintf("%s,%d", (*IDs)?*IDs:"", Connection->mConnectionID); - } - return IDs; -} - -void cConnectionManager::setError(Upnp_Action_Request* Request, int Error){ - Request->ErrCode = Error; - switch(Error){ - case 701: - strn0cpy(Request->ErrStr,_("Incompatible protocol info"),LINE_SIZE); - break; - case 702: - strn0cpy(Request->ErrStr,_("Incompatible directions"),LINE_SIZE); - break; - case 703: - strn0cpy(Request->ErrStr,_("Insufficient network resources"),LINE_SIZE); - break; - case 704: - strn0cpy(Request->ErrStr,_("Local restrictions"),LINE_SIZE); - break; - case 705: - strn0cpy(Request->ErrStr,_("Access denied"),LINE_SIZE); - break; - case 706: - strn0cpy(Request->ErrStr,_("Invalid connection reference"),LINE_SIZE); - break; - case 707: - strn0cpy(Request->ErrStr,_("Not in network"),LINE_SIZE); - break; - default: - cUpnpService::setError(Request, Error); - break; - } -} - -const char* cVirtualConnection::getDirectionString(eDirection Direction){ - switch(Direction){ - case INPUT: - return "Input"; - case OUTPUT: - return "Output"; - default: - return NULL; - } -} - -const char* cVirtualConnection::getStatusString(eConnectionStatus Status){ - switch(Status){ - case OK: - return "OK"; - case CONTENT_FORMAT_MISMATCH: - return "ContentFormatMismatch"; - case INSUFFICIENT_BANDWIDTH: - return "InsufficientBandwidth"; - case UNRELIABLE_CHANNEL: - return "UnreliableChannel"; - case UNKNOWN: - return "Unknown"; - default: - return NULL; - } -} - -int cVirtualConnection::getConnectionStatus(const char* eConnectionStatus){ - if(!strcasecmp(eConnectionStatus,"OK")) - return OK; - if(!strcasecmp(eConnectionStatus,"ContentFormatMismatch")) - return CONTENT_FORMAT_MISMATCH; - if(!strcasecmp(eConnectionStatus,"InsufficientBandwidth")) - return INSUFFICIENT_BANDWIDTH; - if(!strcasecmp(eConnectionStatus,"UnreliableChannel")) - return UNRELIABLE_CHANNEL; - if(!strcasecmp(eConnectionStatus,"Unknown")) - return UNKNOWN; - return -1; -} - -int cVirtualConnection::getDirection(const char* Direction){ - if(!strcasecmp(Direction, "Output")) - return OUTPUT; - if(!strcasecmp(Direction, "Input")) - return INPUT; - return -1; -}
\ No newline at end of file diff --git a/upnpcomponents/connectionmanager.h b/upnpcomponents/connectionmanager.h deleted file mode 100644 index 4aa25f3..0000000 --- a/upnpcomponents/connectionmanager.h +++ /dev/null @@ -1,99 +0,0 @@ -/* - * File: connectionmanager.h - * Author: savop - * - * Created on 21. August 2009, 18:35 - */ - -#ifndef _CONNECTIONMANAGER_H -#define _CONNECTIONMANAGER_H - -#include "upnpservice.h" - -/** - * Connection status - * - * The connection status of a certain virtual connection - */ -enum eConnectionStatus { - OK, - CONTENT_FORMAT_MISMATCH, - INSUFFICIENT_BANDWIDTH, - UNRELIABLE_CHANNEL, - UNKNOWN -}; - -/** - * Direction - * - * The direction of a virtual connection. Input means client to server, Output - * server to client - */ -enum eDirection { - OUTPUT, - INPUT -}; - -/** - * Virtual connection - * - * A virtual connection managed by the connection manager service - */ -class cVirtualConnection : public cListObject { - friend class cConnectionManager; -private: - cString mRemoteProtocolInfo; - cString mRemoteConnectionManager; - eDirection mDirection; - int mRemoteConnectionID; - int mConnectionID; - int mAVTransportID; - const int mRcsID; - eConnectionStatus mStatus; - cVirtualConnection(); - static const char* getStatusString(eConnectionStatus Status); - static const char* getDirectionString(eDirection Direction); - static int getDirection(const char* Direction); - static int getConnectionStatus(const char* ConnectionStatus); -}; - -/** - * The connection manager service - * - * This is the connection manager service which handles all incoming connection, - * creates and destroys connections to clients. - */ -class cConnectionManager : public cUpnpService { -public: - /** - * Constructor of a Connection manager - * - * This creates an instance of a <em>Connection Manager Service</em> and provides - * interfaces for executing actions and subscribing on events. - */ - cConnectionManager( - UpnpDevice_Handle DeviceHandle ///< the UPnP device handle of this root device - ); - virtual ~cConnectionManager(); - /*! @copydoc cUpnpService::subscribe(Upnp_Subscription_Request* Request) */ - virtual int subscribe(Upnp_Subscription_Request* Request); - /*! @copydoc cUpnpService::execute(Upnp_Action_Request* Request) */ - virtual int execute(Upnp_Action_Request* Request); - /*! @copydoc cUpnpService::setError(Upnp_Action_Request* Request, int Error) */ - virtual void setError(Upnp_Action_Request* Request, int Error); -private: - int getProtocolInfo(Upnp_Action_Request* Request); - int getCurrentConnectionIDs(Upnp_Action_Request* Request); - int getCurrentConnectionInfo(Upnp_Action_Request* Request); - int prepareForConnection(Upnp_Action_Request* Request); - int connectionComplete(Upnp_Action_Request* Request); - cVirtualConnection* createVirtualConnection(const char* RemoteProtocolInfo = NULL, const char* RemoteConnectionManager = NULL, int RemoteConnectionID = -1, eDirection Direction = OUTPUT); - bool destroyVirtualConnection(int ConnectionID); - const char* getConnectionIDsCVS(); - cVirtualConnection* mDefaultConnection; - cList<cVirtualConnection>* mVirtualConnections; - cString mSupportedProtocols; -}; - -#endif /* _CONNECTIONMANAGER_H */ - diff --git a/upnpcomponents/contentdirectory.cpp b/upnpcomponents/contentdirectory.cpp deleted file mode 100644 index 494b638..0000000 --- a/upnpcomponents/contentdirectory.cpp +++ /dev/null @@ -1,306 +0,0 @@ -/* - * File: contentdirectory.cpp - * Author: savop - * - * Created on 21. August 2009, 16:12 - */ - -#include <upnp/ixml.h> -#include <upnp/upnptools.h> -#include "contentdirectory.h" -#include "../common.h" -#include "../misc/util.h" - -cContentDirectory::cContentDirectory(UpnpDevice_Handle DeviceHandle, cMediaDatabase* MediaDatabase) -: cUpnpService(DeviceHandle) { - this->mMediaDatabase = MediaDatabase; -} - -cContentDirectory::~cContentDirectory() {} - -int cContentDirectory::subscribe(Upnp_Subscription_Request* Request){ - IXML_Document* PropertySet = NULL; - - /* The system update ID */ - UpnpAddToPropertySet(&PropertySet, "SystemUpdateID", itoa(this->mMediaDatabase->getSystemUpdateID())); - /* The container update IDs as CSV list */ - UpnpAddToPropertySet(&PropertySet, "ContainerUpdateIDs", this->mMediaDatabase->getContainerUpdateIDs()); - /* The transfer IDs, which are not supported, i.e. empty */ - UpnpAddToPropertySet(&PropertySet, "TransferIDs", ""); - // Accept subscription - int ret = UpnpAcceptSubscriptionExt(this->mDeviceHandle, Request->UDN, Request->ServiceId, PropertySet, Request->Sid); - - if(ret != UPNP_E_SUCCESS){ - ERROR("Subscription failed (Error code: %d)", ret); - } - - ixmlDocument_free(PropertySet); - return ret; -} - -void cContentDirectory::Action(){ - static int Retry = 5; - MESSAGE(VERBOSE_CDS, "Start Content directory thread"); - while(this->Running()){ - IXML_Document* PropertySet = NULL; - UpnpAddToPropertySet(&PropertySet, "SystemUpdateID", itoa(this->mMediaDatabase->getSystemUpdateID())); - int ret = UpnpNotifyExt(this->mDeviceHandle, UPNP_DEVICE_UDN, UPNP_CMS_SERVICE_ID, PropertySet); - ixmlDocument_free(PropertySet); - - if(ret != UPNP_E_SUCCESS){ - Retry--; - ERROR("State change notification failed (Error code: %d)",ret); - ERROR("%d of %d notifications failed", (5-Retry), 5); - } - else { - Retry = 5; - } - if (!Retry){ - ERROR("Maximum retries of notifications reached. Stopping..."); - this->Cancel(); - } - // Sleep 2 seconds - cCondWait::SleepMs(2000); - } -} - -int cContentDirectory::execute(Upnp_Action_Request* Request){ - if (Request == NULL) { - ERROR("CMS Action Handler - request is null"); - return UPNP_E_BAD_REQUEST; - } - - if(!strcmp(Request->ActionName, UPNP_CDS_ACTION_BROWSE)) - return this->browse(Request); - if(!strcmp(Request->ActionName, UPNP_CDS_ACTION_SEARCHCAPABILITIES)) - return this->getSearchCapabilities(Request); - if(!strcmp(Request->ActionName, UPNP_CDS_ACTION_SORTCAPABILITIES)) - return this->getSortCapabilities(Request); - if(!strcmp(Request->ActionName, UPNP_CDS_ACTION_SYSTEMUPDATEID)) - return this->getSystemUpdateID(Request); - - return UPNP_E_BAD_REQUEST; -} - - -int cContentDirectory::browse(Upnp_Action_Request* Request){ - MESSAGE(VERBOSE_CDS, "Browse requested by %s.", inet_ntoa(Request->CtrlPtIPAddr)); - - char* ObjectID = NULL; - if(this->parseStringValue(Request->ActionRequest, "ObjectID", &ObjectID)){ - ERROR("Invalid arguments. ObjectID missing or wrong"); - this->setError(Request, UPNP_SOAP_E_INVALID_ARGS); - return Request->ErrCode; - } - - char* BrowseFlag = NULL; - bool BrowseMetadata = false; - if(this->parseStringValue(Request->ActionRequest, "BrowseFlag", &BrowseFlag)){ - ERROR("Invalid arguments. Browse flag missing or wrong"); - this->setError(Request, UPNP_SOAP_E_INVALID_ARGS); - return Request->ErrCode; - } - if(!strcasecmp(BrowseFlag, "BrowseMetadata")){ - BrowseMetadata = true; - } - else if(!strcasecmp(BrowseFlag, "BrowseDirectChildren")){ - BrowseMetadata = false; - } - else { - ERROR("Invalid argument. Browse flag invalid"); - this->setError(Request, UPNP_SOAP_E_INVALID_ARGS); - return Request->ErrCode; - } - - char* Filter = NULL; - if(this->parseStringValue(Request->ActionRequest, "Filter", &Filter)){ - ERROR("Invalid arguments. Filter missing or wrong"); - this->setError(Request, UPNP_SOAP_E_INVALID_ARGS); - return Request->ErrCode; - } - - int StartingIndex = 0; - if(this->parseIntegerValue(Request->ActionRequest, "StartingIndex", &StartingIndex)){ - ERROR("Invalid arguments. Starting index missing or wrong"); - this->setError(Request, UPNP_SOAP_E_INVALID_ARGS); - return Request->ErrCode; - } - - int RequestedCount = 0; - if(this->parseIntegerValue(Request->ActionRequest, "RequestedCount", &RequestedCount)){ - ERROR("Invalid arguments. Requested count missing or wrong"); - this->setError(Request, UPNP_SOAP_E_INVALID_ARGS); - return Request->ErrCode; - } - - char* SortCriteria = NULL; - if(this->parseStringValue(Request->ActionRequest, "SortCriteria", &SortCriteria)){ - ERROR("Invalid arguments. Sort criteria missing or wrong"); - this->setError(Request, UPNP_SOAP_E_INVALID_ARGS); - return Request->ErrCode; - } - - cUPnPResultSet* ResultSet; - - int ret = this->mMediaDatabase->browse(&ResultSet, ObjectID, BrowseMetadata, Filter, StartingIndex, RequestedCount, SortCriteria); - if(ret!=UPNP_E_SUCCESS){ - ERROR("Error while browsing. Code: %d", ret); - this->setError(Request, ret); - return Request->ErrCode; - } - - char* escapedResult = NULL; - escapeXMLCharacters(ResultSet->mResult, &escapedResult); - - if(!escapedResult){ - ERROR("Escaping XML data failed"); - this->setError(Request, UPNP_SOAP_E_ACTION_FAILED); - return Request->ErrCode; - } - - cString Result = cString::sprintf( - "<u:%sResponse xmlns:u=\"%s\"> \ - <Result>%s</Result> \ - <NumberReturned>%d</NumberReturned> \ - <TotalMatches>%d</TotalMatches> \ - <UpdateID>%d</UpdateID> \ - </u:%sResponse>", - Request->ActionName, - UPNP_CDS_SERVICE_TYPE, - escapedResult, - ResultSet->mNumberReturned, - ResultSet->mTotalMatches, - this->mMediaDatabase->getSystemUpdateID(), - Request->ActionName - ); - - Request->ActionResult = ixmlParseBuffer(Result); - Request->ErrCode = UPNP_E_SUCCESS; - - free(escapedResult); - - return Request->ErrCode; - -} - -int cContentDirectory::getSystemUpdateID(Upnp_Action_Request* Request){ - cString Result = cString::sprintf( - "<u:%sResponse xmlns:u=\"%s\"> \ - <Id>%d</Id> \ - </u:%sResponse>", - Request->ActionName, - UPNP_CDS_SERVICE_TYPE, - this->mMediaDatabase->getSystemUpdateID(), - Request->ActionName - ); - - Request->ActionResult = ixmlParseBuffer(Result); - Request->ErrCode = UPNP_E_SUCCESS; - - return Request->ErrCode; -} - -int cContentDirectory::getSearchCapabilities(Upnp_Action_Request* Request){ - MESSAGE(VERBOSE_CDS, "Sorry, no search capabilities yet"); - - cString Result = cString::sprintf( - "<u:%sResponse xmlns:u=\"%s\"> \ - <SearchCaps>%s</SearchCaps> \ - </u:%sResponse>", - Request->ActionName, - UPNP_CDS_SERVICE_TYPE, - UPNP_CDS_SEARCH_CAPABILITIES, - Request->ActionName - ); - - Request->ActionResult = ixmlParseBuffer(Result); - Request->ErrCode = UPNP_E_SUCCESS; - - return Request->ErrCode; -} - -int cContentDirectory::getSortCapabilities(Upnp_Action_Request* Request){ - MESSAGE(VERBOSE_CDS, "Sorry, no sort capabilities yet"); - - cString Result = cString::sprintf( - "<u:%sResponse xmlns:u=\"%s\"> \ - <SortCaps>%s</SortCaps> \ - </u:%sResponse>", - Request->ActionName, - UPNP_CDS_SERVICE_TYPE, - UPNP_CDS_SORT_CAPABILITIES, - Request->ActionName - ); - - Request->ActionResult = ixmlParseBuffer(Result); - Request->ErrCode = UPNP_E_SUCCESS; - - return Request->ErrCode; -} - -void cContentDirectory::setError(Upnp_Action_Request* Request, int Error){ - Request->ErrCode = Error; - switch(Error){ - case UPNP_CDS_E_BAD_METADATA: - strn0cpy(Request->ErrStr,_("Bad metadata"),LINE_SIZE); - break; - case UPNP_CDS_E_CANT_PROCESS_REQUEST: - strn0cpy(Request->ErrStr,_("Cannot process the request"),LINE_SIZE); - break; - case UPNP_CDS_E_DEST_RESOURCE_ACCESS_DENIED: - strn0cpy(Request->ErrStr,_("Destination resource access denied"),LINE_SIZE); - break; - case UPNP_CDS_E_INVALID_CURRENT_TAG: - strn0cpy(Request->ErrStr,_("Invalid current tag"),LINE_SIZE); - break; - case UPNP_CDS_E_INVALID_NEW_TAG: - strn0cpy(Request->ErrStr,_("Invalid new tag"),LINE_SIZE); - break; - case UPNP_CDS_E_INVALID_SEARCH_CRITERIA: - strn0cpy(Request->ErrStr,_("Invalid or unsupported search criteria"),LINE_SIZE); - break; - case UPNP_CDS_E_INVALID_SORT_CRITERIA: - strn0cpy(Request->ErrStr,_("Invalid or unsupported sort criteria"),LINE_SIZE); - break; - case UPNP_CDS_E_NO_SUCH_CONTAINER: - strn0cpy(Request->ErrStr,_("No such container"),LINE_SIZE); - break; - case UPNP_CDS_E_NO_SUCH_DESTINATION_RESOURCE: - strn0cpy(Request->ErrStr,_("No such destination resource"),LINE_SIZE); - break; - case UPNP_CDS_E_NO_SUCH_FILE_TRANSFER: - strn0cpy(Request->ErrStr,_("No such file transfer"),LINE_SIZE); - break; - case UPNP_CDS_E_NO_SUCH_OBJECT: - strn0cpy(Request->ErrStr,_("No such objectID"),LINE_SIZE); - break; - case UPNP_CDS_E_NO_SUCH_SOURCE_RESOURCE: - strn0cpy(Request->ErrStr,_("No such source resource"),LINE_SIZE); - break; - case UPNP_CDS_E_PARAMETER_MISMATCH: - strn0cpy(Request->ErrStr,_("Parameter mismatch"),LINE_SIZE); - break; - case UPNP_CDS_E_READ_ONLY_TAG: - strn0cpy(Request->ErrStr,_("Read only tag"),LINE_SIZE); - break; - case UPNP_CDS_E_REQUIRED_TAG: - strn0cpy(Request->ErrStr,_("Required tag"),LINE_SIZE); - break; - case UPNP_CDS_E_RESOURCE_ACCESS_DENIED: - strn0cpy(Request->ErrStr,_("Resource access denied"),LINE_SIZE); - break; - case UPNP_CDS_E_RESTRICTED_OBJECT: - strn0cpy(Request->ErrStr,_("Restricted object"),LINE_SIZE); - break; - case UPNP_CDS_E_RESTRICTED_PARENT: - strn0cpy(Request->ErrStr,_("Restricted parent"),LINE_SIZE); - break; - case UPNP_CDS_E_TRANSFER_BUSY: - strn0cpy(Request->ErrStr,_("Transfer busy"),LINE_SIZE); - break; - default: - cUpnpService::setError(Request, Error); - break; - } - return; -}
\ No newline at end of file diff --git a/upnpcomponents/contentdirectory.h b/upnpcomponents/contentdirectory.h deleted file mode 100644 index 7fb4bb9..0000000 --- a/upnpcomponents/contentdirectory.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * File: contentdirectory.h - * Author: savop - * - * Created on 21. August 2009, 16:12 - */ - -#ifndef _CONTENTDIRECTORY_H -#define _CONTENTDIRECTORY_H - -#include <upnp/upnp.h> -#include "upnpservice.h" -#include "../database/metadata.h" - -/** - * The content directory service - * - * This is the content directory service which handles all incoming requests - * for contents managed by the media server. - */ -class cContentDirectory : public cUpnpService, public cThread { -public: - /** - * Constructor of a Content Directory - * - * This creates an instance of a <em>Content Directory Service</em> and provides - * interfaces for executing actions and subscribing on events. - */ - cContentDirectory( - UpnpDevice_Handle DeviceHandle, ///< The UPnP device handle of the root device - cMediaDatabase* MediaDatabase ///< the media database where requests are processed - ); - virtual ~cContentDirectory(); - /*! @copydoc cUpnpService::subscribe(Upnp_Subscription_Request* Request) */ - virtual int subscribe(Upnp_Subscription_Request* Request); - /*! @copydoc cUpnpService::execute(Upnp_Action_Request* Request) */ - virtual int execute(Upnp_Action_Request* Request); - /*! @copydoc cUpnpService::setError(Upnp_Action_Request* Request, int Error) */ - virtual void setError(Upnp_Action_Request* Request, int Error); -private: - cMediaDatabase* mMediaDatabase; - void Action(); - int getSearchCapabilities(Upnp_Action_Request* Request); - int getSortCapabilities(Upnp_Action_Request* Request); - int getSystemUpdateID(Upnp_Action_Request* Request); - int browse(Upnp_Action_Request* Request); -// int search(Upnp_Action_Request* Request); -// int createObject(Upnp_Action_Request* Request); -// int destroyObject(Upnp_Action_Request* Request); -// int updateObject(Upnp_Action_Request* Request); -// int deleteResource(Upnp_Action_Request* Request); -// int createReference(Upnp_Action_Request* Request); -}; - -#endif /* _CONTENTDIRECTORY_H */ - diff --git a/upnpcomponents/dlna.cpp b/upnpcomponents/dlna.cpp deleted file mode 100644 index c8bb8a9..0000000 --- a/upnpcomponents/dlna.cpp +++ /dev/null @@ -1,212 +0,0 @@ -/* - * File: dlna.cpp - * Author: savop - * - * Created on 18. April 2009, 23:27 - */ - -#include <stdio.h> -#include <vdr/tools.h> -#include "dlna.h" - -cDlna* cDlna::mInstance = NULL; - -cDlna* cDlna::getInstance(void){ - if(cDlna::mInstance == NULL) - cDlna::mInstance = new cDlna; - - if(cDlna::mInstance != NULL) - return cDlna::mInstance; - else return NULL; -} - -cDlna::cDlna() { - this->mRegisteredProfiles = new cList<cRegisteredProfile>; - this->init(); -} - -cDlna::~cDlna() { - delete this->mRegisteredProfiles; -} - - -void cDlna::init(void){ - this->registerMainProfiles(); -} - -void cDlna::registerProfile(DLNAProfile* Profile, int Op, const char* Ps, int Ci, unsigned int Flags){ - cRegisteredProfile *RegisteredProfile = new cRegisteredProfile(); - RegisteredProfile->Profile = Profile; - RegisteredProfile->Operation = Op; - RegisteredProfile->PlaySpeeds = Ps; - RegisteredProfile->Conversion = Ci; - RegisteredProfile->PrimaryFlags = Flags; - this->mRegisteredProfiles->Add(RegisteredProfile); -} - -void cDlna::registerMainProfiles(){ - this->registerProfile(&DLNA_PROFILE_MPEG_TS_SD_EU, -1, NULL, -1, DLNA_FLAGS_PLUGIN_SUPPORT); - this->registerProfile(&DLNA_PROFILE_AVC_TS_HD_EU, -1, NULL, -1, DLNA_FLAGS_PLUGIN_SUPPORT); - this->registerProfile(&DLNA_PROFILE_MPEG_TS_SD_EU_ISO, -1, NULL, -1, DLNA_FLAGS_PLUGIN_SUPPORT); - this->registerProfile(&DLNA_PROFILE_AVC_TS_HD_EU_ISO, -1, NULL, -1, DLNA_FLAGS_PLUGIN_SUPPORT); -} - -const char* cDlna::getSupportedProtocols(){ - cString Protocols; - cRegisteredProfile* Profile; - for(Profile = this->mRegisteredProfiles->First(); Profile; Profile = this->mRegisteredProfiles->Next(Profile)){ - Protocols = cString::sprintf("%s%s%s",(*Protocols)?*Protocols:"",(*Protocols)?",":"",this->getRegisteredProtocolInfoString(Profile)); - } - return Protocols; -} - -const char* cDlna::getProtocolInfo(DLNAProfile *Prof){ - cRegisteredProfile* Profile; - for(Profile = this->mRegisteredProfiles->First(); Profile && Profile->Profile != Prof; Profile = this->mRegisteredProfiles->Next(Profile)){} - if(Profile){ - return this->getRegisteredProtocolInfoString(Profile); - } - return NULL; -} - -const char* cDlna::getRegisteredProtocolInfoString(cRegisteredProfile *Profile){ - cString DLNA4thField = NULL; - DLNA4thField = cString::sprintf("DLNA.ORG_PN=%s", Profile->Profile->ID); - if(Profile->Operation != -1) - DLNA4thField = cString::sprintf("%s;DLNA.ORG_OP=%d",*DLNA4thField,Profile->Operation); - if(Profile->PlaySpeeds != NULL) - DLNA4thField = cString::sprintf("%s;DLNA.ORG_PS=%s",*DLNA4thField,Profile->PlaySpeeds); - if(Profile->Conversion != -1) - DLNA4thField = cString::sprintf("%s;DLNA.ORG_CI=%d",*DLNA4thField,Profile->Conversion); - if(Profile->PrimaryFlags != 0) - DLNA4thField = cString::sprintf("%s;DLNA.ORG_FLAGS=%.8x%.24x",*DLNA4thField,Profile->PrimaryFlags,0); - - char* Protocol = strdup(cString::sprintf("http-get:*:%s:%s", Profile->Profile->mime, *DLNA4thField)); - return Protocol; -} - -const char* cDlna::getDeviceDescription(const char* URLBase){ - cString description = cString::sprintf( - "<?xml version = \"1.0\" encoding = \"utf-8\"?> \ - <root xmlns=\"%s\" xmlns:%s=\"%s\"> \ - <specVersion> \ - <major>1</major> \ - <minor>0</minor> \ - </specVersion> \ - <URLBase>%s</URLBase> \ - <device> \ - <deviceType>%s</deviceType> \ - <friendlyName>%s</friendlyName> \ - <manufacturer>%s</manufacturer> \ - <manufacturerURL>%s</manufacturerURL> \ - <modelDescription>%s</modelDescription> \ - <modelName>%s</modelName> \ - <modelNumber>%s</modelNumber> \ - <modelURL>%s</modelURL> \ - <serialNumber>%s</serialNumber> \ - <UDN>%s</UDN> \ - <iconList> \ - <icon> \ - <mimetype>%s</mimetype> \ - <width>%d</width> \ - <height>%d</height> \ - <depth>%d</depth> \ - <url>%s</url> \ - </icon> \ - <icon> \ - <mimetype>%s</mimetype> \ - <width>%d</width> \ - <height>%d</height> \ - <depth>%d</depth> \ - <url>%s</url> \ - </icon> \ - <icon> \ - <mimetype>%s</mimetype> \ - <width>%d</width> \ - <height>%d</height> \ - <depth>%d</depth> \ - <url>%s</url> \ - </icon> \ - <icon> \ - <mimetype>%s</mimetype> \ - <width>%d</width> \ - <height>%d</height> \ - <depth>%d</depth> \ - <url>%s</url> \ - </icon> \ - </iconList> \ - <presentationURL>%s</presentationURL> \ - <%s:X_DLNADOC>%s</dlna:X_DLNADOC> \ - <serviceList> \ - <service> \ - <serviceType>%s</serviceType> \ - <serviceId>%s</serviceId> \ - <SCPDURL>%s</SCPDURL> \ - <controlURL>%s</controlURL> \ - <eventSubURL>%s</eventSubURL> \ - </service> \ - <service> \ - <serviceType>%s</serviceType> \ - <serviceId>%s</serviceId> \ - <SCPDURL>%s</SCPDURL> \ - <controlURL>%s</controlURL> \ - <eventSubURL>%s</eventSubURL> \ - </service> \ - </serviceList> \ - </device> \ - </root>", - UPNP_XMLNS_UPNP_DEV, // UPnP Device Namespace (2) - UPNP_XMLNS_PREFIX_DLNA, // DLNA Namespace prefix (2) - UPNP_XMLNS_DLNA_DEV, // DLNA Device Namespace (2) - URLBase, // URLBase (IP:PORT) (7) - UPNP_DEVICE_TYPE, // UPnP Device Type (MediaServer:1) (9) - UPNP_DEVICE_FRIENDLY_NAME, // UPnP Device Friendly Name (10) - UPNP_DEVICE_MANUFACTURER, // UPnP Device Manufacturer (11) - UPNP_DEVICE_MANUFACTURER_URL, // UPnP Device Manufacturer URL (12) - UPNP_DEVICE_MODEL_DESCRIPTION, // UPnP Device Model Description (13) - UPNP_DEVICE_MODEL_NAME, // UPnP Device Model Name (14) - UPNP_DEVICE_MODEL_NUMBER, // UPnP Device Model Number (15) - UPNP_DEVICE_MODEL_URL, // UPnP Device Model URL (16) - UPNP_DEVICE_SERIAL_NUMBER, // UPnP Device Serialnumber (17) - UPNP_DEVICE_UDN, // UPnP Device UDN (18) - DLNA_ICON_JPEG_LRG_24.mime, // UPnP Device Large Icon JPEG Mimetype (21) - DLNA_ICON_JPEG_LRG_24.width, // UPnP Device Large Icon Width (22) - DLNA_ICON_JPEG_LRG_24.height, // UPnP Device Large Icon Height (23) - DLNA_ICON_JPEG_LRG_24.bitDepth, // UPnP Device Large Icon Bit Depth (24) - UPNP_DEVICE_ICON_JPEG_LRG, // UPnP Device Large Icon Path (25) - DLNA_ICON_JPEG_SM_24.mime, // UPnP Device Small Icon JPEG Mimetype (28) - DLNA_ICON_JPEG_SM_24.width, // UPnP Device Small Icon Width (29) - DLNA_ICON_JPEG_SM_24.height, // UPnP Device Small Icon Height (30) - DLNA_ICON_JPEG_SM_24.bitDepth, // UPnP Device Small Icon Bit Depth (31) - UPNP_DEVICE_ICON_JPEG_SM, // UPnP Device Small Icon Path (32) - DLNA_ICON_PNG_SM_24A.mime, // UPnP Device Small Icon PNG Mimetype (35) - DLNA_ICON_PNG_SM_24A.width, // UPnP Device Small Icon Width (36) - DLNA_ICON_PNG_SM_24A.height, // UPnP Device Small Icon Height (37) - DLNA_ICON_PNG_SM_24A.bitDepth, // UPnP Device Small Icon Bit Depth (38) - UPNP_DEVICE_ICON_PNG_SM, // UPnP Device Small Icon Path (39) - DLNA_ICON_PNG_LRG_24A.mime, // UPnP Device Large Icon PNG Mimetype (42) - DLNA_ICON_PNG_LRG_24A.width, // UPnP Device Large Icon Width (43) - DLNA_ICON_PNG_LRG_24A.height, // UPnP Device Large Icon Height (44) - DLNA_ICON_PNG_LRG_24A.bitDepth, // UPnP Device Large Icon Bit Depth (45) - UPNP_DEVICE_ICON_PNG_LRG, // UPnP Device Large Icon Path (46) - UPNP_WEB_PRESENTATION_URL, // UPnP Presentation URL (49) - UPNP_XMLNS_PREFIX_DLNA, // DLNA Namespace prefix (50) - DLNA_DEVICE_DMS_1_5, // DLNA Device Type/Version (50) - UPNP_CMS_SERVICE_TYPE, // UPnP CMS Service Type - UPNP_CMS_SERVICE_ID, // UPnP CMS Service ID - UPNP_CMS_SCPD_URL, // UPnP CMS Service Description - UPNP_CMS_CONTROL_URL, // UPnP CMS Control URL - UPNP_CMS_EVENT_URL, // UPnP CMS Event URL - UPNP_CDS_SERVICE_TYPE, // UPnP CDS Service Type - UPNP_CDS_SERVICE_ID, // UPnP CDS Service ID - UPNP_CDS_SCPD_URL, // UPnP CDS Service Description - UPNP_CDS_CONTROL_URL, // UPnP CDS Control URL - UPNP_CDS_EVENT_URL // UPnP CDS Event URL -// UPNP_AVT_SERVICE_TYPE, // UPnP AVT Service Type -// UPNP_AVT_SERVICE_ID, // UPnP AVT Service ID -// UPNP_AVT_SCPD_URL, // UPnP AVT Service Description -// UPNP_AVT_CONTROL_URL, // UPnP AVT Control URL -// UPNP_AVT_EVENT_URL // UPnP AVT Event URL - ); - return strdup0(*description); -}
\ No newline at end of file diff --git a/upnpcomponents/dlna.h b/upnpcomponents/dlna.h deleted file mode 100644 index 44ed3c4..0000000 --- a/upnpcomponents/dlna.h +++ /dev/null @@ -1,117 +0,0 @@ -/* - * File: dlna.h - * Author: savop - * - * Created on 18. April 2009, 23:27 - */ - -#ifndef _DLNA_H -#define _DLNA_H - -#include "../common.h" -#include <vdr/channels.h> -#include <vdr/recording.h> - -class cDlna; - -/** - * Registered DLNA profile - * - * This class contains information about a certain registered profile - * like play speeds or flags - */ -class cRegisteredProfile : public cListObject { - friend class cDlna; -private: - DLNAProfile* Profile; - int Operation; - const char* PlaySpeeds; - int Conversion; - int PrimaryFlags; -public: - cRegisteredProfile(){}; - virtual ~cRegisteredProfile(){}; -}; - -/** - * Enable DLNA compliant media transfer - * - * This class enables media transmission with DLNA conformity. Its compliant with - * version 1.5 of the DLNA guidelines. - * - */ -class cDlna { - friend class cUPnPServer; -public: - /** - * Returns the instance of DLNA object - * - * This will create a DLNA object instance. It will return the same instance - * on subsequent calls. - * - * @return the DLNA object instance - */ - static cDlna* getInstance(void); - virtual ~cDlna(); - //const char* getProtocolInfo(UPnPObjectID OID); - /** - * Device description document - * - * This will return the device description document with service type - * definitions as well as some DLNA specific information - * - * @return The description document - */ - const char* getDeviceDescription( - const char* URLBase ///< the URLBase to be set in the document - ); - /** - * Registeres a DLNA profile - * - * Registeres a DLNA profile with specific optional options - * - * @see common.h - */ - void registerProfile( - DLNAProfile* Profile, ///< the DLNA profile - int Op = -1, ///< operation mode - const char* Ps = NULL, ///< play speed (CSV list) - int Ci = -1, ///< conversion indication flag - unsigned int Flags = 0 ///< DLNA flags - ); - /** - * Registeres all known DLNA profiles - * - * Registeres all well known DLNA profiles with its known options - */ - void registerMainProfiles(); - /** - * CSV list of supported protocols - * - * Returns a comma separated list with all supported protocols. This - * means, it returns the list of protocols of the registered profiles. - * - * @return CSV list of registered protocols - */ - const char* getSupportedProtocols(); - /** - * Protocol info of a specific DLNA profile - * - * Returns the protocol info string of a specific DLNA profile with its - * options and flags. - * - * @return the protocol info string of the profile - */ - const char* getProtocolInfo( - DLNAProfile *Prof ///< the Profile of which the protocol info shall be returned - ); -private: - const char* getRegisteredProtocolInfoString(cRegisteredProfile *Profile); - cDlna(); - void init(void); - static cDlna* mInstance; - cList<cRegisteredProfile>* mRegisteredProfiles; -}; - -#endif /* _DLNA_H */ - diff --git a/upnpcomponents/upnpservice.cpp b/upnpcomponents/upnpservice.cpp deleted file mode 100644 index fc24cca..0000000 --- a/upnpcomponents/upnpservice.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* - * File: upnpservice.cpp - * Author: savop - * - * Created on 21. August 2009, 18:38 - */ - -#include "upnpservice.h" -#include "../common.h" -#include "../misc/util.h" - -cUpnpService::cUpnpService(UpnpDevice_Handle DeviceHandle) { - this->mDeviceHandle = DeviceHandle; -} - -int cUpnpService::parseIntegerValue(IN IXML_Document* Document, IN const char* Item, OUT int* Value){ - char* Val = NULL; - int Error = 0; - - Val = ixmlGetFirstDocumentItem(Document, Item, &Error); - - if(Error != 0){ - ERROR("Error while parsing integer value for item=%s", Item); - Error = -1; - } - else if(!Value){ - WARNING("Value %s empty!", Item); - *Value = 0; - } - else { - *Value = atoi(Val); - free(Val); - } - return Error; -} - -int cUpnpService::parseStringValue(IN IXML_Document* Document, IN const char* Item, OUT char** Value){ - char* Val = NULL; - int Error = 0; - - Val = ixmlGetFirstDocumentItem(Document, Item, &Error); - - if(Error != 0){ - ERROR("Error while parsing string value for item=%s", Item); - Error = -1; - } - else if(!Val){ - WARNING("Value %s empty!", Item); - *Value = NULL; - } - else { - *Value = strdup(Val); - free(Val); - } - - return Error; -} - -void cUpnpService::setError(Upnp_Action_Request* Request, int Error){ - Request->ErrCode = Error; - switch(Error){ - case UPNP_SOAP_E_INVALID_ACTION: - strn0cpy(Request->ErrStr,_("Invalid action"),LINE_SIZE); - break; - case UPNP_SOAP_E_INVALID_ARGS: - strn0cpy(Request->ErrStr,_("Invalid args"),LINE_SIZE); - break; - case UPNP_SOAP_E_INVALID_VAR: - strn0cpy(Request->ErrStr,_("Invalid var"),LINE_SIZE); - break; - case UPNP_SOAP_E_ACTION_FAILED: - strn0cpy(Request->ErrStr,_("Action failed"),LINE_SIZE); - break; - case UPNP_SOAP_E_ARGUMENT_INVALID: - strn0cpy(Request->ErrStr,_("Argument value invalid"),LINE_SIZE); - break; - case UPNP_SOAP_E_ARGUMENT_OUT_OF_RANGE: - strn0cpy(Request->ErrStr,_("Argument value out of range"),LINE_SIZE); - break; - case UPNP_SOAP_E_ACTION_NOT_IMPLEMENTED: - strn0cpy(Request->ErrStr,_("Optional action not implemented"),LINE_SIZE); - break; - case UPNP_SOAP_E_OUT_OF_MEMORY: - strn0cpy(Request->ErrStr,_("Out of memory"),LINE_SIZE); - break; - case UPNP_SOAP_E_HUMAN_INTERVENTION: - strn0cpy(Request->ErrStr,_("Human intervention required"),LINE_SIZE); - break; - case UPNP_SOAP_E_STRING_TO_LONG: - strn0cpy(Request->ErrStr,_("String argument to long"),LINE_SIZE); - break; - case UPNP_SOAP_E_NOT_AUTHORIZED: - strn0cpy(Request->ErrStr,_("Action not authorized"),LINE_SIZE); - break; - case UPNP_SOAP_E_SIGNATURE_FAILURE: - strn0cpy(Request->ErrStr,_("Signature failure"),LINE_SIZE); - break; - case UPNP_SOAP_E_SIGNATURE_MISSING: - strn0cpy(Request->ErrStr,_("Signature missing"),LINE_SIZE); - break; - case UPNP_SOAP_E_NOT_ENCRYPTED: - strn0cpy(Request->ErrStr,_("Not encrypted"),LINE_SIZE); - break; - case UPNP_SOAP_E_INVALID_SEQUENCE: - strn0cpy(Request->ErrStr,_("Invalid sequence"),LINE_SIZE); - break; - case UPNP_SOAP_E_INVALID_CONTROL_URL: - strn0cpy(Request->ErrStr,_("Invalid control URL"),LINE_SIZE); - break; - case UPNP_SOAP_E_NO_SUCH_SESSION: - strn0cpy(Request->ErrStr,_("No such session"),LINE_SIZE); - break; - case UPNP_SOAP_E_OUT_OF_SYNC: - default: - strn0cpy(Request->ErrStr,_("Unknown error code. Contact the device manufacturer"),LINE_SIZE); - break; - } -}
\ No newline at end of file diff --git a/upnpcomponents/upnpservice.h b/upnpcomponents/upnpservice.h deleted file mode 100644 index df74d9b..0000000 --- a/upnpcomponents/upnpservice.h +++ /dev/null @@ -1,119 +0,0 @@ -/* - * File: upnpservice.h - * Author: savop - * - * Created on 21. August 2009, 18:38 - */ - -#ifndef _UPNPSERVICE_H -#define _UPNPSERVICE_H - -#include <upnp/upnp.h> - -/** - * UPnP Service interface - * - * This is a service interface implemented by a UPnP service like CDS oder CMS - * - * It comes with some tool functions which are commonly useful for processing - * an event or action. - */ -class cUpnpService { -public: - /** - * Constructor of a service - * - * @private - * @param DeviceHandle the UPnP device handle of this root device - */ - cUpnpService( - UpnpDevice_Handle DeviceHandle ///< the UPnP device handle of this root device - ); - virtual ~cUpnpService(){}; - /** - * Subscribes to an event - * - * This is a callback function to register a new subscriber for an event. - * - * @return An integer representing one of the following: - * - \bc UPNP_E_SUCCESS, if subscription was okay - * - or any other non null value in case of an error - * - * @param Request Information about the subscription - */ - virtual int subscribe( - Upnp_Subscription_Request* Request ///< Information about the subscription - ) = 0; - /** - * Executes an action - * - * This executes an action initialized by a control point. The result is - * stored in the first parameter. - * - * @return An integer representing one of the following: - * - \bc UPNP_E_SUCCESS, if subscription was okay - * - or any other non null value in case of an error - * - * @param Request Input and output parameters of an action - */ - virtual int execute( - Upnp_Action_Request* Request ///< Input and output parameters of an action - ) = 0; -protected: - /** - * Sets an error on an action request - * - * This function puts a error message into the action request structure - * according to its error code - * - * @param Request the action request, to set the error for - * @param Error the error code of which the message should be obtained - */ - virtual void setError( - Upnp_Action_Request* Request, ///< the action request, to set the error for - int Error ///< the error code of which the message should be obtained - ); - /** - * Parses an integer value - * - * This tool function parses an integer value from a given \em IXML document. It is searching - * for the very first occurance of the demanded item. - * - * @return Returns - * - \bc 0, if parsing was successful - * - \bc <0, if an error occured - * - * @param Document the document, which is parsed - * @param Item the demanded item - * @param Value the value of the item - */ - int parseIntegerValue( - IN IXML_Document* Document, ///< the document, which is parsed - IN const char* Item, ///< the demanded item - OUT int* Value ///< the value of the item - ); - /** - * Parses a string value - * - * This tool function parses a string value from a given \em IXML document. It is searching - * for the very first occurance of the demanded item. - * - * @return Returns - * - \bc 0, if parsing was successful - * - \bc <0, if an error occured - * - * @param Document the document, which is parsed - * @param Item the demanded item - * @param Value the value of the item - */ - int parseStringValue( - IN IXML_Document* Document, ///< the document, which is parsed - IN const char* Item, ///< the demanded item - OUT char** Value ///< the value of the item - ); - - UpnpDevice_Handle mDeviceHandle; ///< the UPnP device handle of the root device -}; - -#endif /* _UPNPSERVICE_H */ - diff --git a/upnpcomponents/upnpwebserver.cpp b/upnpcomponents/upnpwebserver.cpp deleted file mode 100644 index b192cd9..0000000 --- a/upnpcomponents/upnpwebserver.cpp +++ /dev/null @@ -1,338 +0,0 @@ -/* - * File: upnpwebserver.cpp - * Author: savop - * - * Created on 30. Mai 2009, 18:13 - */ - -#include <time.h> -#include <vdr/channels.h> -#include <map> -#include <upnp/upnp.h> -#include "upnpwebserver.h" -#include "../server/server.h" -#include "../receiver/livereceiver.h" -#include "../receiver/recplayer.h" -#include "../misc/search.h" - -/* COPIED FROM INTEL UPNP TOOLS */ -/******************************************************************************* - * - * Copyright (c) 2000-2003 Intel Corporation - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * 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. - * * Neither name of Intel Corporation nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "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 INTEL OR - * CONTRIBUTORS 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. - * - ******************************************************************************/ -/** @private */ -struct File_Info_ -{ - /** The length of the file. A length less than 0 indicates the size - * is unknown, and data will be sent until 0 bytes are returned from - * a read call. */ - off64_t file_length; - - /** The time at which the contents of the file was modified; - * The time system is always local (not GMT). */ - time_t last_modified; - - /** If the file is a directory, {\bf is_directory} contains - * a non-zero value. For a regular file, it should be 0. */ - int is_directory; - - /** If the file or directory is readable, this contains - * a non-zero value. If unreadable, it should be set to 0. */ - int is_readable; - - /** The content type of the file. This string needs to be allocated - * by the caller using {\bf ixmlCloneDOMString}. When finished - * with it, the SDK frees the {\bf DOMString}. */ - - DOMString content_type; - -}; - -/** @private */ -struct cWebFileHandle { - cString Filename; - off64_t Size; - cFileHandle* FileHandle; -}; - -/**************************************************** - * - * The web server - * - * Handles the virtual directories and the - * provision of data - * - * Interface between the channels/recordings of the - * VDR and the outer world - * - ****************************************************/ - -cUPnPWebServer::cUPnPWebServer(const char* root) : mRootdir(root) { -} - -cUPnPWebServer::~cUPnPWebServer(){} - -cUPnPWebServer* cUPnPWebServer::mInstance = NULL; - -UpnpVirtualDirCallbacks cUPnPWebServer::mVirtualDirCallbacks = { - cUPnPWebServer::getInfo, - cUPnPWebServer::open, - cUPnPWebServer::read, - cUPnPWebServer::write, - cUPnPWebServer::seek, - cUPnPWebServer::close -}; - -bool cUPnPWebServer::init(){ - MESSAGE(VERBOSE_WEBSERVER, "Initialize callbacks for virtual directories."); - - if(UpnpSetWebServerRootDir(this->mRootdir) == UPNP_E_INVALID_ARGUMENT){ - ERROR("The root directory of the webserver is invalid."); - return false; - } - MESSAGE(VERBOSE_WEBSERVER, "Setting up callbacks"); - - if(UpnpSetVirtualDirCallbacks(&cUPnPWebServer::mVirtualDirCallbacks) == UPNP_E_INVALID_ARGUMENT){ - ERROR("The virtual directory callbacks are invalid."); - return false; - } - - if(UpnpIsWebserverEnabled() == FALSE){ - WARNING("The webserver has not been started. For whatever reason..."); - return false; - } - - MESSAGE(VERBOSE_WEBSERVER, "Add virtual directories."); - if(UpnpAddVirtualDir(UPNP_DIR_SHARES) == UPNP_E_INVALID_ARGUMENT){ - ERROR("The virtual directory %s is invalid.",UPNP_DIR_SHARES); - return false; - } - return true; -} - -bool cUPnPWebServer::uninit(){ - MESSAGE(VERBOSE_WEBSERVER, "Disabling the internal webserver"); - UpnpEnableWebserver(FALSE); - - return true; -} - -cUPnPWebServer* cUPnPWebServer::getInstance(const char* rootdir){ - if(cUPnPWebServer::mInstance == NULL) - cUPnPWebServer::mInstance = new cUPnPWebServer(rootdir); - - if(cUPnPWebServer::mInstance){ - return cUPnPWebServer::mInstance; - } - else return NULL; -} - -int cUPnPWebServer::getInfo(const char* filename, File_Info* info){ - MESSAGE(VERBOSE_WEBSERVER, "Getting information of file '%s'", filename); - - propertyMap Properties; - int Method; - int Section; - - if(cPathParser::parse(filename, &Section, &Method, &Properties)){ - switch(Section){ - case 0: - switch(Method){ - case UPNP_WEB_METHOD_STREAM: - { - MESSAGE(VERBOSE_WEBSERVER, "Stream request"); - propertyMap::iterator It = Properties.find("resId"); - unsigned int ResourceID = 0; - if(It == Properties.end()){ - ERROR("No resourceID for stream request"); - return -1; - } - else { - ResourceID = (unsigned)atoi(It->second); - cUPnPResource* Resource = cUPnPResources::getInstance()->getResource(ResourceID); - if(!Resource){ - ERROR("No such resource with ID (%d)", ResourceID); - return -1; - } - else { - File_Info_ finfo; - - finfo.content_type = ixmlCloneDOMString(Resource->getContentType()); - finfo.file_length = Resource->getFileSize(); - finfo.is_directory = 0; - finfo.is_readable = 1; - finfo.last_modified = Resource->getLastModification(); - memcpy(info, &finfo, sizeof(File_Info_)); - - MESSAGE(VERBOSE_METADATA, "==== File info of Resource #%d ====", Resource->getID()); - MESSAGE(VERBOSE_METADATA, "Size: %lld", finfo.file_length); - MESSAGE(VERBOSE_METADATA, "Dir: %s", finfo.is_directory?"yes":"no"); - MESSAGE(VERBOSE_METADATA, "Read: %s", finfo.is_readable?"allowed":"not allowed"); - MESSAGE(VERBOSE_METADATA, "Last modified: %s", ctime(&(finfo.last_modified))); - MESSAGE(VERBOSE_METADATA, "Content-type: %s", finfo.content_type); - } - } - } - break; - case UPNP_WEB_METHOD_BROWSE: - // break; - case UPNP_WEB_METHOD_SHOW: - // break; - case UPNP_WEB_METHOD_SEARCH: - case UPNP_WEB_METHOD_DOWNLOAD: - default: - ERROR("Unknown or unsupported method ID (%d)", Method); - return -1; - } - break; - default: - ERROR("Unknown or unsupported section ID (%d).", Section); - return -1; - } - } - else { - return -1; - } - - return 0; -} - -UpnpWebFileHandle cUPnPWebServer::open(const char* filename, UpnpOpenFileMode mode){ - MESSAGE(VERBOSE_WEBSERVER, "File %s was opened for %s.",filename,mode==UPNP_READ ? "reading" : "writing"); - - propertyMap Properties; - int Method; - int Section; - cWebFileHandle* WebFileHandle = NULL; - - if(cPathParser::parse(filename, &Section, &Method, &Properties)){ - switch(Section){ - case 0: - switch(Method){ - case UPNP_WEB_METHOD_STREAM: - { - MESSAGE(VERBOSE_WEBSERVER, "Stream request"); - propertyMap::iterator It = Properties.find("resId"); - unsigned int ResourceID = 0; - if(It == Properties.end()){ - ERROR("No resourceID for stream request"); - return NULL; - } - else { - ResourceID = (unsigned)atoi(It->second); - cUPnPResource* Resource = cUPnPResources::getInstance()->getResource(ResourceID); - if(!Resource){ - ERROR("No such resource with ID (%d)", ResourceID); - return NULL; - } - else { - WebFileHandle = new cWebFileHandle; - WebFileHandle->Filename = Resource->getResource(); - WebFileHandle->Size = Resource->getFileSize(); - switch(Resource->getResourceType()){ - case UPNP_RESOURCE_CHANNEL: - { - char* ChannelID = strtok(strdup(Resource->getResource()),":"); - int StreamID = atoi(strtok(NULL,":")); - MESSAGE(VERBOSE_LIVE_TV, "Try to create Receiver for Channel %s with Stream ID %d", ChannelID, StreamID); - cChannel* Channel = Channels.GetByChannelID(tChannelID::FromString(ChannelID)); - if(!Channel){ - ERROR("No such channel with ID %s", ChannelID); - return NULL; - } - cLiveReceiver* Receiver = cLiveReceiver::newInstance(Channel,0); - if(!Receiver){ - ERROR("Unable to tune channel. No available tuners?"); - return NULL; - } - WebFileHandle->FileHandle = Receiver; - } - break; - case UPNP_RESOURCE_RECORDING: - // break; - case UPNP_RESOURCE_FILE: - // break; - case UPNP_RESOURCE_URL: - default: - return NULL; - } - } - } - } - break; - case UPNP_WEB_METHOD_BROWSE: - // break; - case UPNP_WEB_METHOD_SHOW: - // break; - case UPNP_WEB_METHOD_SEARCH: - case UPNP_WEB_METHOD_DOWNLOAD: - default: - ERROR("Unknown or unsupported method ID (%d)", Method); - return NULL; - } - break; - default: - ERROR("Unknown or unsupported section ID (%d).", Section); - return NULL; - } - } - else { - return NULL; - } - MESSAGE(VERBOSE_WEBSERVER, "Open the file handle"); - WebFileHandle->FileHandle->open(mode); - return (UpnpWebFileHandle)WebFileHandle; -} - -int cUPnPWebServer::write(UpnpWebFileHandle fh, char* buf, size_t buflen){ - cWebFileHandle* FileHandle = (cWebFileHandle*)fh; - MESSAGE(VERBOSE_BUFFERS, "Writing to %s", *FileHandle->Filename); - return FileHandle->FileHandle->write(buf, buflen); -} - -int cUPnPWebServer::read(UpnpWebFileHandle fh, char* buf, size_t buflen){ - cWebFileHandle* FileHandle = (cWebFileHandle*)fh; - MESSAGE(VERBOSE_BUFFERS, "Reading from %s", *FileHandle->Filename); - return FileHandle->FileHandle->read(buf, buflen); -} - -int cUPnPWebServer::seek(UpnpWebFileHandle fh, off_t offset, int origin){ - cWebFileHandle* FileHandle = (cWebFileHandle*)fh; - MESSAGE(VERBOSE_BUFFERS, "Seeking on %s", *FileHandle->Filename); - return FileHandle->FileHandle->seek(offset, origin); -} - -int cUPnPWebServer::close(UpnpWebFileHandle fh){ - cWebFileHandle *FileHandle = (cWebFileHandle *)fh; - MESSAGE(VERBOSE_WEBSERVER, "Closing file %s", *FileHandle->Filename); - FileHandle->FileHandle->close(); - delete FileHandle->FileHandle; - delete FileHandle; - return 0; -}
\ No newline at end of file diff --git a/upnpcomponents/upnpwebserver.h b/upnpcomponents/upnpwebserver.h deleted file mode 100644 index 0a49cf9..0000000 --- a/upnpcomponents/upnpwebserver.h +++ /dev/null @@ -1,160 +0,0 @@ -/* - * File: upnpwebserver.h - * Author: savop - * - * Created on 30. Mai 2009, 18:13 - */ - -#ifndef _UPNPWEBSERVER_H -#define _UPNPWEBSERVER_H - -#include "../common.h" -#include <upnp/upnp.h> - -/** - * The internal webserver - * - * This is the internal webserver. It distributes all the contents of the - * UPnP-Server. - * - */ -class cUPnPWebServer { - friend class cUPnPServer; -private: - static cUPnPWebServer *mInstance; - static UpnpVirtualDirCallbacks mVirtualDirCallbacks; - const char* mRootdir; - cUPnPWebServer(const char* root = "/"); -protected: -public: - /** - * Initializes the webserver - * - * It enables the webserver which comes with the <em>Intel SDK</em> and creates - * virtual directories for shares media. - * - * @return returns - * - \bc true, if initializing was successful - * - \bc false, otherwise - */ - bool init(); - /** - * Uninitializes the webserver - * - * This stops the webserver. - * - * @return returns - * - \bc true, if initializing was successful - * - \bc false, otherwise - */ - bool uninit(); - /** - * Returns the instance of the webserver - * - * Returns the instance of the webserver. This will create a single - * instance of none is existing on the very first call. A subsequent call - * will return the same instance. - * - * @return the instance of webserver - */ - static cUPnPWebServer* getInstance( - const char* rootdir = "/" /**< the root directory of the webserver */ - ); - virtual ~cUPnPWebServer(); -//}; - - /**************************************************** - * - * The callback functions for the webserver - * - ****************************************************/ - - /** - * Retrieve file information - * - * Returns file related information for an virtual directory file - * - * @return 0 on success, -1 otherwise - * @param filename The filename of which the information is gathered - * @param info The File_Info structure with the data - */ - static int getInfo(const char* filename, struct File_Info* info); - /** - * Opens a virtual directory file - * - * Opens a file in a virtual directory with the specified mode. - * - * Possible modes are: - * - \b UPNP_READ, Opens the file for reading - * - \b UPNP_WRITE, Opens the file for writing - * - * It returns a file handle to the opened file, NULL otherwise - * - * @return FileHandle to the opened file, NULL otherwise - * @param filename The file to open - * @param mode UPNP_WRITE for writing, UPNP_READ for reading. - */ - static UpnpWebFileHandle open(const char* filename, UpnpOpenFileMode mode); - /** - * Reads from the opened file - * - * Reads <code>buflen</code> bytes from the file and stores the content - * to the buffer - * - * Returns 0 no more bytes read (EOF) - * >0 bytes read from file - * - * @return number of bytes read, 0 on EOF - * @param fh the file handle of the opened file - * @param buf the buffer to write the bytes to - * @param buflen the maximum count of bytes to read - * - */ - static int read(UpnpWebFileHandle fh, char* buf, size_t buflen); - /** - * Writes to the opened file - * - * Writes <code>buflen</code> bytes from the buffer and stores the content - * in the file - * - * Returns >0 bytes wrote to file, maybe less the buflen in case of write - * errors - * - * @return number of bytes read, 0 on EOF - * @param fh the file handle of the opened file - * @param buf the buffer to read the bytes from - * @param buflen the maximum count of bytes to write - * - */ - static int write(UpnpWebFileHandle fh, char* buf, size_t buflen); - /** - * Seek in the file - * - * Seeks in the opened file and sets the file pointer to the specified offset - * - * Returns 0 on success, non-zero value otherwise - * - * @return 0 on success, non-zero value otherwise - * @param fh the file handle of the opened file - * @param offset a negative oder positive value which moves the pointer - * forward or backward - * @param origin SEEK_CUR, SEEK_END or SEEK_SET - * - */ - static int seek(UpnpWebFileHandle fh, off_t offset, int origin); - /** - * Closes the file - * - * closes the opened file - * - * Returns 0 on success, non-zero value otherwise - * - * @return 0 on success, non-zero value otherwise - * @param fh the file handle of the opened file - * - */ - static int close(UpnpWebFileHandle fh); -}; - -#endif /* _UPNPWEBSERVER_H */ - diff --git a/web/icons/upnpIconLrg.jpeg b/web/icons/upnpIconLrg.jpeg Binary files differdeleted file mode 100755 index 6421267..0000000 --- a/web/icons/upnpIconLrg.jpeg +++ /dev/null diff --git a/web/icons/upnpIconLrg.png b/web/icons/upnpIconLrg.png Binary files differdeleted file mode 100755 index d93e7c0..0000000 --- a/web/icons/upnpIconLrg.png +++ /dev/null diff --git a/web/icons/upnpIconSm.jpeg b/web/icons/upnpIconSm.jpeg Binary files differdeleted file mode 100755 index b163f05..0000000 --- a/web/icons/upnpIconSm.jpeg +++ /dev/null diff --git a/web/icons/upnpIconSm.png b/web/icons/upnpIconSm.png Binary files differdeleted file mode 100755 index d4320f4..0000000 --- a/web/icons/upnpIconSm.png +++ /dev/null diff --git a/web/xml/cds_scpd.xml b/web/xml/cds_scpd.xml deleted file mode 100644 index dff4252..0000000 --- a/web/xml/cds_scpd.xml +++ /dev/null @@ -1,145 +0,0 @@ -<?xml version = "1.0" encoding="UTF-8"?> -<scpd xmlns="urn:schemas-upnp-org:service-1-0"> -<specVersion> -<major>1</major> -<minor>0</minor> -</specVersion> -<actionList> -<action> -<name>GetSearchCapabilities</name> -<argumentList> -<argument> -<name>SearchCaps</name> -<direction>out</direction> -<relatedStateVariable>SearchCapabilities</relatedStateVariable> -</argument> -</argumentList> -</action> -<action> -<name>GetSortCapabilities</name> -<argumentList> -<argument> -<name>SortCaps</name> -<direction>out</direction> -<relatedStateVariable>SortCapabilities</relatedStateVariable> -</argument> -</argumentList> -</action> -<action> -<name>GetSystemUpdateID</name> -<argumentList> -<argument> -<name>Id</name> -<direction>out</direction> -<relatedStateVariable>SystemUpdateID</relatedStateVariable> -</argument> -</argumentList> -</action> -<action> -<name>Browse</name> -<argumentList> -<argument> -<name>ObjectID</name> -<direction>in</direction> -<relatedStateVariable>A_ARG_TYPE_ObjectID</relatedStateVariable> -</argument> -<argument> -<name>BrowseFlag</name> -<direction>in</direction> -<relatedStateVariable>A_ARG_TYPE_BrowseFlag</relatedStateVariable> -</argument> -<argument> -<name>Filter</name> -<direction>in</direction> -<relatedStateVariable>A_ARG_TYPE_Filter</relatedStateVariable> -</argument> -<argument> -<name>StartingIndex</name> -<direction>in</direction> -<relatedStateVariable>A_ARG_TYPE_Index</relatedStateVariable> -</argument> -<argument> -<name>RequestedCount</name> -<direction>in</direction> -<relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable> -</argument> -<argument> -<name>SortCriteria</name> -<direction>in</direction> -<relatedStateVariable>A_ARG_TYPE_SortCriteria</relatedStateVariable> -</argument> -<argument> -<name>Result</name> -<direction>out</direction> -<relatedStateVariable>A_ARG_TYPE_Result</relatedStateVariable> -</argument> -<argument> -<name>NumberReturned</name> -<direction>out</direction> -<relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable> -</argument> -<argument> -<name>TotalMatches</name> -<direction>out</direction> -<relatedStateVariable>A_ARG_TYPE_Count</relatedStateVariable> -</argument> -<argument> -<name>UpdateID</name> -<direction>out</direction> -<relatedStateVariable>A_ARG_TYPE_UpdateID</relatedStateVariable> -</argument> -</argumentList> -</action> -</actionList> -<serviceStateTable> -<stateVariable sendEvents="no"> -<name>A_ARG_TYPE_ObjectID</name> -<dataType>string</dataType> -</stateVariable> -<stateVariable sendEvents="no"> -<name>A_ARG_TYPE_Result</name> -<dataType>string</dataType> -</stateVariable> -<stateVariable sendEvents="no"> -<name>A_ARG_TYPE_BrowseFlag</name> -<dataType>string</dataType> -<allowedValueList> -<allowedValue>BrowseMetadata</allowedValue> -<allowedValue>BrowseDirectChildren</allowedValue> -</allowedValueList> -</stateVariable> -<stateVariable sendEvents="no"> -<name>A_ARG_TYPE_Filter</name> -<dataType>string</dataType> -</stateVariable> -<stateVariable sendEvents="no"> -<name>A_ARG_TYPE_SortCriteria</name> -<dataType>string</dataType> -</stateVariable> -<stateVariable sendEvents="no"> -<name>A_ARG_TYPE_Index</name> -<dataType>ui4</dataType> -</stateVariable> -<stateVariable sendEvents="no"> -<name>A_ARG_TYPE_Count</name> -<dataType>ui4</dataType> -</stateVariable> -<stateVariable sendEvents="no"> -<name>A_ARG_TYPE_UpdateID</name> -<dataType>ui4</dataType> -</stateVariable> -<stateVariable sendEvents="no"> -<name>SearchCapabilities</name> -<dataType>string</dataType> -</stateVariable> -<stateVariable sendEvents="no"> -<name>SortCapabilities</name> -<dataType>string</dataType> -</stateVariable> -<stateVariable sendEvents="yes"> -<name>SystemUpdateID</name> -<dataType>ui4</dataType> -</stateVariable> -</serviceStateTable> -</scpd> - diff --git a/web/xml/cms_scpd.xml b/web/xml/cms_scpd.xml deleted file mode 100644 index e4071f9..0000000 --- a/web/xml/cms_scpd.xml +++ /dev/null @@ -1,133 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<scpd xmlns="urn:schemas-upnp-org:service-1-0"> - <specVersion> - <major>1</major> - <minor>0</minor> - </specVersion> - <actionList> - <action> - <name>GetProtocolInfo</name> - <argumentList> - <argument> - <name>Source</name> - <direction>out</direction> - <relatedStateVariable>SourceProtocolInfo</relatedStateVariable> - </argument> - <argument> - <name>Sink</name> - <direction>out</direction> - <relatedStateVariable>SinkProtocolInfo</relatedStateVariable> - </argument> - </argumentList> - </action> - <action> - <name>GetCurrentConnectionIDs</name> - <argumentList> - <argument> - <name>ConnectionIDs</name> - <direction>out</direction> - <relatedStateVariable>CurrentConnectionIDs</relatedStateVariable> - </argument> - </argumentList> - </action> - <action> - <name>GetCurrentConnectionInfo</name> - <argumentList> - <argument> - <name>ConnectionID</name> - <direction>in</direction> - <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable> - </argument> - <argument> - <name>RcsID</name> - <direction>out</direction> - <relatedStateVariable>A_ARG_TYPE_RcsID</relatedStateVariable> - </argument> - <argument> - <name>AVTransportID</name> - <direction>out</direction> - <relatedStateVariable>A_ARG_TYPE_AVTransportID</relatedStateVariable> - </argument> - <argument> - <name>ProtocolInfo</name> - <direction>out</direction> - <relatedStateVariable>A_ARG_TYPE_ProtocolInfo</relatedStateVariable> - </argument> - <argument> - <name>PeerConnectionManager</name> - <direction>out</direction> - <relatedStateVariable>A_ARG_TYPE_ConnectionManager</relatedStateVariable> - </argument> - <argument> - <name>PeerConnectionID</name> - <direction>out</direction> - <relatedStateVariable>A_ARG_TYPE_ConnectionID</relatedStateVariable> - </argument> - <argument> - <name>Direction</name> - <direction>out</direction> - <relatedStateVariable>A_ARG_TYPE_Direction</relatedStateVariable> - </argument> - <argument> - <name>Status</name> - <direction>out</direction> - <relatedStateVariable>A_ARG_TYPE_ConnectionStatus</relatedStateVariable> - </argument> - </argumentList> - </action> - </actionList> - <serviceStateTable> - <stateVariable sendEvents="yes"> - <name>SourceProtocolInfo</name> - <dataType>string</dataType> - </stateVariable> - <stateVariable sendEvents="yes"> - <name>SinkProtocolInfo</name> - <dataType>string</dataType> - </stateVariable> - <stateVariable sendEvents="yes"> - <name>CurrentConnectionIDs</name> - <dataType>string</dataType> - </stateVariable> - <stateVariable sendEvents="no"> - <name>A_ARG_TYPE_ConnectionStatus</name> - <dataType>string</dataType> - <allowedValueList> - <allowedValue>OK</allowedValue> - <allowedValue>ContentFormatMismatch</allowedValue> - <allowedValue>InsufficientBandwidth</allowedValue> - <allowedValue>UnreliableChannel</allowedValue> - <allowedValue>Unknown</allowedValue> - </allowedValueList> - </stateVariable> - <stateVariable sendEvents="no"> - <name>A_ARG_TYPE_ConnectionManager</name> - <dataType>string</dataType> - </stateVariable> - <stateVariable sendEvents="no"> - <name>A_ARG_TYPE_Direction</name> - <dataType>string</dataType> - <allowedValueList> - <allowedValue>Input</allowedValue> - <allowedValue>Output</allowedValue> - </allowedValueList> - </stateVariable> - <stateVariable sendEvents="no"> - <name>A_ARG_TYPE_ProtocolInfo</name> - <dataType>string</dataType> - </stateVariable> - <stateVariable sendEvents="no"> - <name>A_ARG_TYPE_ConnectionID</name> - <dataType>i4</dataType> - </stateVariable> - <stateVariable sendEvents="no"> - <name>A_ARG_TYPE_AVTransportID</name> - <dataType>i4</dataType> - </stateVariable> - <stateVariable sendEvents="no"> - <name>A_ARG_TYPE_RcsID</name> - <dataType>i4</dataType> - </stateVariable> - </serviceStateTable> -</scpd> - |