⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vod.c

📁 MINIWEB 0.75, 可以用于嵌入式系统设计。
💻 C
字号:
#include "httppil.h"#include "httpapi.h"#define VOD_PATH "video"typedef struct _PL_ENTRY {	struct _PL_ENTRY *next;	void* data;} PL_ENTRY;typedef enum {	ACT_NOTHING=0,	ACT_SKIP,} VOD_CLIENT_ACTIONS;typedef int (*PL_ENUM_CALLBACK)(PL_ENTRY *entry, void *arg);	PL_ENTRY* plAddEntry(PL_ENTRY **hdr, void* data);PL_ENTRY* plFindEntry(PL_ENTRY *hdr, void* data);void* plGetEntry(PL_ENTRY **hdr);void* plDelEntry(PL_ENTRY **hdr, void* data);void* plAdvanceEntry(PL_ENTRY **hdr, void* data);int plEnumEntries(PL_ENTRY *hdr, PL_ENUM_CALLBACK pfnEnumCallback, 						   void *arg, int from, int count);static PL_ENTRY* plhdr=NULL;static int listindex=0,listcount=0;static PL_ENTRY played={NULL,NULL};static PL_ENTRY *lastplayed=&played;static int playcount=0;static char vodbuf[256];static char streamPath[64];static char *vodroot=NULL;static char *htmlbuf=NULL;static int vodLookForFile(char* keyword, char *pathbuf){	char subdir[4];	char buf[128],httppath[64];	int ret;	subdir[0]=keyword[0];	subdir[1]=keyword[1];	subdir[2]=0;	sprintf(httppath,"%s/%s",vodroot,subdir);	for (ret=ReadDir(httppath,buf);!ret;ret=ReadDir(NULL,buf)) {		if (strstr(buf,keyword)) {			if (pathbuf) sprintf(pathbuf,"%s/%s/%s",VOD_PATH,subdir,buf);			break;		}	}	ReadDir(NULL,NULL);	return ret?0:1;}static int EnumSelections(PL_ENTRY *entry, void *arg){	char **p=(char**)arg;	*p+=sprintf(*p,"%05d ",entry->data);	return 0;}static int EnumSelectionsHtml(PL_ENTRY *entry, void *arg){	char **p=(char**)arg,*q,*s;	char keyword[16];	char buf[128];	int len;	sprintf(keyword,"%05d",entry->data);	vodLookForFile(keyword,buf);	s=strstr(buf,keyword);	q=strchr(s,'.');	if (!q) return 0;	*q=0;	len=sprintf(*p,"<p>%s <a href='/vod/del=%s&inf=list'>[Del]</a> <a href='/vod/adv=%s&inf=list'>[Top]</a></p>",s,keyword,keyword);	*p+=len;	return 0;}int uhVodInit(HttpParam* hp, void* arg){	if (!arg) {		//initialization		vodroot=malloc(strlen(hp->pchWebPath)+7);		sprintf(vodroot,"%s/%s",hp->pchWebPath,VOD_PATH);	} else {		//de-initialization		if (vodroot) free(vodroot);		if (htmlbuf) free(htmlbuf);	}	return 0;}#define VOD_LOOP_COUNT 4int uhVodStream(UrlHandlerParam* param){	if (param->request->iStartByte==0) {		int code;		while ((code=(int)plGetEntry(&plhdr))) {			char keyword[16];			sprintf(keyword,"%05d",code);			if (vodLookForFile(keyword,streamPath)) break;			DEBUG("[vod] %d not available\n",code);		}		if (code) {			lastplayed->next=malloc(sizeof(PL_ENTRY));			lastplayed=lastplayed->next;			lastplayed->data=(void*)code;			lastplayed->next=NULL;			playcount++;		} else {			/*			int i,cnt=0;			do {				i=rand() * VOD_LOOP_COUNT / (RAND_MAX+1);				sprintf(streamPath,"%s/vodloop%d.mkv",vodroot,i);			} while(!IsFileExist(streamPath) && ++cnt<VOD_LOOP_COUNT);			*/			sprintf(streamPath,"%s/vodloop.mkv",VOD_PATH);		}	}	strcpy(param->pucBuffer,streamPath);	DEBUG("[vod] stream: %s\n",streamPath);	return FLAG_DATA_FILE;}int uhVod(UrlHandlerParam* param){	char *req=param->pucRequest;	char *pbuf=param->pucBuffer;	static VOD_CLIENT_ACTIONS action=0;	param->fileType=HTTPFILETYPE_TEXT;	for(;;) {		switch (GETDWORD(req)) {		case DEFDWORD('n','o','p',0):			strcpy(pbuf,"state=OK");			break;		case DEFDWORD('c','m','d','='):			action=ACT_SKIP;			strcpy(pbuf,"Play next");			param->iDataBytes=9;			return FLAG_DATA_RAW;		case DEFDWORD('i','n','f','='): {			int itemcount=0;			req+=4;			switch (GETDWORD(req)) {			case DEFDWORD('l','i','s','t'):				itemcount=listcount;				break;			case DEFDWORD('h','i','s','t'):				itemcount=playcount;				break;			}			pbuf=param->pucBuffer;			if (itemcount>16) {				if (htmlbuf) free(htmlbuf);				htmlbuf=malloc(itemcount*128);				pbuf=htmlbuf;				param->pucBuffer=htmlbuf;			}			//FIXME: css file path			pbuf+=sprintf(pbuf,"<html><head><link href='/vodsys/default.css' rel='stylesheet' type='text/css'></head><body>");			switch (GETDWORD(req)) {			case DEFDWORD('l','i','s','t'): {				int count;				count=plEnumEntries(plhdr, EnumSelectionsHtml, (void*)&pbuf, 0, 0);				pbuf+=sprintf(pbuf,"<p>Total: %d</p>",count);				} break;			case DEFDWORD('h','i','s','t'): {				PL_ENTRY *pl;				pbuf+=sprintf(pbuf,"<html><body>");				for (pl=played.next; pl; pl=pl->next) {					pbuf+=sprintf(pbuf,"<p>%05d</p>",pl->data);				}				pbuf+=sprintf(pbuf,"<p>Total: %d</p>",playcount);				} break;			}			pbuf+=sprintf(pbuf,"</body></html>");			param->iDataBytes=(int)(pbuf)-(int)(param->pucBuffer);			param->fileType=HTTPFILETYPE_HTML;			} return FLAG_DATA_RAW;		case DEFDWORD('l','s','t','='):			switch (GETDWORD(req+4)) {			case DEFDWORD('n','e','x','t'):				if (listindex<listcount-4) listindex+=4;				break;			case DEFDWORD('p','r','e','v'):				listindex-=4;				if (listindex<0) listindex=0;				break;			}		case DEFDWORD('l','s','t',0):			if (listindex>=listcount) listindex=0;			if (listcount==0) {				strcpy(pbuf,"osd=[empty]");			} else {				char *p;				strcpy(pbuf,"osd=");				p=pbuf+4;				if (listindex>0) *(p++)='<';				plEnumEntries(plhdr, EnumSelections, (void*)&p, listindex, 4);				*p=0;				if (listindex+4<listcount) strcat(pbuf,">");				DEBUG("[vod] list item %d-%d\n",listindex,listindex+3);			}			strcat(pbuf,"\notm=900");			break;		case DEFDWORD('a','d','d','='): {			void *data=NULL;			int code;			req+=4;			code=atoi(req);			if (plFindEntry(plhdr,(void*)code)) {				strcpy(pbuf,"osd=ordered");				break;			}			if (vodLookForFile(req,NULL)) {				data=plAddEntry(&plhdr,(void*)code);			}			if (data)				sprintf(pbuf,"osd=[%s]\n",req);			else				strcpy(pbuf,"osd=error");			} break;		case DEFDWORD('d','e','l','='): {			void *data=NULL;			int code=atoi(req+4);			if (code) data=plDelEntry(&plhdr,(void*)code);			if (data)				sprintf(pbuf,"osd=%05d deleted",code);			else				strcpy(pbuf,"osd=error");			} break;		case DEFDWORD('a','d','v','='): {			void *data=NULL;			int code=atoi(req+4);			if (code) data=plAdvanceEntry(&plhdr,(void*)code);			if (data)				sprintf(pbuf,"osd=%05d topped",code);			else				strcpy(pbuf,"osd=error");			} break;		case DEFDWORD('c','n','t',0):			sprintf(pbuf,"osd=%d",playcount);			break;		default:			strcpy(pbuf,"Invalid request");		}		pbuf+=strlen(pbuf);		if (!(req=strchr(req,'&'))) break;		req++;	}	if (action) {		pbuf+=sprintf(pbuf,"\nact=skip");		action=ACT_NOTHING;	}	param->iDataBytes=(int)pbuf-(int)(param->pucBuffer);	return FLAG_DATA_RAW;}//////////////////////////////////////////////////////////////////// Playlist implementation//////////////////////////////////////////////////////////////////PL_ENTRY* plAddEntry(PL_ENTRY **hdr, void* data){	PL_ENTRY *ptr=*hdr;	if (!ptr) {		// allocate header		*hdr=(PL_ENTRY*)malloc(sizeof(PL_ENTRY));		ptr=*hdr;	} else {		// travel to the end of list		while (ptr->next) ptr=ptr->next;		ptr->next=(PL_ENTRY*)malloc(sizeof(PL_ENTRY));	 	ptr=ptr->next;	}	ptr->data=data;	ptr->next=NULL;	listcount++;	return ptr;}void* plGetEntry(PL_ENTRY **hdr){	PL_ENTRY *ptr=*hdr;	void* data;	if (!ptr) return NULL;	data=ptr->data;	*hdr=ptr->next;	free(ptr);	listcount--;	return data;}PL_ENTRY* plFindEntry(PL_ENTRY *hdr, void* data){	PL_ENTRY *ptr;	for (ptr=hdr; ptr; ptr=ptr->next) {		if (ptr->data==data) return ptr;	}	return NULL;}void* plDelEntry(PL_ENTRY **hdr, void* data){	PL_ENTRY *ptr=*hdr,*prev=NULL;	void* deleted;	if (!ptr) return NULL;	if (ptr->data==data) {		deleted=ptr->data;		*hdr=ptr->next;		free(ptr);		listcount--;		return deleted;	}	for (prev=ptr, ptr=ptr->next; ptr; prev=ptr, ptr=ptr->next) {		if (ptr->data==data) { 			deleted=ptr->data;			prev->next=ptr->next;			free(ptr);			listcount--;			return deleted;		}	}	return NULL;}void* plAdvanceEntry(PL_ENTRY **hdr, void* data){	PL_ENTRY *ptr=*hdr,*prev=NULL;	while (ptr) {		if (ptr->data==data) {			if (!prev) return 0;			prev->next=ptr->next;			ptr->next=*hdr;			*hdr=ptr;			return ptr;		}		prev=ptr;		ptr=ptr->next;	}	return NULL;}int plEnumEntries(PL_ENTRY *hdr, PL_ENUM_CALLBACK pfnEnumCallback, 						   void *arg, int from, int count){	PL_ENTRY *ptr=hdr;	int hits;	if (!pfnEnumCallback) return -1;	for (hits=0;ptr;ptr=ptr->next,hits++) {		if (count && hits>=from+count) return hits;		if (hits>=from)			if ((*pfnEnumCallback)(ptr, arg)) break;	}	return hits;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -