long FindPlaybackTime(struct timeval t, long start_pos) { playback_t rec; struct timeval time; if (fseek(Playback_Stream, start_pos, SEEK_SET) < 0) { char *s = strerror(errno); Log(DBG_GEN, "Error seeking in file: %s\n", s); return 0; } do { fread(&rec, sizeof (playback_t), 1, Playback_Stream); time = rec.record.mix_in_time; if (TP_IN_FP_SECS(time) >= TP_IN_FP_SECS(t)) { return (ftell(Playback_Stream) - sizeof (playback_t)); } /* Check if we need to round robing in front of the header */ if (feof(Playback_Stream)) { if (fseek(Playback_Stream, sizeof (struct playback_h), SEEK_SET) < 0) { char *s = strerror(errno); Log(DBG_GEN, "Error seeking in file: %s\n", s); return 0; } } } while (ftell(Playback_Stream) != start_pos); return 0; }
long playbackFindFirstOffset (void) { playback_t cur, prev; long initial_pos = ftell (stream); fread (&prev, sizeof (playback_t), 1, stream); while (!feof (stream)) { fread (&cur, sizeof (playback_t), 1, stream); /* Check if the event we're reading in was earlier than the * previous event. If so, return the position right before * the read */ if (TP_IN_FP_SECS (cur.record.mix_time) < TP_IN_FP_SECS (prev.record.mix_time)) { return (ftell (stream) - sizeof (playback_t)); } } /* If we got here, then we didn't record enough events * to round-robin */ return (initial_pos); }
int playbackFileShutdown (void) { switch (mode) { case RECORD_MODE: /* Finish filling out the header and rewrite it to disk */ header.written = event_cnt; gettimeofday (&header.end_t, NULL); /* At this point, either we're at the end of the file, or * we should currently be pointing at it */ if (loopback_flag) { header.start_pos = ftell (stream); } else { header.start_pos = sizeof (struct playback_h); } #if DEBUG_LEVEL & DBG_PLBK logMsg (DBG_PLBK, "On shutdown, the playback header is:\n"); logMsg (DBG_PLBK, "\tmajor ver: [%d]\n", header.major_ver); logMsg (DBG_PLBK, "\tminor ver: [%d]\n", header.minor_ver); logMsg (DBG_PLBK, "\tmax events: [%d]\n", header.max_events); logMsg (DBG_PLBK, "\tevents written: [%d]\n", header.written); logMsg (DBG_PLBK, "\tstart pos: [%d]\n", header.start_pos); logMsg (DBG_PLBK, "\tstart time: [%lf]\n", TP_IN_FP_SECS (header.start_t)); logMsg (DBG_PLBK, "\tend time: [%lf]\n", TP_IN_FP_SECS (header.end_t)); #endif /* Now seek to the start of the file and write out the header */ if (fseek (stream, 0, SEEK_SET) < 0) { logMsg (DBG_GEN, "Error seeking in file: %s", strerror (errno)); return 0; } fwrite (&header, sizeof (struct playback_h), 1, stream); fflush (stream); break; case PLAY_MODE: logMsg (DBG_DEF, "Finished playback. You just heard %d events.\n", event_cnt); break; default: logMsg (DBG_DEF, "Warning: peepd was in an invalid playback mode."); logMsg (DBG_DEF, "shutdown may not have been successful\n"); } }
int PlaybackFileShut(void) { switch (Mode) { case RECORD_MODE: /* Finish filling out the header and rewrite it to disk */ Header.written = Event_Count; gettimeofday(&Header.end_t, NULL); /* At this point, either we're at the end of the file, or * we should currently be pointing at it */ if (Loopback_Flag) Header.start_pos = ftell(Playback_Stream); else Header.start_pos = sizeof (struct playback_h); #if DEBUG_LEVEL & DBG_PLBK Log(DBG_PLBK, "On shutdown, the playback header is:\n major ver => %d\n minor ver => %d\n max events => %d\n", Header.major_ver, Header.minor_ver, Header.max_events); Log(DBG_PLBK, " events written => %d\n start pos => %ld\n start time => %lf\n end time => %lf\n\n", Header.written, Header.start_pos, TP_IN_FP_SECS(Header.start_t), TP_IN_FP_SECS(Header.end_t)); #endif /* Now seek to the start of the file and write out the header */ if (fseek(Playback_Stream, 0, SEEK_SET) < 0) { char *s = strerror(errno); Log(DBG_GEN, "Error seeking in file: %s", s); return 0; } fwrite(&Header, sizeof (struct playback_h), 1, Playback_Stream); fflush(Playback_Stream); break; case PLAYBACK_MODE: Log(DBG_DEF, "Finished playback. You just heard %d events.\n", Event_Count); break; default: Log(DBG_DEF, "Warning: peepd was in an invalid playback mode."); Log(DBG_DEF, "Shutdown may not have been successful\n"); } }
int playbackRecordEvent (ENGINE_EVENT e) { playback_t rec; /* The record to write out */ /* Record the time when the event occurred */ gettimeofday (&e.mix_time, NULL); #if DEBUG_LEVEL & DBG_PLBK logMsg (DBG_PLBK, "Recording event at time: %lf, file offset: %d\n", TP_IN_FP_SECS (e.mix_time), ftell (stream)); #endif /* Create a record */ rec.record = e; /* Have we written our maximum events? */ if (event_cnt != MAX_PLAYBACK_EVENTS) { if (fwrite (&rec, sizeof (playback_t), 1, stream) == 0) { logMsg (DBG_GEN, "Error writing to recording file: %s\n", strerror (errno)); return 0; } } else { loopback_flag = 1; /* Else, reset our position, right after the header */ if (fseek (stream, sizeof (struct playback_h), SEEK_SET) < 0) { logMsg (DBG_GEN, "Error seeking in file: %s\n", strerror (errno)); return 0; } if (fwrite (&rec, sizeof (playback_t), 1, stream) == 0) { logMsg (DBG_GEN, "Error writing to recording file: %s\n", strerror (errno)); return 0; } } fflush (stream); event_cnt++; return 1; }
/* Initialize all of the playback routines */ int PlaybackFileInit(char *file) { #if DEBUG_LEVEL & DBG_PLBK Log(DBG_PLBK, "Playback routines using file: %s, ", file); if (PlaybackSetMode(NULL) == RECORD_MODE) Log(DBG_PLBK, "mode: 'RECORD_MODE'\n"); else Log(DBG_PLBK, "mode: 'PLAYBACK_MODE'\n"); #endif switch (PlaybackSetMode(NULL)) { case PLAYBACK_MODE: if ((Playback_Stream = fopen(file, "r")) == NULL) { char *s = strerror(errno); Log(DBG_GEN, "Uh Oh! Couldn't open playback file: %s\n", s); Shutdown(); } /* Lead the header into memory */ if (fread(&Header, sizeof (struct playback_h), 1, Playback_Stream) == 0) { char *s = strerror(errno); Log(DBG_GEN, "Error reading in playback header: %s\n", s); return 0; } break; case RECORD_MODE: if ((Playback_Stream = fopen(file, "w")) == NULL) { char *s = strerror(errno); Log(DBG_GEN, "Uh Oh! Couldn't create recoding file: %s\n", s); Shutdown(); } bzero((char *) &Header, sizeof (struct playback_h)); Header.major_ver = PLAYBACK_MAJOR_VER; Header.minor_ver = PLAYBACK_MINOR_VER; Header.max_events = MAX_PLAYBACK_EVENTS; /* Our initial start position can be found right after * the header */ Header.start_pos = sizeof (struct playback_h); gettimeofday(&Header.start_t, NULL); /* Initialize the file with the header. Note that end_t is initially * left at zero */ if (fwrite(&Header, sizeof (struct playback_h), 1, Playback_Stream) == 0) { char *s = strerror(errno); Log(DBG_GEN, "Error initializing file with playback header: %s\n", s); return 0; } /* Flush out the header */ fflush(Playback_Stream); break; default: Log (DBG_DEF, "Uh Oh! peepd asked to use invalid mode for playback. Please specify: {PLAYBACK_MODE, RECORD_MODE}\n"); Shutdown(); } #if DEBUG_LEVEL & DBG_PLBK Log(DBG_PLBK, "The playback header is:\n major ver => %d\n minor ver => %d\n max events => %d\n", Header.major_ver, Header.minor_ver, Header.max_events); Log(DBG_PLBK, " events written => %d\n start pos => %ld\n start time => %lf\n end time => %lf\n\n", Header.written, Header.start_pos, TP_IN_FP_SECS(Header.start_t), TP_IN_FP_SECS(Header.end_t)); #endif return 1; }
/* Read the events from the playback file. User can optionally * specify the starting and ending time to listen to. If these * aren't sepcified (i.e, start_t == NULL and end_t == NULL), * then playback starts at the earlier events in the file, which * should already be pointed at in the file stream by the time * this function is called */ void GoPlaybackMode(char *start_t, char *end_t) { struct timeval start, end, current, event_offset, time_offset; double plbk_offset, cur_time_offset; long start_pos, end_pos; char *Time_Format = PLAYBACK_TIME_FORMAT; playback_t rec; /* Check if we've been given a start time */ if (start_t != NULL) { struct tm tm; /* We need to convert the ascii start and end times into * seconds since the epoch */ bzero((char *) &tm, sizeof (struct tm)); strptime(start_t, Time_Format, &tm); start.tv_sec = mktime(&tm); start.tv_usec = 0; #if DEBUG_LEVEL & DBG_PLBK Log(DBG_PLBK, "Converted start time is: %lf\n", TP_IN_FP_SECS(start)); #endif /* Now find the starting time */ Header.start_pos = FindFirstOffset(); if ((start_pos = FindPlaybackTime(start, Header.start_pos)) == 0) { Log (DBG_DEF, "Couldn't find start time in playback file. Playing from beginning."); start_pos = sizeof (struct playback_h); } /* Now check if we also have an end time */ if (end_t != NULL) { bzero((char *) &tm, sizeof (struct tm)); strptime(end_t, Time_Format, &tm); end.tv_sec = mktime(&tm); end.tv_usec = 0; #if DEBUG_LEVEL & DBG_PLBK Log(DBG_PLBK, "Converted end time is: %lf\n", TP_IN_FP_SECS(end)); #endif /* Check if there's an ending time */ if ((end_pos = FindPlaybackTime(end, FindFirstOffset())) == 0) { /* Since we can't find the end time in the playback file, we want to * end at the end of the round robin in the file which is either right * after the header or the event just prior to the start position */ end_pos = (Header.start_pos == sizeof (struct playback_h)) ? sizeof (struct playback_h) : start_pos - sizeof (playback_t); } } /* Now set ourselves at the start position to be sure we're there */ if (fseek(Playback_Stream, start_pos, SEEK_SET) < 0) { char *s = strerror(errno); Log(DBG_GEN, "Error seeking in file: %s\n", s); Shutdown(); } } else { /* Otherwise, just play from the beginning */ Log(DBG_DEF, "No start and end time given.\n"); Log(DBG_DEF, "Starting playback from the earliest event in file...\n"); /* Check if we last closed the file correctly */ if (TP_IN_FP_SECS(Header.end_t) != 0.0) { if (fseek(Playback_Stream, Header.start_pos, SEEK_SET) < 0) { char *s = strerror(errno); Log(DBG_GEN, "Error seeking in file: %s\n", s); Shutdown(); } } else { /* The file wasn't closed correctly so we need to determine * where the starting position is in the round robin */ if (fseek(Playback_Stream, FindFirstOffset(), SEEK_SET) < 0) { char *s = strerror(errno); Log(DBG_GEN, "Error seeking in file: %s\n", s); Shutdown(); } } start_pos = ftell(Playback_Stream); end_pos = 0; } /* Figure out time diff with respect to our current time */ fread(&rec, sizeof (playback_t), 1, Playback_Stream); event_offset = rec.record.mix_in_time; gettimeofday(&time_offset, NULL); fseek(Playback_Stream, -sizeof (playback_t), SEEK_CUR); #if DEBUG_LEVEL & DBG_PLBK Log(DBG_PLBK, "Calculated event offset: %lf and time offset: %lf...\n", TP_IN_FP_SECS(event_offset), TP_IN_FP_SECS(time_offset)); Log(DBG_PLBK, "Expected start position: %ld and end position: %ld\n", start_pos, end_pos); #endif /* Do the actual playback */ do { #if DEBUG_LEVEL & DBG_PLBK Log(DBG_DEF, "We're currently looking at position: %ld\n", ftell(Playback_Stream)); #endif if (fread(&rec, sizeof (playback_t), 1, Playback_Stream) == 0) { switch (errno) { case EINTR: #if DEBUG_LEVEL & DBG_PLBK Log(DBG_PLBK, "Hit eof. Reseting to end of header...\n"); #endif fseek(Playback_Stream, sizeof (struct playback_h), SEEK_SET); continue; default: { char *s = strerror(errno); Log(DBG_GEN, "Error reading in event: %s. Attempting to continue...\n", s); /* Attempting to continue */ } } } gettimeofday(¤t, NULL); plbk_offset = TP_IN_FP_SECS(rec.record.mix_in_time) - TP_IN_FP_SECS(event_offset); cur_time_offset = TP_IN_FP_SECS(current) - TP_IN_FP_SECS(time_offset); #if DEBUG_LEVEL & DBG_PLBK Log(DBG_PLBK, "Playback: Mix in time: %lf, current time: %lf, mix offset: %lf, time offset: %lf, sleeping: %lf\n", TP_IN_FP_SECS(rec.record.mix_in_time), TP_IN_FP_SECS(current), plbk_offset, cur_time_offset, plbk_offset - cur_time_offset); #endif /* Sleep our event offset if necessary */ if (plbk_offset > cur_time_offset) usleep((unsigned long) ((plbk_offset - cur_time_offset) * 1000000.0)); EngineEnqueue(rec.record); Event_Count++; } while (ftell(Playback_Stream) != end_pos && ftell(Playback_Stream) != start_pos); /* Now that we're done playback, let's wait a bit for the next sound to play * and then shutdown */ sleep(PLAYBACK_TRAIL_TIME); Shutdown(); }
int playbackFileInit (char *file) { #if DEBUG_LEVEL & DBG_PLBK logMsg (DBG_PLBK, "Playback routines using file: %s, ", file); #endif if (playbackSetMode (NULL) == RECORD_MODE) { logMsg (DBG_PLBK, "mode: 'RECORD_MODE'\n"); } else { logMsg (DBG_PLBK, "mode: 'PLAY_MODE'\n"); } switch (playbackSetMode (NULL)) { case PLAY_MODE: if ((stream = fopen (file, "r")) == NULL) { logMsg (DBG_GEN, "Uh Oh! Couldn't open playback file: %s\n", strerror (errno)); shutDown (); } /* Lead the header into memory */ if (fread (&header, sizeof (struct playback_h), 1, stream) == 0) { logMsg (DBG_GEN, "Error reading in playback header: %s\n", strerror (errno)); return 0; } break; case RECORD_MODE: if ((stream = fopen (file, "w")) == NULL) { logMsg (DBG_GEN, "Uh Oh! Couldn't create recoding file: %s\n", strerror (errno)); shutdown (); } memset (&header, 0, sizeof (struct playback_h)); header.major_ver = PLAYBACK_MAJOR_VER; header.minor_ver = PLAYBACK_MINOR_VER; header.max_events = MAX_PLAYBACK_EVENTS; /* Our initial start position can be found right after * the header */ header.start_pos = sizeof (struct playback_h); gettimeofday (&header.start_t, NULL); /* Initialize the file with the header. Note that end_t is initially * left at zero */ if (fwrite (&header, sizeof (struct playback_h), 1, stream) == 0) { logMsg (DBG_GEN, "Error initializing file with playback header: %s\n", strerror (errno)); return 0; } /* Flush out the header */ fflush (stream); break; default: logMsg (DBG_DEF, "Uh Oh! peepd asked to use invalid mode for playback. Please specify: {PLAY_MODE, RECORD_MODE}\n"); shutdown (); } #if DEBUG_LEVEL & DBG_PLBK logMsg (DBG_PLBK, "The playback header is:\n"); logMsg (DBG_PLBK, "\tmajor ver: [%d]\n", header.major_ver); logMsg (DBG_PLBK, "\tminor ver: [%d]\n", header.minor_ver); logMsg (DBG_PLBK, "\tmax events: [%d]\n", header.max_events); logMsg (DBG_PLBK, "\tevents written: [%d]\n", header.written); logMsg (DBG_PLBK, "\tstart pos: [%d]\n", header.start_pos); logMsg (DBG_PLBK, "\tstart time: [%lf]\n", TP_IN_FP_SECS (header.start_t)); logMsg (DBG_PLBK, "\tend time: [%lf]\n", TP_IN_FP_SECS (header.end_t)); #endif return 1; }