redbutton-devel Mailing List for RedButton MHEG Engine (Page 27)
Brought to you by:
skilvington
You can subscribe to this list here.
| 2006 |
Jan
(1) |
Feb
(4) |
Mar
(27) |
Apr
(6) |
May
(46) |
Jun
(45) |
Jul
(7) |
Aug
(4) |
Sep
(7) |
Oct
(5) |
Nov
(10) |
Dec
(11) |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2007 |
Jan
(49) |
Feb
(29) |
Mar
(35) |
Apr
(43) |
May
(23) |
Jun
(4) |
Jul
(1) |
Aug
(58) |
Sep
(66) |
Oct
(27) |
Nov
(15) |
Dec
(1) |
| 2008 |
Jan
(11) |
Feb
|
Mar
(8) |
Apr
|
May
|
Jun
(30) |
Jul
(1) |
Aug
(1) |
Sep
(1) |
Oct
|
Nov
(3) |
Dec
(6) |
| 2009 |
Jan
(6) |
Feb
(1) |
Mar
(2) |
Apr
(5) |
May
(2) |
Jun
(1) |
Jul
(7) |
Aug
|
Sep
(2) |
Oct
(2) |
Nov
|
Dec
(6) |
| 2010 |
Jan
(6) |
Feb
|
Mar
(4) |
Apr
|
May
|
Jun
|
Jul
|
Aug
(6) |
Sep
(4) |
Oct
|
Nov
(11) |
Dec
(4) |
| 2011 |
Jan
|
Feb
(11) |
Mar
(8) |
Apr
|
May
|
Jun
(3) |
Jul
|
Aug
|
Sep
(4) |
Oct
|
Nov
(2) |
Dec
|
| 2012 |
Jan
|
Feb
|
Mar
|
Apr
|
May
(1) |
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: <ski...@us...> - 2006-04-03 10:22:53
|
Revision: 32 Author: skilvington Date: 2006-04-03 03:22:45 -0700 (Mon, 03 Apr 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=32&view=rev Log Message: ----------- import redbutton.sourceforge.net index.html Added Paths: ----------- www/ www/index.html Added: www/index.html =================================================================== --- www/index.html (rev 0) +++ www/index.html 2006-04-03 10:22:45 UTC (rev 32) @@ -0,0 +1,145 @@ +<HTML> +<HEAD> +<TITLE>RedButton MHEG Engine</TITLE> +</HEAD> +<BODY> +<a href="http://sourceforge.net"><img src="http://sflogo.sourceforge.net/sflogo.php?group_id=158629&type=2" width="125" height="37" border="0" alt="SourceForge.net Logo" /></a> +<H1>RedButton MHEG Engine</H1> +RedButton allows you to use the interactive MHEG applications broadcast with DVB digital TV services. +MHEG replaces the text only services available with analogue TV. +<P> +RedButton consists of two parts. The first, rb-download, allows MHEG data to be downloaded from a DVB service. The second, rb-browser, allows the downloaded MHEG applications to be displayed. +<P> +The source for both is released under the GPL and can be +<A HREF="http://sourceforge.net/project/showfiles.php?group_id=158629">downloaded here.</A> +<P> +Just un-tar them and type 'make'. +<P> +You can browser the latest version of the source +<A HREF="http://svn.sourceforge.net/redbutton/">here.</A> +You can download the latest source code with the following Subversion command: +<PRE> +svn checkout https://svn.sourceforge.net/svnroot/redbutton/ +</PRE> +<P> +You can subscribe to the development mailing list +<A HREF="http://lists.sourceforge.net/lists/listinfo/redbutton-devel">here.</A> +<H2>rb-download</H2> +Usage: +<PRE> +rb-download [-d <demux_device>] [-b <base_dir>] [-t <timeout>] [-c <carousel_id>] [<service_id>] +</PRE> +Download the DVB Object Carousel for the given channel onto the local hard disc. +<P> +The default demux device is /dev/dvb/adapter0/demux0. +<P> +If no directory is given with -b, files will be stored under the current directory. +Note that <base_dir> must already exist and be writeable. +<P> +The default timeout is 10 seconds. +If no DSM-CC data is found after this time, it is assumed none is being broadcast. +<P> +The <carousel_id> will normally be read from the PMT, but you can use the -c option to explicitly choose a carousel. +<P> +If no <service_id> is given, a list of possible channels (and their <service_id>) is printed. +These will be the channels available on the MUX your DVB card is currently tuned to. Use dvbtune or equivalent to tune your card. +<P> +The file structure stored under <base_dir> will be: +<PRE> +./services/<service_id> +</PRE> +this is a symlink to the root of the carousel for the given service. +<P> +The actual carousel files and directories are stored under: +<PRE> +./carousels/<PID>/<CID>/ +</PRE> +where <PID> is the PID the carousel was downloaded from +and <CID> is the Carousel ID. +<P> +Just leave it running and any updated files will be downloaded as they are broadcast. +<H2>Notes</H2> +I've compiled and run it under Gentoo and Mandr{ake,iva} Linux on x86, but it should work on any (big- or little-endian) Linux distro. +<P> +It only implements a subset of the whole DSM-CC specs. +However, it is enough to download everything that is currently being broadcast +on the 'Freeview' DVB-T channels in the UK. +<P> +Once the data is downloaded, you can use rb-browser (see below) to view it. +<H2>rb-browser</H2> +Usage: +<PRE> +rb-browser [-v] [-f] [-k <keymap_config_file>] [-t <timeout>] <service_gateway_dir> +</PRE> +Display the MHEG apps downloaded with rb-download. +The <service_gateway_dir> should be one of the entries in the services directory, eg +<PRE> +rb-browser services/4165 +</PRE> +It will display the app in a window, use -f for full screen mode. +<P> +The -v flag enables verbose/debug mode. +<P> +The -t flag determines how long (in seconds) it will poll for missing files before passing an error to the MHEG application. +The default is 10 seconds. +<P> +Use the -k option to load a keymap (keymap config files can be generated with the rb-keymap command). +The default keys to navigate around the apps are: +<P> +<TABLE border="1" cellpadding="5"> +<TR><TH>Key</TH><TH>Function</TH></TR> +<TR align="center"><TD>Cursor Keys</TD><TD>Up/Down/Left/Right</TD></TR> +<TR align="center"><TD>0 - 9</TD><TD>0 - 9</TD></TR> +<TR align="center"><TD>r</TD><TD>Red</TD></TR> +<TR align="center"><TD>g</TD><TD>Green</TD></TR> +<TR align="center"><TD>b</TD><TD>Blue</TD></TR> +<TR align="center"><TD>y</TD><TD>Yellow</TD></TR> +<TR align="center"><TD>Return</TD><TD>OK/Select</TD></TR> +<TR align="center"><TD>Escape</TD><TD>Cancel</TD></TR> +<TR align="center"><TD>t</TD><TD>Text</TD></TR> +</TABLE> +<P> +You will need the "expat" XML parsing library and the xsltproc XML stylesheet processor that comes with "libxslt" to compile it. +On Gentoo, you can just: +<PRE> +emerge expat libxslt +</PRE> +If the compile fails with errors about missing .c files, expat is not installed. +If the compile fails with errors about function names ending in "_dup" being missing, libxslt is not installed. +<P> +To run it you need an X server that supports the Xrender extension and you need to have libpng, libmpeg2 and freetype2 installed. +<H2>Notes</H2> +It's not finished yet! +It'll only draw text, rectangles and PNG bitmaps at the moment and some of the ElementaryActions are not yet implemented. +However, it is enough to be usable. +The main things missing are video and audio streams, at the moment it'll just draw a green box where any video should be. +<P> +It will only display apps that conform to the UK MHEG Profile (available from +<A href="http://www.dtg.org.uk/">www.dtg.org.uk</A>). +<P> +If you get a blank screen when it starts, try pressing 'r' (for BBC) or 't' (for ITV/C4) to activate +any MHEG app that may be waiting for you to do something. +<P> +The default font for the UK MHEG Profile is Tiresias Screenfont which was +developed with the RNIB to be readable on TV screens. +You can download this font as part of the DigiTV iTuner package from +<A href="http://www.nebula-electronics.com/">Nebula Electronics</A>. +Extract the file called tt7268m_802.ttf and add it to your X Windows fonts. +The easiest way is to install DigiTV iTuner on a Windows box and then copy the +C:\Windows\Fonts\tt7268m_802.ttf file onto your Linux box. +To install new X fonts in KDE, open the Control Centre application, +go to the System Administration section and select Font Installer. +<P> +Alternatively, if you know someone in Australia, ABC is currently broadcasting +Tiresias.pfr as part of their TV guide application. +You can download it with rb-download. +The Australian applications are MHP, not MHEG, so you should probably look at +<A href="http://www.openmhp.org/">www.openmhp.org</A> for something to display them. +<P> +If the Tiresias Screenfont is not available, rb-browser uses whatever scalable font Xft returns for "sans" instead. +Note that this font will have different metrics and so may not fit into the spaces in the MHEG apps designed for Tiresias. +<H2>Contact Details</H2> +I can be contacted here: s.kilvington at eris dot qinetiq com. +</BODY> +</HTML> + This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-27 09:18:25
|
Revision: 31 Author: skilvington Date: 2006-03-27 01:18:20 -0800 (Mon, 27 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=31&view=rev Log Message: ----------- display dates in local time not GMT Modified Paths: -------------- redbutton-browser/trunk/ResidentProgramClass.c Modified: redbutton-browser/trunk/ResidentProgramClass.c =================================================================== --- redbutton-browser/trunk/ResidentProgramClass.c 2006-03-26 13:45:10 UTC (rev 30) +++ redbutton-browser/trunk/ResidentProgramClass.c 2006-03-27 09:18:20 UTC (rev 31) @@ -450,7 +450,7 @@ /* convert to UNIX time */ unix_time = ((mheg_date - MHEG_EPOCH_OFFSET) * (24 * 60 * 60)) + mheg_time; /* let libc do all the hard work of working out the year etc */ - tm = gmtime(&unix_time); + tm = localtime(&unix_time); /* write it out */ dateString.size = 0; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-26 13:45:17
|
Revision: 30 Author: skilvington Date: 2006-03-26 05:45:10 -0800 (Sun, 26 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=30&view=rev Log Message: ----------- avoid potential fclose(NULL) Modified Paths: -------------- redbutton-browser/trunk/MHEGBackend.c Modified: redbutton-browser/trunk/MHEGBackend.c =================================================================== --- redbutton-browser/trunk/MHEGBackend.c 2006-03-25 14:31:57 UTC (rev 29) +++ redbutton-browser/trunk/MHEGBackend.c 2006-03-26 13:45:10 UTC (rev 30) @@ -510,7 +510,7 @@ || fgets(pids, sizeof(pids), sock) == NULL) { fclose(sock); - sock = NULL; + return NULL; } /* update the PID variables */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-25 14:32:17
|
Revision: 29 Author: skilvington Date: 2006-03-25 06:31:57 -0800 (Sat, 25 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=29&view=rev Log Message: ----------- capitalisation Modified Paths: -------------- redbutton-download/trunk/command.c Modified: redbutton-download/trunk/command.c =================================================================== --- redbutton-download/trunk/command.c 2006-03-25 14:22:11 UTC (rev 28) +++ redbutton-download/trunk/command.c 2006-03-25 14:31:57 UTC (rev 29) @@ -38,10 +38,10 @@ { "astream", "<ComponentTag>", cmd_astream, "Stream the given audio component tag" }, { "avstream", "<AudioTag> <VideoTag>", cmd_avstream, "Stream the given audio and video component tags" }, { "check", "<ContentReference>", cmd_check, "Check if the given file exists on the carousel" }, - { "exit", "", cmd_quit, "close the connection" }, + { "exit", "", cmd_quit, "Close the connection" }, { "file", "<ContentReference>", cmd_file, "Retrieve the given file from the carousel" }, { "help", "", cmd_help, "List available commands" }, - { "quit", "", cmd_quit, "close the connection" }, + { "quit", "", cmd_quit, "Close the connection" }, { "vstream", "<ComponentTag>", cmd_vstream, "Stream the given video component tag" }, { NULL, NULL, NULL, NULL } }; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-25 14:22:21
|
Revision: 28 Author: skilvington Date: 2006-03-25 06:22:11 -0800 (Sat, 25 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=28&view=rev Log Message: ----------- spacing Modified Paths: -------------- redbutton-download/trunk/listen.c Modified: redbutton-download/trunk/listen.c =================================================================== --- redbutton-download/trunk/listen.c 2006-03-25 14:19:43 UTC (rev 27) +++ redbutton-download/trunk/listen.c 2006-03-25 14:22:11 UTC (rev 28) @@ -235,7 +235,7 @@ { /* strip off any trailing \n */ len = strlen(cmd); - len = (len > 0) ? len -1 : len; + len = (len > 0) ? len - 1 : len; while(len > 0 && (cmd[len] == '\n' || cmd[len] == '\r')) cmd[len--] = '\0'; /* process the command */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-25 14:20:17
|
Revision: 27 Author: skilvington Date: 2006-03-25 06:19:43 -0800 (Sat, 25 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=27&view=rev Log Message: ----------- keep the connection to the backend open Modified Paths: -------------- redbutton-browser/trunk/MHEGBackend.c redbutton-browser/trunk/MHEGBackend.h redbutton-download/trunk/command.c redbutton-download/trunk/command.h redbutton-download/trunk/listen.c redbutton-download/trunk/stream.c redbutton-download/trunk/stream.h redbutton-download/trunk/utils.c redbutton-download/trunk/utils.h Modified: redbutton-browser/trunk/MHEGBackend.c =================================================================== --- redbutton-browser/trunk/MHEGBackend.c 2006-03-25 10:43:15 UTC (rev 26) +++ redbutton-browser/trunk/MHEGBackend.c 2006-03-25 14:19:43 UTC (rev 27) @@ -45,7 +45,7 @@ static int parse_addr(char *, struct in_addr *, in_port_t *); static int get_host_addr(char *, struct in_addr *); -static FILE *remote_command(MHEGBackend *, char *); +static FILE *remote_command(MHEGBackend *, bool, char *); static unsigned int remote_response(FILE *); static char *external_filename(MHEGBackend *, OctetString *); @@ -61,6 +61,9 @@ b->addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); b->addr.sin_port = htons(DEFAULT_REMOTE_PORT); + /* no connection to the backend yet */ + b->be_sock = NULL; + if(remote) { /* backend is on a different host, srg_loc is the remote host[:port] */ @@ -83,6 +86,11 @@ void MHEGBackend_fini(MHEGBackend *b) { + /* send quit command */ + if(b->be_sock != NULL + && remote_command(b, true, "quit\n") != NULL) + fclose(b->be_sock); + return; } @@ -142,23 +150,30 @@ /* * send the given command to the remote backend + * if reuse is true, reuse the existing connection to the backend * returns a socket FILE to read the response from * returns NULL if it can't contact the backend */ static FILE * -remote_command(MHEGBackend *t, char *cmd) +remote_command(MHEGBackend *t, bool reuse, char *cmd) { int sock; FILE *file; - /* connect to the backend */ + /* can we use the existing connection */ + if(reuse && t->be_sock != NULL) + { + fputs(cmd, t->be_sock); + return t->be_sock; + } + + /* need to connect to the backend */ if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { error("Unable to create backend socket: %s", strerror(errno)); return NULL; } - if(connect(sock, (struct sockaddr *) &t->addr, sizeof(struct sockaddr_in)) < 0) { error("Unable to connect to backend: %s", strerror(errno)); @@ -178,6 +193,10 @@ close(sock); } + /* remember it if we need to reuse it */ + if(reuse) + t->be_sock = file; + return file; } @@ -342,13 +361,11 @@ snprintf(cmd, sizeof(cmd), "check %s\n", MHEGEngine_absoluteFilename(name)); - if((sock = remote_command(t, cmd)) == NULL) + if((sock = remote_command(t, true, cmd)) == NULL) return false; exists = (remote_response(sock) == BACKEND_RESPONSE_OK); - fclose(sock); - return exists; } @@ -368,7 +385,7 @@ snprintf(cmd, sizeof(cmd), "file %s\n", MHEGEngine_absoluteFilename(name)); - if((sock = remote_command(t, cmd)) == NULL) + if((sock = remote_command(t, true, cmd)) == NULL) return false; /* if it exists, read the file size */ @@ -377,7 +394,6 @@ || sscanf(cmd, "Length %u", &size) != 1) { error("Unable to load '%.*s'", name->size, name->data); - fclose(sock); return false; } @@ -390,8 +406,6 @@ while(!feof(sock) && nread < size) nread += fread(out->data + nread, 1, size - nread, sock); - fclose(sock); - /* did we read it all */ if(nread < size) { @@ -422,7 +436,7 @@ snprintf(cmd, sizeof(cmd), "file %s\n", MHEGEngine_absoluteFilename(name)); - if((sock = remote_command(t, cmd)) == NULL) + if((sock = remote_command(t, true, cmd)) == NULL) return NULL; /* if it exists, read the file size */ @@ -430,7 +444,6 @@ || fgets(cmd, sizeof(cmd), sock) == NULL || sscanf(cmd, "Length %u", &size) != 1) { - fclose(sock); return NULL; } @@ -449,8 +462,6 @@ size -= nread; } - fclose(sock); - /* rewind the file */ if(out != NULL) rewind(out); @@ -490,7 +501,8 @@ else snprintf(cmd, sizeof(cmd), "vstream %d\n", *video_tag); - if((sock = remote_command(t, cmd)) == NULL) + /* false => create a new connection to the backend */ + if((sock = remote_command(t, false, cmd)) == NULL) return NULL; /* did it work */ Modified: redbutton-browser/trunk/MHEGBackend.h =================================================================== --- redbutton-browser/trunk/MHEGBackend.h 2006-03-25 10:43:15 UTC (rev 26) +++ redbutton-browser/trunk/MHEGBackend.h 2006-03-25 14:19:43 UTC (rev 27) @@ -16,6 +16,7 @@ { char *base_dir; /* local Service Gateway root directory */ struct sockaddr_in addr; /* remote backend IP and port */ + FILE *be_sock; /* connection to remote backend */ /* function pointers */ struct MHEGBackendFns { Modified: redbutton-download/trunk/command.c =================================================================== --- redbutton-download/trunk/command.c 2006-03-25 10:43:15 UTC (rev 26) +++ redbutton-download/trunk/command.c 2006-03-25 14:19:43 UTC (rev 27) @@ -19,35 +19,35 @@ #define ARGV_MAX 10 /* the commands */ -bool cmd_astream(struct listen_data *, int, int, char **); -bool cmd_avstream(struct listen_data *, int, int, char **); -bool cmd_check(struct listen_data *, int, int, char **); -bool cmd_file(struct listen_data *, int, int, char **); -bool cmd_help(struct listen_data *, int, int, char **); -bool cmd_quit(struct listen_data *, int, int, char **); -bool cmd_vstream(struct listen_data *, int, int, char **); +bool cmd_astream(struct listen_data *, FILE *, int, char **); +bool cmd_avstream(struct listen_data *, FILE *, int, char **); +bool cmd_check(struct listen_data *, FILE *, int, char **); +bool cmd_file(struct listen_data *, FILE *, int, char **); +bool cmd_help(struct listen_data *, FILE *, int, char **); +bool cmd_quit(struct listen_data *, FILE *, int, char **); +bool cmd_vstream(struct listen_data *, FILE *, int, char **); static struct { char *name; char *args; - bool (*proc)(struct listen_data *, int, int, char **); + bool (*proc)(struct listen_data *, FILE *, int, char **); char *help; } command[] = { { "astream", "<ComponentTag>", cmd_astream, "Stream the given audio component tag" }, { "avstream", "<AudioTag> <VideoTag>", cmd_avstream, "Stream the given audio and video component tags" }, { "check", "<ContentReference>", cmd_check, "Check if the given file exists on the carousel" }, - { "exit", "", cmd_quit, "Kill the programme" }, + { "exit", "", cmd_quit, "close the connection" }, { "file", "<ContentReference>", cmd_file, "Retrieve the given file from the carousel" }, { "help", "", cmd_help, "List available commands" }, - { "quit", "", cmd_quit, "Kill the programme" }, + { "quit", "", cmd_quit, "close the connection" }, { "vstream", "<ComponentTag>", cmd_vstream, "Stream the given video component tag" }, { NULL, NULL, NULL, NULL } }; /* send an OK/error code etc response down client_sock */ -#define SEND_RESPONSE(RC, MESSAGE) write_string(client_sock, #RC " " MESSAGE "\n") +#define SEND_RESPONSE(RC, MESSAGE) fputs(#RC " " MESSAGE "\n", client) /* internal routines */ char *external_filename(struct listen_data *, char *); @@ -55,11 +55,11 @@ /* * process the given command - * return true if we should quit the programme + * return true if we should close the connection */ bool -process_command(struct listen_data *listen_data, int client_sock, char *cmd) +process_command(struct listen_data *listen_data, FILE *client, char *cmd) { int argc; char *argv[ARGV_MAX]; @@ -102,7 +102,7 @@ for(i=0; command[i].name != NULL; i++) { if(strncmp(argv[0], command[i].name, cmd_len) == 0) - return (command[i].proc)(listen_data, client_sock, argc, argv); + return (command[i].proc)(listen_data, client, argc, argv); } SEND_RESPONSE(500, "Unrecognised command"); @@ -113,10 +113,10 @@ /* * the commands * listen_data is global data needed by listener commands - * client_sock is where any response data should go + * client is where any response data should go * argc is the number of arguments passed to it * argv[0] is the command name (or the abreviation the user used) - * return true if we should quit the programme + * return true if we should close the connection */ #define CHECK_USAGE(ARGC, SYNTAX) \ @@ -135,7 +135,7 @@ */ bool -cmd_astream(struct listen_data *listen_data, int client_sock, int argc, char *argv[]) +cmd_astream(struct listen_data *listen_data, FILE *client, int argc, char *argv[]) { struct carousel *car = listen_data->carousel; int tag; @@ -174,16 +174,17 @@ /* tell the client what PID the component tag resolved to */ snprintf(hdr, sizeof(hdr), "AudioPID %u\n", pid); - write_string(client_sock, hdr); + fputs(hdr, client); - /* shovel the transport stream down client_sock until the client closes it or we get an error */ - stream_ts(ts_fd, client_sock); + /* shovel the transport stream to client until the client closes or we get an error */ + stream_ts(ts_fd, client); /* clean up */ close(ts_fd); close(audio_fd); - return false; + /* close the connection */ + return true; } /* @@ -195,7 +196,7 @@ */ bool -cmd_vstream(struct listen_data *listen_data, int client_sock, int argc, char *argv[]) +cmd_vstream(struct listen_data *listen_data, FILE *client, int argc, char *argv[]) { struct carousel *car = listen_data->carousel; int tag; @@ -234,16 +235,17 @@ /* tell the client what PID the component tag resolved to */ snprintf(hdr, sizeof(hdr), "VideoPID %u\n", pid); - write_string(client_sock, hdr); + fputs(hdr, client); /* shovel the transport stream down client_sock until the client closes it or we get an error */ - stream_ts(ts_fd, client_sock); + stream_ts(ts_fd, client); /* clean up */ close(ts_fd); close(video_fd); - return false; + /* close the connection */ + return true; } /* @@ -255,7 +257,7 @@ */ bool -cmd_avstream(struct listen_data *listen_data, int client_sock, int argc, char *argv[]) +cmd_avstream(struct listen_data *listen_data, FILE *client, int argc, char *argv[]) { struct carousel *car = listen_data->carousel; int audio_tag; @@ -310,17 +312,18 @@ /* tell the client what PIDs the component tags resolved to */ snprintf(hdr, sizeof(hdr), "AudioPID %u VideoPID %u\n", audio_pid, video_pid); - write_string(client_sock, hdr); + fputs(hdr, client); /* shovel the transport stream down client_sock until the client closes it or we get an error */ - stream_ts(ts_fd, client_sock); + stream_ts(ts_fd, client); /* clean up */ close(ts_fd); close(audio_fd); close(video_fd); - return false; + /* close the connection */ + return true; } /* @@ -330,7 +333,7 @@ */ bool -cmd_check(struct listen_data *listen_data, int client_sock, int argc, char *argv[]) +cmd_check(struct listen_data *listen_data, FILE *client, int argc, char *argv[]) { char *filename; FILE *file; @@ -363,7 +366,7 @@ */ bool -cmd_file(struct listen_data *listen_data, int client_sock, int argc, char *argv[]) +cmd_file(struct listen_data *listen_data, FILE *client, int argc, char *argv[]) { char *filename; FILE *file; @@ -400,14 +403,14 @@ /* send the file length */ snprintf(hdr, sizeof(hdr), "Length %ld\n", size); - write_string(client_sock, hdr); + fputs(hdr, client); /* send the file contents */ left = size; while(left > 0) { nread = fread(buff, 1, sizeof(buff), file); - write_all(client_sock, buff, nread); + fwrite(buff, 1, nread, client); left -= nread; } @@ -421,7 +424,7 @@ */ bool -cmd_help(struct listen_data *listen_data, int client_sock, int argc, char *argv[]) +cmd_help(struct listen_data *listen_data, FILE *client, int argc, char *argv[]) { int i; char name_args[64]; @@ -433,7 +436,7 @@ { snprintf(name_args, sizeof(name_args), "%s %s", command[i].name, command[i].args); snprintf(help_line, sizeof(help_line), "%-30s %s\n", name_args, command[i].help); - write_string(client_sock, help_line); + fputs(help_line, client); } return false; @@ -444,7 +447,7 @@ */ bool -cmd_quit(struct listen_data *listen_data, int client_sock, int argc, char *argv[]) +cmd_quit(struct listen_data *listen_data, FILE *client, int argc, char *argv[]) { return true; } Modified: redbutton-download/trunk/command.h =================================================================== --- redbutton-download/trunk/command.h 2006-03-25 10:43:15 UTC (rev 26) +++ redbutton-download/trunk/command.h 2006-03-25 14:19:43 UTC (rev 27) @@ -7,6 +7,6 @@ #include "listen.h" -bool process_command(struct listen_data *, int, char *); +bool process_command(struct listen_data *, FILE *, char *); #endif Modified: redbutton-download/trunk/listen.c =================================================================== --- redbutton-download/trunk/listen.c 2006-03-25 10:43:15 UTC (rev 26) +++ redbutton-download/trunk/listen.c 2006-03-25 14:19:43 UTC (rev 27) @@ -25,7 +25,7 @@ /* internal functions */ static int get_host_addr(char *, struct in_addr *); -static bool handle_connection(struct listen_data *, int, struct sockaddr_in *); +static void handle_connection(struct listen_data *, int, struct sockaddr_in *); static void dead_child(int); /* @@ -117,7 +117,6 @@ fd_set read_fds; socklen_t addr_len; struct sockaddr_in client_addr; - bool quit; /* * fork: @@ -189,10 +188,8 @@ { /* child */ close(listen_sock); - quit = handle_connection(listen_data, accept_sock, &client_addr); + handle_connection(listen_data, accept_sock, &client_addr); close(accept_sock); -/* TODO */ -if(quit) printf("TODO: QUIT\n"); /* use _exit in child so stdio etc don't clean up twice */ _exit(EXIT_SUCCESS); } @@ -213,31 +210,44 @@ * handle a connection from a remote rb-browser */ -static bool +static void handle_connection(struct listen_data *listen_data, int client_sock, struct sockaddr_in *client_addr) { + FILE *client; char cmd[1024]; - ssize_t nread; - bool quit = false; + size_t len; + bool quit; printf("Connection from %s:%d\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); - /* read the command from the client */ - if((nread = read(client_sock, cmd, sizeof(cmd)-1)) > 0) + if((client = fdopen(client_sock, "r+")) == NULL) + return; + + /* read commands from the client */ + quit = false; + while(!feof(client) && !quit) { - /* \0 terminate the buffer */ - cmd[nread] = '\0'; - /* strip off any trailing \n */ - nread --; - while(nread > 0 && (cmd[nread] == '\n' || cmd[nread] == '\r')) - cmd[nread--] = '\0'; - /* process the command */ - quit = process_command(listen_data, client_sock, cmd); + if(fgets(cmd, sizeof(cmd), client) == NULL) + { + quit = true; + } + else + { + /* strip off any trailing \n */ + len = strlen(cmd); + len = (len > 0) ? len -1 : len; + while(len > 0 && (cmd[len] == '\n' || cmd[len] == '\r')) + cmd[len--] = '\0'; + /* process the command */ + quit = process_command(listen_data, client, cmd); + } } + fclose(client); + printf("Connection from %s:%d closed\n", inet_ntoa(client_addr->sin_addr), ntohs(client_addr->sin_port)); - return quit; + return; } static void Modified: redbutton-download/trunk/stream.c =================================================================== --- redbutton-download/trunk/stream.c 2006-03-25 10:43:15 UTC (rev 26) +++ redbutton-download/trunk/stream.c 2006-03-25 14:19:43 UTC (rev 27) @@ -44,20 +44,20 @@ static unsigned char _ts_buf[8 * 1024]; void -stream_ts(int ts_fd, int client_sock) +stream_ts(int ts_fd, FILE *client) { ssize_t nread; - ssize_t nwritten; + size_t nwritten; do { nread = read(ts_fd, _ts_buf, sizeof(_ts_buf)); if(nread > 0) - nwritten = write(client_sock, _ts_buf, nread); + nwritten = fwrite(_ts_buf, 1, nread, client); else nwritten = nread; } - while(nread == nwritten); + while(!feof(client) && nread == nwritten); return; } Modified: redbutton-download/trunk/stream.h =================================================================== --- redbutton-download/trunk/stream.h 2006-03-25 10:43:15 UTC (rev 26) +++ redbutton-download/trunk/stream.h 2006-03-25 14:19:43 UTC (rev 27) @@ -5,11 +5,12 @@ #ifndef __STREAM_H__ #define __STREAM_H__ +#include <stdio.h> #include <stdint.h> #include <linux/dvb/dmx.h> int add_demux_filter(char *, uint16_t, dmx_pes_type_t); -void stream_ts(int, int); +void stream_ts(int, FILE *); #endif /* __STREAM_H__ */ Modified: redbutton-download/trunk/utils.c =================================================================== --- redbutton-download/trunk/utils.c 2006-03-25 10:43:15 UTC (rev 26) +++ redbutton-download/trunk/utils.c 2006-03-25 14:19:43 UTC (rev 27) @@ -31,46 +31,6 @@ #include "utils.h" /* - * write the given string (ie upto \0) to the given fd - */ - -void -write_string(int fd, const char *str) -{ - write_all(fd, str, strlen(str)); - - return; -} - -/* - * guarantee writing count bytes from buf to fd - * W. Richard Stevens - */ - -void -write_all(int fd, const void *buf, size_t count) -{ - size_t nwritten; - const char *buf_ptr; - - buf_ptr = buf; - while(count > 0) - { - if((nwritten = write(fd, buf_ptr, count)) < 0) - { - if(errno == EINTR || errno == EAGAIN) - nwritten = 0; - else - fatal("write: %s\n", strerror(errno)); - } - count -= nwritten; - buf_ptr += nwritten; - } - - return; -} - -/* * move str to the next non-white space character (or the end of the string) */ Modified: redbutton-download/trunk/utils.h =================================================================== --- redbutton-download/trunk/utils.h 2006-03-25 10:43:15 UTC (rev 26) +++ redbutton-download/trunk/utils.h 2006-03-25 14:19:43 UTC (rev 27) @@ -37,9 +37,6 @@ /* DVB dvr device - %u is card number */ #define DVR_DEVICE "/dev/dvb/adapter%u/dvr0" -void write_string(int, const char *); -void write_all(int, const void *, size_t); - char *skip_ws(char *); char hex_digit(uint8_t); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-25 10:43:26
|
Revision: 26 Author: skilvington Date: 2006-03-25 02:43:15 -0800 (Sat, 25 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=26&view=rev Log Message: ----------- backend returns file size Modified Paths: -------------- redbutton-browser/trunk/MHEGBackend.c redbutton-download/trunk/command.c Modified: redbutton-browser/trunk/MHEGBackend.c =================================================================== --- redbutton-browser/trunk/MHEGBackend.c 2006-03-21 16:52:10 UTC (rev 25) +++ redbutton-browser/trunk/MHEGBackend.c 2006-03-25 10:43:15 UTC (rev 26) @@ -363,41 +363,46 @@ { char cmd[PATH_MAX]; FILE *sock; - char buf[8 * 1024]; + unsigned int size; size_t nread; - bool success = false; snprintf(cmd, sizeof(cmd), "file %s\n", MHEGEngine_absoluteFilename(name)); if((sock = remote_command(t, cmd)) == NULL) return false; - /* does it exist */ - if(remote_response(sock) == BACKEND_RESPONSE_OK) + /* if it exists, read the file size */ + if(remote_response(sock) != BACKEND_RESPONSE_OK + || fgets(cmd, sizeof(cmd), sock) == NULL + || sscanf(cmd, "Length %u", &size) != 1) { - verbose("Loading '%.*s'", name->size, name->data); - /* read from the socket until EOF */ - while(!feof(sock)) - { -/* TODO */ -/* could read straight into out->data rather than doing memcpy */ - if((nread = fread(buf, 1, sizeof(buf), sock)) > 0) - { - out->data = safe_realloc(out->data, out->size + nread); - memcpy(out->data + out->size, buf, nread); - out->size += nread; - } - } - success = true; + error("Unable to load '%.*s'", name->size, name->data); + fclose(sock); + return false; } - else + + verbose("Loading '%.*s'", name->size, name->data); + + out->size = size; + out->data = safe_malloc(size); + + nread = 0; + while(!feof(sock) && nread < size) + nread += fread(out->data + nread, 1, size - nread, sock); + + fclose(sock); + + /* did we read it all */ + if(nread < size) { error("Unable to load '%.*s'", name->size, name->data); + safe_free(out->data); + out->data = NULL; + out->size = 0; + return false; } - fclose(sock); - - return success; + return true; } /* @@ -410,39 +415,38 @@ { char cmd[PATH_MAX]; FILE *sock; + unsigned int size; char buf[8 * 1024]; size_t nread; - size_t nwritten; - FILE *out = NULL; + FILE *out; snprintf(cmd, sizeof(cmd), "file %s\n", MHEGEngine_absoluteFilename(name)); if((sock = remote_command(t, cmd)) == NULL) return NULL; - /* does it exist */ - if(remote_response(sock) == BACKEND_RESPONSE_OK) + /* if it exists, read the file size */ + if(remote_response(sock) != BACKEND_RESPONSE_OK + || fgets(cmd, sizeof(cmd), sock) == NULL + || sscanf(cmd, "Length %u", &size) != 1) { - /* tmpfile() will delete the file when we fclose() it */ - if((out = tmpfile()) != NULL) + fclose(sock); + return NULL; + } + + /* tmpfile() will delete the file when we fclose() it */ + out = tmpfile(); + while(out != NULL && size > 0) + { + nread = (size < sizeof(buf)) ? size : sizeof(buf); + nread = fread(buf, 1, nread, sock); + if(fwrite(buf, 1, nread, out) != nread) { - /* read from the socket until EOF */ - do - { - if((nread = fread(buf, 1, sizeof(buf), sock)) > 0) - nwritten = fwrite(buf, 1, nread, out); - else - nwritten = 0; - } - while(!feof(sock) && nread == nwritten); - /* could we write the file ok */ - if(nread != nwritten) - { - error("Unable to write to local file"); - fclose(out); - out = NULL; - } + error("Unable to write to local file"); + fclose(out); + out = NULL; } + size -= nread; } fclose(sock); Modified: redbutton-download/trunk/command.c =================================================================== --- redbutton-download/trunk/command.c 2006-03-21 16:52:10 UTC (rev 25) +++ redbutton-download/trunk/command.c 2006-03-25 10:43:15 UTC (rev 26) @@ -367,6 +367,9 @@ { char *filename; FILE *file; + long size; + char hdr[64]; + long left; size_t nread; char buff[1024 * 8]; @@ -384,15 +387,29 @@ return false; } + /* find the file length */ + if(fseek(file, 0, SEEK_END) < 0 + || (size = ftell(file)) < 0) + { + SEND_RESPONSE(500, "Error reading file"); + return false; + } + rewind(file); + SEND_RESPONSE(200, "OK"); + /* send the file length */ + snprintf(hdr, sizeof(hdr), "Length %ld\n", size); + write_string(client_sock, hdr); + /* send the file contents */ - do + left = size; + while(left > 0) { nread = fread(buff, 1, sizeof(buff), file); write_all(client_sock, buff, nread); + left -= nread; } - while(nread == sizeof(buff)); fclose(file); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-21 16:52:26
|
Revision: 25 Author: skilvington Date: 2006-03-21 08:52:10 -0800 (Tue, 21 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=25&view=rev Log Message: ----------- remove old-code.c Removed Paths: ------------- redbutton-browser/trunk/old-code.c Deleted: redbutton-browser/trunk/old-code.c =================================================================== --- redbutton-browser/trunk/old-code.c 2006-03-20 10:03:14 UTC (rev 24) +++ redbutton-browser/trunk/old-code.c 2006-03-21 16:52:10 UTC (rev 25) @@ -1,567 +0,0 @@ -print values of variables in ElementaryAction_execute - -{ -VariableClass *var; -ObjectReference ref; -ref.choice = ObjectReference_external_reference; -ref.u.external_reference.object_number = 204; -ref.u.external_reference.group_identifier.size = 3; -ref.u.external_reference.group_identifier.data = "~/a"; -if((var = (VariableClass *) MHEGEngine_findObjectReference(&ref, NULL)) && var->rootClass.inst.rtti == RTTI_VariableClass) -{ - printf("%s = ", ObjectReference_name(&ref)); - printf("%s\n", ObjectReference_name(&var->inst.Value->u.object_reference)); -} -ref.u.external_reference.object_number = 234; -if((var = (VariableClass *) MHEGEngine_findObjectReference(&ref, NULL)) && var->rootClass.inst.rtti == RTTI_VariableClass) -{ - printf("%s = ", ObjectReference_name(&ref)); - printf("%.*s\n", var->inst.Value->u.octetstring.size, var->inst.Value->u.octetstring.data); -} -} - ---------------------------------------------------------------------------------------------- - -print active links in MHEGEngine_run - -{ -LIST_TYPE(LinkClassPtr) *l = engine.active_links; -while(l) -{ - printf("%s; ", ObjectReference_name(&l->item->link_condition.event_source)); - printf("%s ", EventType_name(l->item->link_condition.event_type)); - if(l->item->link_condition.have_event_data && l->item->link_condition.event_data.choice == EventData_integer) - printf("%d", l->item->link_condition.event_data.u.integer); - printf("\n"); - l = l->next; -} -printf("\n"); -} - ---------------------------------------------------------------------------------------------- - -from MHEGDisplay_newBitmap() - -this works, ie creates a scaled up copy of the bitmap and mask -but I can't get rid of the black line along the bottom and right hand side - -/* set the xform matrix */ -... -/* set the filters */ -... -/* cache the scaled image */ -Pixmap unscaled; -Picture unscaled_pic; -XRenderColor transparent = { 0, 0, 0, 0 }; -XRenderColor opaque = { 65535, 65535, 65535, 65535 }; -unsigned int scaled_width = (c->width * d->xres) / MHEG_XRES; -unsigned int scaled_height = (c->height * d->yres) / MHEG_YRES; - -unscaled = b->image; -unscaled_pic = b->image_pic; -b->image = XCreatePixmap(d->dpy, d->win, scaled_width, scaled_height, d->depth); -b->image_pic = XRenderCreatePicture(d->dpy, b->image, d->pic_format, 0, NULL); -XRenderFillRectangle(d->dpy, PictOpSrc, b->image_pic, &transparent, 0, 0, scaled_width, scaled_height); -XRenderComposite(d->dpy, PictOpOver, unscaled_pic, None, b->image_pic, 0, 0, 0, 0, 0, 0, scaled_width, scaled_height); -XRenderFreePicture(d->dpy, unscaled_pic); -XFreePixmap(d->dpy, unscaled); -/* cache the scaled mask */ -unscaled = b->mask; -unscaled_pic = b->mask_pic; -b->mask = XCreatePixmap(d->dpy, d->win, scaled_width, scaled_height, d->depth); -b->mask_pic = XRenderCreatePicture(d->dpy, b->mask, d->pic_format, 0, NULL); -XRenderFillRectangle(d->dpy, PictOpSrc, b->mask_pic, &opaque, 0, 0, scaled_width, scaled_height); -XRenderComposite(d->dpy, PictOpOver, unscaled_pic, None, b->mask_pic, 0, 0, 0, 0, 0, 0, scaled_width, scaled_height); -XRenderFreePicture(d->dpy, unscaled_pic); -XFreePixmap(d->dpy, unscaled); - - ------------------------------ - -UK MHEG Profile doesnt need to support ButtonClass or its derivatives - -<HotspotClass> -typedef struct HotspotClassInstanceVars -{ - /* inherited from VisibleClass */ - OriginalBoxSize *BoxSize; - XYPosition *Position; - bool have_PaletteRef; /* OPTIONAL */ - ObjectReference *PaletteRef; - /* inherited from ButtonClass */ - bool SelectionStatus; -} HotspotClassInstanceVars; -</HotspotClass> - -void -default_HotspotClassInstanceVars(HotspotClass *t, HotspotClassInstanceVars *v) -{ - bzero(v, sizeof(HotspotClassInstanceVars)); - - /* VisibleClass */ - v->BoxSize = &t->ButtonClass.original_box_size; - v->Position = &t->ButtonClass.original_position; - v->have_PaletteRef = t->ButtonClass.have_original_palette_ref; - v->PaletteRef= &t->ButtonClass.original_palette_ref; - - /* ButtonClass */ - v->SelectionStatus = false; - - return; -} - -void -free_HotspotClassInstanceVars(HotspotClassInstanceVars *v) -{ - return; -} - -<PushButtonClass> -typedef struct PushButtonClassInstanceVars -{ - /* inherited from VisibleClass */ - OriginalBoxSize *BoxSize; - XYPosition *Position; - bool have_PaletteRef; /* OPTIONAL */ - ObjectReference *PaletteRef; - /* inherited from ButtonClass */ - bool SelectionStatus; - /* PushButtonClass */ - bool have_Label; /* OPTIONAL */ - OctetString *Label; -} PushButtonClassInstanceVars; -</PushButtonClass> - -void -default_PushButtonClassInstanceVars(PushButtonClass *t, PushButtonClassInstanceVars *v) -{ - bzero(v, sizeof(PushButtonClassInstanceVars)); - - /* VisibleClass */ - v->BoxSize = &t->original_box_size; - v->Position = &t->original_position; - v->have_PaletteRef = t->have_original_palette_ref; - v->PaletteRef= &t->original_palette_ref; - - /* ButtonClass */ - v->SelectionStatus = false; - - /* PushButtonClass */ - v->have_Label = t->have_original_label; - v->Label = &t->original_label; - - return; -} - -void -free_PushButtonClassInstanceVars(PushButtonClassInstanceVars *v) -{ - return; -} - -<SwitchButtonClass> -typedef struct SwitchButtonClassInstanceVars -{ - /* inherited from VisibleClass */ - OriginalBoxSize *BoxSize; - XYPosition *Position; - bool have_PaletteRef; /* OPTIONAL */ - ObjectReference *PaletteRef; - /* inherited from ButtonClass */ - bool SelectionStatus; - /* inherited from PushButtonClass */ - bool have_Label; /* OPTIONAL */ - OctetString *Label; -} SwitchButtonClassInstanceVars; -</SwitchButtonClass> - -void -default_SwitchButtonClassInstanceVars(SwitchButtonClass *t, SwitchButtonClassInstanceVars *v) -{ - bzero(v, sizeof(SwitchButtonClassInstanceVars)); - - /* VisibleClass */ - v->BoxSize = &t->original_box_size; - v->Position = &t->original_position; - v->have_PaletteRef = t->have_original_palette_ref; - v->PaletteRef= &t->original_palette_ref; - - /* ButtonClass */ - v->SelectionStatus = false; - - /* PushButtonClass */ - v->have_Label = t->have_original_label; - v->Label = &t->original_label; - - return; -} - -void -free_SwitchButtonClassInstanceVars(SwitchButtonClassInstanceVars *v) -{ - return; -} - - - ------------------------------------------------------------------------------------------------------------ - -UK MHEG Profile doesnt need to support RTGraphicsClass - -<RTGraphicsClass> -typedef struct RTGraphicsClassInstanceVars -{ - /* inherited from VisibleClass */ - OriginalBoxSize *BoxSize; - XYPosition *Position; - bool have_PaletteRef; /* OPTIONAL */ - ObjectReference *PaletteRef; -} RTGraphicsClassInstanceVars; -</RTGraphicsClass> - -void -default_RTGraphicsClassInstanceVars(RTGraphicsClass *t, RTGraphicsClassInstanceVars *v) -{ - bzero(v, sizeof(RTGraphicsClassInstanceVars)); - - /* VisibleClass */ - v->BoxSize = &t->original_box_size; - v->Position = &t->original_position; - v->have_PaletteRef = t->have_original_palette_ref; - v->PaletteRef= &t->original_palette_ref; - - return; -} - -void -free_RTGraphicsClassInstanceVars(RTGraphicsClassInstanceVars *v) -{ - return; -} - ------------------------------------------------------------------------------------------------------ - -VisibleClass and IngredientClass are abstract and so should never be created - -<VisibleClass> -typedef struct VisibleClassInstanceVars -{ - OriginalBoxSize *BoxSize; - XYPosition *Position; - bool have_PaletteRef; /* OPTIONAL */ - ObjectReference *PaletteRef; -} VisibleClassInstanceVars; -</VisibleClass> - -void -default_VisibleClassInstanceVars(VisibleClass *t, VisibleClassInstanceVars *v) -{ - bzero(v, sizeof(VisibleClassInstanceVars)); - - v->BoxSize = &t->original_box_size; - v->Position = &t->original_position; - v->have_PaletteRef = t->have_original_palette_ref; - v->PaletteRef= &t->original_palette_ref; - - return; -} - -void -free_VisibleClassInstanceVars(VisibleClassInstanceVars *v) -{ - return; -} - -<IngredientClass> -typedef struct IngredientClassInstanceVars -{ - bool have_Content; /* OPTIONAL */ - ContentBody *Content; -} IngredientClassInstanceVars; -</IngredientClass> - -void -default_IngredientClassInstanceVars(IngredientClass *t, IngredientClassInstanceVars *v) -{ - bzero(v, sizeof(IngredientClassInstanceVars)); - - v->have_Content = t->have_original_content; - v->Content = &t->original_content; - - return; -} - -void -free_IngredientClassInstanceVars(IngredientClassInstanceVars *v) -{ - return; -} - -------------------------------------------------------------------------------------------------- - - - -/* - * IngredientClass.c - */ - -#include "MHEGEngine.h" -#include "IngredientClass.h" -#include "RemoteProgramClass.h" -#include "ResidentProgramClass.h" -#include "InterchangedProgramClass.h" -#include "PaletteClass.h" -#include "FontClass.h" -#include "CursorShapeClass.h" -#include "VariableClass.h" -#include "LinkClass.h" -#include "AudioClass.h" -#include "VideoClass.h" -#include "RTGraphicsClass.h" -#include "StreamClass.h" -#include "BitmapClass.h" -#include "DynamicLineArtClass.h" -#include "RectangleClass.h" -#include "HotspotClass.h" -#include "SwitchButtonClass.h" -#include "PushButtonClass.h" -#include "TextClass.h" -#include "EntryFieldClass.h" -#include "HyperTextClass.h" -#include "SliderClass.h" -#include "TokenGroupClass.h" -#include "ListGroupClass.h" -#include "rtti.h" - -void -IngredientClass_Unload(RootClass *r) -{ - switch(r->inst.rtti) - { - case RTTI_RemoteProgramClass: - RemoteProgramClass_Destruction((RemoteProgramClass *) r); - break; - - case RTTI_ResidentProgramClass: - ResidentProgramClass_Destruction((ResidentProgramClass *) r); - break; - - case RTTI_InterchangedProgramClass: - InterchangedProgramClass_Destruction((InterchangedProgramClass *) r); - break; - - case RTTI_PaletteClass: - PaletteClass_Destruction((PaletteClass *) r); - break; - - case RTTI_FontClass: - FontClass_Destruction((FontClass *) r); - break; - - case RTTI_CursorShapeClass: - CursorShapeClass_Destruction((CursorShapeClass *) r); - break; - - case RTTI_VariableClass: - VariableClass_Destruction((VariableClass *) r); - break; - - case RTTI_LinkClass: - LinkClass_Destruction((LinkClass *) r); - break; - - case RTTI_AudioClass: - AudioClass_Destruction((AudioClass *) r); - break; - - case RTTI_VideoClass: - VideoClass_Destruction((VideoClass *) r); - break; - - case RTTI_RTGraphicsClass: - RTGraphicsClass_Destruction((RTGraphicsClass *) r); - break; - - case RTTI_StreamClass: - StreamClass_Destruction((StreamClass *) r); - break; - - case RTTI_BitmapClass: - BitmapClass_Destruction((BitmapClass *) r); - break; - - case RTTI_DynamicLineArtClass: - DynamicLineArtClass_Destruction((DynamicLineArtClass *) r); - break; - - case RTTI_RectangleClass: - RectangleClass_Destruction((RectangleClass *) r); - break; - - case RTTI_HotspotClass: - HotspotClass_Destruction((HotspotClass *) r); - break; - - case RTTI_SwitchButtonClass: - SwitchButtonClass_Destruction((SwitchButtonClass *) r); - break; - - case RTTI_PushButtonClass: - PushButtonClass_Destruction((PushButtonClass *) r); - break; - - case RTTI_TextClass: - TextClass_Destruction((TextClass *) r); - break; - - case RTTI_EntryFieldClass: - EntryFieldClass_Destruction((EntryFieldClass *) r); - break; - - case RTTI_HyperTextClass: - HyperTextClass_Destruction((HyperTextClass *) r); - break; - - case RTTI_SliderClass: - SliderClass_Destruction((SliderClass *) r); - break; - - case RTTI_TokenGroupClass: - TokenGroupClass_Destruction((TokenGroupClass *) r); - break; - - case RTTI_ListGroupClass: - ListGroupClass_Destruction((ListGroupClass *) r); - break; - - default: - error("Unknown IngredientClass type: %d", r->inst.rtti); - break; - } - - return; -} - -------------------------------------------------------------------------------------- - -hand written dup/copy routines... - -/* - * calls safe_free on any existing data in dst - * (use ObjectReference_dup if dst is not initialised) - */ - -void -ObjectReference_copy(ObjectReference *dst, ObjectReference *src) -{ - /* free any existing data */ - if(dst->choice == ObjectReference_external_reference) - safe_free(dst->u.external_reference.group_identifier.data); - - dst->choice = src->choice; - - switch(src->choice) - { - case ObjectReference_internal_reference: - dst->u.internal_reference = src->u.internal_reference; - break; - - case ObjectReference_external_reference: - OctetString_dup(&dst->u.external_reference.group_identifier, &src->u.external_reference.group_identifier); - dst->u.external_reference.object_number = src->u.external_reference.object_number; - break; - - default: - error("Unknown ObjectReference type: %d", src->choice); - break; - } - - return; -} - -/* - * should only be used when dst is uninitialised - * any existing data in dst will be lost - * (use ObjectReference_copy if dst is initialised) - */ - -void -ObjectReference_dup(ObjectReference *dst, ObjectReference *src) -{ - dst->choice = src->choice; - - switch(src->choice) - { - case ObjectReference_internal_reference: - dst->u.internal_reference = src->u.internal_reference; - break; - - case ObjectReference_external_reference: - OctetString_dup(&dst->u.external_reference.group_identifier, &src->u.external_reference.group_identifier); - dst->u.external_reference.object_number = src->u.external_reference.object_number; - break; - - default: - error("Unknown ObjectReference type: %d", src->choice); - break; - } - - return; -} - -/* - * free's any exisiting data - */ - -void -OriginalValue_copy(OriginalValue *dst, OriginalValue *src) -{ - /* free any old data */ - free_OriginalValue(dst); - - /* dup the new data */ - OriginalValue_dup(dst, src); - - return; -} - -/* - * any existing data in dst will be lost - */ - -void -OriginalValue_dup(OriginalValue *dst, OriginalValue *src) -{ - dst->choice = src->choice; - - switch(dst->choice) - { - case OriginalValue_boolean: - dst->u.boolean = src->u.boolean; - break; - - case OriginalValue_integer: - dst->u.integer = src->u.integer; - break; - - case OriginalValue_octetstring: - OctetString_dup(&dst->u.octetstring, &src->u.octetstring); - break; - - case OriginalValue_object_reference: - ObjectReference_dup(&dst->u.object_reference, &src->u.object_reference); - break; - - case OriginalValue_content_reference: - /* ContentReference is just an OctetString */ - OctetString_dup(&dst->u.content_reference, &src->u.content_reference); - break; - - default: - error("Unknown OriginalValue type: %d", dst->choice); - break; - } - - return; -} - This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-20 10:03:25
|
Revision: 24 Author: skilvington Date: 2006-03-20 02:03:14 -0800 (Mon, 20 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=24&view=rev Log Message: ----------- add extra TODO item Modified Paths: -------------- redbutton-download/trunk/TODO Modified: redbutton-download/trunk/TODO =================================================================== --- redbutton-download/trunk/TODO 2006-03-18 17:51:02 UTC (rev 23) +++ redbutton-download/trunk/TODO 2006-03-20 10:03:14 UTC (rev 24) @@ -1,3 +1,5 @@ +be able to read from a file + have a verbose flag use a linked list of modules rather than an array in struct carousel This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-18 17:51:11
|
Revision: 23 Author: skilvington Date: 2006-03-18 09:51:02 -0800 (Sat, 18 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=23&view=rev Log Message: ----------- set stream FILE to NULL when closed Modified Paths: -------------- redbutton-browser/trunk/MHEGStreamPlayer.c Modified: redbutton-browser/trunk/MHEGStreamPlayer.c =================================================================== --- redbutton-browser/trunk/MHEGStreamPlayer.c 2006-03-18 09:56:46 UTC (rev 22) +++ redbutton-browser/trunk/MHEGStreamPlayer.c 2006-03-18 17:51:02 UTC (rev 23) @@ -75,7 +75,10 @@ verbose("MHEGStreamPlayer_stop"); if(p->ts != NULL) + { fclose(p->ts); + p->ts = NULL; + } return; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-18 09:57:03
|
Revision: 22 Author: skilvington Date: 2006-03-18 01:56:46 -0800 (Sat, 18 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=22&view=rev Log Message: ----------- return audio/video PIDs to stream player Modified Paths: -------------- redbutton-browser/trunk/MHEGBackend.c redbutton-browser/trunk/MHEGBackend.h redbutton-browser/trunk/MHEGEngine.c redbutton-browser/trunk/MHEGEngine.h redbutton-browser/trunk/MHEGStreamPlayer.c redbutton-browser/trunk/MHEGStreamPlayer.h Modified: redbutton-browser/trunk/MHEGBackend.c =================================================================== --- redbutton-browser/trunk/MHEGBackend.c 2006-03-15 16:03:26 UTC (rev 21) +++ redbutton-browser/trunk/MHEGBackend.c 2006-03-18 09:56:46 UTC (rev 22) @@ -17,7 +17,7 @@ bool local_checkContentRef(MHEGBackend *, ContentReference *); bool local_loadFile(MHEGBackend *, OctetString *, OctetString *); FILE *local_openFile(MHEGBackend *, OctetString *); -FILE *local_openStream(MHEGBackend *, bool, int, bool, int); +FILE *local_openStream(MHEGBackend *, bool, int *, bool, int *); static struct MHEGBackendFns local_backend_fns = { @@ -31,7 +31,7 @@ bool remote_checkContentRef(MHEGBackend *, ContentReference *); bool remote_loadFile(MHEGBackend *, OctetString *, OctetString *); FILE *remote_openFile(MHEGBackend *, OctetString *); -FILE *remote_openStream(MHEGBackend *, bool, int, bool, int); +FILE *remote_openStream(MHEGBackend *, bool, int *, bool, int *); static struct MHEGBackendFns remote_backend_fns = { @@ -305,13 +305,14 @@ /* * return a read-only FILE handle for an MPEG Transport Stream * the TS will contain an audio stream (if have_audio is true) and a video stream (if have_video is true) - * the audio_tag and video_tag numbers refer to Component/Association Tag values from the DVB PMT - * if audio_tag or video_tag is -1, the default audio and/or video stream for the current Service ID is used + * the *audio_tag and *video_tag numbers refer to Component/Association Tag values from the DVB PMT + * if *audio_tag or *video_tag is -1, the default audio and/or video stream for the current Service ID is used + * updates *audio_tag and/or *video_tag to the actual PIDs in the Transport Stream * returns NULL on error */ FILE * -local_openStream(MHEGBackend *t, bool have_audio, int audio_tag, bool have_video, int video_tag) +local_openStream(MHEGBackend *t, bool have_audio, int *audio_tag, bool have_video, int *video_tag) { /* * we need to convert the audio/video_tag into PIDs @@ -456,40 +457,67 @@ /* * return a read-only FILE handle for an MPEG Transport Stream * the TS will contain an audio stream (if have_audio is true) and a video stream (if have_video is true) - * the audio_tag and video_tag numbers refer to Component/Association Tag values from the DVB PMT - * if audio_tag or video_tag is -1, the default audio and/or video stream for the current Service ID is used + * the *audio_tag and *video_tag numbers refer to Component/Association Tag values from the DVB PMT + * if *audio_tag or *video_tag is -1, the default audio and/or video stream for the current Service ID is used + * updates *audio_tag and/or *video_tag to the actual PIDs in the Transport Stream * returns NULL on error */ FILE * -remote_openStream(MHEGBackend *t, bool have_audio, int audio_tag, bool have_video, int video_tag) +remote_openStream(MHEGBackend *t, bool have_audio, int *audio_tag, bool have_video, int *video_tag) { char cmd[PATH_MAX]; FILE *sock; + char pids[128]; + unsigned int audio_pid = 0; + unsigned int video_pid = 0; + bool err; /* no PIDs required */ if(!have_audio && !have_video) return NULL; /* video and audio */ else if(have_audio && have_video) - snprintf(cmd, sizeof(cmd), "avstream %d %d\n", audio_tag, video_tag); + snprintf(cmd, sizeof(cmd), "avstream %d %d\n", *audio_tag, *video_tag); /* audio only */ else if(have_audio) - snprintf(cmd, sizeof(cmd), "astream %d\n", audio_tag); + snprintf(cmd, sizeof(cmd), "astream %d\n", *audio_tag); /* video only */ else - snprintf(cmd, sizeof(cmd), "vstream %d\n", video_tag); + snprintf(cmd, sizeof(cmd), "vstream %d\n", *video_tag); if((sock = remote_command(t, cmd)) == NULL) return NULL; /* did it work */ - if(remote_response(sock) != BACKEND_RESPONSE_OK) + if(remote_response(sock) != BACKEND_RESPONSE_OK + || fgets(pids, sizeof(pids), sock) == NULL) { fclose(sock); sock = NULL; } + /* update the PID variables */ + if(have_audio && have_video) + err = (sscanf(pids, "AudioPID %u VideoPID %u", &audio_pid, &video_pid) != 2); + else if(have_audio) + err = (sscanf(pids, "AudioPID %u", &audio_pid) != 1); + else + err = (sscanf(pids, "VideoPID %u", &video_pid) != 1); + + if(!err) + { + if(have_audio) + *audio_tag = audio_pid; + if(have_video) + *video_tag = video_pid; + } + else + { + fclose(sock); + sock = NULL; + } + return sock; } Modified: redbutton-browser/trunk/MHEGBackend.h =================================================================== --- redbutton-browser/trunk/MHEGBackend.h 2006-03-15 16:03:26 UTC (rev 21) +++ redbutton-browser/trunk/MHEGBackend.h 2006-03-18 09:56:46 UTC (rev 22) @@ -22,7 +22,7 @@ bool (*checkContentRef)(struct MHEGBackend *, ContentReference *); /* check a carousel file exists */ bool (*loadFile)(struct MHEGBackend *, OctetString *, OctetString *); /* load a carousel file */ FILE *(*openFile)(struct MHEGBackend *, OctetString *); /* open a carousel file */ - FILE *(*openStream)(struct MHEGBackend *, bool, int, bool, int); /* open an MPEG Transport Stream */ + FILE *(*openStream)(struct MHEGBackend *, bool, int *, bool, int *); /* open an MPEG Transport Stream */ } *fns; } MHEGBackend; Modified: redbutton-browser/trunk/MHEGEngine.c =================================================================== --- redbutton-browser/trunk/MHEGEngine.c 2006-03-15 16:03:26 UTC (rev 21) +++ redbutton-browser/trunk/MHEGEngine.c 2006-03-18 09:56:46 UTC (rev 22) @@ -1331,6 +1331,21 @@ } /* + * return a read-only FILE handle for an MPEG Transport Stream + * the TS will contain an audio stream (if have_audio is true) and a video stream (if have_video is true) + * the *audio_tag and *video_tag numbers refer to Component/Association Tag values from the DVB PMT + * if *audio_tag or *video_tag is -1, the default audio and/or video stream for the current Service ID is used + * updates *audio_tag and/or *video_tag to the actual PIDs in the Transport Stream + * returns NULL on error + */ + +FILE * +MHEGEngine_openStream(bool have_audio, int *audio_tag, bool have_video, int *video_tag) +{ + return (*(engine.backend.fns->openStream))(&engine.backend, have_audio, audio_tag, have_video, video_tag); +} + +/* * returns the absolute group ID, ie it always starts with "~//" * returns a ptr to static string that will be overwritten by the next call to this routine * section 8.3.2 of the UK MHEG Profile says the filename prefixes are: Modified: redbutton-browser/trunk/MHEGEngine.h =================================================================== --- redbutton-browser/trunk/MHEGEngine.h 2006-03-15 16:03:26 UTC (rev 21) +++ redbutton-browser/trunk/MHEGEngine.h 2006-03-18 09:56:46 UTC (rev 22) @@ -221,6 +221,7 @@ bool MHEGEngine_checkContentRef(ContentReference *); bool MHEGEngine_loadFile(OctetString *, OctetString *); FILE *MHEGEngine_openFile(OctetString *); +FILE *MHEGEngine_openStream(bool, int *, bool, int *); char *MHEGEngine_absoluteFilename(OctetString *); Modified: redbutton-browser/trunk/MHEGStreamPlayer.c =================================================================== --- redbutton-browser/trunk/MHEGStreamPlayer.c 2006-03-15 16:03:26 UTC (rev 21) +++ redbutton-browser/trunk/MHEGStreamPlayer.c 2006-03-18 09:56:46 UTC (rev 22) @@ -5,6 +5,7 @@ #include <string.h> #include <stdio.h> +#include "MHEGEngine.h" #include "MHEGStreamPlayer.h" #include "utils.h" @@ -35,6 +36,7 @@ p->have_video = true; p->video_tag = tag; + p->video_pid = -1; return; } @@ -47,6 +49,7 @@ p->have_audio = true; p->audio_tag = tag; + p->audio_pid = -1; return; } @@ -54,10 +57,14 @@ void MHEGStreamPlayer_play(MHEGStreamPlayer *p) { + verbose("MHEGStreamPlayer_play: audio_tag=%d video_tag=%d", p->audio_tag, p->video_tag); + + p->audio_pid = p->audio_tag; + p->video_pid = p->video_tag; +// if((p->ts = MHEGEngine_openStream(p->have_audio, &p->audio_pid, p->have_video, &p->video_pid)) == NULL) +// error("Unable to open MPEG stream"); /* TODO */ printf("TODO: MHEGStreamPlayer_play: not yet implemented\n"); -if(p->have_audio) printf("TODO: audio tag=%d\n", p->audio_tag); -if(p->have_video) printf("TODO: video tag=%d\n", p->video_tag); return; } @@ -65,9 +72,11 @@ void MHEGStreamPlayer_stop(MHEGStreamPlayer *p) { -/* TODO */ -printf("TODO: MHEGStreamPlayer_stop: not yet implemented\n"); + verbose("MHEGStreamPlayer_stop"); + if(p->ts != NULL) + fclose(p->ts); + return; } Modified: redbutton-browser/trunk/MHEGStreamPlayer.h =================================================================== --- redbutton-browser/trunk/MHEGStreamPlayer.h 2006-03-15 16:03:26 UTC (rev 21) +++ redbutton-browser/trunk/MHEGStreamPlayer.h 2006-03-18 09:56:46 UTC (rev 22) @@ -13,6 +13,9 @@ bool have_audio; /* false if we have no audio stream */ int video_tag; /* video stream component tag (-1 => default for current service ID) */ int audio_tag; /* audio stream component tag (-1 => default for current service ID) */ + int video_pid; /* PID in MPEG Transport Stream (-1 => not yet known) */ + int audio_pid; /* PID in MPEG Transport Stream (-1 => not yet known) */ + FILE *ts; /* MPEG Transport Stream */ } MHEGStreamPlayer; void MHEGStreamPlayer_init(MHEGStreamPlayer *); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-15 16:03:36
|
Revision: 21 Author: skilvington Date: 2006-03-15 08:03:26 -0800 (Wed, 15 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=21&view=rev Log Message: ----------- open audio and video streams in blocking mode Modified Paths: -------------- redbutton-download/trunk/command.c redbutton-download/trunk/stream.c Modified: redbutton-download/trunk/command.c =================================================================== --- redbutton-download/trunk/command.c 2006-03-15 14:47:18 UTC (rev 20) +++ redbutton-download/trunk/command.c 2006-03-15 16:03:26 UTC (rev 21) @@ -162,7 +162,7 @@ } /* we can now read a transport stream from the dvr device */ - if((ts_fd = open(car->dvr_device, O_RDONLY | O_NONBLOCK)) < 0) + if((ts_fd = open(car->dvr_device, O_RDONLY)) < 0) { SEND_RESPONSE(500, "Unable to open DVB device"); close(audio_fd); @@ -222,7 +222,7 @@ } /* we can now read a transport stream from the dvr device */ - if((ts_fd = open(car->dvr_device, O_RDONLY | O_NONBLOCK)) < 0) + if((ts_fd = open(car->dvr_device, O_RDONLY)) < 0) { SEND_RESPONSE(500, "Unable to open DVB device"); close(video_fd); @@ -297,7 +297,7 @@ } /* we can now read a transport stream from the dvr device */ - if((ts_fd = open(car->dvr_device, O_RDONLY | O_NONBLOCK)) < 0) + if((ts_fd = open(car->dvr_device, O_RDONLY)) < 0) { SEND_RESPONSE(500, "Unable to open DVB device"); close(audio_fd); Modified: redbutton-download/trunk/stream.c =================================================================== --- redbutton-download/trunk/stream.c 2006-03-15 14:47:18 UTC (rev 20) +++ redbutton-download/trunk/stream.c 2006-03-15 16:03:26 UTC (rev 21) @@ -54,8 +54,10 @@ nread = read(ts_fd, _ts_buf, sizeof(_ts_buf)); if(nread > 0) nwritten = write(client_sock, _ts_buf, nread); + else + nwritten = nread; } - while(nread > 0 && nread == nwritten); + while(nread == nwritten); return; } This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-15 14:47:22
|
Revision: 20 Author: skilvington Date: 2006-03-15 06:47:18 -0800 (Wed, 15 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=20&view=rev Log Message: ----------- expect correct number of args to stream commands Modified Paths: -------------- redbutton-download/trunk/command.c Modified: redbutton-download/trunk/command.c =================================================================== --- redbutton-download/trunk/command.c 2006-03-15 14:30:18 UTC (rev 19) +++ redbutton-download/trunk/command.c 2006-03-15 14:47:18 UTC (rev 20) @@ -144,7 +144,7 @@ int ts_fd; char hdr[64]; - CHECK_USAGE(1, "astream <ComponentTag>"); + CHECK_USAGE(2, "astream <ComponentTag>"); tag = strtol(argv[1], NULL, 0); @@ -204,7 +204,7 @@ int ts_fd; char hdr[64]; - CHECK_USAGE(1, "vstream <ComponentTag>"); + CHECK_USAGE(2, "vstream <ComponentTag>"); tag = strtol(argv[1], NULL, 0); @@ -267,7 +267,7 @@ int ts_fd; char hdr[64]; - CHECK_USAGE(2, "avstream <AudioTag> <VideoTag>"); + CHECK_USAGE(3, "avstream <AudioTag> <VideoTag>"); audio_tag = strtol(argv[1], NULL, 0); video_tag = strtol(argv[2], NULL, 0); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-15 14:30:21
|
Revision: 19 Author: skilvington Date: 2006-03-15 06:30:18 -0800 (Wed, 15 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=19&view=rev Log Message: ----------- hide _ts_buf outside this file Modified Paths: -------------- redbutton-download/trunk/stream.c Modified: redbutton-download/trunk/stream.c =================================================================== --- redbutton-download/trunk/stream.c 2006-03-15 14:21:25 UTC (rev 18) +++ redbutton-download/trunk/stream.c 2006-03-15 14:30:18 UTC (rev 19) @@ -41,7 +41,7 @@ } /* don't want it on the stack */ -unsigned char _ts_buf[8 * 1024]; +static unsigned char _ts_buf[8 * 1024]; void stream_ts(int ts_fd, int client_sock) This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-15 14:21:34
|
Revision: 18 Author: skilvington Date: 2006-03-15 06:21:25 -0800 (Wed, 15 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=18&view=rev Log Message: ----------- allow rb-download to stream audio and video to rb-browser Modified Paths: -------------- redbutton-download/trunk/Makefile redbutton-download/trunk/command.c Added Paths: ----------- redbutton-download/trunk/stream.c redbutton-download/trunk/stream.h Modified: redbutton-download/trunk/Makefile =================================================================== --- redbutton-download/trunk/Makefile 2006-03-15 12:39:15 UTC (rev 17) +++ redbutton-download/trunk/Makefile 2006-03-15 14:21:25 UTC (rev 18) @@ -6,6 +6,7 @@ findmheg.o \ listen.o \ command.o \ + stream.o \ assoc.o \ carousel.o \ module.o \ Modified: redbutton-download/trunk/command.c =================================================================== --- redbutton-download/trunk/command.c 2006-03-15 12:39:15 UTC (rev 17) +++ redbutton-download/trunk/command.c 2006-03-15 14:21:25 UTC (rev 18) @@ -2,22 +2,30 @@ * command.c */ +#include <unistd.h> #include <stdio.h> #include <string.h> #include <stdbool.h> +#include <stdint.h> +#include <fcntl.h> #include "command.h" +#include "assoc.h" #include "fs.h" +#include "stream.h" #include "utils.h" /* max number of args that can be passed to a command (arbitrary) */ #define ARGV_MAX 10 /* the commands */ +bool cmd_astream(struct listen_data *, int, int, char **); +bool cmd_avstream(struct listen_data *, int, int, char **); bool cmd_check(struct listen_data *, int, int, char **); bool cmd_file(struct listen_data *, int, int, char **); bool cmd_help(struct listen_data *, int, int, char **); bool cmd_quit(struct listen_data *, int, int, char **); +bool cmd_vstream(struct listen_data *, int, int, char **); static struct { @@ -27,11 +35,14 @@ char *help; } command[] = { + { "astream", "<ComponentTag>", cmd_astream, "Stream the given audio component tag" }, + { "avstream", "<AudioTag> <VideoTag>", cmd_avstream, "Stream the given audio and video component tags" }, { "check", "<ContentReference>", cmd_check, "Check if the given file exists on the carousel" }, { "exit", "", cmd_quit, "Kill the programme" }, { "file", "<ContentReference>", cmd_file, "Retrieve the given file from the carousel" }, { "help", "", cmd_help, "List available commands" }, { "quit", "", cmd_quit, "Kill the programme" }, + { "vstream", "<ComponentTag>", cmd_vstream, "Stream the given video component tag" }, { NULL, NULL, NULL, NULL } }; @@ -116,6 +127,203 @@ } /* + * astream <tag> + * send the given audio stream down the connection + * the tag should be an association/component_tag number as found in the PMT + * the tag is converted to a PID and that PID is sent as a MPEG Transport Stream down the connection + * if tag is -1, the default audio stream for the current service_id is sent + */ + +bool +cmd_astream(struct listen_data *listen_data, int client_sock, int argc, char *argv[]) +{ + struct carousel *car = listen_data->carousel; + int tag; + uint16_t pid; + int audio_fd; + int ts_fd; + char hdr[64]; + + CHECK_USAGE(1, "astream <ComponentTag>"); + + tag = strtol(argv[1], NULL, 0); + + /* map the tag to a PID, or use the default */ + if(tag == -1) + pid = car->audio_pid; + else + pid = stream2pid(&car->assoc, tag); + + /* add the PID to the demux device */ + if((audio_fd = add_demux_filter(car->demux_device, pid, DMX_PES_AUDIO)) < 0) + { + SEND_RESPONSE(500, "Unable to open audio PID"); + return false; + } + + /* we can now read a transport stream from the dvr device */ + if((ts_fd = open(car->dvr_device, O_RDONLY | O_NONBLOCK)) < 0) + { + SEND_RESPONSE(500, "Unable to open DVB device"); + close(audio_fd); + return false; + } + + /* send the OK code */ + SEND_RESPONSE(200, "OK"); + + /* tell the client what PID the component tag resolved to */ + snprintf(hdr, sizeof(hdr), "AudioPID %u\n", pid); + write_string(client_sock, hdr); + + /* shovel the transport stream down client_sock until the client closes it or we get an error */ + stream_ts(ts_fd, client_sock); + + /* clean up */ + close(ts_fd); + close(audio_fd); + + return false; +} + +/* + * vstream <tag> + * send the given video stream down the connection + * the tag should be an association/component_tag number as found in the PMT + * the tag is converted to a PID and that PID is sent as a MPEG Transport Stream down the connection + * if tag is -1, the default video stream for the current service_id is sent + */ + +bool +cmd_vstream(struct listen_data *listen_data, int client_sock, int argc, char *argv[]) +{ + struct carousel *car = listen_data->carousel; + int tag; + uint16_t pid; + int video_fd; + int ts_fd; + char hdr[64]; + + CHECK_USAGE(1, "vstream <ComponentTag>"); + + tag = strtol(argv[1], NULL, 0); + + /* map the tag to a PID, or use the default */ + if(tag == -1) + pid = car->video_pid; + else + pid = stream2pid(&car->assoc, tag); + + /* add the PID to the demux device */ + if((video_fd = add_demux_filter(car->demux_device, pid, DMX_PES_VIDEO)) < 0) + { + SEND_RESPONSE(500, "Unable to open video PID"); + return false; + } + + /* we can now read a transport stream from the dvr device */ + if((ts_fd = open(car->dvr_device, O_RDONLY | O_NONBLOCK)) < 0) + { + SEND_RESPONSE(500, "Unable to open DVB device"); + close(video_fd); + return false; + } + + /* send the OK code */ + SEND_RESPONSE(200, "OK"); + + /* tell the client what PID the component tag resolved to */ + snprintf(hdr, sizeof(hdr), "VideoPID %u\n", pid); + write_string(client_sock, hdr); + + /* shovel the transport stream down client_sock until the client closes it or we get an error */ + stream_ts(ts_fd, client_sock); + + /* clean up */ + close(ts_fd); + close(video_fd); + + return false; +} + +/* + * avstream <audio_tag> <video_tag> + * send the given audio and video streams down the connection + * the tags should be association/component_tag numbers as found in the PMT + * the tags are converted to PIDs and those PIDs are sent as a MPEG Transport Stream down the connection + * if a tag is -1, the default audio or video stream for the current service_id is sent + */ + +bool +cmd_avstream(struct listen_data *listen_data, int client_sock, int argc, char *argv[]) +{ + struct carousel *car = listen_data->carousel; + int audio_tag; + int video_tag; + uint16_t audio_pid; + uint16_t video_pid; + int audio_fd; + int video_fd; + int ts_fd; + char hdr[64]; + + CHECK_USAGE(2, "avstream <AudioTag> <VideoTag>"); + + audio_tag = strtol(argv[1], NULL, 0); + video_tag = strtol(argv[2], NULL, 0); + + /* map the tags to PIDs, or use the defaults */ + if(audio_tag == -1) + audio_pid = car->audio_pid; + else + audio_pid = stream2pid(&car->assoc, audio_tag); + + if(video_tag == -1) + video_pid = car->video_pid; + else + video_pid = stream2pid(&car->assoc, video_tag); + + /* add the PIDs to the demux device */ + if((audio_fd = add_demux_filter(car->demux_device, audio_pid, DMX_PES_AUDIO)) < 0) + { + SEND_RESPONSE(500, "Unable to open audio PID"); + return false; + } + if((video_fd = add_demux_filter(car->demux_device, video_pid, DMX_PES_VIDEO)) < 0) + { + SEND_RESPONSE(500, "Unable to open video PID"); + close(audio_fd); + return false; + } + + /* we can now read a transport stream from the dvr device */ + if((ts_fd = open(car->dvr_device, O_RDONLY | O_NONBLOCK)) < 0) + { + SEND_RESPONSE(500, "Unable to open DVB device"); + close(audio_fd); + close(video_fd); + return false; + } + + /* send the OK code */ + SEND_RESPONSE(200, "OK"); + + /* tell the client what PIDs the component tags resolved to */ + snprintf(hdr, sizeof(hdr), "AudioPID %u VideoPID %u\n", audio_pid, video_pid); + write_string(client_sock, hdr); + + /* shovel the transport stream down client_sock until the client closes it or we get an error */ + stream_ts(ts_fd, client_sock); + + /* clean up */ + close(ts_fd); + close(audio_fd); + close(video_fd); + + return false; +} + +/* * check <ContentReference> * check if the given file is on the carousel * ContentReference should be absolute, ie start with "~//" Added: redbutton-download/trunk/stream.c =================================================================== --- redbutton-download/trunk/stream.c (rev 0) +++ redbutton-download/trunk/stream.c 2006-03-15 14:21:25 UTC (rev 18) @@ -0,0 +1,62 @@ +/* + * stream.c + */ + +#include <unistd.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <sys/ioctl.h> + +#include "stream.h" +#include "utils.h" + +int +add_demux_filter(char *demux_dev, uint16_t pid, dmx_pes_type_t pes_type) +{ + int fd; + struct dmx_pes_filter_params pes_filter; + + if((fd = open(demux_dev, O_RDWR)) < 0) + { + error("open '%s': %s", demux_dev, strerror(errno)); + return -1; + } + + bzero(&pes_filter, sizeof(pes_filter)); + pes_filter.input = DMX_IN_FRONTEND; + pes_filter.output = DMX_OUT_TS_TAP; + pes_filter.flags = DMX_IMMEDIATE_START; + pes_filter.pid = pid; + pes_filter.pes_type = pes_type; + + if(ioctl(fd, DMX_SET_PES_FILTER, &pes_filter) < 0) + { + error("ioctl DMX_SET_PES_FILTER: %s", strerror(errno)); + close(fd); + return -1; + } + + return fd; +} + +/* don't want it on the stack */ +unsigned char _ts_buf[8 * 1024]; + +void +stream_ts(int ts_fd, int client_sock) +{ + ssize_t nread; + ssize_t nwritten; + + do + { + nread = read(ts_fd, _ts_buf, sizeof(_ts_buf)); + if(nread > 0) + nwritten = write(client_sock, _ts_buf, nread); + } + while(nread > 0 && nread == nwritten); + + return; +} + Added: redbutton-download/trunk/stream.h =================================================================== --- redbutton-download/trunk/stream.h (rev 0) +++ redbutton-download/trunk/stream.h 2006-03-15 14:21:25 UTC (rev 18) @@ -0,0 +1,15 @@ +/* + * stream.h + */ + +#ifndef __STREAM_H__ +#define __STREAM_H__ + +#include <stdint.h> +#include <linux/dvb/dmx.h> + +int add_demux_filter(char *, uint16_t, dmx_pes_type_t); + +void stream_ts(int, int); + +#endif /* __STREAM_H__ */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-15 12:39:26
|
Revision: 17 Author: skilvington Date: 2006-03-15 04:39:15 -0800 (Wed, 15 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=17&view=rev Log Message: ----------- replace -d option with -a Modified Paths: -------------- redbutton-download/trunk/findmheg.c redbutton-download/trunk/findmheg.h redbutton-download/trunk/list.c redbutton-download/trunk/list.h redbutton-download/trunk/module.h redbutton-download/trunk/rb-download.c redbutton-download/trunk/table.c redbutton-download/trunk/utils.h Modified: redbutton-download/trunk/findmheg.c =================================================================== --- redbutton-download/trunk/findmheg.c 2006-03-04 14:42:35 UTC (rev 16) +++ redbutton-download/trunk/findmheg.c 2006-03-15 12:39:15 UTC (rev 17) @@ -72,7 +72,7 @@ static struct carousel _car; struct carousel * -find_mheg(char *device, unsigned int timeout, uint16_t service_id, int carousel_id) +find_mheg(unsigned int adapter, unsigned int timeout, uint16_t service_id, int carousel_id) { unsigned char *pat; uint16_t section_length; @@ -88,7 +88,8 @@ uint16_t component_tag; /* carousel data we know so far */ - _car.device = device; + snprintf(_car.demux_device, sizeof(_car.demux_device), DEMUX_DEVICE, adapter); + snprintf(_car.dvr_device, sizeof(_car.dvr_device), DVR_DEVICE, adapter); _car.timeout = timeout; _car.service_id = service_id; @@ -108,7 +109,7 @@ _car.modules = NULL; /* get the PAT */ - if((pat = read_table(device, PID_PAT, TID_PAT, timeout)) == NULL) + if((pat = read_table(_car.demux_device, PID_PAT, TID_PAT, timeout)) == NULL) fatal("Unable to read PAT"); section_length = 3 + (((pat[1] & 0x0f) << 8) + pat[2]); @@ -136,7 +137,7 @@ // printf("programme_map_PID: 0x%x\n", map_pid); /* get the PMT */ - if((pmt = read_table(device, map_pid, TID_PMT, timeout)) == NULL) + if((pmt = read_table(_car.demux_device, map_pid, TID_PMT, timeout)) == NULL) fatal("Unable to read PMT"); section_length = 3 + (((pmt[1] & 0x0f) << 8) + pmt[2]); Modified: redbutton-download/trunk/findmheg.h =================================================================== --- redbutton-download/trunk/findmheg.h 2006-03-04 14:42:35 UTC (rev 16) +++ redbutton-download/trunk/findmheg.h 2006-03-15 12:39:15 UTC (rev 17) @@ -25,7 +25,7 @@ #include <stdint.h> -struct carousel *find_mheg(char *, unsigned int, uint16_t, int); +struct carousel *find_mheg(unsigned int, unsigned int, uint16_t, int); #endif /* __FINDMHEG_H__ */ Modified: redbutton-download/trunk/list.c =================================================================== --- redbutton-download/trunk/list.c 2006-03-04 14:42:35 UTC (rev 16) +++ redbutton-download/trunk/list.c 2006-03-15 12:39:15 UTC (rev 17) @@ -21,20 +21,22 @@ */ #include <stdio.h> +#include <limits.h> #include "table.h" #include "utils.h" /* PID and TID we want */ -#define PID_SDT 0x0011 +#define PID_SDT 0x0011 #define TID_SDS 0x42 /* service_descriptor tag */ #define TAG_SERVICE_DESCRIPTOR 0x48 void -list_channels(char *device, unsigned int timeout) +list_channels(unsigned int adapter, unsigned int timeout) { + char demux_dev[PATH_MAX]; unsigned char *sds; uint16_t size; uint16_t offset; @@ -44,12 +46,14 @@ uint8_t desc_length; uint8_t name_len; + snprintf(demux_dev, sizeof(demux_dev), DEMUX_DEVICE, adapter); + printf("Channels on this mutiplex:\n\n"); printf("ID\tChannel\n"); printf("==\t=======\n"); /* grab the Service Description Section table */ - if((sds = read_table(device, PID_SDT, TID_SDS, timeout)) == NULL) + if((sds = read_table(demux_dev, PID_SDT, TID_SDS, timeout)) == NULL) fatal("Unable to read SDT"); /* 12 bit section_length field */ Modified: redbutton-download/trunk/list.h =================================================================== --- redbutton-download/trunk/list.h 2006-03-04 14:42:35 UTC (rev 16) +++ redbutton-download/trunk/list.h 2006-03-15 12:39:15 UTC (rev 17) @@ -23,7 +23,7 @@ #ifndef __LIST_H__ #define __LIST_H__ -void list_channels(char *, unsigned int); +void list_channels(unsigned int, unsigned int); #endif /* __LIST_H__ */ Modified: redbutton-download/trunk/module.h =================================================================== --- redbutton-download/trunk/module.h 2006-03-04 14:42:35 UTC (rev 16) +++ redbutton-download/trunk/module.h 2006-03-15 12:39:15 UTC (rev 17) @@ -25,6 +25,7 @@ #include <stdint.h> #include <stdbool.h> +#include <limits.h> #include "dsmcc.h" #include "assoc.h" @@ -54,8 +55,9 @@ /* the whole carousel */ struct carousel { - char *device; /* demux device */ - unsigned int timeout; /* timeout for the demux device */ + char demux_device[PATH_MAX]; /* demux device path */ + char dvr_device[PATH_MAX]; /* dvr device path */ + unsigned int timeout; /* timeout for the DVB devices */ uint16_t service_id; uint32_t carousel_id; uint16_t audio_pid; /* PID of default audio stream for this service_id */ Modified: redbutton-download/trunk/rb-download.c =================================================================== --- redbutton-download/trunk/rb-download.c 2006-03-04 14:42:35 UTC (rev 16) +++ redbutton-download/trunk/rb-download.c 2006-03-15 12:39:15 UTC (rev 17) @@ -1,5 +1,5 @@ /* - * rb-download [-d <demux_device>] [-b <base_dir>] [-t <timeout>] [-l[<listen-addr>]] [-c <carousel_id>] [<service_id>] + * rb-download [-a <adapter>] [-b <base_dir>] [-t <timeout>] [-l[<listen-addr>]] [-c <carousel_id>] [<service_id>] * * Download the DVB Object Carousel for the given channel onto the local hard disc * files will be stored under the current dir if no -b option is given @@ -10,6 +10,11 @@ * the default timeout is 10 seconds * if no DSMCC data is read after this time, it is assumed none is being broadcast * + * the DVB devices used will be: + * /dev/dvb/adapter0/demux0 + * /dev/dvb/adapter0/dvr0 + * use the -a option to change the adapter number (eg "-a 1" will use /dev/dvb/adapter1/demux0 etc) + * * if -l is given, rb-download listens on the network for commands from a remote rb-browser * the default IP to listen on is 0.0.0.0 (ie all interfaces), the default TCP port is 10101 * listen-addr should be given in the form "host:port", where host defaults to 0.0.0.0 and port defaults to 10101 @@ -60,9 +65,6 @@ #include "listen.h" #include "utils.h" -/* DVB demux device */ -#define DEFAULT_DEVICE "/dev/dvb/adapter0/demux0" - /* seconds before we assume no DSMCC data is available on this PID */ #define DEFAULT_TIMEOUT 10 @@ -76,7 +78,7 @@ main(int argc, char *argv[]) { char *prog_name = argv[0]; - char *device = DEFAULT_DEVICE; + unsigned int adapter = 0; unsigned int timeout = DEFAULT_TIMEOUT; bool listen = false; struct listen_data listen_data; @@ -85,12 +87,12 @@ struct carousel *car; int arg; - while((arg = getopt(argc, argv, "d:b:t:l::c:")) != EOF) + while((arg = getopt(argc, argv, "a:b:t:l::c:")) != EOF) { switch(arg) { - case 'd': - device = optarg; + case 'a': + adapter = strtoul(optarg, NULL, 0); break; case 'b': @@ -124,12 +126,12 @@ if(argc == optind) { - list_channels(device, timeout); + list_channels(adapter, timeout); } else if(argc - optind == 1) { service_id = strtoul(argv[optind], NULL, 0); - car = find_mheg(device, timeout, service_id, carousel_id); + car = find_mheg(adapter, timeout, service_id, carousel_id); printf("Carousel ID=%u\n", car->carousel_id); printf("Video PID=%u\n", car->video_pid); printf("Audio PID=%u\n", car->audio_pid); @@ -151,7 +153,7 @@ void usage(char *prog_name) { - fatal("Usage: %s [-d <demux_device>] " + fatal("Usage: %s [-a <adapter>] " "[-b <base_dir>] " "[-t <timeout>] " "[-l[<listen-addr>]] " Modified: redbutton-download/trunk/table.c =================================================================== --- redbutton-download/trunk/table.c 2006-03-04 14:42:35 UTC (rev 16) +++ redbutton-download/trunk/table.c 2006-03-15 12:39:15 UTC (rev 17) @@ -163,7 +163,7 @@ } if(fd == -1) { - error("Timeout reading %s", car->device); + error("Timeout reading %s", car->demux_device); return NULL; } /* read the table */ @@ -205,8 +205,8 @@ fds->pid = pid; /* open an fd to read the DSMCC control tables (DSI and DII) */ - if((fds->fd_ctrl = open(car->device, O_RDWR)) < 0) - fatal("open '%s': %s", car->device, strerror(errno)); + if((fds->fd_ctrl = open(car->demux_device, O_RDWR)) < 0) + fatal("open '%s': %s", car->demux_device, strerror(errno)); /* set the table filter */ memset(&sctFilterParams, 0, sizeof(sctFilterParams)); @@ -219,8 +219,8 @@ fatal("ioctl DMX_SET_FILTER: %s", strerror(errno)); /* open an fd to read the DSMCC data table (DDB) */ - if((fds->fd_data = open(car->device, O_RDWR)) < 0) - fatal("open '%s': %s", car->device, strerror(errno)); + if((fds->fd_data = open(car->demux_device, O_RDWR)) < 0) + fatal("open '%s': %s", car->demux_device, strerror(errno)); /* set the table filter */ memset(&sctFilterParams, 0, sizeof(sctFilterParams)); Modified: redbutton-download/trunk/utils.h =================================================================== --- redbutton-download/trunk/utils.h 2006-03-04 14:42:35 UTC (rev 16) +++ redbutton-download/trunk/utils.h 2006-03-15 12:39:15 UTC (rev 17) @@ -31,6 +31,12 @@ #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif +/* DVB demux device - %u is card number */ +#define DEMUX_DEVICE "/dev/dvb/adapter%u/demux0" + +/* DVB dvr device - %u is card number */ +#define DVR_DEVICE "/dev/dvb/adapter%u/dvr0" + void write_string(int, const char *); void write_all(int, const void *, size_t); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-04 14:42:45
|
Revision: 16 Author: skilvington Date: 2006-03-04 06:42:35 -0800 (Sat, 04 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=16&view=rev Log Message: ----------- default backend is at 127.0.0.1 Modified Paths: -------------- redbutton-browser/trunk/MHEGBackend.c Modified: redbutton-browser/trunk/MHEGBackend.c =================================================================== --- redbutton-browser/trunk/MHEGBackend.c 2006-03-03 16:51:20 UTC (rev 15) +++ redbutton-browser/trunk/MHEGBackend.c 2006-03-04 14:42:35 UTC (rev 16) @@ -56,13 +56,15 @@ { bzero(b, sizeof(MHEGBackend)); + /* default backend is on the loopback */ + b->addr.sin_family = AF_INET; + b->addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + b->addr.sin_port = htons(DEFAULT_REMOTE_PORT); + if(remote) { /* backend is on a different host, srg_loc is the remote host[:port] */ b->fns = &remote_backend_fns; - b->addr.sin_family = AF_INET; - b->addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - b->addr.sin_port = htons(DEFAULT_REMOTE_PORT); if(parse_addr(srg_loc, &b->addr.sin_addr, &b->addr.sin_port) < 0) fatal("Unable to resolve host %s", srg_loc); verbose("Remote backend at %s:%u", inet_ntoa(b->addr.sin_addr), ntohs(b->addr.sin_port)); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-03 16:51:28
|
Revision: 15 Author: skilvington Date: 2006-03-03 08:51:20 -0800 (Fri, 03 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=15&view=rev Log Message: ----------- add openStream() to frontend Modified Paths: -------------- redbutton-browser/trunk/MHEGApp.c redbutton-browser/trunk/MHEGBackend.c redbutton-browser/trunk/MHEGBackend.h redbutton-browser/trunk/MHEGEngine.c redbutton-browser/trunk/MHEGEngine.h Modified: redbutton-browser/trunk/MHEGApp.c =================================================================== --- redbutton-browser/trunk/MHEGApp.c 2006-03-03 13:45:56 UTC (rev 14) +++ redbutton-browser/trunk/MHEGApp.c 2006-03-03 16:51:20 UTC (rev 15) @@ -61,7 +61,7 @@ m->app = safe_malloc(sizeof(InterchangedObject)); bzero(m->app, sizeof(InterchangedObject)); - if((der = MHEGEngine_openFile(derfile, "r")) == NULL) + if((der = MHEGEngine_openFile(derfile)) == NULL) { error("Unable to open '%.*s'", derfile->size, derfile->data); safe_free(m->app); @@ -116,7 +116,7 @@ m->scene = safe_malloc(sizeof(InterchangedObject)); bzero(m->scene, sizeof(InterchangedObject)); - if((der = MHEGEngine_openFile(derfile, "r")) == NULL) + if((der = MHEGEngine_openFile(derfile)) == NULL) { error("Unable to open '%.*s'", derfile->size, derfile->data); safe_free(m->scene); Modified: redbutton-browser/trunk/MHEGBackend.c =================================================================== --- redbutton-browser/trunk/MHEGBackend.c 2006-03-03 13:45:56 UTC (rev 14) +++ redbutton-browser/trunk/MHEGBackend.c 2006-03-03 16:51:20 UTC (rev 15) @@ -16,25 +16,29 @@ /* local backend funcs */ bool local_checkContentRef(MHEGBackend *, ContentReference *); bool local_loadFile(MHEGBackend *, OctetString *, OctetString *); -FILE *local_openFile(MHEGBackend *, OctetString *, char *); +FILE *local_openFile(MHEGBackend *, OctetString *); +FILE *local_openStream(MHEGBackend *, bool, int, bool, int); static struct MHEGBackendFns local_backend_fns = { local_checkContentRef, /* checkContentRef */ local_loadFile, /* loadFile */ local_openFile, /* openFile */ + local_openStream, /* openStream */ }; /* remote backend funcs */ bool remote_checkContentRef(MHEGBackend *, ContentReference *); bool remote_loadFile(MHEGBackend *, OctetString *, OctetString *); -FILE *remote_openFile(MHEGBackend *, OctetString *, char *); +FILE *remote_openFile(MHEGBackend *, OctetString *); +FILE *remote_openStream(MHEGBackend *, bool, int, bool, int); static struct MHEGBackendFns remote_backend_fns = { remote_checkContentRef, /* checkContentRef */ remote_loadFile, /* loadFile */ remote_openFile, /* openFile */ + remote_openStream, /* openStream */ }; /* internal functions */ @@ -283,15 +287,42 @@ return (out->data != NULL); } +/* + * return a read-only FILE handle for the given carousel file + * returns NULL on error + */ + FILE * -local_openFile(MHEGBackend *t, OctetString *name, char *mode) +local_openFile(MHEGBackend *t, OctetString *name) { char *external = external_filename(t, name); - return fopen(external, mode); + return fopen(external, "r"); } /* + * return a read-only FILE handle for an MPEG Transport Stream + * the TS will contain an audio stream (if have_audio is true) and a video stream (if have_video is true) + * the audio_tag and video_tag numbers refer to Component/Association Tag values from the DVB PMT + * if audio_tag or video_tag is -1, the default audio and/or video stream for the current Service ID is used + * returns NULL on error + */ + +FILE * +local_openStream(MHEGBackend *t, bool have_audio, int audio_tag, bool have_video, int video_tag) +{ + /* + * we need to convert the audio/video_tag into PIDs + * we could either: + * 1. parse the PMT ourselves, and open the DVB device ourselves + * 2. have a backend command to convert Component Tags to PIDs, then open the DVB device ourselves + * 3. just stream the TS from the backend + * we choose 3, to avoid duplicating code and having to pass "-d <device>" options etc + */ + return remote_openStream(t, have_audio, audio_tag, have_video, video_tag); +} + +/* * remote routines */ @@ -366,8 +397,13 @@ return success; } +/* + * return a read-only FILE handle for the given carousel file + * returns NULL on error + */ + FILE * -remote_openFile(MHEGBackend *t, OctetString *name, char *mode) +remote_openFile(MHEGBackend *t, OctetString *name) { char cmd[PATH_MAX]; FILE *sock; @@ -415,3 +451,43 @@ return out; } +/* + * return a read-only FILE handle for an MPEG Transport Stream + * the TS will contain an audio stream (if have_audio is true) and a video stream (if have_video is true) + * the audio_tag and video_tag numbers refer to Component/Association Tag values from the DVB PMT + * if audio_tag or video_tag is -1, the default audio and/or video stream for the current Service ID is used + * returns NULL on error + */ + +FILE * +remote_openStream(MHEGBackend *t, bool have_audio, int audio_tag, bool have_video, int video_tag) +{ + char cmd[PATH_MAX]; + FILE *sock; + + /* no PIDs required */ + if(!have_audio && !have_video) + return NULL; + /* video and audio */ + else if(have_audio && have_video) + snprintf(cmd, sizeof(cmd), "avstream %d %d\n", audio_tag, video_tag); + /* audio only */ + else if(have_audio) + snprintf(cmd, sizeof(cmd), "astream %d\n", audio_tag); + /* video only */ + else + snprintf(cmd, sizeof(cmd), "vstream %d\n", video_tag); + + if((sock = remote_command(t, cmd)) == NULL) + return NULL; + + /* did it work */ + if(remote_response(sock) != BACKEND_RESPONSE_OK) + { + fclose(sock); + sock = NULL; + } + + return sock; +} + Modified: redbutton-browser/trunk/MHEGBackend.h =================================================================== --- redbutton-browser/trunk/MHEGBackend.h 2006-03-03 13:45:56 UTC (rev 14) +++ redbutton-browser/trunk/MHEGBackend.h 2006-03-03 16:51:20 UTC (rev 15) @@ -19,9 +19,10 @@ /* function pointers */ struct MHEGBackendFns { - bool (*checkContentRef)(struct MHEGBackend *, ContentReference *); /* check a file exists */ - bool (*loadFile)(struct MHEGBackend *, OctetString *, OctetString *); /* load a file */ - FILE *(*openFile)(struct MHEGBackend *, OctetString *, char *); /* open a file */ + bool (*checkContentRef)(struct MHEGBackend *, ContentReference *); /* check a carousel file exists */ + bool (*loadFile)(struct MHEGBackend *, OctetString *, OctetString *); /* load a carousel file */ + FILE *(*openFile)(struct MHEGBackend *, OctetString *); /* open a carousel file */ + FILE *(*openStream)(struct MHEGBackend *, bool, int, bool, int); /* open an MPEG Transport Stream */ } *fns; } MHEGBackend; Modified: redbutton-browser/trunk/MHEGEngine.c =================================================================== --- redbutton-browser/trunk/MHEGEngine.c 2006-03-03 13:45:56 UTC (rev 14) +++ redbutton-browser/trunk/MHEGEngine.c 2006-03-03 16:51:20 UTC (rev 15) @@ -1320,15 +1320,14 @@ } /* - * returns a FILE handle for the given carousel file - * mode is an fopen() mode, ie "r", "w", etc + * returns a read-only FILE handle for the given carousel file * returns NULL on error */ FILE * -MHEGEngine_openFile(OctetString *name, char *mode) +MHEGEngine_openFile(OctetString *name) { - return (*(engine.backend.fns->openFile))(&engine.backend, name, mode); + return (*(engine.backend.fns->openFile))(&engine.backend, name); } /* Modified: redbutton-browser/trunk/MHEGEngine.h =================================================================== --- redbutton-browser/trunk/MHEGEngine.h 2006-03-03 13:45:56 UTC (rev 14) +++ redbutton-browser/trunk/MHEGEngine.h 2006-03-03 16:51:20 UTC (rev 15) @@ -220,7 +220,7 @@ bool MHEGEngine_checkContentRef(ContentReference *); bool MHEGEngine_loadFile(OctetString *, OctetString *); -FILE *MHEGEngine_openFile(OctetString *, char *); +FILE *MHEGEngine_openFile(OctetString *); char *MHEGEngine_absoluteFilename(OctetString *); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-03 12:17:13
|
Revision: 13 Author: skilvington Date: 2006-03-03 04:17:06 -0800 (Fri, 03 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=13&view=rev Log Message: ----------- wrap socket to backend in a FILE Modified Paths: -------------- redbutton-browser/trunk/MHEGApp.c redbutton-browser/trunk/MHEGBackend.c redbutton-browser/trunk/MHEGBackend.h redbutton-browser/trunk/MHEGEngine.c redbutton-browser/trunk/MHEGEngine.h redbutton-browser/trunk/utils.c redbutton-browser/trunk/utils.h Modified: redbutton-browser/trunk/MHEGApp.c =================================================================== --- redbutton-browser/trunk/MHEGApp.c 2006-03-03 12:11:41 UTC (rev 12) +++ redbutton-browser/trunk/MHEGApp.c 2006-03-03 12:17:06 UTC (rev 13) @@ -76,7 +76,7 @@ len = ftell(der); rewind(der); rc = der_decode_InterchangedObject(der, m->app, len); - MHEGEngine_closeFile(der); + fclose(der); if(rc < 0 || m->app->choice != InterchangedObject_application) { @@ -131,7 +131,7 @@ len = ftell(der); rewind(der); rc = der_decode_InterchangedObject(der, m->scene, len); - MHEGEngine_closeFile(der); + fclose(der); if(rc < 0 || m->scene->choice != InterchangedObject_scene) { Modified: redbutton-browser/trunk/MHEGBackend.c =================================================================== --- redbutton-browser/trunk/MHEGBackend.c 2006-03-03 12:11:41 UTC (rev 12) +++ redbutton-browser/trunk/MHEGBackend.c 2006-03-03 12:17:06 UTC (rev 13) @@ -17,37 +17,35 @@ bool local_checkContentRef(MHEGBackend *, ContentReference *); bool local_loadFile(MHEGBackend *, OctetString *, OctetString *); FILE *local_openFile(MHEGBackend *, OctetString *, char *); -int local_closeFile(MHEGBackend *, FILE *); static struct MHEGBackendFns local_backend_fns = { local_checkContentRef, /* checkContentRef */ local_loadFile, /* loadFile */ local_openFile, /* openFile */ - local_closeFile /* closeFile */ }; /* remote backend funcs */ bool remote_checkContentRef(MHEGBackend *, ContentReference *); bool remote_loadFile(MHEGBackend *, OctetString *, OctetString *); FILE *remote_openFile(MHEGBackend *, OctetString *, char *); -int remote_closeFile(MHEGBackend *, FILE *); static struct MHEGBackendFns remote_backend_fns = { remote_checkContentRef, /* checkContentRef */ remote_loadFile, /* loadFile */ remote_openFile, /* openFile */ - remote_closeFile /* closeFile */ }; /* internal functions */ static int parse_addr(char *, struct in_addr *, in_port_t *); static int get_host_addr(char *, struct in_addr *); -static int remote_command(MHEGBackend *, char *); -static unsigned int remote_response(int); +static FILE *remote_command(MHEGBackend *, char *); +static unsigned int remote_response(FILE *); +static char *external_filename(MHEGBackend *, OctetString *); + /* public interface */ void MHEGBackend_init(MHEGBackend *b, bool remote, char *srg_loc) @@ -138,72 +136,69 @@ /* * send the given command to the remote backend - * returns a socket fd to read the response from - * returns <0 if it can't contact the backend + * returns a socket FILE to read the response from + * returns NULL if it can't contact the backend */ -static int +static FILE * remote_command(MHEGBackend *t, char *cmd) { int sock; + FILE *file; /* connect to the backend */ if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) { error("Unable to create backend socket: %s", strerror(errno)); - return -1; + return NULL; } if(connect(sock, (struct sockaddr *) &t->addr, sizeof(struct sockaddr_in)) < 0) { error("Unable to connect to backend: %s", strerror(errno)); - return -1; + close(sock); + return NULL; } - /* send the command */ - write_string(sock, cmd); + /* associate a FILE with the socket (so stdio can do buffering) */ + if((file = fdopen(sock, "r+")) != NULL) + { + /* send the command */ + fputs(cmd, file); + } + else + { + error("Unable to buffer backend connection: %s", strerror(errno)); + close(sock); + } - return sock; + return file; } /* - * read the backend response from the given socket fd + * read the backend response from the given socket FILE * returns the OK/error code */ #define BACKEND_RESPONSE_OK 200 +#define BACKEND_RESPONSE_ERROR 500 static unsigned int -remote_response(int sock) +remote_response(FILE *file) { char buf[1024]; - char byte; - unsigned int total; - ssize_t nread; unsigned int rc; /* read upto \n */ - total = 0; - do - { - if((nread = read(sock, &byte, 1)) == 1) - buf[total++] = byte; - } - while(nread == 1 && byte != '\n' && total < (sizeof(buf) - 1)); + if(fgets(buf, sizeof(buf), file) == NULL) + return BACKEND_RESPONSE_ERROR; - /* \0 terminate it */ - buf[total] = '\0'; - rc = atoi(buf); return rc; } /* - * local routines - */ - -/* * returns a filename that can be loaded from the file system * ie ~// at the start of the absolute name is replaced with base_dir * returns a ptr to a static string that will be overwritten by the next call to this routine @@ -226,6 +221,10 @@ } /* + * local routines + */ + +/* * returns true if the file exists on the carousel */ @@ -293,16 +292,6 @@ } /* - * close a FILE opened with MHEGEngine_openFile() - */ - -int -local_closeFile(MHEGBackend *t, FILE *file) -{ - return fclose(file); -} - -/* * remote routines */ @@ -314,17 +303,17 @@ remote_checkContentRef(MHEGBackend *t, ContentReference *name) { char cmd[PATH_MAX]; - int sock; + FILE *sock; bool exists; snprintf(cmd, sizeof(cmd), "check %s\n", MHEGEngine_absoluteFilename(name)); - if((sock = remote_command(t, cmd)) < 0) + if((sock = remote_command(t, cmd)) == NULL) return false; exists = (remote_response(sock) == BACKEND_RESPONSE_OK); - close(sock); + fclose(sock); return exists; } @@ -339,14 +328,14 @@ remote_loadFile(MHEGBackend *t, OctetString *name, OctetString *out) { char cmd[PATH_MAX]; - int sock; + FILE *sock; char buf[8 * 1024]; - ssize_t nread; + size_t nread; bool success = false; snprintf(cmd, sizeof(cmd), "file %s\n", MHEGEngine_absoluteFilename(name)); - if((sock = remote_command(t, cmd)) < 0) + if((sock = remote_command(t, cmd)) == NULL) return false; /* does it exist */ @@ -354,16 +343,17 @@ { verbose("Loading '%.*s'", name->size, name->data); /* read from the socket until EOF */ - do + while(!feof(sock)) { - if((nread = read(sock, buf, sizeof(buf))) > 0) +/* TODO */ +/* could read straight into out->data rather than doing memcpy */ + if((nread = fread(buf, 1, sizeof(buf), sock)) > 0) { out->data = safe_realloc(out->data, out->size + nread); memcpy(out->data + out->size, buf, nread); out->size += nread; } } - while(nread > 0); success = true; } else @@ -371,7 +361,7 @@ error("Unable to load '%.*s'", name->size, name->data); } - close(sock); + fclose(sock); return success; } @@ -380,58 +370,48 @@ remote_openFile(MHEGBackend *t, OctetString *name, char *mode) { char cmd[PATH_MAX]; - int sock; + FILE *sock; char buf[8 * 1024]; - ssize_t nread; + size_t nread; size_t nwritten; - FILE *file = NULL; + FILE *out = NULL; snprintf(cmd, sizeof(cmd), "file %s\n", MHEGEngine_absoluteFilename(name)); - if((sock = remote_command(t, cmd)) < 0) + if((sock = remote_command(t, cmd)) == NULL) return NULL; /* does it exist */ if(remote_response(sock) == BACKEND_RESPONSE_OK) { - if((file = tmpfile()) != NULL) + /* tmpfile() will delete the file when we fclose() it */ + if((out = tmpfile()) != NULL) { /* read from the socket until EOF */ do { - if((nread = read(sock, buf, sizeof(buf))) > 0) - nwritten = fwrite(buf, 1, nread, file); + if((nread = fread(buf, 1, sizeof(buf), sock)) > 0) + nwritten = fwrite(buf, 1, nread, out); else nwritten = 0; } - while(nread > 0 && nread == nwritten); + while(!feof(sock) && nread == nwritten); /* could we write the file ok */ if(nread != nwritten) { error("Unable to write to local file"); - fclose(file); - file = NULL; + fclose(out); + out = NULL; } } } - close(sock); + fclose(sock); /* rewind the file */ - if(file != NULL) - rewind(file); + if(out != NULL) + rewind(out); - return file; + return out; } -/* - * close a FILE opened with MHEGEngine_openFile() - */ - -int -remote_closeFile(MHEGBackend *t, FILE *file) -{ - /* tmpfile() will delete the file for us */ - return fclose(file); -} - Modified: redbutton-browser/trunk/MHEGBackend.h =================================================================== --- redbutton-browser/trunk/MHEGBackend.h 2006-03-03 12:11:41 UTC (rev 12) +++ redbutton-browser/trunk/MHEGBackend.h 2006-03-03 12:17:06 UTC (rev 13) @@ -22,7 +22,6 @@ bool (*checkContentRef)(struct MHEGBackend *, ContentReference *); /* check a file exists */ bool (*loadFile)(struct MHEGBackend *, OctetString *, OctetString *); /* load a file */ FILE *(*openFile)(struct MHEGBackend *, OctetString *, char *); /* open a file */ - int (*closeFile)(struct MHEGBackend *, FILE *); /* close a file */ } *fns; } MHEGBackend; Modified: redbutton-browser/trunk/MHEGEngine.c =================================================================== --- redbutton-browser/trunk/MHEGEngine.c 2006-03-03 12:11:41 UTC (rev 12) +++ redbutton-browser/trunk/MHEGEngine.c 2006-03-03 12:17:06 UTC (rev 13) @@ -1332,16 +1332,6 @@ } /* - * close a FILE opened with MHEGEngine_openFile() - */ - -int -MHEGEngine_closeFile(FILE *file) -{ - return (*(engine.backend.fns->closeFile))(&engine.backend, file); -} - -/* * returns the absolute group ID, ie it always starts with "~//" * returns a ptr to static string that will be overwritten by the next call to this routine * section 8.3.2 of the UK MHEG Profile says the filename prefixes are: Modified: redbutton-browser/trunk/MHEGEngine.h =================================================================== --- redbutton-browser/trunk/MHEGEngine.h 2006-03-03 12:11:41 UTC (rev 12) +++ redbutton-browser/trunk/MHEGEngine.h 2006-03-03 12:17:06 UTC (rev 13) @@ -221,7 +221,7 @@ bool MHEGEngine_checkContentRef(ContentReference *); bool MHEGEngine_loadFile(OctetString *, OctetString *); FILE *MHEGEngine_openFile(OctetString *, char *); -int MHEGEngine_closeFile(FILE *); + char *MHEGEngine_absoluteFilename(OctetString *); /* convert PNG to internal format */ Modified: redbutton-browser/trunk/utils.c =================================================================== --- redbutton-browser/trunk/utils.c 2006-03-03 12:11:41 UTC (rev 12) +++ redbutton-browser/trunk/utils.c 2006-03-03 12:17:06 UTC (rev 13) @@ -31,46 +31,6 @@ #include "utils.h" /* - * write the given string (ie upto \0) to the given fd - */ - -void -write_string(int fd, const char *str) -{ - write_all(fd, str, strlen(str)); - - return; -} - -/* - * guarantee writing count bytes from buf to fd - * W. Richard Stevens - */ - -void -write_all(int fd, const void *buf, size_t count) -{ - size_t nwritten; - const char *buf_ptr; - - buf_ptr = buf; - while(count > 0) - { - if((nwritten = write(fd, buf_ptr, count)) < 0) - { - if(errno == EINTR || errno == EAGAIN) - nwritten = 0; - else - fatal("write: %s\n", strerror(errno)); - } - count -= nwritten; - buf_ptr += nwritten; - } - - return; -} - -/* * returns 15 for 'f' etc */ Modified: redbutton-browser/trunk/utils.h =================================================================== --- redbutton-browser/trunk/utils.h 2006-03-03 12:11:41 UTC (rev 12) +++ redbutton-browser/trunk/utils.h 2006-03-03 12:17:06 UTC (rev 13) @@ -33,9 +33,6 @@ #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif -void write_string(int, const char *); -void write_all(int, const void *, size_t); - unsigned int char2hex(unsigned char); int next_utf8(unsigned char *, int, int *); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-03 12:11:48
|
Revision: 12 Author: skilvington Date: 2006-03-03 04:11:41 -0800 (Fri, 03 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=12&view=rev Log Message: ----------- find default video and audio PIDs Modified Paths: -------------- redbutton-download/trunk/findmheg.c redbutton-download/trunk/module.h redbutton-download/trunk/rb-download.c Modified: redbutton-download/trunk/findmheg.c =================================================================== --- redbutton-download/trunk/findmheg.c 2006-03-02 17:11:17 UTC (rev 11) +++ redbutton-download/trunk/findmheg.c 2006-03-03 12:11:41 UTC (rev 12) @@ -37,10 +37,13 @@ /* Programme Map Section */ #define TID_PMT 0x02 -/* stream_type we are interested in */ +/* stream_types we are interested in */ +#define STREAM_TYPE_VIDEO 0x02 +#define STREAM_TYPE_AUDIO 0x03 #define STREAM_TYPE_ISO13818_6_B 0x0b /* descriptors we want */ +#define TAG_LANGUAGE_DESCRIPTOR 0x0a #define TAG_CAROUSEL_ID_DESCRIPTOR 0x13 #define TAG_STREAM_ID_DESCRIPTOR 0x52 @@ -55,6 +58,12 @@ uint8_t component_tag; }; +struct language_descriptor +{ + char language_code[3]; + uint8_t audio_type; +} __attribute__((__packed__)); + /* * fills in a struct carousel based on the given service_id * returns a ptr to a static struct that will be overwritten be the next call to this routine @@ -85,6 +94,9 @@ /* unknown */ _car.carousel_id = 0; + _car.audio_pid = 0; + _car.video_pid = 0; + _car.current_pid = 0; /* map between stream_id_descriptors and elementary_PIDs */ init_assoc(&_car.assoc); /* no PIDs yet */ @@ -135,8 +147,7 @@ offset += 2 + info_length; /* - * find the carousel_identification_descriptor - * and the stream_identification_descriptor + * find the Descriptor Tags we are interested in */ while(offset < (section_length - 4)) { @@ -144,6 +155,10 @@ offset += 1; elementary_pid = ((pmt[offset] & 0x1f) << 8) + pmt[offset+1]; offset += 2; + /* is it the default video stream for this service */ + if(stream_type == STREAM_TYPE_VIDEO) + _car.video_pid = elementary_pid; + /* read the descriptors */ info_length = ((pmt[offset] & 0x0f) << 8) + pmt[offset+1]; offset += 2; while(info_length != 0) @@ -171,6 +186,14 @@ // printf("pid=0x%x component_tag=0x%x\n", elementary_pid, component_tag); add_assoc(&_car.assoc, elementary_pid, desc->component_tag); } + else if(desc_tag == TAG_LANGUAGE_DESCRIPTOR && stream_type == STREAM_TYPE_AUDIO) + { + struct language_descriptor *desc; + desc = (struct language_descriptor *) &pmt[offset]; + /* only remember the normal audio stream (not visually impaired stream) */ + if(desc->audio_type == 0) + _car.audio_pid = elementary_pid; + } offset += desc_length; info_length -= desc_length; } Modified: redbutton-download/trunk/module.h =================================================================== --- redbutton-download/trunk/module.h 2006-03-02 17:11:17 UTC (rev 11) +++ redbutton-download/trunk/module.h 2006-03-03 12:11:41 UTC (rev 12) @@ -58,6 +58,8 @@ unsigned int timeout; /* timeout for the demux device */ uint16_t service_id; uint32_t carousel_id; + uint16_t audio_pid; /* PID of default audio stream for this service_id */ + uint16_t video_pid; /* PID of default video stream for this service_id */ uint16_t current_pid; /* PID we downloaded the last table from */ struct assoc assoc; /* map stream_id's to elementary_pid's */ int32_t npids; /* PIDs we are reading data from */ Modified: redbutton-download/trunk/rb-download.c =================================================================== --- redbutton-download/trunk/rb-download.c 2006-03-02 17:11:17 UTC (rev 11) +++ redbutton-download/trunk/rb-download.c 2006-03-03 12:11:41 UTC (rev 12) @@ -131,6 +131,8 @@ service_id = strtoul(argv[optind], NULL, 0); car = find_mheg(device, timeout, service_id, carousel_id); printf("Carousel ID=%u\n", car->carousel_id); + printf("Video PID=%u\n", car->video_pid); + printf("Audio PID=%u\n", car->audio_pid); if(listen) { listen_data.carousel = car; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-02 17:11:27
|
Revision: 11 Author: skilvington Date: 2006-03-02 09:11:17 -0800 (Thu, 02 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=11&view=rev Log Message: ----------- retry reading demux device after EOVERFLOW errors Modified Paths: -------------- redbutton-download/trunk/TODO redbutton-download/trunk/table.c Modified: redbutton-download/trunk/TODO =================================================================== --- redbutton-download/trunk/TODO 2006-03-02 17:10:15 UTC (rev 10) +++ redbutton-download/trunk/TODO 2006-03-02 17:11:17 UTC (rev 11) @@ -1,7 +1,3 @@ -work out why this happened on BBC1 once: -read: Value too large for defined data type -Unable to read PID - have a verbose flag use a linked list of modules rather than an array in struct carousel @@ -11,9 +7,6 @@ => need to download again if it gets bigger (we currently just look at the module version, is this enough?) -what happens when you change channel? -(kill -9 and restart with the new programme_number?) - create carousels/PID/CID dir in add_dsmcc_pid() (may need to use carousels/<assoc_tag> as stream2pid may return 0) Modified: redbutton-download/trunk/table.c =================================================================== --- redbutton-download/trunk/table.c 2006-03-02 17:10:15 UTC (rev 10) +++ redbutton-download/trunk/table.c 2006-03-02 17:11:17 UTC (rev 11) @@ -169,8 +169,12 @@ /* read the table */ if((n = read(fd, _buf, sizeof(_buf))) < 0) { + /* + * may get EOVERFLOW if we don't read quick enough, + * so just report it and have another go + */ error("read: %s", strerror(errno)); - return NULL; + _buf[0] = 0; } } while(_buf[0] != TID_DSMCC_CONTROL && _buf[0] != TID_DSMCC_DATA); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-02 17:10:33
|
Revision: 10 Author: skilvington Date: 2006-03-02 09:10:15 -0800 (Thu, 02 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=10&view=rev Log Message: ----------- allow rb-browser to use remote backends Modified Paths: -------------- redbutton-browser/trunk/MHEGApp.c redbutton-browser/trunk/MHEGApp.h redbutton-browser/trunk/MHEGBackend.c redbutton-browser/trunk/MHEGBackend.h redbutton-browser/trunk/MHEGDisplay.c redbutton-browser/trunk/MHEGDisplay.h redbutton-browser/trunk/MHEGEngine.c redbutton-browser/trunk/MHEGEngine.h redbutton-browser/trunk/TODO redbutton-browser/trunk/rb-browser.c redbutton-browser/trunk/utils.c redbutton-browser/trunk/utils.h redbutton-download/trunk/listen.c Modified: redbutton-browser/trunk/MHEGApp.c =================================================================== --- redbutton-browser/trunk/MHEGApp.c 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/MHEGApp.c 2006-03-02 17:10:15 UTC (rev 10) @@ -21,7 +21,7 @@ } void -MHEGApp_stop(MHEGApp *m) +MHEGApp_fini(MHEGApp *m) { if(m->app != NULL) free_InterchangedObject(m->app); @@ -63,7 +63,7 @@ if((der = MHEGEngine_openFile(derfile, "r")) == NULL) { - error("Unable to open '%.*s': %s", derfile->size, derfile->data, strerror(errno)); + error("Unable to open '%.*s'", derfile->size, derfile->data); safe_free(m->app); m->app = NULL; return NULL; @@ -118,7 +118,7 @@ if((der = MHEGEngine_openFile(derfile, "r")) == NULL) { - error("Unable to open '%.*s': %s", derfile->size, derfile->data, strerror(errno)); + error("Unable to open '%.*s'", derfile->size, derfile->data); safe_free(m->scene); m->scene = NULL; return NULL; Modified: redbutton-browser/trunk/MHEGApp.h =================================================================== --- redbutton-browser/trunk/MHEGApp.h 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/MHEGApp.h 2006-03-02 17:10:15 UTC (rev 10) @@ -14,7 +14,7 @@ } MHEGApp; void MHEGApp_init(MHEGApp *); -void MHEGApp_stop(MHEGApp *); +void MHEGApp_fini(MHEGApp *); ApplicationClass *MHEGApp_loadApplication(MHEGApp *, OctetString *); SceneClass *MHEGApp_loadScene(MHEGApp *, OctetString *); Modified: redbutton-browser/trunk/MHEGBackend.c =================================================================== --- redbutton-browser/trunk/MHEGBackend.c 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/MHEGBackend.c 2006-03-02 17:10:15 UTC (rev 10) @@ -2,62 +2,211 @@ * MHEGBackend.c */ +#include <unistd.h> #include <stdio.h> #include <string.h> #include <errno.h> +#include <netdb.h> +#include <arpa/inet.h> +#include <sys/socket.h> #include "MHEGEngine.h" #include "utils.h" +/* local backend funcs */ bool local_checkContentRef(MHEGBackend *, ContentReference *); bool local_loadFile(MHEGBackend *, OctetString *, OctetString *); FILE *local_openFile(MHEGBackend *, OctetString *, char *); int local_closeFile(MHEGBackend *, FILE *); -static MHEGBackend local_backend = +static struct MHEGBackendFns local_backend_fns = { - NULL, /* base_dir */ local_checkContentRef, /* checkContentRef */ local_loadFile, /* loadFile */ local_openFile, /* openFile */ local_closeFile /* closeFile */ }; -MHEGBackend * -new_MHEGBackend(bool remote, char *srg_loc) +/* remote backend funcs */ +bool remote_checkContentRef(MHEGBackend *, ContentReference *); +bool remote_loadFile(MHEGBackend *, OctetString *, OctetString *); +FILE *remote_openFile(MHEGBackend *, OctetString *, char *); +int remote_closeFile(MHEGBackend *, FILE *); + +static struct MHEGBackendFns remote_backend_fns = { - MHEGBackend *b = NULL; + remote_checkContentRef, /* checkContentRef */ + remote_loadFile, /* loadFile */ + remote_openFile, /* openFile */ + remote_closeFile /* closeFile */ +}; +/* internal functions */ +static int parse_addr(char *, struct in_addr *, in_port_t *); +static int get_host_addr(char *, struct in_addr *); + +static int remote_command(MHEGBackend *, char *); +static unsigned int remote_response(int); + +/* public interface */ +void +MHEGBackend_init(MHEGBackend *b, bool remote, char *srg_loc) +{ + bzero(b, sizeof(MHEGBackend)); + if(remote) { - /* backend is on a different host, srg_loc is the remote host */ -/* TODO */ -fatal("TODO: remote backends not supported: %s", srg_loc); + /* backend is on a different host, srg_loc is the remote host[:port] */ + b->fns = &remote_backend_fns; + b->addr.sin_family = AF_INET; + b->addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); + b->addr.sin_port = htons(DEFAULT_REMOTE_PORT); + if(parse_addr(srg_loc, &b->addr.sin_addr, &b->addr.sin_port) < 0) + fatal("Unable to resolve host %s", srg_loc); + verbose("Remote backend at %s:%u", inet_ntoa(b->addr.sin_addr), ntohs(b->addr.sin_port)); } else { /* backend and frontend on same host, srg_loc is the base directory */ - b = &local_backend; + b->fns = &local_backend_fns; b->base_dir = srg_loc; + verbose("Local backend; carousel file root '%s'", srg_loc); } - return b; + return; } void -free_MHEGBackend(MHEGBackend *b) +MHEGBackend_fini(MHEGBackend *b) { return; } /* + * extract the IP addr and port number from a string in one of these forms: + * host:port + * ip-addr:port + * host + * ip-addr + * if the port is not defined in the string, the value passed to this routine is unchanged + * ip and port are both returned in network byte order + * returns -1 on error (can't resolve host name) + */ + +static int +parse_addr(char *str, struct in_addr *ip, in_port_t *port) +{ + char *p; + + if((p = strchr(str, ':')) != NULL) + { + /* its either host:port or ip:port */ + *(p++) = '\0'; + if(get_host_addr(str, ip) < 0) + return -1; + *port = htons(atoi(p)); + /* reconstruct the string */ + *(--p) = ':'; + } + else if(get_host_addr(str, ip) < 0) + { + return -1; + } + + return 0; +} + +/* + * puts the IP address associated with the given host into output buffer + * host can be a.b.c.d or a host name + * returns 0 if successful, -1 on error + */ + +static int +get_host_addr(char *host, struct in_addr *output) +{ + struct hostent *he; + int error = 0; + + if(((he = gethostbyname(host)) != NULL) && (he->h_addrtype == AF_INET)) + memcpy(output, he->h_addr, sizeof(struct in_addr)); + else + error = -1; + + return error; +} + +/* + * send the given command to the remote backend + * returns a socket fd to read the response from + * returns <0 if it can't contact the backend + */ + +static int +remote_command(MHEGBackend *t, char *cmd) +{ + int sock; + + /* connect to the backend */ + if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0) + { + error("Unable to create backend socket: %s", strerror(errno)); + return -1; + } + + if(connect(sock, (struct sockaddr *) &t->addr, sizeof(struct sockaddr_in)) < 0) + { + error("Unable to connect to backend: %s", strerror(errno)); + return -1; + } + + /* send the command */ + write_string(sock, cmd); + + return sock; +} + +/* + * read the backend response from the given socket fd + * returns the OK/error code + */ + +#define BACKEND_RESPONSE_OK 200 + +static unsigned int +remote_response(int sock) +{ + char buf[1024]; + char byte; + unsigned int total; + ssize_t nread; + unsigned int rc; + + /* read upto \n */ + total = 0; + do + { + if((nread = read(sock, &byte, 1)) == 1) + buf[total++] = byte; + } + while(nread == 1 && byte != '\n' && total < (sizeof(buf) - 1)); + + /* \0 terminate it */ + buf[total] = '\0'; + + rc = atoi(buf); + + return rc; +} + +/* * local routines */ /* * returns a filename that can be loaded from the file system * ie ~// at the start of the absolute name is replaced with base_dir - * returns a ptr to static string that will be overwritten by the next call to this routine + * returns a ptr to a static string that will be overwritten by the next call to this routine */ static char _external[PATH_MAX]; @@ -71,7 +220,7 @@ absolute = MHEGEngine_absoluteFilename(name); /* construct the filename */ - snprintf(_external, sizeof(_external), "%s%s", t->base_dir, &absolute[1]); + snprintf(_external, sizeof(_external), "%s%s", t->base_dir, &absolute[2]); return _external; } @@ -98,6 +247,7 @@ /* * file contents are stored in out (out->data will need to be free'd) * returns false if it can't load the file (out will be {0,NULL}) + * out should be {0,NULL} before calling this */ bool @@ -106,16 +256,6 @@ char *fullname; FILE *file; - out->size = 0; - out->data = NULL; - - /* just in case */ - if(name->size == 0) - { - verbose("local_loadFile: no filename given"); - return false; - } - fullname = external_filename(t, name); /* open it */ @@ -162,3 +302,136 @@ return fclose(file); } +/* + * remote routines + */ + +/* + * returns true if the file exists on the carousel + */ + +bool +remote_checkContentRef(MHEGBackend *t, ContentReference *name) +{ + char cmd[PATH_MAX]; + int sock; + bool exists; + + snprintf(cmd, sizeof(cmd), "check %s\n", MHEGEngine_absoluteFilename(name)); + + if((sock = remote_command(t, cmd)) < 0) + return false; + + exists = (remote_response(sock) == BACKEND_RESPONSE_OK); + + close(sock); + + return exists; +} + +/* + * file contents are stored in out (out->data will need to be free'd) + * returns false if it can't load the file (out will be {0,NULL}) + * out should be {0,NULL} before calling this + */ + +bool +remote_loadFile(MHEGBackend *t, OctetString *name, OctetString *out) +{ + char cmd[PATH_MAX]; + int sock; + char buf[8 * 1024]; + ssize_t nread; + bool success = false; + + snprintf(cmd, sizeof(cmd), "file %s\n", MHEGEngine_absoluteFilename(name)); + + if((sock = remote_command(t, cmd)) < 0) + return false; + + /* does it exist */ + if(remote_response(sock) == BACKEND_RESPONSE_OK) + { + verbose("Loading '%.*s'", name->size, name->data); + /* read from the socket until EOF */ + do + { + if((nread = read(sock, buf, sizeof(buf))) > 0) + { + out->data = safe_realloc(out->data, out->size + nread); + memcpy(out->data + out->size, buf, nread); + out->size += nread; + } + } + while(nread > 0); + success = true; + } + else + { + error("Unable to load '%.*s'", name->size, name->data); + } + + close(sock); + + return success; +} + +FILE * +remote_openFile(MHEGBackend *t, OctetString *name, char *mode) +{ + char cmd[PATH_MAX]; + int sock; + char buf[8 * 1024]; + ssize_t nread; + size_t nwritten; + FILE *file = NULL; + + snprintf(cmd, sizeof(cmd), "file %s\n", MHEGEngine_absoluteFilename(name)); + + if((sock = remote_command(t, cmd)) < 0) + return NULL; + + /* does it exist */ + if(remote_response(sock) == BACKEND_RESPONSE_OK) + { + if((file = tmpfile()) != NULL) + { + /* read from the socket until EOF */ + do + { + if((nread = read(sock, buf, sizeof(buf))) > 0) + nwritten = fwrite(buf, 1, nread, file); + else + nwritten = 0; + } + while(nread > 0 && nread == nwritten); + /* could we write the file ok */ + if(nread != nwritten) + { + error("Unable to write to local file"); + fclose(file); + file = NULL; + } + } + } + + close(sock); + + /* rewind the file */ + if(file != NULL) + rewind(file); + + return file; +} + +/* + * close a FILE opened with MHEGEngine_openFile() + */ + +int +remote_closeFile(MHEGBackend *t, FILE *file) +{ + /* tmpfile() will delete the file for us */ + return fclose(file); +} + Modified: redbutton-browser/trunk/MHEGBackend.h =================================================================== --- redbutton-browser/trunk/MHEGBackend.h 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/MHEGBackend.h 2006-03-02 17:10:15 UTC (rev 10) @@ -7,17 +7,26 @@ #include <stdio.h> #include <stdbool.h> +#include <netinet/in.h> +/* default TCP port to contact backend on */ +#define DEFAULT_REMOTE_PORT 10101 + typedef struct MHEGBackend { - char *base_dir; /* Service Gateway root directory */ - bool (*checkContentRef)(struct MHEGBackend *, ContentReference *); /* check a file exists */ - bool (*loadFile)(struct MHEGBackend *, OctetString *, OctetString *); /* load a file */ - FILE *(*openFile)(struct MHEGBackend *, OctetString *, char *); /* open a file */ - int (*closeFile)(struct MHEGBackend *, FILE *); /* close a file */ + char *base_dir; /* local Service Gateway root directory */ + struct sockaddr_in addr; /* remote backend IP and port */ + /* function pointers */ + struct MHEGBackendFns + { + bool (*checkContentRef)(struct MHEGBackend *, ContentReference *); /* check a file exists */ + bool (*loadFile)(struct MHEGBackend *, OctetString *, OctetString *); /* load a file */ + FILE *(*openFile)(struct MHEGBackend *, OctetString *, char *); /* open a file */ + int (*closeFile)(struct MHEGBackend *, FILE *); /* close a file */ + } *fns; } MHEGBackend; -MHEGBackend *new_MHEGBackend(bool, char *); -void free_MHEGBackend(MHEGBackend *); +void MHEGBackend_init(MHEGBackend *, bool, char *); +void MHEGBackend_fini(MHEGBackend *); #endif /* __MHEGBACKEND_H__ */ Modified: redbutton-browser/trunk/MHEGDisplay.c =================================================================== --- redbutton-browser/trunk/MHEGDisplay.c 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/MHEGDisplay.c 2006-03-02 17:10:15 UTC (rev 10) @@ -240,7 +240,7 @@ } void -MHEGDisplay_stop(MHEGDisplay *d) +MHEGDisplay_fini(MHEGDisplay *d) { /* calls XCloseDisplay for us which free's all our Windows, Pixmaps, etc */ XtDestroyApplicationContext(d->app); Modified: redbutton-browser/trunk/MHEGDisplay.h =================================================================== --- redbutton-browser/trunk/MHEGDisplay.h 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/MHEGDisplay.h 2006-03-02 17:10:15 UTC (rev 10) @@ -52,7 +52,7 @@ } MHEGDisplay; void MHEGDisplay_init(MHEGDisplay *, bool, char *); -void MHEGDisplay_stop(MHEGDisplay *); +void MHEGDisplay_fini(MHEGDisplay *); bool MHEGDisplay_processEvents(MHEGDisplay *, bool); Modified: redbutton-browser/trunk/MHEGEngine.c =================================================================== --- redbutton-browser/trunk/MHEGEngine.c 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/MHEGEngine.c 2006-03-02 17:10:15 UTC (rev 10) @@ -173,7 +173,7 @@ MHEGDisplay_init(&engine.display, fullscreen, keymap); - engine.backend = new_MHEGBackend(remote, srg_loc); + MHEGBackend_init(&engine.backend, remote, srg_loc); MHEGApp_init(&engine.active_app); @@ -223,7 +223,7 @@ ApplicationClass_Deactivation(app); ApplicationClass_Destruction(app); /* clean up */ - MHEGApp_stop(&engine.active_app); + MHEGApp_fini(&engine.active_app); LIST_FREE(&engine.objects, RootClassPtr, safe_free); LIST_FREE(&engine.missing_content, MissingContent, free_MissingContentListItem); LIST_FREE(&engine.active_links, LinkClassPtr, safe_free); @@ -264,15 +264,15 @@ } void -MHEGEngine_stop(void) +MHEGEngine_fini(void) { - MHEGDisplay_stop(&engine.display); + MHEGDisplay_fini(&engine.display); LIST_FREE(&engine.persistent, PersistentData, free_PersistentDataListItem); si_free(); - free_MHEGBackend(engine.backend); + MHEGBackend_fini(&engine.backend); return; } @@ -1293,18 +1293,30 @@ bool MHEGEngine_checkContentRef(ContentReference *name) { - return (*(engine.backend->checkContentRef))(engine.backend, name); + return (*(engine.backend.fns->checkContentRef))(&engine.backend, name); } /* * file contents are stored in out (out->data will need to be free'd) * returns false if it can't load the file (out will be {0,NULL}) + * out should be uninitialised before calling this */ bool MHEGEngine_loadFile(OctetString *name, OctetString *out) { - return (*(engine.backend->loadFile))(engine.backend, name, out); + /* in case it fails */ + out->size = 0; + out->data = NULL; + + /* just in case */ + if(name->size == 0) + { + verbose("MHEGEngine_loadFile: no filename given"); + return false; + } + + return (*(engine.backend.fns->loadFile))(&engine.backend, name, out); } /* @@ -1316,7 +1328,7 @@ FILE * MHEGEngine_openFile(OctetString *name, char *mode) { - return (*(engine.backend->openFile))(engine.backend, name, mode); + return (*(engine.backend.fns->openFile))(&engine.backend, name, mode); } /* @@ -1326,7 +1338,7 @@ int MHEGEngine_closeFile(FILE *file) { - return (*(engine.backend->closeFile))(engine.backend, file); + return (*(engine.backend.fns->closeFile))(&engine.backend, file); } /* Modified: redbutton-browser/trunk/MHEGEngine.h =================================================================== --- redbutton-browser/trunk/MHEGEngine.h 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/MHEGEngine.h 2006-03-02 17:10:15 UTC (rev 10) @@ -154,7 +154,7 @@ int verbose; /* -v cmd line flag */ unsigned int timeout; /* how long to poll for missing content before generating an error */ MHEGDisplay display; /* make porting easier */ - MHEGBackend *backend; /* local or remote access to DSMCC carousel and MPEG streams */ + MHEGBackend backend; /* local or remote access to DSMCC carousel and MPEG streams */ MHEGApp active_app; /* application we are currently running */ QuitReason quit_reason; /* do we need to stop the current app */ OctetString quit_data; /* new app to Launch or Spawn, or channel to Retune to */ @@ -171,7 +171,7 @@ /* prototypes */ void MHEGEngine_init(bool, char *, int, unsigned int, bool, char *); int MHEGEngine_run(OctetString *); -void MHEGEngine_stop(); +void MHEGEngine_fini(); MHEGDisplay *MHEGEngine_getDisplay(void); Modified: redbutton-browser/trunk/TODO =================================================================== --- redbutton-browser/trunk/TODO 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/TODO 2006-03-02 17:10:15 UTC (rev 10) @@ -1,3 +1,6 @@ +handle SIGPIPE - default handler terminates the process + + are all inherited instance vars added to classes? @@ -12,7 +15,8 @@ cope with DSM: and CI: filename prefixes -cope with .. in filenames +cope with .. in filenames (may not be needed, remote backend does it for us, +for local backend filesystem does it for us) see 8.3.2 in UK MHEG Profile Modified: redbutton-browser/trunk/rb-browser.c =================================================================== --- redbutton-browser/trunk/rb-browser.c 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/rb-browser.c 2006-03-02 17:10:15 UTC (rev 10) @@ -113,7 +113,7 @@ } /* clean up */ - MHEGEngine_stop(); + MHEGEngine_fini(); return rc; } Modified: redbutton-browser/trunk/utils.c =================================================================== --- redbutton-browser/trunk/utils.c 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/utils.c 2006-03-02 17:10:15 UTC (rev 10) @@ -20,14 +20,57 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ +#include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <stdarg.h> +#include <string.h> #include <ctype.h> +#include <errno.h> #include "utils.h" /* + * write the given string (ie upto \0) to the given fd + */ + +void +write_string(int fd, const char *str) +{ + write_all(fd, str, strlen(str)); + + return; +} + +/* + * guarantee writing count bytes from buf to fd + * W. Richard Stevens + */ + +void +write_all(int fd, const void *buf, size_t count) +{ + size_t nwritten; + const char *buf_ptr; + + buf_ptr = buf; + while(count > 0) + { + if((nwritten = write(fd, buf_ptr, count)) < 0) + { + if(errno == EINTR || errno == EAGAIN) + nwritten = 0; + else + fatal("write: %s\n", strerror(errno)); + } + count -= nwritten; + buf_ptr += nwritten; + } + + return; +} + +/* * returns 15 for 'f' etc */ @@ -38,7 +81,7 @@ return 0; else if(c >= '0' && c <= '9') return c - '0'; - else + else return 10 + (tolower(c) - 'a'); } Modified: redbutton-browser/trunk/utils.h =================================================================== --- redbutton-browser/trunk/utils.h 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-browser/trunk/utils.h 2006-03-02 17:10:15 UTC (rev 10) @@ -33,6 +33,9 @@ #define MAX(a, b) ((a) > (b) ? (a) : (b)) #endif +void write_string(int, const char *); +void write_all(int, const void *, size_t); + unsigned int char2hex(unsigned char); int next_utf8(unsigned char *, int, int *); Modified: redbutton-download/trunk/listen.c =================================================================== --- redbutton-download/trunk/listen.c 2006-03-02 11:50:43 UTC (rev 9) +++ redbutton-download/trunk/listen.c 2006-03-02 17:10:15 UTC (rev 10) @@ -192,8 +192,9 @@ quit = handle_connection(listen_data, accept_sock, &client_addr); close(accept_sock); /* TODO */ -if(quit) printf("QUIT!!!\n"); - exit(EXIT_SUCCESS); +if(quit) printf("TODO: QUIT\n"); + /* use _exit in child so stdio etc don't clean up twice */ + _exit(EXIT_SUCCESS); } else { @@ -226,7 +227,7 @@ { /* \0 terminate the buffer */ cmd[nread] = '\0'; - /* strip off an trailing \n (only needed when testing with telnet etc) */ + /* strip off any trailing \n */ nread --; while(nread > 0 && (cmd[nread] == '\n' || cmd[nread] == '\r')) cmd[nread--] = '\0'; This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-02 11:50:46
|
Revision: 9 Author: skilvington Date: 2006-03-02 03:50:43 -0800 (Thu, 02 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=9&view=rev Log Message: ----------- remove // and /./ in canonical ContentReferences Modified Paths: -------------- redbutton-download/trunk/command.c Modified: redbutton-download/trunk/command.c =================================================================== --- redbutton-download/trunk/command.c 2006-03-02 11:22:44 UTC (rev 8) +++ redbutton-download/trunk/command.c 2006-03-02 11:50:43 UTC (rev 9) @@ -287,15 +287,24 @@ /* no more slashes => nothing left to do */ if(*slash == '\0') return _canon; - /* if the next path component is "../", eat the previous one */ - if(strncmp(slash, "/../", 4) == 0) + /* if this component is empty (ie ./ or /) remove it */ + if(strncmp(start, "./", 2) == 0 || *start == '/') { /* include \0 terminator */ - len = strlen(start) + 1; - memmove(start, slash + 4, len - ((slash - start) + 4)); + len = strlen(slash + 1) + 1; + memmove(start, slash + 1, len); /* restart the search */ start = _canon; } + /* if the next path component is "../", eat this one */ + else if(strncmp(slash, "/../", 4) == 0) + { + /* include \0 terminator */ + len = strlen(slash + 4) + 1; + memmove(start, slash + 4, len); + /* restart the search */ + start = _canon; + } else { /* move to the next component */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-02 11:22:48
|
Revision: 8 Author: skilvington Date: 2006-03-02 03:22:44 -0800 (Thu, 02 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=8&view=rev Log Message: ----------- extra .. check when canonicalising ContentReferences Modified Paths: -------------- redbutton-download/trunk/command.c Modified: redbutton-download/trunk/command.c =================================================================== --- redbutton-download/trunk/command.c 2006-03-02 11:11:58 UTC (rev 7) +++ redbutton-download/trunk/command.c 2006-03-02 11:22:44 UTC (rev 8) @@ -245,7 +245,7 @@ canon_cref = canonical_filename(cref + 3); /* if the canonical name starts with "../", it is invalid */ - if(strncmp(canon_cref, "../", 3) == 0) + if(strcmp(canon_cref, "..") == 0 || strncmp(canon_cref, "../", 3) == 0) return NULL; /* create the carousel filename, ie prepend the servive gateway directory */ This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |
|
From: <ski...@us...> - 2006-03-02 11:12:08
|
Revision: 7 Author: skilvington Date: 2006-03-02 03:11:58 -0800 (Thu, 02 Mar 2006) ViewCVS: http://svn.sourceforge.net/redbutton/?rev=7&view=rev Log Message: ----------- canonicalise ContentReferences passed to rb-download Modified Paths: -------------- redbutton-download/trunk/command.c redbutton-download/trunk/listen.h redbutton-download/trunk/rb-download.c Modified: redbutton-download/trunk/command.c =================================================================== --- redbutton-download/trunk/command.c 2006-03-01 16:32:29 UTC (rev 6) +++ redbutton-download/trunk/command.c 2006-03-02 11:11:58 UTC (rev 7) @@ -7,12 +7,14 @@ #include <stdbool.h> #include "command.h" +#include "fs.h" #include "utils.h" /* max number of args that can be passed to a command (arbitrary) */ #define ARGV_MAX 10 /* the commands */ +bool cmd_check(struct listen_data *, int, int, char **); bool cmd_file(struct listen_data *, int, int, char **); bool cmd_help(struct listen_data *, int, int, char **); bool cmd_quit(struct listen_data *, int, int, char **); @@ -25,13 +27,21 @@ char *help; } command[] = { - { "exit", "", cmd_quit, "Kill the programme" }, - { "file", "<ContentReference>", cmd_file, "Retrieve the given file from the carousel" }, - { "help", "", cmd_help, "List available commands" }, - { "quit", "", cmd_quit, "Kill the programme" }, + { "check", "<ContentReference>", cmd_check, "Check if the given file exists on the carousel" }, + { "exit", "", cmd_quit, "Kill the programme" }, + { "file", "<ContentReference>", cmd_file, "Retrieve the given file from the carousel" }, + { "help", "", cmd_help, "List available commands" }, + { "quit", "", cmd_quit, "Kill the programme" }, { NULL, NULL, NULL, NULL } }; +/* send an OK/error code etc response down client_sock */ +#define SEND_RESPONSE(RC, MESSAGE) write_string(client_sock, #RC " " MESSAGE "\n") + +/* internal routines */ +char *external_filename(struct listen_data *, char *); +char *canonical_filename(char *); + /* * process the given command * return true if we should quit the programme @@ -84,7 +94,7 @@ return (command[i].proc)(listen_data, client_sock, argc, argv); } - write_string(client_sock, "500 Unrecognised command\n"); + SEND_RESPONSE(500, "Unrecognised command"); return false; } @@ -98,7 +108,47 @@ * return true if we should quit the programme */ +#define CHECK_USAGE(ARGC, SYNTAX) \ +if(argc != ARGC) \ +{ \ + SEND_RESPONSE(500, "Syntax: " SYNTAX); \ + return false; \ +} + /* + * check <ContentReference> + * check if the given file is on the carousel + * ContentReference should be absolute, ie start with "~//" + */ + +bool +cmd_check(struct listen_data *listen_data, int client_sock, int argc, char *argv[]) +{ + char *filename; + FILE *file; + + CHECK_USAGE(2, "check <ContentReference>"); + + if((filename = external_filename(listen_data, argv[1])) == NULL) + { + SEND_RESPONSE(500, "Invalid ContentReference"); + return false; + } + + if((file = fopen(filename, "r")) != NULL) + { + fclose(file); + SEND_RESPONSE(200, "OK"); + } + else + { + SEND_RESPONSE(404, "Not found"); + } + + return false; +} + +/* * file <ContentReference> * send the given file down client_sock * ContentReference should be absolute, ie start with "~//" @@ -112,32 +162,23 @@ size_t nread; char buff[1024 * 8]; - if(argc != 2) - { - write_string(client_sock, "500 Syntax: file <ContentReference>\n"); - return false; - } + CHECK_USAGE(2, "file <ContentReference>"); - filename = argv[1]; - - /* is ContentReference absolute */ - if(strlen(filename) < 3 || strncmp(filename, "~//", 3) != 0) + if((filename = external_filename(listen_data, argv[1])) == NULL) { - write_string(client_sock, "500 ContentReference is not absolute\n"); + SEND_RESPONSE(500, "Invalid ContentReference"); return false; } - /* strip off the ~// prefix */ - filename += 3; - if((file = fopen(filename, "r")) == NULL) { - write_string(client_sock, "404 Not found\n"); + SEND_RESPONSE(404, "Not found"); return false; } - write_string(client_sock, "200 OK\n"); + SEND_RESPONSE(200, "OK"); + /* send the file contents */ do { nread = fread(buff, 1, sizeof(buff), file); @@ -161,7 +202,7 @@ char name_args[64]; char help_line[128]; - write_string(client_sock, "200 OK\n"); + SEND_RESPONSE(200, "OK"); for(i=0; command[i].name != NULL; i++) { @@ -183,3 +224,86 @@ return true; } +/* + * return a filename that can be used to load the given ContentReference from the filesystem + * returns a static string that will be overwritten by the next call to this routine + * returns NULL if the ContentReference is invalid (does not start with ~// or has too many .. components) + */ + +static char _external[PATH_MAX]; + +char * +external_filename(struct listen_data *listen_data, char *cref) +{ + char *canon_cref; + + /* is ContentReference absolute */ + if(strlen(cref) < 3 || strncmp(cref, "~//", 3) != 0) + return NULL; + + /* strip off the ~// prefix, and canonicalise the reference */ + canon_cref = canonical_filename(cref + 3); + + /* if the canonical name starts with "../", it is invalid */ + if(strncmp(canon_cref, "../", 3) == 0) + return NULL; + + /* create the carousel filename, ie prepend the servive gateway directory */ + snprintf(_external, sizeof(_external), "%s/%u/%s", SERVICES_DIR, listen_data->carousel->service_id, canon_cref); + + return _external; +} + +/* + * return a string that recursively removes all sequences of the form '/x/../' in path + * returns a static string that will be overwritten by the next call to this routine + */ + +static char _canon[PATH_MAX]; + +char * +canonical_filename(char *path) +{ + char *start; + char *slash; + size_t len; + + /* copy path into the output buffer */ + strncpy(_canon, path, sizeof(_canon)); + /* just in case */ + _canon[sizeof(_canon)-1] = '\0'; + + /* keep removing "/x/../" until there are none left */ + start = _canon; + while(true) + { + /* find the start of the first path component that is not "../" */ + while(strncmp(start, "../", 3) == 0) + start += 3; + /* find the next slash in the path */ + slash = start; + while(*slash != '/' && *slash != '\0') + slash ++; + /* no more slashes => nothing left to do */ + if(*slash == '\0') + return _canon; + /* if the next path component is "../", eat the previous one */ + if(strncmp(slash, "/../", 4) == 0) + { + /* include \0 terminator */ + len = strlen(start) + 1; + memmove(start, slash + 4, len - ((slash - start) + 4)); + /* restart the search */ + start = _canon; + } + else + { + /* move to the next component */ + start = slash + 1; + } + } + + /* not reached */ + return NULL; +} + Modified: redbutton-download/trunk/listen.h =================================================================== --- redbutton-download/trunk/listen.h 2006-03-01 16:32:29 UTC (rev 6) +++ redbutton-download/trunk/listen.h 2006-03-02 11:11:58 UTC (rev 7) @@ -7,9 +7,12 @@ #include <netinet/in.h> +#include "module.h" + struct listen_data { struct sockaddr_in addr; /* ip:port to listen on */ + struct carousel *carousel; /* carousel we are downloading */ }; int parse_addr(char *, struct in_addr *, in_port_t *); Modified: redbutton-download/trunk/rb-download.c =================================================================== --- redbutton-download/trunk/rb-download.c 2006-03-01 16:32:29 UTC (rev 6) +++ redbutton-download/trunk/rb-download.c 2006-03-02 11:11:58 UTC (rev 7) @@ -132,7 +132,10 @@ car = find_mheg(device, timeout, service_id, carousel_id); printf("Carousel ID=%u\n", car->carousel_id); if(listen) + { + listen_data.carousel = car; start_listener(&listen_data); + } load_carousel(car); } else This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |