/* * cmyth_recorder_get_program_info() * * Scope: PRIVATE (static) * * Description: * * Request program information from the recorder 'rec' for the current * program in the program guide (i.e. current channel and time slot). * * The program information will be used to fill out 'proginfo'. * * This does not affect the current recording. * * Return Value: * * Success: 1 - valid channel, 0 - invalid channel * * Failure: -(ERRNO) */ static cmyth_proginfo_t cmyth_recorder_get_program_info(cmyth_recorder_t rec) { int err, count, ct; char msg[256]; cmyth_proginfo_t proginfo = NULL; if (!rec) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n", __FUNCTION__); return NULL; } proginfo = cmyth_proginfo_create(); if (proginfo == NULL) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: proginfo_create failed\n", __FUNCTION__); goto out; } pthread_mutex_lock(&mutex); if(rec->rec_conn->conn_version >= 26) snprintf(msg, sizeof(msg), "QUERY_RECORDER %"PRIu32"[]:[]GET_CURRENT_RECORDING", rec->rec_id); else snprintf(msg, sizeof(msg), "QUERY_RECORDER %"PRIu32"[]:[]GET_PROGRAM_INFO", rec->rec_id); if ((err=cmyth_send_message(rec->rec_conn, msg)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err); ref_release(proginfo); proginfo = NULL; goto out; } count = cmyth_rcv_length(rec->rec_conn); if(rec->rec_conn->conn_version >= 26) ct = cmyth_rcv_proginfo(rec->rec_conn, &err, proginfo, count); else ct = cmyth_rcv_chaninfo(rec->rec_conn, &err, proginfo, count); if (ct != count) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_proginfo() < count\n", __FUNCTION__); ref_release(proginfo); proginfo = NULL; goto out; } out: pthread_mutex_unlock(&mutex); return proginfo; }
cmyth_event_t cmyth_event_get(cmyth_conn_t conn, char * data, int len) { int count, err, consumed, i; char tmp[1024]; cmyth_event_t event; cmyth_proginfo_t proginfo = NULL; if (conn == NULL) goto fail; if ((count=cmyth_rcv_length(conn)) <= 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); return CMYTH_EVENT_CLOSE; } consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; if (strcmp(tmp, "BACKEND_MESSAGE") != 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, count); goto fail; } consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; if (strcmp(tmp, "RECORDING_LIST_CHANGE") == 0) { event = CMYTH_EVENT_RECORDING_LIST_CHANGE; } else if (strncmp(tmp, "RECORDING_LIST_CHANGE ADD", 25) == 0) { event = CMYTH_EVENT_RECORDING_LIST_CHANGE_ADD; strncpy(data, tmp + 26, len); } else if (strcmp(tmp, "RECORDING_LIST_CHANGE UPDATE") == 0) { event = CMYTH_EVENT_RECORDING_LIST_CHANGE_UPDATE; /* receive a proginfo structure - do nothing with it (yet?)*/ proginfo = cmyth_proginfo_create(); if (!proginfo) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_proginfo_create() failed\n", __FUNCTION__); goto fail; } consumed = cmyth_rcv_proginfo(conn, &err, proginfo, count); ref_release(proginfo); proginfo = NULL; count -= consumed; } else if (strncmp(tmp, "RECORDING_LIST_CHANGE DELETE", 28) == 0) { event = CMYTH_EVENT_RECORDING_LIST_CHANGE_DELETE; strncpy(data, tmp + 29, len); } else if (strcmp(tmp, "SCHEDULE_CHANGE") == 0) { event = CMYTH_EVENT_SCHEDULE_CHANGE; } else if (strncmp(tmp, "DONE_RECORDING", 14) == 0) { event = CMYTH_EVENT_DONE_RECORDING; } else if (strncmp(tmp, "QUIT_LIVETV", 11) == 0) { event = CMYTH_EVENT_QUIT_LIVETV; } else if (strncmp(tmp, "LIVETV_WATCH", 12) == 0) { event = CMYTH_EVENT_WATCH_LIVETV; strncpy(data, tmp + 13, len); /* Sergio: Added to support the new live tv protocol */ } else if (strncmp(tmp, "LIVETV_CHAIN UPDATE", 19) == 0) { event = CMYTH_EVENT_LIVETV_CHAIN_UPDATE; strncpy(data, tmp + 20, len); } else if (strncmp(tmp, "SIGNAL", 6) == 0) { event = CMYTH_EVENT_SIGNAL; /* get slock, signal, seen_pat, matching_pat */ while (count > 0) { /* get signalmonitorvalue name */ consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; /* get signalmonitorvalue status */ consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; } } else if (strncmp(tmp, "ASK_RECORDING", 13) == 0) { event = CMYTH_EVENT_ASK_RECORDING; if (cmyth_conn_get_protocol_version(conn) < 37) { /* receive 4 string - do nothing with them */ for (i = 0; i < 4; i++) { consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) -1, count); count -= consumed; } } else { /* receive a proginfo structure - do nothing with it (yet?)*/ proginfo = cmyth_proginfo_create(); if (!proginfo) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_proginfo_create() failed\n", __FUNCTION__); goto fail; } consumed = cmyth_rcv_proginfo(conn, &err, proginfo, count); ref_release(proginfo); proginfo = NULL; count -= consumed; } } else if (strncmp(tmp, "CLEAR_SETTINGS_CACHE", 20) == 0) { event = CMYTH_EVENT_CLEAR_SETTINGS_CACHE; } else if (strncmp(tmp, "GENERATED_PIXMAP", 16) == 0) { /* capture the file which a pixmap has been generated for */ event = CMYTH_EVENT_GENERATED_PIXMAP; consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; if (strncmp(tmp, "OK", 2) == 0) { consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; strncpy(data, tmp, len); } else { data[0] = 0; } } else if (strncmp(tmp, "SYSTEM_EVENT", 12) == 0) { event = CMYTH_EVENT_SYSTEM_EVENT; strncpy(data, tmp + 13, len); } else if (strncmp(tmp, "UPDATE_FILE_SIZE", 16) == 0) { event = CMYTH_EVENT_UPDATE_FILE_SIZE; strncpy(data, tmp + 17, len); } else if (strncmp(tmp, "COMMFLAG_START", 14) == 0) { event = CMYTH_EVENT_COMMFLAG_START; strncpy(data, tmp + 15, len); } else { cmyth_dbg(CMYTH_DBG_ERROR, "%s: unknown mythtv BACKEND_MESSAGE '%s'\n", __FUNCTION__, tmp); event = CMYTH_EVENT_UNKNOWN; strncpy(data, tmp, len); } while(count > 0) { consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; cmyth_dbg(CMYTH_DBG_DEBUG, "%s: leftover data %s\n", __FUNCTION__, tmp); } return event; fail: return CMYTH_EVENT_ERROR; }
cmyth_event_t cmyth_event_get(cmyth_conn_t conn, char * data, int len) { int count, err, consumed, i; char tmp[1024]; cmyth_event_t event; cmyth_proginfo_t proginfo = NULL; if (conn == NULL) goto fail; if ((count=cmyth_rcv_length(conn)) <= 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); return CMYTH_EVENT_CLOSE; } consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; if (strcmp(tmp, "BACKEND_MESSAGE") != 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, count); goto fail; } consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; if (strcmp(tmp, "RECORDING_LIST_CHANGE") == 0) { event = CMYTH_EVENT_RECORDING_LIST_CHANGE; } else if (strcmp(tmp, "SCHEDULE_CHANGE") == 0) { event = CMYTH_EVENT_SCHEDULE_CHANGE; } else if (strncmp(tmp, "DONE_RECORDING", 14) == 0) { event = CMYTH_EVENT_DONE_RECORDING; } else if (strncmp(tmp, "QUIT_LIVETV", 11) == 0) { event = CMYTH_EVENT_QUIT_LIVETV; /* Sergio: Added to support the new live tv protocol */ } else if (strncmp(tmp, "LIVETV_CHAIN UPDATE", 19) == 0) { event = CMYTH_EVENT_LIVETV_CHAIN_UPDATE; strncpy(data,tmp,len); } else if (strncmp(tmp, "SIGNAL", 6) == 0) { event = CMYTH_EVENT_SIGNAL; /* get slock, signal, seen_pat, matching_pat */ while (count > 0) { /* get signalmonitorvalue name */ consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; /* get signalmonitorvalue status */ consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; } } else if (strncmp(tmp, "ASK_RECORDING", 13) == 0) { event = CMYTH_EVENT_ASK_RECORDING; if (cmyth_conn_get_protocol_version(conn) < 37) { /* receive 4 string - do nothing with them */ for (i=0; i<4; i++) { consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) -1, count); count -= consumed; } } else { /* receive a proginfo structure - do nothing with it (yet?)*/ proginfo = cmyth_proginfo_create(); if (!proginfo) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_proginfo_create() failed\n", __FUNCTION__); goto fail; } consumed = cmyth_rcv_proginfo(conn, &err, proginfo, count); ref_release(proginfo); proginfo=NULL; count -= consumed; } } else { cmyth_dbg(CMYTH_DBG_DETAIL, "%s: unknown mythtv BACKEND_MESSAGE '%s'\n", __FUNCTION__, tmp); event = CMYTH_EVENT_UNKNOWN; } while(count > 0) { consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; cmyth_dbg(CMYTH_DBG_DEBUG, "%s: leftover data %s\n", __FUNCTION__, tmp); } return event; fail: return CMYTH_EVENT_UNKNOWN; }
cmyth_event_t cmyth_event_get_message(cmyth_conn_t conn, char * data, int32_t len, cmyth_proginfo_t * prog) { int count, err, consumed; char tmp[1024]; cmyth_event_t event; cmyth_proginfo_t proginfo = NULL; if (conn == NULL) return CMYTH_EVENT_UNKNOWN; if ((count = cmyth_rcv_length(conn)) <= 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); return CMYTH_EVENT_CLOSE; } data[0] = 0; consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; if (strcmp(tmp, "BACKEND_MESSAGE") != 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, count); event = CMYTH_EVENT_UNKNOWN; goto out; } consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; /* * RECORDING_LIST_CHANGE */ if (strcmp(tmp, "RECORDING_LIST_CHANGE") == 0) { event = CMYTH_EVENT_RECORDING_LIST_CHANGE; } /* * RECORDING_LIST_CHANGE ADD */ else if (strncmp(tmp, "RECORDING_LIST_CHANGE ADD", 25) == 0) { event = CMYTH_EVENT_RECORDING_LIST_CHANGE_ADD; strncpy(data, tmp + 26, len); } /* * RECORDING_LIST_CHANGE UPDATE */ else if (strcmp(tmp, "RECORDING_LIST_CHANGE UPDATE") == 0) { event = CMYTH_EVENT_RECORDING_LIST_CHANGE_UPDATE; proginfo = cmyth_proginfo_create(); if (!proginfo) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_proginfo_create() failed\n", __FUNCTION__); event = CMYTH_EVENT_UNKNOWN; goto out; } consumed = cmyth_rcv_proginfo(conn, &err, proginfo, count); count -= consumed; *prog = proginfo; } /* * RECORDING_LIST_CHANGE DELETE */ else if (strncmp(tmp, "RECORDING_LIST_CHANGE DELETE", 28) == 0) { event = CMYTH_EVENT_RECORDING_LIST_CHANGE_DELETE; strncpy(data, tmp + 29, len); } /* * SCHEDULE_CHANGE */ else if (strcmp(tmp, "SCHEDULE_CHANGE") == 0) { event = CMYTH_EVENT_SCHEDULE_CHANGE; } /* * DONE_RECORDING */ else if (strncmp(tmp, "DONE_RECORDING", 14) == 0) { event = CMYTH_EVENT_DONE_RECORDING; strncpy(data, tmp + 15, len); } /* * QUIT_LIVETV */ else if (strncmp(tmp, "QUIT_LIVETV", 11) == 0) { event = CMYTH_EVENT_QUIT_LIVETV; } /* * LIVETV_WATCH */ else if (strncmp(tmp, "LIVETV_WATCH", 12) == 0) { event = CMYTH_EVENT_LIVETV_WATCH; strncpy(data, tmp + 13, len); } /* * LIVETV_CHAIN UPDATE */ else if (strncmp(tmp, "LIVETV_CHAIN UPDATE", 19) == 0) { event = CMYTH_EVENT_LIVETV_CHAIN_UPDATE; strncpy(data, tmp + 20, len); } /* * SIGNAL */ else if (strncmp(tmp, "SIGNAL", 6) == 0) { int32_t dstlen = len; event = CMYTH_EVENT_SIGNAL; /*Get Recorder ID */ strncat(data, "cardid ", 7); strncat(data, tmp + 7, consumed - 12); strncat(data, ";", 2); /* get slock, signal, seen_pat, matching_pat */ while (count > 0) { /* get signalmonitorvalue name */ consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; /*strncat(data,tmp,dstlen-2); strncat(data,"=",2); dstlen -= consumed;*/ /* get signalmonitorvalue status */ consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; strncat(data,tmp,dstlen-2); strncat(data,";",2); dstlen -= consumed; } } /* * ASK_RECORDING */ else if (strncmp(tmp, "ASK_RECORDING", 13) == 0) { event = CMYTH_EVENT_ASK_RECORDING; strncpy(data, tmp + 14, len); if (cmyth_conn_get_protocol_version(conn) >= 37) { proginfo = cmyth_proginfo_create(); if (!proginfo) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_proginfo_create() failed\n", __FUNCTION__); event = CMYTH_EVENT_UNKNOWN; goto out; } consumed = cmyth_rcv_proginfo(conn, &err, proginfo, count); count -= consumed; *prog = proginfo; } } /* * CLEAR_SETTINGS_CACHE */ else if (strncmp(tmp, "CLEAR_SETTINGS_CACHE", 20) == 0) { event = CMYTH_EVENT_CLEAR_SETTINGS_CACHE; } /* * GENERATED_PIXMAP */ else if (strncmp(tmp, "GENERATED_PIXMAP", 16) == 0) { /* capture the file which a pixmap has been generated for */ event = CMYTH_EVENT_GENERATED_PIXMAP; consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; if (strncmp(tmp, "OK", 2) == 0) { /* receive <chanid_timestamp (isoformat)> */ consumed = cmyth_rcv_string(conn, &err, tmp, sizeof(tmp) - 1, count); count -= consumed; strncpy(data, tmp, len); } } /* * SYSTEM_EVENT */ else if (strncmp(tmp, "SYSTEM_EVENT", 12) == 0) { event = CMYTH_EVENT_SYSTEM_EVENT; strncpy(data, tmp + 13, len); } /* * UPDATE_FILE_SIZE */ else if (strncmp(tmp, "UPDATE_FILE_SIZE", 16) == 0) { event = CMYTH_EVENT_UPDATE_FILE_SIZE; strncpy(data, tmp + 17, len); } /* * Unknown message */ else { cmyth_dbg(CMYTH_DBG_INFO, "%s: unknown BACKEND_MESSAGE '%s'\n", __FUNCTION__, tmp); event = CMYTH_EVENT_UNKNOWN; } out: while(count > 0 && err == 0) { consumed = cmyth_rcv_data(conn, &err, tmp, sizeof(tmp) - 1, count); cmyth_dbg(CMYTH_DBG_DEBUG, "%s: leftover data: count %i, read %i, errno %i\n", __FUNCTION__, count, consumed, err); count -= consumed; } return event; }
/* * cmyth_proginfo_fill(cmyth_conn_t control, cmyth_proginfo_t prog) * * Scope: PRIVATE (static) * * Description * * Fill out a (possibly incomplete) program info. Incomplete program * info comes from program listings. Since this modifies the contents of * the supplied program info, it must never be called with a program info * that has more than one reference). * * Return Value: * * Success: 0 * * Failure: a negative error code. */ static int cmyth_proginfo_fill(cmyth_conn_t control, cmyth_proginfo_t prog) { int err = 0; int count; int ret; long long length = 0; if (!control) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", __FUNCTION__); return -EINVAL; } if (!prog) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: no program info\n", __FUNCTION__); return -EINVAL; } pthread_mutex_lock(&control->conn_mutex); length = prog->proginfo_Length; if ((ret=fill_command(control, prog, "FILL_PROGRAM_INFO") != 0)) goto out; count = cmyth_rcv_length(control); if (count < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); ret = count; goto out; } if (cmyth_rcv_proginfo(control, &err, prog, count) != count) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_proginfo() < count\n", __FUNCTION__); ret = err; goto out; } /* * Myth seems to cache the program length, rather than call stat() * every time it needs to know. Using FILL_PROGRAM_INFO has worked * to force mythbackend to call stat() and return the correct length. * * However, some users are reporting that FILL_PROGRAM_INFO is * returning 0 for the program length. In that case, the original * number is still probably wrong, but it's better than 0. */ if (prog->proginfo_Length == 0) { prog->proginfo_Length = length; ret = -1; goto out; } ret = 0; out: pthread_mutex_unlock(&control->conn_mutex); return ret; }
cmyth_proginfo_t cmyth_proginfo_get_from_timeslot(cmyth_conn_t control, uint32_t chanid, const cmyth_timestamp_t recstartts) { int err = 0; int count, i; char msg[4096]; cmyth_proginfo_t prog = NULL; cmyth_proglist_t list = NULL; char time[15]; if (!control) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", __FUNCTION__); return NULL; } if ((err = cmyth_timestamp_to_numstring(time, recstartts)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_timestamp_to_numstring() failed (%d)\n", __FUNCTION__, err); return NULL; } if(control->conn_version >= 32) { pthread_mutex_lock(&control->conn_mutex); snprintf(msg, sizeof(msg), "QUERY_RECORDING TIMESLOT %"PRIu32" %s", chanid, time); if ((err=cmyth_send_message(control, msg)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err); goto out; } count = cmyth_rcv_length(control); if (count < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); goto out; } i = cmyth_rcv_string(control, &err, msg, sizeof(msg), count); if (err) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed\n", __FUNCTION__); goto out; } count -= i; if (strcmp(msg, "OK") != 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: didn't recieve OK as response\n", __FUNCTION__); goto out; } prog = cmyth_proginfo_create(); if (cmyth_rcv_proginfo(control, &err, prog, count) != count) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_proginfo() < count\n", __FUNCTION__); goto out; } pthread_mutex_unlock(&control->conn_mutex); return prog; out: pthread_mutex_unlock(&control->conn_mutex); if(prog) ref_release(prog); return NULL; } else { list = cmyth_proglist_get_all_recorded(control); if (!list) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: no program list\n", __FUNCTION__); } count = cmyth_proglist_get_count(list); for (i = 0;i < count; i++) { prog = cmyth_proglist_get_item(list, i); if (!prog) { cmyth_dbg(CMYTH_DBG_DEBUG, "%s: no program info\n", __FUNCTION__); continue; } if (cmyth_timestamp_compare(prog->proginfo_rec_start_ts, recstartts) != 0 || prog->proginfo_chanId != chanid) { ref_release(prog); prog = NULL; continue; } break; } ref_release(list); return prog; } }
cmyth_proginfo_t cmyth_proginfo_get_from_basename(cmyth_conn_t control, const char* basename) { int err = 0; int count, i; char msg[4096]; char *base; cmyth_proginfo_t prog = NULL; cmyth_proglist_t list = NULL; if (!control) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", __FUNCTION__); return NULL; } /* * mythbackend doesn't support spaces in basenames * when doing QUERY_RECORDING. If there are spaces, fallback * to enumerating all recordings */ if(control->conn_version >= 32 && strchr(basename, ' ') == NULL) { pthread_mutex_lock(&control->conn_mutex); snprintf(msg, sizeof(msg), "QUERY_RECORDING BASENAME %s", basename); if ((err=cmyth_send_message(control, msg)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err); goto out; } count = cmyth_rcv_length(control); if (count < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); goto out; } i = cmyth_rcv_string(control, &err, msg, sizeof(msg), count); if (err) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed\n", __FUNCTION__); goto out; } count -= i; if (strcmp(msg, "OK") != 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: didn't recieve OK as response\n", __FUNCTION__); goto out; } prog = cmyth_proginfo_create(); if (cmyth_rcv_proginfo(control, &err, prog, count) != count) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_proginfo() < count\n", __FUNCTION__); goto out; } pthread_mutex_unlock(&control->conn_mutex); return prog; out: pthread_mutex_unlock(&control->conn_mutex); if(prog) ref_release(prog); return NULL; } else { list = cmyth_proglist_get_all_recorded(control); if (!list) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: no program list\n", __FUNCTION__); } count = cmyth_proglist_get_count(list); for (i = 0;i < count; i++) { prog = cmyth_proglist_get_item(list, i); if (!prog) { cmyth_dbg(CMYTH_DBG_DEBUG, "%s: no program info\n", __FUNCTION__); continue; } base = strrchr(prog->proginfo_pathname, '/'); if (!base || strcmp(base+1, basename) !=0) { ref_release(prog); prog = NULL; continue; } break; } ref_release(list); return prog; } }
/* * cmyth_proginfo_fill() * * Scope: PRIVATE (static) * * Description * * Fill out a (possibly incomplete) program info. Incomplete program * info comes from program listings. Since this modifies the contents of * the supplied program info, it must never be called with a program info * that has more than one reference). * * Return Value: * * Success: 0 * * Failure: a negative error code. */ static int cmyth_proginfo_fill(cmyth_conn_t control, cmyth_proginfo_t prog) { int err = 0; int count = 0; int ret = 0; char *buf; char *proginfo; int64_t length = 0; if (!control) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", __FUNCTION__); return -EINVAL; } if (!prog) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: no program info\n", __FUNCTION__); return -EINVAL; } proginfo = cmyth_proginfo_string(control, prog); if (proginfo == NULL) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: program_info failed.\n", __FUNCTION__); return -EINVAL; } buf = malloc(strlen(proginfo) + 34 + 1); if (!buf) { free(proginfo); return -ENOMEM; } sprintf(buf, "FILL_PROGRAM_INFO cmyth[]:[]0[]:[]%s", proginfo); free(proginfo); pthread_mutex_lock(&control->conn_mutex); length = prog->proginfo_Length; if ((err = cmyth_send_message(control, buf)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err); ret = err; goto out; } count = cmyth_rcv_length(control); if (count < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); ret = count; goto out; } if (cmyth_rcv_proginfo(control, &err, prog, count) != count) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_proginfo() < count\n", __FUNCTION__); ret = err; goto out; } /* * Myth seems to cache the program length, rather than call stat() * every time it needs to know. Using FILL_PROGRAM_INFO has worked * to force mythbackend to call stat() and return the correct length. * * However, some users are reporting that FILL_PROGRAM_INFO is * returning 0 for the program length. In that case, the original * number is still probably wrong, but it's better than 0. */ if (prog->proginfo_Length == 0) { prog->proginfo_Length = length; } out: pthread_mutex_unlock(&control->conn_mutex); free(buf); return ret; }