📄 mmscp.c
字号:
#ifdef WIN32#ifdef _DEBUG#define _CRTDBG_MAP_ALLOC#endif#endif#include <stdlib.h>#ifdef WIN32#include <crtdbg.h>#endif#include "MmsCp.h"#include "MSCP_ControlPoint.h"#include "ILibParsers.h"#include "MyString.h"#include <stdio.h>#include <string.h>#include <netinet/in.h>/* #### Begin CARDEA code #### */#define ALLOW_OS_CODE#include "ms_upnp.h"/* #### End CARDEA code #### */#ifndef UNDER_CE#include "assert.h"#else#define stricmp _stricmp#endif#ifdef UNDER_CE#define strnicmp _strnicmp#endif#ifdef _POSIX#define strnicmp strncasecmp#define stricmp strcasecmp#endif#define UNSUPPORTED_BY_CP printf("Action is not supported by this implementation."); ASSERT(1);#define MMSCP_DEVICE_ADDED 1#define MMSCP_DEVICE_REMOVED 0#define MMSCP_BROWSE_FLAG_METADATA_STRING "BrowseMetadata"#define MMSCP_BROWSE_FLAG_CHILDREN_STRING "BrowseDirectChildren"/* CDS normative tag names and attributes */#define MMSCP_ATTRIB_ID "id"#define MMSCP_ATTRIB_PARENTID "parentID"#define MMSCP_ATTRIB_REFID "refID"#define MMSCP_ATTRIB_RESTRICTED "restricted"#define MMSCP_ATTRIB_SEARCHABLE "searchable"#define MMSCP_ATTRIB_PROTOCOLINFO "protocolInfo"#define MMSCP_ATTRIB_RESOLUTION "resolution"#define MMSCP_ATTRIB_DURATION "duration"#define MMSCP_ATTRIB_BITRATE "bitrate"#define MMSCP_ATTRIB_COLORDEPTH "colorDepth"#define MMSCP_ATTRIB_SIZE "size"#define MMSCP_TAG_DIDL "DIDL-Lite"#define MMSCP_TAG_CONTAINER "container"#define MMSCP_TAG_ITEM "item"#define MMSCP_TAG_RESOURCE "res"#define MMSCP_TAG_CREATOR "dc:creator"#define MMSCP_TAG_TITLE "dc:title"#define MMSCP_TAG_MEDIACLASS "upnp:class"#define MMSCP_TAG_GENRE "upnp:genre"#define MMSCP_TAG_ALBUM "upnp:album"#ifdef _DEBUG#define ASSERT(x) assert (x)#define MMSCP_MALLOC(x) malloc(x)//MMSCP_malloc(x)#define MMSCP_FREE(x) free(x)//MMSCP_free(x)#define DEBUGONLY(x) x#else#ifndef UNDER_CE#define ASSERT(x)#endif#define MMSCP_MALLOC(x) malloc(x)#define MMSCP_FREE(x) free(x)#define DEBUGONLY(x)#endif#ifdef _TEMPDEBUG#define TEMPDEBUGONLY(x) x#else#define TEMPDEBUGONLY(x) #endif/*********************************************************************************************************************** * BEGIN: MMSCP static values ***********************************************************************************************************************//* * The relative order of strings within these arrays must correspond to the MMSCP_CLASS_MASK_xxx bitmask mappings. */const char* MMSCP_CLASS_OBJECT_TYPE[] = {"object", "item", "container"};const char* MMSCP_CLASS_MAJOR_TYPE[] = {"", "imageItem", "audioItem", "videoItem", "playlistItem", "textItem", "person", "playlistContainer", "album", "genre", "storageSystem", "storageVolume", "storageFolder"};const char* MMSCP_CLASS_MINOR_TYPE[] = {"", "photo", "musicTrack", "audioBroadcast", "audioBook", "movie", "videoBroadcast", "musicVideClip", "musicArtist", "musicAlbum", "photoAlbum", "musicGenre", "movieGenre"};#define MMSCP_CLASS_FIRST_MAJOR_TYPE MMSCP_CLASS_MASK_MAJOR_IMAGEITEM/* * Maximum length of a string in * MMSCP_CLASS_OBJECT_TYPE, MMSCP_CLASS_MAJOR_TYPE, and MMSCP_CLASS_MINOR_TYPE. * Size includes null terminator. */#define MMSCP_MAX_CLASS_FRAGMENT_LEN 17#define MMSCP_MAX_CLASS_FRAGMENT_SIZE 18#define MIN(X, Y) ((X) < (Y) ? (X) : (Y))/* * These are the types of strings that can be searched. */enum MMSCP_SearchableStringTypes{ MMSCP_STRTYPE_ID, MMSCP_STRTYPE_CREATOR, MMSCP_STRTYPE_PROTOCOLINFO};const char* MMSCP_TRUE_STRINGS[] = {"1", "true", "yes"};const char* MMSCP_FALSE_STRINGS[] = {"0", "false", "no"};#define MMSCP_TRUE_STRINGS_LEN 3#define MMSCP_FALSE_STRINGS_LEN 3/*********************************************************************************************************************** * END: MMSCP static values ***********************************************************************************************************************//*********************************************************************************************************************** * BEGIN: MMSCP state variables ***********************************************************************************************************************//* Function pointer for sending Browse results back to caller */MMSCP_Fn_Result_Browse MMSCP_Callback_Browse;MMSCP_Fn_Device_AddRemove MMSCP_Callback_DeviceAddRemove;int MMSCP_malloc_counter = 0;/*********************************************************************************************************************** * END: MMSCP state variables ***********************************************************************************************************************//*********************************************************************************************************************** * BEGIN: Helper methods ***********************************************************************************************************************//* TODO: debug malloc/MMSCP_FREE is not thread safe */#ifdef _DEBUG/*static void* MMSCP_malloc(int sz){ ++MMSCP_malloc_counter; return((void*)malloc(sz));}*//*static void MMSCP_free(void* ptr){ --MMSCP_malloc_counter; free(ptr); }*//*static int MMSCP_malloc_GetCount(){ return(MMSCP_malloc_counter);}*/#endif/* * Copies bytes from copyFrom to copyHere. * Will not copy more than copyMaxChars bytes. * Stops copying when ., <, null, or " char is found. */static void MMSCP_CopyUntilClassFragmentTerminator(char *copyHere, const char *copyFrom, int copyMaxChars){ int i; char c; for (i=0; i < copyMaxChars; i++) { c = copyFrom[i]; if (c == '.' || c == '<' || c == '\0' || c == '"') { copyHere[i] = '\0'; return; } else { copyHere[i] = c; } }}/* * Given an array of strings, finds the index in that array with a matching string. */static int MMSCP_FindStringInArray(const char* str,const char** strarray,const int strarraylen){ int i; for (i=0;i<strarraylen;i++) {if (stricmp(str,strarray[i]) == 0) {return i;}} return -1;}/* * Sets things up so that pointer-based data for an MMSCP_MediaObject is properly stored in the * trailing data blocks that follow the struct itself. * * fixThis : The string-based field on the CDS object that needs to be fixed so * : that it points to somewhere in the data blocks that follow the the portion * : allocated for the MMSCP_MediaObject. * * di : This is a pointer to the data block that follows the MMSCP_MediaObject. * : This points to the location where the string needs to be stored. * * data : This is the data that needs to be copied. * * rangeStart/rangeEnd : If the location of 'data' is not within [rangeStart,rangeEnd], then * : it means that 'data' is effectively a static string. 'fixThis' will * : point to that static string. */static void MMSCP_StringFixup(char **fixThis, char** di, char *emptyStr, const char *data, const char *rangeStart, const char *rangeEnd){ int len; if (data != NULL) { if ((rangeStart <= data) && (data <= rangeEnd)) { /* store an XML-unescaped representation */ *fixThis = *di; len = (int) strlen(data); memcpy(*di, data, len); ILibInPlaceXmlUnEscape(*di); *di = *di + len + 1; } else { *fixThis = (char*)data; } } else { *fixThis = emptyStr; }}/* * Calculates the number of bytes needed to store the string data for the CDS object. * * obj : this is the CDS object that has data values * obj2 : Deprecated. Use NULL. * : An older implementation of MMSCP used a single shared memory block * : for all CDS objects in a set of results. Unfortunately, this made it * : impossible to individual CDS objects within a list. Developers had * : to deallocate the entire list. By sending NULL, you force the method * : to increment the size needed for data. * : * : By sending a non-NULL value for this param, you allow this method * : to assign a field on 'obj' to point to the same data that the * : corresponding field on 'obj2' is pointing to (assuming the data values * : are the same). */static int MMSCP_GetRequiredSizeForMediaObject(struct MMSCP_MediaObject *obj, struct MMSCP_MediaObject *obj2){ int retVal; struct MMSCP_MediaResource *res; struct MMSCP_MediaResource *res2; unsigned char addProtInfo; unsigned char addResolution; struct MMSCP_MediaResource *resProt; struct MMSCP_MediaResource *resRes; retVal = 0; /* * For most fields, the pattern is simple. * -check for non-null on the desired field (on obj) * -if obj2 is specified and the fields on obj and obj2 match, then * assign obj's field will point to the same data that obj2 is * pointing to. * -else increment retVal by the size needed to store the field on obj. * Be sure to add 1 for NULL terminator. */ if (obj->ID != NULL) { retVal += ((int) strlen(obj->ID) +1); } if (obj->ParentID != NULL) { if ((obj2 != NULL) && (strcmp(obj2->ParentID, obj->ParentID) == 0)) { obj->ParentID = obj2->ParentID; } else { retVal += ((int) strlen(obj->ParentID) +1); } } if (obj->RefID != NULL) { retVal += ((int) strlen(obj->RefID) +1); } if (obj->Title != NULL) { retVal += ((int) strlen(obj->Title) +1); } if (obj->Creator != NULL) { if ((obj2 != NULL) && (strcmp(obj2->Creator, obj->Creator) == 0)) { obj->Creator = obj2->Creator; } else { retVal += ((int) strlen(obj->Creator) +1); } } if (obj->Genre != NULL) { if ((obj2 != NULL) && (strcmp(obj2->Genre, obj->Genre) == 0)) { obj->Genre = obj2->Genre; } else { retVal += ((int) strlen(obj->Genre) +1); } } if (obj->Album != NULL) { if ((obj2 != NULL) && (strcmp(obj2->Album, obj->Album) == 0)) { obj->Album = obj2->Album; } else { retVal += ((int) strlen(obj->Album) +1); } } /* * The pattern for <res> elements is as follows. * -Enumerate through each <res> element * -determine if we need to allocate memory for each res attribute (i.e. non-NULL value) * -Enumerate through previous <res> elements in our list * -if the res attribute matches a previous value, * then we don't need to allocate additional memory for the field * -if we determine that we need to allocate additional memory, then increase retVal by the * necessary amount. */ res = obj->Res; res2 = NULL; while (res != NULL) { //if (res->ProtocolInfo != NULL) /* determine whether we need to store data for the attributes */ addProtInfo = (res->ProtocolInfo != NULL); addResolution = (res->Resolution != NULL); { if (obj2 != NULL) { res2 = obj2->Res; } resProt = NULL; resRes = NULL; while (res2 != NULL) { if (addProtInfo && (res2->ProtocolInfo != NULL) && (strcmp(res2->ProtocolInfo, res->ProtocolInfo) == 0)) { addProtInfo = 0; resProt = res2; } if (addResolution && (res2->Resolution != NULL) && (strcmp(res2->Resolution, res->Resolution) == 0)) { addResolution = 0; resRes = res2; } if ((addProtInfo != 0) || (addResolution != 0)) { res2 = res2->Next; } else { res2 = NULL; } } if (addProtInfo != 0) { retVal += ((int) strlen(res->ProtocolInfo) +1); } else if (resProt != NULL) { res->ProtocolInfo = resProt->ProtocolInfo; } if (addResolution != 0) { retVal += ((int) strlen(res->Resolution) +1); } else if (resRes != NULL) { res->Resolution = resRes->Resolution; } } if (res->Uri != NULL) { retVal += ((int) strlen(res->Uri) +1);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -