/// Creates a UPnpService and adds it to the UPnpDevice's list of services.
void UPnpServiceImpl::RegisterService(UPnpDevice *pDevice)
{
    if (pDevice != NULL)
    {
        UPnpService *pService = new UPnpService();
            
        pService->m_sServiceType = GetServiceType();
        pService->m_sServiceId   = GetServiceId();
        pService->m_sSCPDURL     = GetServiceDescURL();
        pService->m_sControlURL  = GetServiceControlURL();
        pService->m_sEventSubURL = GetServiceEventURL();

        pDevice->m_listServices.push_back(pService);
    }
}
/*
 * Parse Event Information Table
 */
static void parseEIT(u_char *data, size_t len) {
	struct eit *e = (struct eit *) data;
	u_char *p;
	struct tm dvb_time;
	const char *xmltvid;
	char date_strbuf[256];

	len -= 4; //remove CRC

	// For each event listing
	for (p = (u_char *) (&e->data); p < (u_char *) (data + len); p
			+= EIT_EVENT_LEN + GetEITDescriptorsLoopLength(p)) {
		struct eit_event *evt = (struct eit_event *) p;
		struct chninfo *c;
		// find existing information?
		for (c = channels; c != NULL; c = c->next) {
			// found it
			if (c->sid == HILO(e->service_id)
					&& (c->eid == HILO(evt->event_id))) {
				if (c->ver <= e->version_number) // seen it before or its older FIXME: wrap-around to 0
					return;
				else {
					c->ver = e->version_number; // update outputted version
					update_count++;
					if (ignore_updates)
						return;
					break;
				}
			}
		}

		// its a new program
		if (c == NULL) {
			chninfo_t *nc = (chninfo_t *) malloc(sizeof(struct chninfo));
			nc->sid = HILO(e->service_id);
			nc->eid = HILO(evt->event_id);
			nc->ver = e->version_number;
			nc->sname = strdup("not-yet-known");
			nc->next = channels;
			channels = nc;
		}

		/* we have more data, refresh alarm */
		if (timeout)
		{
			setTimeoutDeadline();
			//alarm(timeout);
		}

		// No program info at end! Just skip it
		if (GetEITDescriptorsLoopLength(evt) == 0)
			return;

		parseMJD(HILO(evt->mjd), &dvb_time);

		dvb_time.tm_sec = BcdCharToInt(evt->start_time_s);
		dvb_time.tm_min = BcdCharToInt(evt->start_time_m);
		dvb_time.tm_hour = BcdCharToInt(evt->start_time_h) + time_offset;
		time_t start_time = timegm(&dvb_time);

		dvb_time.tm_sec += BcdCharToInt(evt->duration_s);
		dvb_time.tm_min += BcdCharToInt(evt->duration_m);
		dvb_time.tm_hour += BcdCharToInt(evt->duration_h);
		time_t stop_time = timegm(&dvb_time);

		time_t now;
		time(&now);
		// basic bad date check. if the program ends before this time yesterday, or two weeks from today, forget it.
		if ((difftime(stop_time, now) < -24 * 60 * 60) || (difftime(now,
						stop_time) > 14 * 24 * 60 * 60)) {
			invalid_date_count++;
			if (ignore_bad_dates)
				return;
		}
		// a program must have a title that isn't empty
		if (!validateDescription((u_char *) (&evt->data),
					GetEITDescriptorsLoopLength(evt))) {
			return;
		}

		programme_count++;

		if ((start_time >= start_of_period) && (start_time < end_of_period)) {
			xmltvid = dvbxmltvid(GetServiceId(e));
			if (xmltvid != NULL) {
				printf("<programme channel=\"%s\" ", xmltvid);
				strftime(date_strbuf, sizeof(date_strbuf),
						"start=\"%Y%m%d%H%M%S %z\"", localtime(&start_time));
				printf("%s ", date_strbuf);
				strftime(date_strbuf, sizeof(date_strbuf),
						"stop=\"%Y%m%d%H%M%S %z\"", localtime(&stop_time));
				printf("%s>\n ", date_strbuf);

				//printf("\t<EventID>%i</EventID>\n", HILO(evt->event_id));
				//printf("\t<RunningStatus>%i</RunningStatus>\n", evt->running_status);
				//1 Airing, 2 Starts in a few seconds, 3 Pausing, 4 About to air

				parseDescription((u_char *) (&evt->data),
						GetEITDescriptorsLoopLength(evt));
				printf("</programme>\n");
			}
		}
	}
}