From: tytso@mit.edu Here are a set patches which you might find helpful. They do three things: 1) When playing back a stream which can't be seeked (i.e., one of stdin or through the TCP pipeline), then when seeking forwards, simply skip the requisite number of chunks. 2) Allow the video and audio programs to be overrideen via environment variables. 3) Add a -r option which immediately puts the Playitsame into record mode. This is useful when you want to pull a large number of programs off the Tivo in batch mode, using a shell script. Cheers! - Ted diff -u Playitsam-1.57.orig/playitsam.c Playitsam-1.57/playitsam.c --- Playitsam-1.57.orig/playitsam.c Tue Jan 29 05:28:13 2002 +++ Playitsam-1.57/playitsam.c Fri May 31 12:03:12 2002 @@ -234,16 +234,40 @@ exit_things |= EXIT_CLOSEAVDEVS; } +/* + * Read in a loop; we return -1 or a partial size on an error + */ +int read_loop(int fd, void *buf, size_t count) +{ + int amt = 0, c, tries = 0; + while (count > 0) { + c = read(fd, buf, count); + if (c == 0) { + if (tries++ > 3) + return amt; + } + if (c < 0) { + if (amt) + return amt; + else + return -1; + } + buf += c; + count -= c; + amt += c; + } + return amt; +} + /* Read a specific chunk from the input stream. * Return 1 if ok, 0 if failure */ int read_a_chunk(int fd, int chunknum) { - char *bptr = buf; int numread = 0; - int numleft = CHUNK_SIZE; + static int curr_chunk = -1; switch (inputtype) { #ifdef TIVO @@ -261,18 +285,19 @@ /* We only seek if we can. This means that the forward/backward * commands are NOT going to work for input on stdin. */ - if (seeking_ok) lseek(fd, CHUNK_SIZE * chunknum, SEEK_SET); - - /* Loop until we do get CHUNK_SIZE bytes of data */ - while (numleft > 0) { - numread = read(fd, bptr, numleft); - if (numread < 1) { - fprintf(stderr, "Failure reading chunk %d\r\n", chunknum); - Exit(1); - } - numleft -= numread; - bptr += numread; + if (seeking_ok) { + lseek(fd, CHUNK_SIZE * chunknum, SEEK_SET); + curr_chunk = chunknum; } + + do { + numread = read_loop(fd, buf, CHUNK_SIZE); + if (numread != CHUNK_SIZE) { + fprintf(stderr, "Failure reading chunk %d\r\n", chunknum); + Exit(1); + } + curr_chunk++; + } while (curr_chunk < chunknum); return (1); default: return (0); @@ -659,15 +684,21 @@ extern char *optarg; extern int optind; int c, cmd, cstart, is_a_cut=0; + int do_record = 0; /* Start immediately in record mode */ int paused = 0; /* Start in non-paused mode */ int skip_cut_sections=0; /* Toggle: if 0 we play all chunks, cut */ /* or not. If 1, we skip cuts. Not yet */ /* implemented */ + char *audio_prog, *video_prog; #ifdef TIVO - argflags= "vhnpMD"; + argflags= "vhnprMD"; #else - argflags= "vhnpc"; + argflags= "vhnprc"; + if (!(audio_prog = getenv("AUDIO_PROG"))) + audio_prog = AUDIO_PROG; + if (!(video_prog = getenv("VIDEO_PROG"))) + video_prog = VIDEO_PROG; #endif /* Get the various flags to the program */ @@ -691,6 +722,8 @@ case 'D': do_osd=0; break; + case 'r': do_record = 1; break; + case 'h': default: usage(); } @@ -717,6 +750,16 @@ } #endif + /* Try to open the input up */ + fname = argv[0]; outfname = argv[1]; + fd = open_input(fname); + if (fd==-1) { fprintf(stderr, "Can't open input file %s\n",fname); Exit(1); } + + if (do_record) { + record_program(outfname, fd); + Exit(0); + } + /* Set the keyboard to raw mode & non-blocking, * so we can get single character commands */ @@ -729,11 +772,6 @@ exit_things |= EXIT_FIXKEYBOARD; } - /* Try to open the input up */ - fname = argv[0]; outfname = argv[1]; - fd = open_input(fname); - if (fd==-1) { fprintf(stderr, "Can't open input file %s\n",fname); Exit(1); } - /* Open the output devices if we are going to play things back */ if (allow_playback) { #ifdef TIVO @@ -741,7 +779,7 @@ open_remote_device(); set_high_process_priority(); #else - openpipes(AUDIO_PROG, VIDEO_PROG); + openpipes(audio_prog, video_prog); #endif }