long long cmyth_get_bookmark(cmyth_conn_t conn, cmyth_proginfo_t prog) { char *buf; unsigned int len = CMYTH_TIMESTAMP_LEN + CMYTH_LONGLONG_LEN + 18; int err; long long ret; int count; int64_t ll; int r; char start_ts_dt[CMYTH_TIMESTAMP_LEN + 1]; cmyth_datetime_to_string(start_ts_dt, prog->proginfo_rec_start_ts); buf = alloca(len); if (!buf) { return -ENOMEM; } sprintf(buf,"%s %ld %s","QUERY_BOOKMARK",prog->proginfo_chanId, start_ts_dt); pthread_mutex_lock(&conn->conn_mutex); if ((err = cmyth_send_message(conn,buf)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err); ret = err; goto out; } count = cmyth_rcv_length(conn); if (count < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); ret = count; goto out; } if ((r=cmyth_rcv_int64(conn, &err, &ll, count)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_int64() failed (%d)\n", __FUNCTION__, r); ret = err; goto out; } ret = ll; out: pthread_mutex_unlock(&conn->conn_mutex); return ret; }
/* * cmyth_recorder_get_keyframe_pos() * * Scope: PUBLIC * * Description * * Obtain the position in a recording of the key frame number 'keynum' * on the recorder 'rec'. * * Return Value: * * Success: long long seek offset >= 0 * * Failure: long long -(ERRNO) */ int64_t cmyth_recorder_get_keyframe_pos(cmyth_recorder_t rec, uint32_t keynum) { int r, err, count; int64_t ret; char msg[256]; if (!rec || !rec->rec_conn) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n", __FUNCTION__); return (int64_t) -EINVAL; } pthread_mutex_lock(&rec->rec_conn->conn_mutex); if (rec->rec_conn->conn_version >= 66) { snprintf(msg, sizeof(msg), "QUERY_RECORDER %"PRIu32"[]:[]GET_KEYFRAME_POS[]:[]%"PRIu32, rec->rec_id, keynum); if ((r = cmyth_send_message(rec->rec_conn, msg)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, r); ret = r; goto fail; } count = cmyth_rcv_length(rec->rec_conn); if ((r = cmyth_rcv_int64(rec->rec_conn, &err, &ret, count)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_int64() failed (%d)\n", __FUNCTION__, r); ret = err; goto fail; } } else { ret = (int64_t) -EPERM; } fail: pthread_mutex_unlock(&rec->rec_conn->conn_mutex); return ret; }
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; }
/* * cmyth_file_seek() * * Scope: PUBLIC * * Description * * Seek to a new position in the file based on the value of whence: * WHENCE_SET * The offset is set to offset bytes. * WHENCE_CUR * The offset is set to the current position plus offset bytes. * WHENCE_END * The offset is set to the size of the file minus offset bytes. * * Return Value: * * Sucess: 0 * * Failure: an int containing -errno */ int64_t cmyth_file_seek(cmyth_file_t file, int64_t offset, int8_t whence) { char msg[128]; int err; int count; int64_t c; int r; int64_t ret; if (file == NULL) return -EINVAL; if ((offset == 0) && (whence == WHENCE_CUR)) return file->file_pos; if ((offset == file->file_pos) && (whence == WHENCE_SET)) return file->file_pos; pthread_mutex_lock(&mutex); ret = 0; while(file->file_pos < file->file_req) { c = file->file_req - file->file_pos; if(c > sizeof(msg)) c = sizeof(msg); if ((ret = cmyth_file_get_block(file, msg, (size_t)c)) < 0) break; } if (ret < 0) goto out; if (file->file_control->conn_version >= 66) { /* * Since protocol 66 mythbackend expects to receive a single 64 bit integer rather than * two 32 bit hi and lo integers. */ snprintf(msg, sizeof(msg), "QUERY_FILETRANSFER %"PRIu32"[]:[]SEEK[]:[]%"PRId64"[]:[]%"PRId8"[]:[]%"PRId64, file->file_id, offset, whence, file->file_pos); } else { snprintf(msg, sizeof(msg), "QUERY_FILETRANSFER %"PRIu32"[]:[]SEEK[]:[]%"PRId32"[]:[]%"PRId32"[]:[]%"PRId8"[]:[]%"PRId32"[]:[]%"PRId32, file->file_id, (int32_t)(offset >> 32), (int32_t)(offset & 0xffffffff), whence, (int32_t)(file->file_pos >> 32), (int32_t)(file->file_pos & 0xffffffff)); } if ((err = cmyth_send_message(file->file_control, msg)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err); ret = err; goto out; } if ((count=cmyth_rcv_length(file->file_control)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); ret = count; goto out; } if ((r=cmyth_rcv_int64(file->file_control, &err, &c, count)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_int64() failed (%d)\n", __FUNCTION__, r); ret = err; goto out; } file->file_pos = c; file->file_req = file->file_pos; if(file->file_pos > file->file_length) file->file_length = file->file_pos; ret = file->file_pos; out: pthread_mutex_unlock(&mutex); return ret; }
int cmyth_conn_get_freespace(cmyth_conn_t control, long long *total, long long *used) { int err, count, ret = 0; int r; char msg[256]; char reply[256]; int64_t lreply; if (control == NULL) return -EINVAL; if ((total == NULL) || (used == NULL)) return -EINVAL; pthread_mutex_lock(&mutex); if (control->conn_version >= 32) { snprintf(msg, sizeof(msg), "QUERY_FREE_SPACE_SUMMARY"); } else if (control->conn_version >= 17) { snprintf(msg, sizeof(msg), "QUERY_FREE_SPACE"); } else { snprintf(msg, sizeof(msg), "QUERY_FREESPACE"); } if ((err = cmyth_send_message(control, msg)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err); ret = err; goto out; } if ((count=cmyth_rcv_length(control)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); ret = count; goto out; } if (control->conn_version >= 17) { if ((r=cmyth_rcv_int64(control, &err, &lreply, count)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_int64() failed (%d)\n", __FUNCTION__, err); ret = err; goto out; } *total = lreply; if ((r=cmyth_rcv_int64(control, &err, &lreply, count - r)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_int64() failed (%d)\n", __FUNCTION__, err); ret = err; goto out; } *used = lreply; } else { if ((r=cmyth_rcv_string(control, &err, reply, sizeof(reply)-1, count)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, err); ret = err; goto out; } *total = atoi(reply); if ((r=cmyth_rcv_string(control, &err, reply, sizeof(reply)-1, count-r)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed (%d)\n", __FUNCTION__, err); ret = err; goto out; } *used = atoi(reply); *used *= 1024; *total *= 1024; } out: pthread_mutex_unlock(&mutex); return ret; }
/* * cmyth_file_seek(cmyth_file_t file, long long offset, int whence) * * Scope: PUBLIC * * Description * * Seek to a new position in the file based on the value of whence: * SEEK_SET * The offset is set to offset bytes. * SEEK_CUR * The offset is set to the current position plus offset bytes. * SEEK_END * The offset is set to the size of the file minus offset bytes. * * Return Value: * * Sucess: 0 * * Failure: an int containing -errno */ long long cmyth_file_seek(cmyth_file_t file, long long offset, int whence) { char msg[128]; int err; int count; int64_t c; long r; long long ret; if (file == NULL) return -EINVAL; if ((offset == 0) && (whence == SEEK_CUR)) return file->file_pos; if ((offset == file->file_pos) && (whence == SEEK_SET)) return file->file_pos; while(file->file_pos < file->file_req) { c = file->file_req - file->file_pos; if(c > sizeof(msg)) c = sizeof(msg); if (cmyth_file_get_block(file, msg, (unsigned long)c) < 0) return -1; } pthread_mutex_lock(&mutex); if (file->file_control->conn_version >= 66) { /* * Since protocol 66 mythbackend expects to receive a single 64 bit integer rather than * two 32 bit hi and lo integers. */ snprintf(msg, sizeof(msg), "QUERY_FILETRANSFER %ld[]:[]SEEK[]:[]%"PRIu64"[]:[]%d[]:[]%"PRIu64, file->file_id, (int64_t)offset, whence, (int64_t)file->file_pos); } else { snprintf(msg, sizeof(msg), "QUERY_FILETRANSFER %ld[]:[]SEEK[]:[]%d[]:[]%d[]:[]%d[]:[]%d[]:[]%d", file->file_id, (int32_t)(offset >> 32), (int32_t)(offset & 0xffffffff), whence, (int32_t)(file->file_pos >> 32), (int32_t)(file->file_pos & 0xffffffff)); } if ((err = cmyth_send_message(file->file_control, msg)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err); ret = err; goto out; } if ((count=cmyth_rcv_length(file->file_control)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_length() failed (%d)\n", __FUNCTION__, count); ret = count; goto out; } if ((r=cmyth_rcv_int64(file->file_control, &err, &c, count)) < 0) { cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_int64() failed (%d)\n", __FUNCTION__, r); ret = err; goto out; } switch (whence) { case SEEK_SET: file->file_pos = offset; break; case SEEK_CUR: file->file_pos += offset; break; case SEEK_END: file->file_pos = file->file_length - offset; break; } file->file_req = file->file_pos; if(file->file_pos > file->file_length) file->file_length = file->file_pos; ret = file->file_pos; out: pthread_mutex_unlock(&mutex); return ret; }