int cmyth_rcv_commbreaklist(cmyth_conn_t conn, int *err, cmyth_commbreaklist_t breaklist, int count) { int consumed; int total = 0; long rows; int64_t mark; long long start = -1; char *failed = NULL; cmyth_commbreak_t commbreak; unsigned short type; unsigned short start_type; int i; if (count <= 0) { *err = EINVAL; return 0; } /* * Get number of rows */ consumed = cmyth_rcv_long(conn, err, &rows, count); count -= consumed; total += consumed; if (*err) { failed = "cmyth_rcv_long"; goto fail; } if (rows < 0) { cmyth_dbg(CMYTH_DBG_DEBUG, "%s: no commercial breaks found.\n", __FUNCTION__); return 0; } for (i = 0; i < rows; i++) { consumed = cmyth_rcv_ushort(conn, err, &type, count); count -= consumed; total += consumed; if (*err) { failed = "cmyth_rcv_ushort"; goto fail; } consumed = cmyth_rcv_int64(conn, err, &mark, count); count -= consumed; total += consumed; if (*err) { failed = "cmyth_rcv_long long"; goto fail; } if (type == CMYTH_COMMBREAK_START || type == CMYTH_CUTLIST_START) { start = mark; start_type = type; } else if (type == CMYTH_COMMBREAK_END || type == CMYTH_CUTLIST_END) { if (start >= 0 && ((type == CMYTH_COMMBREAK_END && start_type == CMYTH_COMMBREAK_START) || (type == CMYTH_CUTLIST_END && start_type == CMYTH_CUTLIST_START))) { commbreak = cmyth_commbreak_create(); commbreak->start_mark = start; commbreak->end_mark = mark; start = -1; breaklist->commbreak_list = realloc(breaklist->commbreak_list, (++breaklist->commbreak_count) * sizeof(cmyth_commbreak_t)); breaklist->commbreak_list[breaklist->commbreak_count - 1] = commbreak; } else { cmyth_dbg(CMYTH_DBG_WARN, "%s: ignoring 'end' marker without a 'start' marker at %lld\n", __FUNCTION__, type, mark); } } else { cmyth_dbg(CMYTH_DBG_WARN, "%s: type (%d) is not a COMMBREAK or CUTLIST\n", __FUNCTION__, type); } } /* * If the last entry is a start marker then it doesn't have an associated end marker. In this * case we choose to simply ignore it. Another option is to put in a really large fake end marker * but that may cause strange seek behaviour in a client application. */ return total; fail: cmyth_dbg(CMYTH_DBG_ERROR, "%s: %s() failed (%d)\n", __FUNCTION__, failed, *err); return total; }
int cmyth_rcv_commbreaklist(cmyth_conn_t conn, int *err, cmyth_commbreaklist_t breaklist, int count) { int consumed; int total = 0; long rows; char *failed = NULL; cmyth_commbreak_t commbreak; unsigned short type; int i; int j; if (count <= 0) { *err = EINVAL; return 0; } /* * Get number of rows */ consumed = cmyth_rcv_long(conn, err, &rows, count); count -= consumed; total += consumed; if (*err) { failed = "cmyth_rcv_long"; goto fail; } if (rows < 0) { cmyth_dbg(CMYTH_DBG_DEBUG, "%s: no commercial breaks found.\n", __FUNCTION__); return 0; } else { /* * Don't check for an uneven row count. mythcommflag can mark the start of the last * commercial break, but then not mark the end before it reaches the end of the file. * For this case the last commercial break is ignored. */ breaklist->commbreak_count = rows / 2; } breaklist->commbreak_list = malloc(breaklist->commbreak_count * sizeof(cmyth_commbreak_t)); if (!breaklist->commbreak_list) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: malloc() failed for list\n", __FUNCTION__); *err = ENOMEM; return consumed; } memset(breaklist->commbreak_list, 0, breaklist->commbreak_count * sizeof(cmyth_commbreak_t)); for (i = 0; i < breaklist->commbreak_count; i++) { commbreak = cmyth_commbreak_create(); for (j = 0; j < 2; j++) { consumed = cmyth_rcv_ushort(conn, err, &type, count); count -= consumed; total += consumed; if (*err) { failed = "cmyth_rcv_ushort"; goto fail; } /* * Do a little sanity-checking. */ if (j == 0 && type != CMYTH_COMMBREAK_START) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: type was not CMYTH_COMMBREAK_START\n", __FUNCTION__); return 0; } else if (j == 1 && type != CMYTH_COMMBREAK_END) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: type was not CMYTH_COMMBREAK_END\n", __FUNCTION__); return 0; } /* * Only marks are returned, not the offsets. Marks are encoded in long_long. */ if (j == 0) { consumed = cmyth_rcv_long_long(conn, err, &commbreak->start_mark, count); } else { consumed = cmyth_rcv_long_long(conn, err, &commbreak->end_mark, count); } count -= consumed; total += consumed; if (*err) { failed = "cmyth_rcv_long"; goto fail; } } breaklist->commbreak_list[i] = commbreak; } return total; fail: cmyth_dbg(CMYTH_DBG_ERROR, "%s: %s() failed (%d)\n", __FUNCTION__, failed, *err); return total; }
int cmyth_mysql_get_commbreak_list(cmyth_database_t db, int chanid, char * start_ts_dt, cmyth_commbreaklist_t breaklist, int conn_version) { MYSQL_RES *res = NULL; MYSQL_ROW row; int resolution = 30; char * query_str; int rows = 0; cmyth_mysql_query_t * query; cmyth_commbreak_t commbreak = NULL; int i = 0; long long start_previous = 0; long long end_previous = 0; if (conn_version>=43) { query_str = "SELECT m.type,m.mark,s.mark,s.offset FROM recordedmarkup m INNER JOIN recordedseek AS s ON m.chanid = s.chanid AND m.starttime = s.starttime WHERE m.chanid = ? AND m.starttime = ? AND m.type in (?,?) and FLOOR(m.mark/?)=FLOOR(s.mark/?) ORDER BY `m`.`mark` LIMIT 300 "; } else { query_str = "SELECT m.type AS type, m.mark AS mark, s.offset AS offset FROM recordedmarkup m INNER JOIN recordedseek AS s ON (m.chanid = s.chanid AND m.starttime = s.starttime AND (FLOOR(m.mark / 15) + 1) = s.mark) WHERE m.chanid = ? AND m.starttime = ? AND m.type IN (?, ?) ORDER BY mark;"; } query = cmyth_mysql_query_create(db,query_str); cmyth_dbg(CMYTH_DBG_ERROR,"%s, query=%s\n", __FUNCTION__,query_str); if ( (conn_version>=43) && ( cmyth_mysql_query_param_int(query, chanid) < 0 || cmyth_mysql_query_param_str(query, start_ts_dt) < 0 || cmyth_mysql_query_param_int(query, CMYTH_COMMBREAK_START) < 0 || cmyth_mysql_query_param_int(query, CMYTH_COMMBREAK_END) < 0 || cmyth_mysql_query_param_int(query, resolution ) < 0 || cmyth_mysql_query_param_int(query, resolution ) < 0 ) ) { cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); ref_release(query); return -1; } if ( (conn_version < 43) && (cmyth_mysql_query_param_int(query, chanid) < 0 || cmyth_mysql_query_param_str(query, start_ts_dt) < 0 || cmyth_mysql_query_param_int(query, CMYTH_COMMBREAK_START) < 0 || cmyth_mysql_query_param_int(query, CMYTH_COMMBREAK_END) < 0 ) ) { cmyth_dbg(CMYTH_DBG_ERROR,"%s, binding of query parameters failed! Maybe we're out of memory?\n", __FUNCTION__); ref_release(query); return -1; } res = cmyth_mysql_query_result(query); ref_release(query); if (res == NULL) { cmyth_dbg(CMYTH_DBG_ERROR, "%s, finalisation/execution of query failed!\n", __FUNCTION__); return -1; } if (conn_version >=43) { breaklist->commbreak_count = cmyth_mysql_query_commbreak_count(db,chanid,start_ts_dt); } else { breaklist->commbreak_count = mysql_num_rows(res) / 2; } breaklist->commbreak_list = malloc(breaklist->commbreak_count * sizeof(cmyth_commbreak_t)); //cmyth_dbg(CMYTH_DBG_ERROR, "%s: %ld\n",__FUNCTION__,breaklist->commbreak_count); if (!breaklist->commbreak_list) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: malloc() failed for list\n", __FUNCTION__); return -1; } memset(breaklist->commbreak_list, 0, breaklist->commbreak_count * sizeof(cmyth_commbreak_t)); if (conn_version >=43) { while ((row = mysql_fetch_row(res))) { if (safe_atoi(row[0]) == CMYTH_COMMBREAK_START) { if ( safe_atoll(row[1]) != start_previous ) { commbreak = cmyth_commbreak_create(); commbreak->start_mark = safe_atoll(row[1]); commbreak->start_offset = safe_atoll(row[3]); start_previous = commbreak->start_mark; } else if ( safe_atoll(row[1]) == safe_atoll(row[2]) ) { commbreak = cmyth_commbreak_create(); commbreak->start_mark = safe_atoll(row[1]); commbreak->start_offset = safe_atoll(row[3]); } } else if (safe_atoi(row[0]) == CMYTH_COMMBREAK_END) { if ( safe_atoll(row[1]) != end_previous ) { commbreak->end_mark = safe_atoll(row[1]); commbreak->end_offset = safe_atoll(row[3]); breaklist->commbreak_list[rows] = commbreak; end_previous = commbreak->end_mark; rows++; } else if ( safe_atoll(row[1]) == safe_atoll(row[2]) ) { commbreak->end_mark = safe_atoll(row[1]); commbreak->end_offset = safe_atoll(row[3]); breaklist->commbreak_list[rows] = commbreak; if (end_previous != safe_atoll(row[1]) ) { rows++; } } } else { cmyth_dbg(CMYTH_DBG_ERROR, "%s: Unknown COMMBREAK returned\n", __FUNCTION__); return -1; } i++; } } // mythtv protolcol version < 43 else { while ((row = mysql_fetch_row(res))) { if ((i % 2) == 0) { if (safe_atoi(row[0]) != CMYTH_COMMBREAK_START) { return -1; } commbreak = cmyth_commbreak_create(); commbreak->start_mark = safe_atoll(row[1]); commbreak->start_offset = safe_atoll(row[2]); i++; } else { if (safe_atoi(row[0]) != CMYTH_COMMBREAK_END) { return -1; } commbreak->end_mark = safe_atoll(row[1]); commbreak->end_offset = safe_atoll(row[2]); breaklist->commbreak_list[rows] = commbreak; i = 0; rows++; } } } mysql_free_result(res); cmyth_dbg(CMYTH_DBG_ERROR, "%s: COMMBREAK rows= %d\n", __FUNCTION__, rows); return rows; }