summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
Diffstat (limited to 'include')
-rw-r--r--include/config.h126
-rw-r--r--include/connection.h84
-rw-r--r--include/connectionManager.h70
-rw-r--r--include/contentDirectory.h58
-rw-r--r--include/media/mediaManager.h87
-rw-r--r--include/media/profile.h50
-rw-r--r--include/plugin.h484
-rw-r--r--include/plugin.h.txt486
-rw-r--r--include/pluginManager.h20
-rw-r--r--include/server.h110
-rw-r--r--include/service.h108
-rw-r--r--include/tools.h162
-rw-r--r--include/webserver.h66
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_ */