diff options
author | Denis Loh <denis.loh@web.de> | 2012-09-13 20:01:49 +0200 |
---|---|---|
committer | Denis Loh <denis.loh@web.de> | 2012-09-13 20:01:49 +0200 |
commit | 4d808c7f57e7de856154c7d13b6d2dc6501bb6fc (patch) | |
tree | fac25d52dae381703533f417cd7f400bc74317e9 /include | |
download | vdr-plugin-upnp-4d808c7f57e7de856154c7d13b6d2dc6501bb6fc.tar.gz vdr-plugin-upnp-4d808c7f57e7de856154c7d13b6d2dc6501bb6fc.tar.bz2 |
Initial commit
Diffstat (limited to 'include')
-rw-r--r-- | include/config.h | 126 | ||||
-rw-r--r-- | include/connection.h | 84 | ||||
-rw-r--r-- | include/connectionManager.h | 70 | ||||
-rw-r--r-- | include/contentDirectory.h | 58 | ||||
-rw-r--r-- | include/media/mediaManager.h | 87 | ||||
-rw-r--r-- | include/media/profile.h | 50 | ||||
-rw-r--r-- | include/plugin.h | 484 | ||||
-rw-r--r-- | include/plugin.h.txt | 486 | ||||
-rw-r--r-- | include/pluginManager.h | 20 | ||||
-rw-r--r-- | include/server.h | 110 | ||||
-rw-r--r-- | include/service.h | 108 | ||||
-rw-r--r-- | include/tools.h | 162 | ||||
-rw-r--r-- | include/webserver.h | 66 |
13 files changed, 1911 insertions, 0 deletions
diff --git a/include/config.h b/include/config.h new file mode 100644 index 0000000..b149316 --- /dev/null +++ b/include/config.h @@ -0,0 +1,126 @@ +/* + * config.h + * + * Created on: 03.08.2012 + * Author: savop + */ + +#ifndef CONFIG_H_ +#define CONFIG_H_ + +#include <string> +#include <stdint.h> +#include "media/profile.h" + +using namespace std; + +namespace upnp { + +struct cConfig { + cConfig(); + /** + * Enable the media server + * + * If this is true, the media server is running on startup. + */ + bool enabled; + /** + * Enable expert settings + * + * If this is true, the user may customize additional settings, which should + * only be done, if the user is very experienced or want to use that for + * debugging. + */ + bool expertSettings; + /** + * Use the internal web server + * + * If this is true, the internal web server is used for streaming of files. + * Otherwise an external URL is used. + */ + bool useInternalWebserver; + /** + * Web server root directory + * + * This is the directory, where the internal web server is looking for files. If it + * is empty, the default directory (plugins configuration folder) is used. + */ + string webServerRoot; + /** + * Web server port + * + * This is the port where the web server is listening on. + */ + uint16_t webServerPort; + /** + * External web server URL + * + * This is the URL, which is used instead of the internal web server URL. If it is + * empty, the default presentation URL, which is /index.html is used. + */ + string presentationURL; + /** + * Maximum size of SOAP messages + * + * This is the maximum size in bytes of soap messages received by the UPnP library. + */ + size_t maxContentLength; + + /** + * Maximum age of upnp announcements + * + * This is the number of seconds an announcement is valid until the device is declared + * as out-dated and has to re-new its announcement. + */ + int announceMaxAge; + + /** + * DeviceUUID + * + * This is the unique identifier for this media server device. If this is empty + * it will be generated. + */ + string deviceUUID; + + /** + * Service URL + * + * This is the URL to the services and service descriptors of that services. + */ + string serviceURL; + + /** + * Static content URL + * + * This is the URL to the static content of the server. They must be located within the + * network of the server. + */ + string staticContentURL; + /** + * Bind the server to an IP address + * + * If this is true, the media server is bound to the specified IP address, + * otherwise the specified interface will be used. + */ + bool bindToAddress; + + string address; + string interface; + /** + * The media server listening port + * + * This is the port which the media server is listening for incoming connections + */ + uint16_t port; + + /** + * The sqlite database file + * + * This is the path to the database file. + */ + string databaseFile; +}; + +} + +#endif /* CONFIG_H_ */ diff --git a/include/connection.h b/include/connection.h new file mode 100644 index 0000000..ebd1f4f --- /dev/null +++ b/include/connection.h @@ -0,0 +1,84 @@ +/* + * connection.h + * + * Created on: 31.07.2012 + * Author: savop + */ + +#ifndef CONNECTION_H_ +#define CONNECTION_H_ + +#include <vdr/tools.h> +#include <string> + +namespace upnp { + +class cVirtualConnection { +public: + enum Direction { + VC_OUTPUT, + VC_INPUT, + NumDirections + }; + + enum Status { + VC_OKAY, + VC_CONTENT_FORMAT_MISMATCH, + VC_INSUFFICIENT_BANDWIDTH, + VC_UNRELIABLE_CHANNEL, + VC_UNKNOWN, + NumStatus + }; + + static cVirtualConnection* GenerateVirtualConnection( + const std::string& pemoteProtocolInfo, + const std::string& peerConnectionManager, + int32_t peerConnectionID, + Direction direction); + + static cVirtualConnection* GenerateVirtualConnection( + const std::string& pemoteProtocolInfo, + const std::string& peerConnectionManager, + int32_t peerConnectionID, + const std::string& direction); + + static void DestroyVirtualConnection(cVirtualConnection* connection); + + const std::string& GetRemoteProtocolInfo() const { return mRemoteProtocolInfo; } + const std::string& GetPeerConnectionManager() const { return mPeerConnectionManager; } + int32_t GetPeerConnectionID() const { return mPeerConnectionID; } + int32_t GetConnectionID() const { return mConnectionID; } + int32_t GetAVTransportID() const { return mAVTransportID; } + int32_t GetRcsID() const { return mRcsID; } + Direction GetDirection() const { return mDirection; } + std::string GetDirectionString() const; + Status GetStatus() const { return mStatus; } + std::string GetStatusString() const; + +private: + cVirtualConnection( + int32_t connectionID, + const std::string & remoteProtocolInfo, + const std::string & peerConnectionManager, + int32_t peerConnectionID, + Direction direction); + cVirtualConnection(const cVirtualConnection & other); + cVirtualConnection& operator=(const cVirtualConnection & other); + + virtual ~cVirtualConnection(){} + + static int32_t NextConnectionID(); + + std::string mRemoteProtocolInfo; + std::string mPeerConnectionManager; + int32_t mPeerConnectionID; + int32_t mConnectionID; + int32_t mAVTransportID; + int32_t mRcsID; + Direction mDirection; + Status mStatus; +}; + +}; + +#endif /* CONNECTION_H_ */ diff --git a/include/connectionManager.h b/include/connectionManager.h new file mode 100644 index 0000000..9680891 --- /dev/null +++ b/include/connectionManager.h @@ -0,0 +1,70 @@ +/* + * connectionManager.h + * + * Created on: 27.08.2012 + * Author: savop + */ + +#ifndef CONNECTIONMANAGER_H_ +#define CONNECTIONMANAGER_H_ + +#include "../include/service.h" +#include "../include/connection.h" +#include "../include/tools.h" +#include <string> +#include <list> +#include <map> + +namespace upnp { + +/** + * 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: + + typedef std::map<int32_t, cVirtualConnection*> ConnectionList; + /** + * 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(); + 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); + const std::string GetConnectionIDsCVS(); + + void DeleteConnections(); + bool DeleteConnection(int32_t connectionID); + bool CreateConnection( + const std::string & remoteProtocolInfo, + const std::string & peerConnectionManager, + int32_t peerConnectionID, + const std::string & direction + ); + + bool OnConnectionChange(); + + ConnectionList mVirtualConnections; + StringList mSupportedProtocols; +} ConnectionManager; + +} // namespace upnp + +#endif /* CONNECTIONMANAGER_H_ */ diff --git a/include/contentDirectory.h b/include/contentDirectory.h new file mode 100644 index 0000000..c2edffc --- /dev/null +++ b/include/contentDirectory.h @@ -0,0 +1,58 @@ +/* + * contentDirectory.h + * + * Created on: 27.08.2012 + * Author: savop + */ + +#ifndef CONTENTDIRECTORY_H_ +#define CONTENTDIRECTORY_H_ + +#include "../include/service.h" +#include "../include/tools.h" +#include <vdr/thread.h> + +namespace upnp { + +class cContentDirectory : public cUPnPService, public cThread { +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. + */ + cContentDirectory(); + 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); + + virtual void Init(cMediaServer* server, UpnpDevice_Handle deviceHandle); +private: + 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); + int StopTransferResource(Upnp_Action_Request* Request); + int GetTransferProgress(Upnp_Action_Request* Request); + int ExportResource(Upnp_Action_Request* Request); + int ImportResource(Upnp_Action_Request* Request); + + void Action(); + +} ContentDirectory; + +} // namespace upnp + +#endif /* CONTENTDIRECTORY_H_ */ diff --git a/include/media/mediaManager.h b/include/media/mediaManager.h new file mode 100644 index 0000000..7b3bf83 --- /dev/null +++ b/include/media/mediaManager.h @@ -0,0 +1,87 @@ +/* + * mediaManager.h + * + * Created on: 31.08.2012 + * Author: savop + */ + +#ifndef MEDIAMANAGER_H_ +#define MEDIAMANAGER_H_ + +#include <vdr/thread.h> +#include <list> +#include <string> +#include <stdint.h> +#include <tntdb/connection.h> +#include <tntdb/connect.h> +#include "../../include/tools.h" + +namespace upnp { + +class cMediaManager : public cThread { +private: + + struct MediaRequest { + int64_t objectID; + std::string filter; + uint32_t startIndex; + uint32_t requestCount; + std::string sortCriteria; + std::string result; + uint32_t numberReturned; + uint32_t totalMatches; + uint32_t updateID; + }; + +public: + + enum BrowseFlag { + CD_BROWSE_METADATA, + CD_BROWSE_DIRECT_CHILDREN, + NumBrowseFlags + }; + + struct BrowseRequest : public MediaRequest { + BrowseFlag browseMetadata; + }; + + struct SearchRequest : public MediaRequest { + std::string searchCriteria; + }; + + cMediaManager(); + virtual ~cMediaManager(); + + void SetDatabaseFile(string file); + + bool Initialise(); + + uint32_t GetSystemUpdateID() const; + IdList GetContainerUpdateIDs(bool unevented = false); + StringList GetSearchCapabilities() const; + StringList GetSortCapabilities() const; + StringList GetSupportedProtocolInfos() const; + + int Browse(BrowseRequest& request); + int Search(SearchRequest& request); + + static BrowseFlag ToBrowseFlag(std::string browseFlag); + +private: + + void Action(); + bool CheckIntegrity(); + + void OnContainerUpdate(string containerID, long updateID); + + uint32_t mSystemUpdateID; + IdList mEventedContainerUpdateIDs; + string mDatabaseFile; + tntdb::Connection mConnection; + +}; + +} // namespace upnp + + +#endif /* MEDIAMANAGER_H_ */ diff --git a/include/media/profile.h b/include/media/profile.h new file mode 100644 index 0000000..867de66 --- /dev/null +++ b/include/media/profile.h @@ -0,0 +1,50 @@ +/* + * profile.h + * + * Created on: 05.08.2012 + * Author: savop + */ + +#ifndef PROFILE_H_ +#define PROFILE_H_ + +#include <string> +#include <stdint.h> + +using namespace std; + +namespace upnp { + +namespace video { + +} + +namespace audio { + +} + +namespace image { + +struct cIcon { + const char* mime; ///< the mime type of the image + uint16_t width; ///< image width in pixel + uint16_t height; ///< image height in pixel + uint8_t bitDepth; ///< bit depth in bits per pixel +}; + +/* JPEG Icons */ +//extern cIcon DLNA_ICON_JEPG_TN; ///< DLNA jpeg thumbnail profile of images +extern cIcon DLNA_ICON_JPEG_SM_24; ///< DLNA icon profile of small jpeg images +extern cIcon DLNA_ICON_JPEG_LRG_24; ///< DLNA icon profile of large jpeg images + +/* PNG Icons */ +extern cIcon DLNA_ICON_PNG_SM_24A; ///< DLNA icon profile of small png images +extern cIcon DLNA_ICON_PNG_LRG_24A; ///< DLNA icon profile of large png images +//extern cIcon DLNA_ICON_PNG_TN; ///< DLNA png thumbnail profile of images + +} /* NS:image */ + +} /* NS:upnp */ + + +#endif /* PROFILE_H_ */ diff --git a/include/plugin.h b/include/plugin.h new file mode 100644 index 0000000..94a60da --- /dev/null +++ b/include/plugin.h @@ -0,0 +1,484 @@ +/* + * plugin.h + * + * Created on: 31.08.2012 + * Author: savop + */ + +#ifndef PLUGIN_H_ +#define PLUGIN_H_ + +#include <string> +#include <map> +#include <list> +#include <stdint.h> + +using namespace std; + +namespace upnp { + +/** + * Metadata class + * + * This class describes the content of a multimedia item like a video or audio file. + * + * It contains some general information like the title or a detailed description of + * the content and one or more resources to the file. + * + * Why are multiple resources possible, though I just have that one file? Lets say, + * you want to display images. It is very useful if there are thumbnail pictures + * available, which may speed up the display process as the UPnP media renderer may + * first display those thumbnails rather than the huge image itself. Those images + * both refer to the same meta information. However, they have different resource + * information. This may also apply to videos (different resolution, bit rate, + * whatever...) + * + * Every plugin implementor is requested to add as much as available information about + * a resource, because the media renderer may display them in their user interface, + * which in turn makes the navigation and identifying the contents much easier. + * + * The metadata class itself offers some major properties, which are very common in + * the VDRs context. However, the implementor may add additional custom information + * to the list of properties. + * + * A Property with the same name but different value may exist multiple times. It is + * added multiple times to the output. Property attributes are NOT supported. However, + * there only a handful of attributes, which are likely to be unimportant. + * + */ +class cMetadata { +public: + + /** + * Property class + * + * This is a basic key-value class, which holds a property (the key) + * and a value. The value is kept in a string representation. There + * is a set of getter methods to convert the string in to the corresponding + * data type. However, there is no type safety given. The implementor + * must know what the contents of the properties are. + */ + class Property { + public: + Property(){}; + Property(string key, string value); + Property(string key, long value); + Property(string key, bool value); + + string GetKey() const; + string GetString() const; + long GetInteger() const; + bool GetBoolean() const; + + private: + string key; + string value; + }; + + /** + * Resource class + * + * The resource class contains information about a specific resource. + * + * Most of the information are optional except the protocolInfo and the + * resourceUri. + * + * The resourceUri is the locator to the file or stream or whatever. The uri + * is provided by the resourceProvider plugins and must be understood by the + * mediaProfiler plugins. + */ + class Resource { + public: + + bool SetResourceUri(string resourceUri); + bool SetProtocolInfo(string protocolInfo); + bool SetDuration(string duration); + bool SetResolution(string resolution); + bool SetBitrate(uint32_t bitrate); + bool SetSize(uint32_t size); + bool SetSampleFrequency(uint32_t sampleFrequency); + bool SetBitsPerSample(uint32_t bitsPerSample); + bool SetNrAudioChannels(uint32_t nrAudioChannels); + bool SetColorDepth(uint32_t colorDepth); + + string GetResourceUri() const { return resourceUri; } + string GetProtocolInfo() const { return protocolInfo; } + string GetDuration() const { return duration; } + string GetResolution() const { return resolution; } + uint32_t GetBitrate() const { return bitrate; } + uint32_t GetSize() const { return size; } + uint32_t GetSampleFrequency() const { return sampleFrequency; } + uint32_t GetBitsPerSample() const { return bitsPerSample; } + uint32_t GetNrAudioChannels() const { return nrAudioChannels; } + uint32_t GetColorDepth() const { return colorDepth; } + + private: + string resourceUri; + string protocolInfo; + string duration; + string resolution; + uint32_t bitrate; + uint32_t size; + uint32_t sampleFrequency; + uint32_t bitsPerSample; + uint32_t nrAudioChannels; + uint32_t colorDepth; + }; + + typedef multimap<string, Property> PropertyMap; + typedef pair<PropertyMap::iterator,PropertyMap::iterator> PropertyRange; + typedef list<Resource> ResourceList; + + bool AddProperty(Property property); + bool SetProperty(Property property, int index = 0); + + Property& GetPropertyByKey(string property); + PropertyRange GetPropertiesByKey(string property); + PropertyRange GetAllProperties(); + + bool SetObjectID(string objectID); + bool SetObjectIDByUri(string uri); + string GetObjectID() const { return objectID; } + bool SetParentID(string parentID); + bool SetParentIDByUri(string uri); + string GetParentID() const { return parentID; } + bool SetTitle(string title); + string GetTitle() const { return title; } + bool SetUpnpClass(string upnpClass); + string GetUpnpClass() const { return upnpClass; } + bool SetRestricted(bool restricted); + bool GetRestricted() const { return restricted; } + bool SetDescription(string description); + string GetDescription() const { return description; } + bool SetLongDescription(string longDescription); + string GetLongDescription() const { return longDescription; } + bool SetDate(string date); + string GetDate() const { return date; } + bool SetLanguage(string language); + string GetLanguage() const { return language; } + bool SetChannelNr(int channelNr); + int GetChannelNr() const { return channelNr; } + bool SetChannelName(string channelName); + string GetChannelName() const { return channelName; } + bool SetScheduledStart(string scheduledStart); + string GetScheduledStart() const { return scheduledStart; } + bool SetScheduledEnd(string scheduledEnd); + string GetScheduledEnd() const { return scheduledEnd; } + +private: + + PropertyMap properties; + ResourceList resources; + + string objectID; + string parentID; + string title; + string upnpClass; + bool restricted; + string description; + string longDescription; + string date; + string language; + int channelNr; + string channelName; + string scheduledStart; + string scheduledEnd; + +}; + +#define UPNP_REGISTER_RESOURCE_PROVIDER(cls) extern "C" void *UPnPCreateResourceProvider(void) { return new cls; } + +class cUPnPResourceProvider { +public: + + typedef list<string> EntryList; + + virtual ~cUPnPResourceProvider(){}; + + /** + * Returns the schema of this provider + * + * Each provider provides a specific uri schema. This + * is required to distinguish the different kind of file + * types and resource types. + * + * This can be for instance (without ://): + * + * Schema Description + * vdr:// external http stream + * rec:// recording + * file:// any other file, which is not managed by the vdr or the upnp plugin + * + */ + virtual string ProvidesSchema() = 0; + + /** + * Returns the root container of the provider. + * + * This function is used to determine the root of the provider. + * The returned string is prepended to every uri. + * + * This results in the following uri: + * + * <schema>://<rootContainer>/<path>... + */ + virtual string GetRootContainer() = 0; + + /** + * Return a list of the elements in a container. + * + * This function returns a list of elements in a container. + * Each element will be checked by the plugin manager, if it is + * an item or another container. + * + * If an element is a container, the manager will append the + * element to the URI and creates a new call to this function + * to recurse through the directory tree. + * + * The implementor MUST skip entries, which redirects to the + * parent container or itself, i.e. containers like "." and "..". + * + * Additionally, link loops MUST be avoided as much as possible. + * The plugin manager will try to detect a loop. However, you + * should not use links. + * + * The given URI is an absolute URI. + */ + virtual EntryList GetContainerEntries(string uri) = 0; + + /** + * Checks if the given URI is a container. + * + * This function is used by the plugin manager to check if + * the given absolute URI is a container or not. + * + * If it is a container, the plugin manager will try to recurse + * into that directory and get the elements of it. + */ + virtual bool IsContainer(string uri) = 0; + + /** + * Checks if the given URI is a link to another element. + * + * The plugin manager uses this function in conjuction with + * the IsContainer() function to iterate and recurse through + * the tree. If a link directs to a container (IsContainer() + * return true), then the plugin manager tries to detect + * loops. + * + * If target is not empty, the target is evaluated and + * registered as a reference to the original element. Otherwise + * the element is skipped. + */ + virtual bool IsLink(string uri, string& target) = 0; + + /** + * Returns the containerUpdateId of the given container + * + * This function called every time a container gets evaluated. + * + * This happens at the start of the media server and on every + * change to that container. + * + * This function MUST return an identifier, which enables the + * plugin manager to distinguish a change of a container. + * + * The identifier MUST overcome restarts. If the container was + * not changes after a restart of the server, the identifier + * must be equal to the one returned before the server was + * restarted. If the container was changed, the identifier must + * be greater than the previous one. The identifier must not + * decrease in the scope of an unsigned integer, as this may + * cause clients which were offline for some time to get + * confused, if the elements differ though the updateId remains + * the same. + */ + virtual long GetContainerUpdateId(string uri) = 0; + + /** + * Returns the meta data of a specific container. + * + * This function is used to retrieve meta informatio about a + * container. It is NOT used to get information about files or + * resources, as this is done by the media plugins. + * + * However, a resource provider may override this function + * to add more detailed information about a specific container, + * for instance if it is a special container like a photo album. + * + * The implementor is requested to return meta information about + * the resource provider like title or description when called + * with the root container uri. + * + * The default implementation will fill the required meta data + * properties with the best matching information, i.e: + * + * - Class: object.container + * - Title: the element name + * - Restricted: true + * + */ + virtual cMetadata* GetMetadata(string uri); + + /** + * Get the HTTP Uri. + * + * This function returns the HTTP Uri if the stream is accessible + * from an external server via HTTP. + * + * The resource MUST be located in the same network than the server. + * + * This function returns an empty string by default, which means + * that the resource provider uses internal access via the file + * access function Open(), Read(), Close(). + * + * The implementor of a resource provider MUST either implement + * this function or the file access methods below. + */ + virtual string GetHTTPUri(string uri); + + /** + * Opens a resource + * + * If the resource provider uses internal file access it MUST + * implement the file access methods Open(), i.e. this one, Read() + * and Close(). + * + * This opens the given uri and prepares the provider to read + * from the file. If there is an error while opening the resource, + * it must return false. + * + * The default implementation return false. + */ + virtual bool Open(string uri); + + /** + * Reads data from the stream + * + * This functions reads up to "buflen" number the number of bytes + * into the buffer and returns the actual number of bytes read. + * + * If there was an error while reading the function MUST return -1. + * This also applies to when there was no Open() call before reading. + * + * If the resource provider reached end of file, it MUST return 0. + * + * The default implementation return 0. + */ + virtual size_t Read(char* buf, size_t bufLen); + + /** + * Closes the file + * + * This function closes the file opened by Open(). It MUST free all + * acquired memory resources. + * + */ + virtual void Close(); + +protected: + + /** + * Called whenever a container was changed. + * + * This function MUST be called by a resource provider whenever + * a container was changed during the runtime of the server. + * + * The containerUpdateId must equal to the one returned by + * GetContainerUpdateId() with the same URI. This means, + * if the provider detected a change of a container, this function + * is called. Then, the plugin manager might call + * GetContainerUpdateId() with the URI to retrieve the Id again. + * + * The following rules MUST be applied: + * + * - A change must be signaled if a file or directory was + * - created + * - modified + * - deleted + * - moved + * - If a file or directory was created, the parent container + * URI was changed. Therefore, this URI is signaled with + * an appropriate updateID. + * - If a file was modified, the parent container must be + * signaled. + * - A file is modified, when its contents or metadata have + * changed. + * - If a container was modified, the container itself must be + * signaled. The parent container is kept untouched. + * - If a file or container was deleted, the parent container + * must be signaled. + * - If a file or container is moved, two changes must be + * signaled: + * - change of the parent container, where the file or container + * was moved from + * - change of the parent container, where the file or container + * was moved to + */ + void OnContainerUpdate(string uri, long containerUpdateId); + +}; + +#define UPNP_REGISTER_MEDIA_PLUGIN(cls) extern "C" void *UPnPCreateMediaProfiler(void) { return new cls; } + +class cMediaProfiler { +public: + + virtual ~cMediaProfiler(){}; + + /** + * Tell the manager if this plugin can handle a specific uri schema + * + * This function gets called by the plugin manager multiple times to check + * if the plugin can handle a specific uri schema. + * + * This can be for instance (without ://): + * + * Schema Description + * vdr:// live-tv stream + * rec:// recording + * file:// any other file, which is not managed by the vdr or the upnp plugin + * + * The plugin must reject all but the schemas it is capable of. + * + * @return \b true if the plugin can handle the uri schema, \b false if not. + */ + virtual bool CanHandleSchema(string schema) = 0; + + /** + * Get the metadata from a specific resource. + * + * This function is called by the plugin manager when the manager scans for + * files in a container. The implementor must create and fill a mediaResource + * object which contains all information about the resource. + * + * If the plugin is not able to fill the required information about the resource, + * it MUST return NULL. The plugin manager will then rotate through all the + * registered plugins until it finds a suitable one. + * + * The required information MUST be set in the cMediaResource::Create function + * correctly. Otherwise the object creation might fail and a NULL pointer will + * be returned. + * + * Additionally, a plugin implementor is advised to add as many as possible + * metadata about a resource. Especially, information about the contents might + * help the user. + * + * The URI is a absolute path to the resource. + * + * The plugin manager tries to reduce the calls of the resources as much as + * possible. It will only requests new information, if the resource was + * changed. + * + * A change of a resource is indicated by the resource provider. + * + * @param uri the absolute path to the resource. + * @return the media resource information. + */ + virtual cMetadata* GetMetadata(string uri) = 0; +protected: +}; + +} // namespace upnp + +#endif /* PLUGIN_H_ */ diff --git a/include/plugin.h.txt b/include/plugin.h.txt new file mode 100644 index 0000000..d4bb970 --- /dev/null +++ b/include/plugin.h.txt @@ -0,0 +1,486 @@ +/* + * plugin.h + * + * Created on: 31.08.2012 + * Author: savop + */ + +#ifndef PLUGIN_H_ +#define PLUGIN_H_ + +#include <string> +#include <map> +#include <list> + +using namespace std; + +namespace upnp { + +/** + * Metadata class + * + * This class describes the content of a multimedia item like a video or audio file. + * + * It contains some general information like the title or a detailed description of + * the content and one or more resources to the file. + * + * Why are multiple resources possible, though I just have that one file? Lets say, + * you want to display images. It is very useful if there are thumbnail pictures + * available, which may speed up the display process as the UPnP media renderer may + * first display those thumbnails rather than the huge image itself. Those images + * both refer to the same meta information. However, they have different resource + * information. This may also apply to videos (different resolution, bit rate, + * whatever...) + * + * Every plugin implementor is requested to add as much as available information about + * a resource, because the media renderer may display them in their user interface, + * which in turn makes the navigation and identifying the contents much easier. + * + * The metadata class itself offers some major properties, which are very common in + * the VDRs context. However, the implementor may add additional custom information + * to the list of properties. + * + * A Property with the same name but different value may exist multiple times. It is + * added multiple times to the output. Property attributes are NOT supported. However, + * there only a handful of attributes, which are likely to be unimportant. + * + */ +class cMetadata { +public: + + /** + * Property class + * + * This is a basic key-value class, which holds a property (the key) + * and a value. The value is kept in a string representation. There + * is a set of getter methods to convert the string in to the corresponding + * data type. However, there is no type safety given. The implementor + * must know what the contents of the properties are. + */ + class Property { + public: + Property(){}; + Property(string key, string value); + Property(string key, long value); + Property(string key, bool value); + + /** + * Returns the string representation of the value. + */ + string operator()() const; + + string GetKey() const; + string GetString() const; + long GetInteger() const; + bool GetBoolean() const; + + private: + string key; + string value; + }; + + /** + * Resource class + * + * The resource class contains information about a specific resource. + * + * Most of the information are optional except the protocolInfo and the + * resourceUri. + * + * The resourceUri is the locator to the file or stream or whatever. The uri + * is provided by the resourceProvider plugins and must be understood by the + * mediaProfiler plugins. + */ + class Resource { + public: + + bool SetResourceUri(string resourceUri); + bool SetProtocolInfo(string protocolInfo); + bool SetDuration(string duration); + bool SetResolution(string resolution); + bool SetBitrate(uint32_t bitrate); + bool SetSize(uint32_t size); + bool SetSampleFrequency(uint32_t sampleFrequency); + bool SetBitsPerSample(uint32_t bitsPerSample); + bool SetNrAudioChannels(uint32_t nrAudioChannels); + bool SetColorDepth(uint32_t colorDepth); + + string GetResourceUri() const { return resourceUri; } + string GetProtocolInfo() const { return protocolInfo; } + string GetDuration() const { return duration; } + string GetResolution() const { return resolution; } + uint32_t GetBitrate() const { return bitrate; } + uint32_t GetSize() const { return size; } + uint32_t GetSampleFrequency() const { return sampleFrequency; } + uint32_t GetBitsPerSample() const { return bitsPerSample; } + uint32_t GetNrAudioChannels() const { return nrAudioChannels; } + uint32_t GetColorDepth() const { return colorDepth; } + + private: + string resourceUri; + string protocolInfo; + string duration; + string resolution; + uint32_t bitrate; + uint32_t size; + uint32_t sampleFrequency; + uint32_t bitsPerSample; + uint32_t nrAudioChannels; + uint32_t colorDepth; + }; + + typedef multimap<string, Property> PropertyMap; + typedef pair<PropertyMap::iterator,PropertyMap::iterator> PropertyRange; + typedef list<Resource> ResourceList; + + bool AddProperty(Property property); + bool SetProperty(Property property, int index = 0); + + Property& GetPropertyByKey(string property); + PropertyRange GetPropertiesByKey(string property); + PropertyRange GetAllProperties(); + + bool SetObjectID(string objectID); + string GetObjectID() const { return objectID; } + bool SetParentID(string parentID); + string GetParentID() const { return parentID; } + bool SetTitle(string title); + string GetTitle() const { return title; } + bool SetUpnpClass(string upnpClass); + string GetUpnpClass() const { return upnpClass; } + bool SetRestricted(bool restricted); + bool GetRestricted() const { return restricted; } + bool SetDescription(string description); + string GetDescription() const { return description; } + bool SetLongDescription(string longDescription); + string GetLongDescription() const { return longDescription; } + bool SetDate(string date); + string GetDate() const { return date; } + bool SetLanguage(string language); + string GetLanguage() const { return language; } + bool SetChannelNr(int channelNr); + int GetChannelNr() const { return channelNr; } + bool SetChannelName(string channelName); + string GetChannelName() const { return channelName; } + bool SetScheduledStart(string scheduledStart); + string GetScheduledStart() const { return scheduledStart; } + bool SetScheduledEnd(string scheduledEnd); + string GetScheduledEnd() const { return scheduledEnd; } + +private: + + PropertyMap properties; + ResourceList resources; + + string objectID; + string parentID; + string title; + string upnpClass; + bool restricted; + string description; + string longDescription; + string date; + string language; + int channelNr; + string channelName; + string scheduledStart; + string scheduledEnd; + +}; + +#define UPNP_REGISTER_RESOURCE_PROVIDER(cls) extern "C" void *UPnPCreateResourceProvider(void) { return new cls; } + +class cUPnPResourceProvider { +public: + + typedef list<string> EntryList; + + virtual ~cUPnPResourceProvider(){}; + + /** + * Returns the schema of this provider + * + * Each provider provides a specific uri schema. This + * is required to distinguish the different kind of file + * types and resource types. + * + * This can be for instance (without ://): + * + * Schema Description + * vdr:// external http stream + * rec:// recording + * file:// any other file, which is not managed by the vdr or the upnp plugin + * + */ + virtual string ProvidesSchema() = 0; + + /** + * Returns the root container of the provider. + * + * This function is used to determine the root of the provider. + * The returned string is prepended to every uri. + * + * This results in the following uri: + * + * <schema>://<rootContainer>/<path>... + */ + virtual string GetRootContainer() = 0; + + /** + * Return a list of the elements in a container. + * + * This function returns a list of elements in a container. + * Each element will be checked by the plugin manager, if it is + * an item or another container. + * + * If an element is a container, the manager will append the + * element to the URI and creates a new call to this function + * to recurse through the directory tree. + * + * The implementor MUST skip entries, which redirects to the + * parent container or itself, i.e. containers like "." and "..". + * + * Additionally, link loops MUST be avoided as much as possible. + * The plugin manager will try to detect a loop. However, you + * should not use links. + * + * The given URI is an absolute URI. + */ + virtual EntryList GetContainerEntries(string uri) = 0; + + /** + * Checks if the given URI is a container. + * + * This function is used by the plugin manager to check if + * the given absolute URI is a container or not. + * + * If it is a container, the plugin manager will try to recurse + * into that directory and get the elements of it. + */ + virtual bool IsContainer(string uri) = 0; + + /** + * Checks if the given URI is a link to another element. + * + * The plugin manager uses this function in conjuction with + * the IsContainer() function to iterate and recurse through + * the tree. If a link directs to a container (IsContainer() + * return true), then the plugin manager tries to detect + * loops. + * + * If target is not empty, the target is evaluated and + * registered as a reference to the original element. Otherwise + * the element is skipped. + */ + virtual bool IsLink(string uri, string& target) = 0; + + /** + * Returns the containerUpdateId of the given container + * + * This function called every time a container gets evaluated. + * + * This happens at the start of the media server and on every + * change to that container. + * + * This function MUST return an identifier, which enables the + * plugin manager to distinguish a change of a container. + * + * The identifier MUST overcome restarts. If the container was + * not changes after a restart of the server, the identifier + * must be equal to the one returned before the server was + * restarted. If the container was changed, the identifier must + * be greater than the previous one. The identifier must not + * decrease in the scope of an unsigned integer, as this may + * cause clients which were offline for some time to get + * confused, if the elements differ though the updateId remains + * the same. + */ + virtual long GetContainerUpdateId(string uri) = 0; + + /** + * Returns the meta data of a specific container. + * + * This function is used to retrieve meta informatio about a + * container. It is NOT used to get information about files or + * resources, as this is done by the media plugins. + * + * However, a resource provider may override this function + * to add more detailed information about a specific container, + * for instance if it is a special container like a photo album. + * + * The implementor is requested to return meta information about + * the resource provider like title or description when called + * with the root container uri. + * + * The default implementation will fill the required meta data + * properties with the best matching information, i.e: + * + * - Class: object.container + * - Title: the element name + * - Restricted: true + * + */ + virtual cMetadata* GetMetadata(string uri); + + /** + * Get the HTTP Uri. + * + * This function returns the HTTP Uri if the stream is accessible + * from an external server via HTTP. + * + * The resource MUST be located in the same network than the server. + * + * This function returns an empty string by default, which means + * that the resource provider uses internal access via the file + * access function Open(), Read(), Close(). + * + * The implementor of a resource provider MUST either implement + * this function or the file access methods below. + */ + virtual string GetHTTPUri(string uri); + + /** + * Opens a resource + * + * If the resource provider uses internal file access it MUST + * implement the file access methods Open(), i.e. this one, Read() + * and Close(). + * + * This opens the given uri and prepares the provider to read + * from the file. If there is an error while opening the resource, + * it must return false. + * + * The default implementation return false. + */ + virtual bool Open(string uri); + + /** + * Reads data from the stream + * + * This functions reads up to "buflen" number the number of bytes + * into the buffer and returns the actual number of bytes read. + * + * If there was an error while reading the function MUST return -1. + * This also applies to when there was no Open() call before reading. + * + * If the resource provider reached end of file, it MUST return 0. + * + * The default implementation return 0. + */ + virtual size_t Read(char* buf, size_t bufLen); + + /** + * Closes the file + * + * This function closes the file opened by Open(). It MUST free all + * acquired memory resources. + * + */ + virtual void Close(); + +protected: + + /** + * Called whenever a container was changed. + * + * This function MUST be called by a resource provider whenever + * a container was changed during the runtime of the server. + * + * The containerUpdateId must equal to the one returned by + * GetContainerUpdateId() with the same URI. This means, + * if the provider detected a change of a container, this function + * is called. Then, the plugin manager might call + * GetContainerUpdateId() with the URI to retrieve the Id again. + * + * The following rules MUST be applied: + * + * - A change must be signaled if a file or directory was + * - created + * - modified + * - deleted + * - moved + * - If a file or directory was created, the parent container + * URI was changed. Therefore, this URI is signaled with + * an appropriate updateID. + * - If a file was modified, the parent container must be + * signaled. + * - A file is modified, when its contents or metadata have + * changed. + * - If a container was modified, the container itself must be + * signaled. The parent container is kept untouched. + * - If a file or container was deleted, the parent container + * must be signaled. + * - If a file or container is moved, two changes must be + * signaled: + * - change of the parent container, where the file or container + * was moved from + * - change of the parent container, where the file or container + * was moved to + */ + void OnContainerUpdate(string uri, long containerUpdateId); + +}; + +#define UPNP_REGISTER_MEDIA_PLUGIN(cls) extern "C" void *UPnPCreateMediaProfiler(void) { return new cls; } + +class cMediaProfiler { +public: + + virtual ~cMediaProfiler(){}; + + /** + * Tell the manager if this plugin can handle a specific uri schema + * + * This function gets called by the plugin manager multiple times to check + * if the plugin can handle a specific uri schema. + * + * This can be for instance (without ://): + * + * Schema Description + * vdr:// live-tv stream + * rec:// recording + * file:// any other file, which is not managed by the vdr or the upnp plugin + * + * The plugin must reject all but the schemas it is capable of. + * + * @return \b true if the plugin can handle the uri schema, \b false if not. + */ + virtual bool CanHandleSchema(string schema) = 0; + + /** + * Get the metadata from a specific resource. + * + * This function is called by the plugin manager when the manager scans for + * files in a container. The implementor must create and fill a mediaResource + * object which contains all information about the resource. + * + * If the plugin is not able to fill the required information about the resource, + * it MUST return NULL. The plugin manager will then rotate through all the + * registered plugins until it finds a suitable one. + * + * The required information MUST be set in the cMediaResource::Create function + * correctly. Otherwise the object creation might fail and a NULL pointer will + * be returned. + * + * Additionally, a plugin implementor is advised to add as many as possible + * metadata about a resource. Especially, information about the contents might + * help the user. + * + * The URI is a absolute path to the resource. + * + * The plugin manager tries to reduce the calls of the resources as much as + * possible. It will only requests new information, if the resource was + * changed. + * + * A change of a resource is indicated by the resource provider. + * + * @param uri the absolute path to the resource. + * @return the media resource information. + */ + virtual cMetadata* GetMetadata(string uri) = 0; +protected: +}; + +} // namespace upnp + +#endif /* PLUGIN_H_ */ diff --git a/include/pluginManager.h b/include/pluginManager.h new file mode 100644 index 0000000..90ee456 --- /dev/null +++ b/include/pluginManager.h @@ -0,0 +1,20 @@ +/* + * pluginManager.h + * + * Created on: 05.09.2012 + * Author: savop + */ + +#ifndef PLUGINMANAGER_H_ +#define PLUGINMANAGER_H_ + +namespace upnp { + +class cPluginManager { +public: +private: +}; + +} // namespace upnp + +#endif /* PLUGINMANAGER_H_ */ diff --git a/include/server.h b/include/server.h new file mode 100644 index 0000000..03a7524 --- /dev/null +++ b/include/server.h @@ -0,0 +1,110 @@ +/* + * server.h + * + * Created on: 31.07.2012 + * Author: savop + */ + +#ifndef SERVER_H_ +#define SERVER_H_ + +#include <string> +#include <upnp/upnp.h> +#include "../include/webserver.h" +#include "../include/config.h" + +using namespace std; + +namespace upnp { + +class cUPnPService; +class cMediaManager; + +class cMediaServer { +public: + + struct Description { + Description(string, string, string , string, string, string , string, string); + string friendlyName; + string manufacturer; + string manufacturerURL; + string modelDescription; + string modelName; + string modelNumber; + string modelURL; + string serialNumber; + }; + + struct ServerIcon { + ServerIcon(image::cIcon, string); + image::cIcon profile; + string filename; + }; + + typedef map<string, cUPnPService*> serviceMap; + typedef list<ServerIcon> iconList; + + virtual ~cMediaServer(); + + bool Initialize(); + bool Start(); + bool Stop(); + + bool IsRunning() const; + + static cMediaServer* GetInstance(); + + void SetConfiguration(upnp::cConfig newConfig); + upnp::cConfig GetConfiguration() const; + + const char* GetServerIPAddress() const; + uint16_t GetServerPort() const; + + int GetAnnounceMaxAge() const { return mAnnounceMaxAge; } + size_t GetMaxContentLength() const { return mMaxContentLength; } + + const cWebserver& GetWebserver() const { return *mWebserver; } + cMediaManager& GetManager() const { return *mMediaManager; } + + const string GetDeviceUUID() const { return mCurrentConfiguration.deviceUUID; } + + const Description& GetServerDescription() const { return mServerDescription; } + const iconList& GetServerIcons() const { return mServerIcons; } + const serviceMap& GetServices() const { return mServices; } + + static void RegisterService(cUPnPService* service); + +private: + class RuntimeException : public std::exception { + public: + virtual const char* what() const throw(); + }; + + cMediaServer(); + + string GetDeviceDescriptionUrl() const; + void SetAnnounceMaxAge(int announceMaxAge); + void SetMaxContentLength(size_t maxContentLength); + bool CheckDeviceUUID(string deviceUUID) const; + + static int ActionCallback(Upnp_EventType eventtype, void *event, void *cookie); + + Description mServerDescription; + iconList mServerIcons; + upnp::cConfig mCurrentConfiguration; + UpnpDevice_Handle mDeviceHandle; + int mAnnounceMaxAge; + size_t mMaxContentLength; + bool mIsRunning; + + cWebserver* mWebserver; + cMediaManager* mMediaManager; + + static serviceMap mServices; + +}; + +} + + +#endif /* SERVER_H_ */ diff --git a/include/service.h b/include/service.h new file mode 100644 index 0000000..ddcf614 --- /dev/null +++ b/include/service.h @@ -0,0 +1,108 @@ +/* + * service.h + * + * Created on: 27.08.2012 + * Author: savop + */ + +#ifndef SERVICE_H_ +#define SERVICE_H_ + +#include <upnp/upnp.h> +#include <string> + +namespace upnp { + +class cMediaServer; + +class cUPnPService { +public: + + struct Description { + Description(std::string, std::string, std::string, std::string, std::string); + std::string serviceType; + std::string serviceID; + std::string SCPDXML; + std::string controlDescriptor; + std::string eventSubscriberDescriptor; + }; + + cUPnPService(Description serviceDescription); + + virtual ~cUPnPService(); + + virtual void Init(cMediaServer* server, UpnpDevice_Handle deviceHandle); + + virtual int Subscribe( + Upnp_Subscription_Request* Request ///< Information about the subscription + ) = 0; + + virtual int Execute( + Upnp_Action_Request* Request ///< Input and output parameters of an action + ) = 0; + + const Description& GetServiceDescription() const { return mServiceDescription; }; + +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( + IXML_Document* Document, ///< the document, which is parsed + std::string Item, ///< the demanded item + long& 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( + IXML_Document* Document, ///< the document, which is parsed + std::string Item, ///< the demanded item + std::string& Value ///< the value of the item + ); + + cMediaServer* mMediaServer; + UpnpDevice_Handle mDeviceHandle; ///< the UPnP device handle of the root device + Description mServiceDescription; + +}; + +} // namespace upnp + + +#endif /* SERVICE_H_ */ diff --git a/include/tools.h b/include/tools.h new file mode 100644 index 0000000..b12f6be --- /dev/null +++ b/include/tools.h @@ -0,0 +1,162 @@ +/* + * tools.h + * + * Created on: 03.08.2012 + * Author: savop + */ + +#ifndef TOOLS_H_ +#define TOOLS_H_ + +#include <vector> +#include <string> +#include <iostream> +#include <upnp/upnp.h> +#include <string.h> +#include <vdr/tools.h> +#include <map> +#include <list> + +using namespace std; + +#define KB(s) (s * 1024) +#define MB(s) (s * 1024 * 1024) + +#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0])) + +#define CRLF "\r\n" + +#define NL "\n" + +#define att(s) strchr(s,'@')!=NULL?strchr(s,'@')+1:NULL +#define prop(s) substr(s, 0, strchr(s,'@')-s) + +#define MAX_METADATA_LENGTH 1024 + +/** + * 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); + +/**************************************************** + * + * Known Errors + * + ****************************************************/ + +/* Errors 401-404, 501 are already defined in + * Intel SDK, however 403 MUST NOT USED. + */ + +/****** 600 Common Action Errors ******/ + +#define UPNP_SOAP_E_ARGUMENT_INVALID 600 +#define UPNP_SOAP_E_ARGUMENT_OUT_OF_RANGE 601 +#define UPNP_SOAP_E_ACTION_NOT_IMPLEMENTED 602 +#define UPNP_SOAP_E_OUT_OF_MEMORY 603 +#define UPNP_SOAP_E_HUMAN_INTERVENTION 604 +#define UPNP_SOAP_E_STRING_TO_LONG 605 +#define UPNP_SOAP_E_NOT_AUTHORIZED 606 +#define UPNP_SOAP_E_SIGNATURE_FAILURE 607 +#define UPNP_SOAP_E_SIGNATURE_MISSING 608 +#define UPNP_SOAP_E_NOT_ENCRYPTED 609 +#define UPNP_SOAP_E_INVALID_SEQUENCE 610 +#define UPNP_SOAP_E_INVALID_CONTROL_URL 611 +#define UPNP_SOAP_E_NO_SUCH_SESSION 612 + +/****** 700 Action specific Errors ******/ + +#define UPNP_CDS_E_NO_SUCH_OBJECT 701 +#define UPNP_CDS_E_INVALID_CURRENT_TAG 702 +#define UPNP_CDS_E_INVALID_NEW_TAG 703 +#define UPNP_CDS_E_REQUIRED_TAG 704 +#define UPNP_CDS_E_READ_ONLY_TAG 705 +#define UPNP_CDS_E_PARAMETER_MISMATCH 706 +#define UPNP_CDS_E_INVALID_SEARCH_CRITERIA 708 +#define UPNP_CDS_E_INVALID_SORT_CRITERIA 709 +#define UPNP_CDS_E_NO_SUCH_CONTAINER 710 +#define UPNP_CDS_E_RESTRICTED_OBJECT 711 +#define UPNP_CDS_E_BAD_METADATA 712 +#define UPNP_CDS_E_RESTRICTED_PARENT 713 +#define UPNP_CDS_E_NO_SUCH_SOURCE_RESOURCE 714 +#define UPNP_CDS_E_RESOURCE_ACCESS_DENIED 715 +#define UPNP_CDS_E_TRANSFER_BUSY 716 +#define UPNP_CDS_E_NO_SUCH_FILE_TRANSFER 717 +#define UPNP_CDS_E_NO_SUCH_DESTINATION_RESOURCE 718 +#define UPNP_CDS_E_DEST_RESOURCE_ACCESS_DENIED 719 +#define UPNP_CDS_E_CANT_PROCESS_REQUEST 720 + +#define UPNP_CMS_E_INCOMPATIBLE_PROTOCOL_INFO 701 +#define UPNP_CMS_E_INCOMPATIBLE_DIRECTIONS 702 +#define UPNP_CMS_E_INSUFFICIENT_RESOURCES 703 +#define UPNP_CMS_E_LOCAL_RESTRICTIONS 704 +#define UPNP_CMS_E_ACCESS_DENIED 705 +#define UPNP_CMS_E_INVALID_CONNECTION_REFERENCE 706 +#define UPNP_CMS_E_NOT_IN_NETWORK 707 + +namespace upnp { + + typedef std::list<std::string> StringList; + typedef std::map<std::string, uint32_t> IdList; + +namespace tools { + string GetAddressByInterface(string Interface); + string GetNetworkInterfaceByIndex(int Index, bool skipLoop); + vector<string> GetNetworkInterfaces(bool skipLoop); + + string ToString(long number); + + string StringListToCSV(StringList list); + string IdListToCSV(IdList list); + + string GenerateUUIDFromURL(string url); + string GenerateUUIDRandomly(); +} + +namespace ixml { + void XmlEscapeSpecialChars(string& doc); + /** + * 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 error the error code in case of an error + * @param doc the \c IXML document to be parsed + * @param item the item which shall be found + * @param the value of the item + */ + int IxmlGetFirstDocumentItem( IN IXML_Document * doc, IN const string item, string& value ); + /** + * 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 NULL, in case of an error + * - \bc the newly created property node or the node at which the attribute was + * appended to + * @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 + */ + IXML_Element* IxmlAddProperty(IN IXML_Document* document, IN IXML_Element* node, IN const char* upnpproperty, IN const char* value ); + + IXML_Element* IxmlAddFilteredProperty(IN cStringList* Filter, IN IXML_Document* document, IN IXML_Element* node, IN const char* upnpproperty, IN const char* value ); + + IXML_Element* IxmlReplaceProperty(IN IXML_Document* document, IN IXML_Element* node, IN const char* upnpproperty, IN const char* newValue ); +} + +} + +#endif /* TOOLS_H_ */ diff --git a/include/webserver.h b/include/webserver.h new file mode 100644 index 0000000..240d4d6 --- /dev/null +++ b/include/webserver.h @@ -0,0 +1,66 @@ +/* + * webserver.h + * + * Created on: 06.08.2012 + * Author: savop + */ + +#ifndef WEBSERVER_H_ +#define WEBSERVER_H_ + +#include <tnt/tntnet.h> +#include <stdint.h> +#include <string> +#include <vdr/thread.h> + +namespace upnp { + + class cMediaServer; + + class cWebserver { + public: + cWebserver(std::string address); + virtual ~cWebserver(); + + void SetWebserverRootDir(std::string rootDirectory, std::string staticContentUrl, std::string presentationUrl); + void SetServiceUrl(std::string descriptionUrl, std::string controlUrl); + + void SetListenerPort(uint16_t port); + + bool Initialise(); + + bool Start(); + void Stop(); + + const std::string GetBaseUrl() const; + const std::string GetServiceUrl() const; + const std::string GetControlUrl() const; + const std::string GetStaticContentUrl() const; + const std::string GetPresentationUrl() const; + + std::string GetListenerAddress() const { return mListenerAddress; } + uint16_t GetListenerPort() const { return mListenerPort; } + + private: + tnt::Tntnet mApplication; + std::string mWebserverRootDir; + std::string mListenerAddress; + uint16_t mListenerPort; + + std::string mServiceUrl; + std::string mControlUrl; + std::string mStaticContentUrl; + std::string mPresentationUrl; + + class cWSThread : public cThread { + public: + cWSThread(cWebserver& webServer); + virtual void Action(void); + private: + cWebserver& mWebserver; + } mWebserverThread; + }; + +}; + +#endif /* WEBSERVER_H_ */ |