📄 upnp_tv_ctrlpt.c
字号:
* TvCtrlPointAddDevice * * Description: * If the device is not already included in the global device list, * add it. Otherwise, update its advertisement expiration timeout. * * Parameters: * DescDoc -- The description document for the device * location -- The location of the description document URL * expires -- The expiration time for this advertisement * ********************************************************************************/void TvCtrlPointAddDevice (Upnp_Document DescDoc, char *location, int expires) { char *deviceType=NULL; char *friendlyName=NULL; char presURL[200]; char *baseURL=NULL; char *relURL=NULL; char *UDN=NULL; char *serviceId[TV_SERVICE_SERVCOUNT] = {NULL, NULL}; char *eventURL[TV_SERVICE_SERVCOUNT] = {NULL, NULL}; char *controlURL[TV_SERVICE_SERVCOUNT] = {NULL, NULL}; Upnp_SID eventSID[TV_SERVICE_SERVCOUNT]; int TimeOut[TV_SERVICE_SERVCOUNT] = {default_timeout, default_timeout}; struct TvDeviceNode *deviceNode; struct TvDeviceNode *tmpdevnode; int ret=1; int found=0; int service, var; pthread_mutex_lock(&DeviceListMutex); /* Read key elements from description document */ UDN = SampleUtil_GetFirstDocumentItem(DescDoc, "UDN"); deviceType = SampleUtil_GetFirstDocumentItem(DescDoc, "deviceType"); friendlyName = SampleUtil_GetFirstDocumentItem(DescDoc, "friendlyName"); baseURL = SampleUtil_GetFirstDocumentItem(DescDoc, "URLBase"); relURL = SampleUtil_GetFirstDocumentItem(DescDoc, "presentationURL"); if (baseURL) ret = UpnpResolveURL(baseURL, relURL, presURL); else ret = UpnpResolveURL(location, relURL, presURL); if (ret!=UPNP_E_SUCCESS) printf("Error generating presURL from %s + %s\n", baseURL, relURL); if (strcmp(deviceType, TvDeviceType) == 0) { printf("Found Tv device!!!\n"); // Check if this device is already in the list tmpdevnode = GlobalDeviceList; while (tmpdevnode) { if (strcmp(tmpdevnode->device.UDN,UDN) == 0) { found=1; break; } tmpdevnode = tmpdevnode->next; } if (found) { // The device is already there, so just update // the advertisement timeout field tmpdevnode->device.AdvrTimeOut = expires; } else { for (service = 0; service<TV_SERVICE_SERVCOUNT; service++) { if (SampleUtil_FindAndParseService(DescDoc, location, TvServiceType[service], &serviceId[service], &eventURL[service], &controlURL[service])) { printf("Subscribing to EventURL %s...\n", eventURL[service]); ret=UpnpSubscribe(ctrlpt_handle,eventURL[service], &TimeOut[service],eventSID[service]); if (ret==UPNP_E_SUCCESS) { printf("Subscribed to EventURL with SID=%s\n", eventSID[service]); } else { printf("Error Subscribing to EventURL -- %d\n", ret); strcpy(eventSID[service], ""); } } else { printf("Error: Could not find Service: %s\n", TvServiceType[service]); } } /* Create a new device node */ deviceNode = (struct TvDeviceNode *) malloc (sizeof(struct TvDeviceNode)); strcpy(deviceNode->device.UDN, UDN); strcpy(deviceNode->device.DescDocURL, location); strcpy(deviceNode->device.FriendlyName, friendlyName); strcpy(deviceNode->device.PresURL, presURL); deviceNode->device.AdvrTimeOut = expires; for (service = 0; service<TV_SERVICE_SERVCOUNT; service++) { strcpy(deviceNode->device.TvService[service].ServiceId, serviceId[service]); strcpy(deviceNode->device.TvService[service].ServiceType, TvServiceType[service]); strcpy(deviceNode->device.TvService[service].ControlURL, controlURL[service]); strcpy(deviceNode->device.TvService[service].EventURL, eventURL[service]); strcpy(deviceNode->device.TvService[service].SID, eventSID[service]); for (var = 0; var < TvVarCount[service]; var++) { deviceNode->device.TvService[service].VariableStrVal[var] = (char *) malloc (TV_MAX_VAL_LEN); strcpy(deviceNode->device.TvService[service].VariableStrVal[var], ""); } } deviceNode->next = NULL; // Insert the new device node in the list if ((tmpdevnode = GlobalDeviceList)) { while (tmpdevnode) { if (tmpdevnode->next) { tmpdevnode = tmpdevnode->next; } else { tmpdevnode->next = deviceNode; break; } } } else { GlobalDeviceList = deviceNode; } } } pthread_mutex_unlock(&DeviceListMutex); if (deviceType) free(deviceType); if (friendlyName) free(friendlyName); if (UDN) free(UDN); if (baseURL) free(baseURL); if (relURL) free(relURL); for (service = 0; service<TV_SERVICE_SERVCOUNT; service++) { if (serviceId[service]) free(serviceId[service]); if (controlURL[service]) free(controlURL[service]); if (eventURL[service]) free(eventURL[service]); }}/******************************************************************************** * TvStateUpdate * * Description: * Update a Tv state table. Called when an event is * received. Note: this function is NOT thread save. It must be * called from another function that has locked the global device list. * * Parameters: * Service -- The service state table to update * ChangedVariables -- DOM document representing the XML received * with the event * State -- pointer to the state table for the Tv service * to update * ********************************************************************************/void TvStateUpdate(int Service, Upnp_Document ChangedVariables, char **State){ Upnp_NodeList properties; Upnp_NodeList variables; int length; int length1; int i; Upnp_Node property; Upnp_Node variable; int j; char *tmpstate=NULL; printf("Tv State Update:\n"); /* Find all of the e:property tags in the document */ properties=UpnpDocument_getElementsByTagName(ChangedVariables, "e:property"); if (properties!=NULL) { length= UpnpNodeList_getLength(properties); /* Loop through each property change found */ for (i=0;i<(length);i++) { property = UpnpNodeList_item(properties,i); /* For each variable name in the state table, check if this is a corresponding property change */ for (j=0;j<TvVarCount[Service];j++) { variables= UpnpElement_getElementsByTagName(property, TvVarName[Service][j]); /* If a match is found, extract the value, and update the state table */ if (variables) { length1= UpnpNodeList_getLength(variables); if (length1) { variable=UpnpNodeList_item(variables,0); tmpstate=SampleUtil_GetElementValue(variable); if (tmpstate) { strcpy(State[j], tmpstate); printf("\tVariable Name: %s New Value:'%s'\n", TvVarName[Service][j],State[j]); } UpnpNode_free(variable); variable=NULL; if (tmpstate) free(tmpstate); tmpstate=NULL; } UpnpNodeList_free(variables); variables=NULL; } } UpnpNode_free(property); } UpnpNodeList_free(properties); } }/******************************************************************************** * TvCtrlPointHandleEvent * * Description: * Handle a UPnP event that was received. Process the event and update * the appropriate service state table. * * Parameters: * sid -- The subscription id for the event * eventkey -- The eventkey number for the event * changes -- The DOM document representing the changes * ********************************************************************************/void TvCtrlPointHandleEvent(Upnp_SID sid, int evntkey, Upnp_Document changes) { struct TvDeviceNode *tmpdevnode; int service; pthread_mutex_lock(&DeviceListMutex); tmpdevnode = GlobalDeviceList; while (tmpdevnode) { for (service=0; service<TV_SERVICE_SERVCOUNT; service++) { if (strcmp(tmpdevnode->device.TvService[service].SID,sid) == 0) { printf("Received Tv %s Event: %d for SID %s\n", TvServiceName[service], evntkey, sid); TvStateUpdate(service,changes,(char **)&tmpdevnode->device.TvService[service].VariableStrVal); break; } } tmpdevnode = tmpdevnode->next; } pthread_mutex_unlock(&DeviceListMutex);}/******************************************************************************** * TvCtrlPointHandleSubscribeUpdate * * Description: * Handle a UPnP subscription update that was received. Find the * service the update belongs to, and update its subscription * timeout. * * Parameters: * eventURL -- The event URL for the subscription * sid -- The subscription id for the subscription * timeout -- The new timeout for the subscription * ********************************************************************************/void TvCtrlPointHandleSubscribeUpdate(char *eventURL, Upnp_SID sid, int timeout) { struct TvDeviceNode *tmpdevnode; int service; pthread_mutex_lock(&DeviceListMutex); tmpdevnode = GlobalDeviceList; while (tmpdevnode) { for (service = 0; service<TV_SERVICE_SERVCOUNT; service++) { if (strcmp(tmpdevnode->device.TvService[service].EventURL,eventURL) == 0) { printf("Received Tv %s Event Renewal for eventURL %s\n", TvServiceName[service], eventURL); strcpy(tmpdevnode->device.TvService[service].SID, sid); break; } } tmpdevnode = tmpdevnode->next; } pthread_mutex_unlock(&DeviceListMutex);}/******************************************************************************** * TvCtrlPointCallbackEventHandler * * Description: * The callback handler registered with the SDK while registering * the control point. Detects the type of callback, and passes the * request on to the appropriate function. * * Parameters: * EventType -- The type of callback event * Event -- Data structure containing event data * Cookie -- Optional data specified during callback registration * ********************************************************************************/int TvCtrlPointCallbackEventHandler(Upnp_EventType EventType, void *Event, void *Cookie){ SampleUtil_PrintEvent(EventType, Event); switch ( EventType) { /* SSDP Stuff */ case UPNP_DISCOVERY_ADVERTISEMENT_ALIVE: case UPNP_DISCOVERY_SEARCH_RESULT: { struct Upnp_Discovery *d_event = (struct Upnp_Discovery * ) Event; Upnp_Document DescDoc=NULL; int ret; if (d_event->ErrCode != UPNP_E_SUCCESS) printf("Error in Discovery Callback -- %d\n", d_event->ErrCode); if ((ret=UpnpDownloadXmlDoc(d_event->Location, &DescDoc)) != UPNP_E_SUCCESS) { printf("Error obtaining device description from %s -- error = %d\n", d_event->Location, ret ); } else { TvCtrlPointAddDevice(DescDoc, d_event->Location, d_event->Expires); } if (DescDoc) UpnpDocument_free(DescDoc); TvCtrlPointPrintList(); } break; case UPNP_DISCOVERY_SEARCH_TIMEOUT: /* Nothing to do here... */ break; case UPNP_DISCOVERY_ADVERTISEMENT_BYEBYE: { struct Upnp_Discovery *d_event = (struct Upnp_Discovery * ) Event; if (d_event->ErrCode != UPNP_E_SUCCESS) printf("Error in Discovery ByeBye Callback -- %d\n", d_event->ErrCode); printf("Received ByeBye for Device: %s\n", d_event->DeviceId); TvCtrlPointRemoveDevice(d_event->DeviceId); printf("After byebye:\n"); TvCtrlPointPrintList(); } break; /* SOAP Stuff */ case UPNP_CONTROL_ACTION_COMPLETE: { struct Upnp_Action_Complete *a_event = (struct Upnp_Action_Complete * ) Event; if (a_event->ErrCode != UPNP_E_SUCCESS) printf("Error in Action Complete Callback -- %d\n", a_event->ErrCode); /* No need for any processing here, just print out results. Service state table updates are handled by events. */ } break; case UPNP_CONTROL_GET_VAR_COMPLETE: { struct Upnp_State_Var_Complete *sv_event = (struct Upnp_State_Var_Complete * ) Event; if (sv_event->ErrCode != UPNP_E_SUCCESS) printf("Error in Get Var Complete Callback -- %d\n", sv_event->ErrCode); } break; /* GENA Stuff */ case UPNP_EVENT_RECEIVED: { struct Upnp_Event *e_event = (struct Upnp_Event * ) Event; TvCtrlPointHandleEvent(e_event->Sid, e_event->EventKey, e_event->ChangedVariables); } break; case UPNP_EVENT_SUBSCRIBE_COMPLETE: case UPNP_EVENT_UNSUBSCRIBE_COMPLETE: case UPNP_EVENT_RENEWAL_COMPLETE: { struct Upnp_Event_Subscribe *es_event = (struct Upnp_Event_Subscribe * ) Event; if (es_event->ErrCode != UPNP_E_SUCCESS) printf("Error in Event Subscribe Callback -- %d\n", es_event->ErrCode); else TvCtrlPointHandleSubscribeUpdate(es_event->PublisherUrl, es_event->Sid, es_event->TimeOut);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -