📄 program.c
字号:
/*
* Openmysee
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "echo.h"
extern time_t CurrentTime;
extern char *PREFIX;
static struct Channel *ProgramHash[MAX_CHANNEL];
static struct Channel *ProgramList;
static int NumNewProg;
static struct Channel *findProgram (char *name, int len)
{
return getChannel (ProgramHash, name, len);
}
#define skipSeparator(ptr,end) do\
{\
while ((*ptr == '=' || isspace (*ptr)) && ptr < end) ptr ++;\
} while (0)
#define skipSpace(ptr,end) do\
{\
while (isspace (*ptr) && ptr < end) ptr ++;\
} while (0)
#define skipNonalnum(ptr,end) do\
{\
while ((!isalnum (*ptr)) && ptr < end) ptr ++;\
} while (0)
#define lineup(ptr,end) do\
{\
while (*ptr != '\r' && *ptr != '\n' && ptr < end) ptr ++;\
} while (0)
#define copyStr(src,dst,max,end) do\
{\
while ((!isspace (*ptr)) && max >= 0 && ptr < end)\
{\
*dst++ = *src++;\
max --;\
}\
*dst = 0;\
} while (0)
static int read_prog_config (char *name, char *cname, int maxlen, float *bitrate, int *bsize, int *datalen, char **data)
{
int len, size;
FILE *in;
char *buffer=NULL, *ptr, *end;
char *p, *dst;
struct stat stbuf;
if (stat (name, &stbuf) != 0 || !(S_ISREG (stbuf.st_mode)))
{
PDEBUG ("Config file %s does not exist.\n", name);
return -1;
}
if ((in=fopen (name, "r")) == NULL)
{
PDEBUG ("Cannot open file %s\n", name);
return -1;
}
size = stbuf.st_size;
buffer = calloc (1, size+1);
if (fread (buffer, size, 1, in) != 1)
{
PDEBUG ("Cannot read all the file %s.\n", name);
fclose (in);
free (buffer);
return -1;
}
end = buffer + size + 1;
for (ptr=buffer; ptr<end;)
{
skipSpace (ptr, end);
if (strncasecmp (ptr, "ChannelName", strlen ("ChannelName")) == 0)
{
ptr += strlen ("ChannelName");
if (isalnum (*ptr))
{
lineup (ptr,end);
continue;
}
skipSeparator(ptr,end);
if (ptr >= end) break;
copyStr (ptr, cname, maxlen,end);
lineup (ptr,end);
}
else if (strncasecmp (ptr, "BitRate", strlen ("BitRate")) == 0)
{
ptr += strlen ("BitRate");
if (isalnum (*ptr)) lineup (ptr,end);
skipNonalnum (ptr,end);
if (ptr >= end) break;
*bitrate = atof (ptr);
lineup (ptr,end);
}
else if (strncasecmp (ptr, "BlockSize", strlen ("BlockSize")) == 0)
{
ptr += strlen ("BlockSize");
if (isalnum (*ptr)) lineup (ptr,end);
skipNonalnum (ptr,end);
if (ptr >= end) break;
*bsize = atoi (ptr);
lineup (ptr,end);
}
else if (strncasecmp (ptr, "DataLength", strlen ("DataLength")) == 0)
{
ptr += strlen ("DataLength");
if (isalnum (*ptr)) lineup (ptr,end);
skipNonalnum (ptr,end);
if (ptr >= end) break;
*datalen = atoi (ptr);
lineup (ptr,end);
}
else if (strncasecmp (ptr, "Data", strlen ("Data")) == 0)
{
ptr += strlen ("Data=");
len = *datalen;
if (ptr >= end) break;
dst = p = calloc (1, len+1);
while (len >= 0)
{
*p++ = *ptr++;
len --;
}
*data = dst;
lineup (ptr,end);
}
else
{
lineup (ptr,end);
}
}
fclose (in);
if (buffer != NULL) free (buffer);
return 0;
}
static inline void buildProgPath (char *buf, int len, char *md5)
{
snprintf (buf, len, "%s/%s/", PREFIX, PROG_PREFIX);
strcat (buf, md5);
}
// Return 1 to indicate write available, return 0 to indicate now writable.
static inline int newPListChannelFile (struct Channel *p)
{
struct stat stbuf;
char buffer[MAX_LINE];
struct LiveChannelInfo *pcinfo = p->pcinfo;
if (pcinfo->numinput >= MAX_FILEINPUT)
{
PDEBUG ("Max file input has been reached, %s:%d.\n", p->fname,pcinfo->numinput);
return -1;
}
snprintf (buffer, MAX_LINE, "%s/%d", p->fname, pcinfo->numinput);
if (stat (buffer, &stbuf) == 0 && (pcinfo->input[pcinfo->numinput] = fopen (buffer, "r")) != NULL)
{
pcinfo->maxID += stbuf.st_size / p->maxblocksize;
pcinfo->numinput ++;
return 0;
}
return -1;
}
static int init_prog (struct Channel *p)
{
int i;
struct stat stbuf;
char buffer[MAX_LINE];
struct LiveChannelInfo *pcinfo = p->pcinfo;
if (p->maxblocksize == 0) p->maxblocksize = DEFAULT_BLOCK;
while ((i = newPListChannelFile (p)) == 0);
pcinfo->max_queue = BLOCK_PER_FILE;
snprintf (buffer, MAX_LINE, "%s/keysample", p->fname);
if (stat (buffer, &stbuf) == 0)
{
if (!S_ISREG (stbuf.st_mode))
{
PDEBUG ("File %s exist and not a regular file", buffer);
return -1;
}
}
pcinfo->keyfile = fopen (buffer, "r");
if (pcinfo->keyfile == NULL)
{
PDEBUG ("File %s can not be opened.\n", buffer);
return -1;
}
pcinfo->total = 0;
pcinfo->isSave = 1;
// timer_add (CurrentTime, (TimerFunc)send_spupdate, p, NULL);
return 0;
}
static struct Channel *newProg (char *name, struct Session *source, char *cmd5, float bitrate, int maxblocksize)
{
int id;
struct Channel *p;
struct LiveChannelInfo *pcinfo;
if (NumNewProg >= MAX_CHANNEL) return (struct Channel *)0;
p = (struct Channel *)calloc (sizeof (struct Channel), 1);
memcpy (p->channel_md5, cmd5, MD5_LEN);
if (name) strncpy (p->channel_name, name, sizeof (p->channel_name));
p->channel_md5[MD5_LEN] = 0;
p->upsize = 0;
p->downsize = 0;
p->maxblocksize = maxblocksize;
p->ctime = time (NULL);
p->pcinfo = (struct LiveChannelInfo *)calloc (sizeof (struct LiveChannelInfo), 1);
pcinfo = p->pcinfo;
pcinfo->dataSource = source;
pcinfo->bitrate = bitrate;
buildProgPath (p->fname, CHNLURL_LEN, cmd5);
if (init_prog (p) < 0)
{
PDEBUG ("newPlistChannel error for %p.", p);
free_livechannel (p);
free (pcinfo);
free (p);
return (struct Channel *)0;
}
id = hash_str (p->channel_md5, MD5_LEN);
PDEBUG("newPlistChannel hash %.32s(fname=%s) to %d.\n", p->channel_md5, p->fname, id);
p->next = ProgramHash[id];
ProgramHash[id] = p;
p->lnext = ProgramList;
ProgramList = p;
NumNewProg ++;
return p;
}
static struct Channel *add_prog (char *buffer, char *md5)
{
struct stat stbuf;
struct Channel *pc=NULL;
char *data=NULL, cname[MAX_DATA];
float bitrate=0.0;
int bsize=16384, dlen=0;
if (stat (buffer, &stbuf) < 0) return NULL;
if (!S_ISDIR (stbuf.st_mode))
return NULL;
else
{
strcat (buffer, "/config");
if (read_prog_config (buffer, cname, sizeof(cname), &bitrate, &bsize, &dlen, &data) < 0)
{
PDEBUG ("Error in parse file %s.\n", buffer);
return NULL;
}
if ((pc=newProg (cname, NULL, md5, bitrate, bsize)) == NULL)
{
PDEBUG ("Cannot new plist Channel %s\n", cname);
free (data);
return NULL;
}
pc->pcinfo->media = calloc (1, sizeof (struct MediaData));
pc->pcinfo->media[0].start = 0;
pc->pcinfo->media[0].len = pc->pcinfo->maxID;
pc->pcinfo->media[0].dlen = dlen;
pc->pcinfo->media[0].data = data;
pc->pcinfo->cur_channel = pc->pcinfo->max_channel = 1;
}
return pc;
}
struct Channel *getProgrambymd5 (char *name, int len)
{
char buffer[MAX_DATA];
struct Channel *result;
if ((result = findProgram (name, len)) != NULL)
return result;
snprintf (buffer, MAX_DATA, "%s/%s/%s/", PREFIX, PROG_PREFIX, name);
return add_prog (buffer, name);
}
int locateprog_by_id (struct Channel *pc, unsigned int id, char *buf, int max)
{
int i, pos, *msg;
struct LiveChannelInfo *c = pc->pcinfo;
if (c == NULL)
{
PDEBUG ("c is %p and id is (%d,%d).\n", c, c->maxID, id);
return -1;
}
i = id % c->maxID;
pos = i / c->max_queue;
i = i % c->max_queue;
if (pc->maxblocksize + 2*sizeof(int) > max)
{
PDEBUG ("too small buffer %d for %d", max, pc->maxblocksize);
return -2;
}
if (pos >= c->numinput || c->input[pos] == NULL)
{
PDEBUG ("file %d does not exist. (%d,%p)\n", pos, c->numinput, c->input[pos]);
return -1;
}
if (fseeko (c->input[pos], ((off_t)(i)) * pc->maxblocksize, SEEK_SET) != 0)
{
PDEBUG ("Fssek failed. (%d, %d, %d)\n", pos, i, pc->maxblocksize);
return -1;
}
if ((i=fread (buf+2*sizeof(int), 1, pc->maxblocksize, c->input[pos])) != pc->maxblocksize)
{
PDEBUG ("Fread failed. (%d, %d, %d)\n", pos, i, pc->maxblocksize);
return -1;
}
msg = (int *)buf;
msg[0] = id;
msg[1] = pc->maxblocksize;
pc->upsize += msg[1];
return msg[1];
}
inline void freeProgram (struct Channel *pc, void *p)
{
freeChannel (ProgramHash, &ProgramList, &NumNewProg, pc);
}
void freeAllProgram ()
{
apply_hash (ProgramHash, freeProgram, NULL);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -