Exemple #1
0
/*
 * cmyth_recorder_cancel_next_recording()
 *
 * Scope: PUBLIC
 *
 * Description
 *
 * Request that the recorder 'rec' cancels its next scheduled recording.
 * This is used as response to ASK_RECORDING when the user does not want
 * to allow the recorder to be taken for a pending recording.
 *
 * Return Value:
 *
 * Success: 0
 *
 * Failure: -(ERRNO)
 */
int
cmyth_recorder_cancel_next_recording(cmyth_recorder_t rec, int cancel)
{
	int err;
	int ret = -1;
	char msg[256];

	if (!rec) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n", __FUNCTION__);
		return -ENOSYS;
	}

	pthread_mutex_lock(&mutex);

	snprintf(msg, sizeof(msg), "QUERY_RECORDER %"PRIu32"[]:[]CANCEL_NEXT_RECORDING[]:[]%"PRIu32 ,rec->rec_id, cancel == 1);

	if ((err = cmyth_send_message(rec->rec_conn, msg)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_send_message() failed (%d)\n", __FUNCTION__, err);
		goto fail;
	}

	if ((err = cmyth_rcv_okay(rec->rec_conn)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_okay() failed (%d)\n", __FUNCTION__, err);
		goto fail;
	}

	ret = 0;

fail:
	pthread_mutex_unlock(&mutex);

	return ret;
}
static int cmyth_conn_set_setting_unlocked(cmyth_conn_t conn,
               const char* hostname, const char* setting, const char* value)
{
	char msg[1024];
	int err = 0;

	if(conn->conn_version < 17) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: protocol version doesn't support SET_SETTING\n",
			  __FUNCTION__);
		return -1;
	}

	if (!conn) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n",
			  __FUNCTION__);
		return -2;
	}

	snprintf(msg, sizeof(msg), "SET_SETTING %s %s %s", hostname, setting, value);
	if ((err = cmyth_send_message(conn, msg)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message() failed (%d)\n",
			  __FUNCTION__, err);
		return -3;
	}

	if (cmyth_rcv_okay(conn) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_okay() failed\n",
			  __FUNCTION__);
		return -4;
	}

	return 1;
}
Exemple #3
0
/*
 * cmyth_recorder_change_channel()
 *
 * Scope: PUBLIC
 *
 * Description
 *
 * Request that the recorder 'rec' change channels in one of the
 * followin
 *
 * CHANNEL_DIRECTION_UP       - Go up one channel in the listing
 *
 * CHANNEL_DIRECTION_DOWN     - Go down one channel in the listing
 *
 * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel
 *
 * CHANNEL_DIRECTION_SAME     - Stay on the same (current) channel
 *
 * Note that the recorder must not be actively recording when this
 * request is made or bad things may happen to the server (i.e. it may
 * segfault).
 *
 * Return Value:
 *
 * Success: 0
 *
 * Failure: -(ERRNO)
 */
int
cmyth_recorder_change_channel(cmyth_recorder_t rec,
			      cmyth_channeldir_t direction)
{
	int err;
	int ret = -1;
	char msg[256];
	cmyth_livetv_chain_t newchain = NULL;
	cmyth_livetv_chain_t oldchain = NULL;

	if (!rec) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n",
			  __FUNCTION__);
		return -EINVAL;
	}

	pthread_mutex_lock(&rec->rec_conn->conn_mutex);

	snprintf(msg, sizeof(msg),
		 "QUERY_RECORDER %"PRIu32"[]:[]CHANGE_CHANNEL[]:[]%d",
		 rec->rec_id, direction);

	if ((err = cmyth_send_message(rec->rec_conn, msg)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message() failed (%d)\n",
			  __FUNCTION__, err);
		goto out;
	}

	if ((err = cmyth_rcv_okay(rec->rec_conn)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_okay() failed (%d)\n",
			  __FUNCTION__, err);
		goto out;
	}

	if (rec->rec_ring)
		rec->rec_ring->file_pos = 0;
	else {
		oldchain = rec->rec_livetv_chain;
		newchain = cmyth_livetv_chain_create(oldchain->chainid);
		newchain->livetv_buflen = oldchain->livetv_buflen;
		newchain->livetv_tcp_rcvbuf = oldchain->livetv_tcp_rcvbuf;
		newchain->prog_update_callback = oldchain->prog_update_callback;
		newchain->chain_switch_on_create = 1;
		rec->rec_livetv_chain = newchain;
	}

	ret = 0;

out:
	pthread_mutex_unlock(&rec->rec_conn->conn_mutex);
	if (oldchain)
		ref_release(oldchain);
	return ret;
}
Exemple #4
0
/*
 * cmyth_recorder_change_channel()
 *
 * Scope: PUBLIC
 *
 * Description
 *
 * Request that the recorder 'rec' change channels in one of the
 * followin
 *
 * CHANNEL_DIRECTION_UP       - Go up one channel in the listing
 *
 * CHANNEL_DIRECTION_DOWN     - Go down one channel in the listing
 *
 * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel
 *
 * CHANNEL_DIRECTION_SAME     - Stay on the same (current) channel
 *
 * Note that the recorder must not be actively recording when this
 * request is made or bad things may happen to the server (i.e. it may
 * segfault).
 *
 * Return Value:
 *
 * Success: 0
 *
 * Failure: -(ERRNO)
 */
int
cmyth_recorder_change_channel(cmyth_recorder_t rec,
			      cmyth_channeldir_t direction)
{
	int err;
	int ret = -1;
	char msg[256];
	cmyth_livetv_chain_t newchain = 0;

	if (!rec) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n",
			  __FUNCTION__);
		return -ENOSYS;
	}

	pthread_mutex_lock(&mutex);

	snprintf(msg, sizeof(msg),
		 "QUERY_RECORDER %"PRIu32"[]:[]CHANGE_CHANNEL[]:[]%d",
		 rec->rec_id, direction);

	if ((err=cmyth_send_message(rec->rec_conn, msg)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	if ((err=cmyth_rcv_okay(rec->rec_conn)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_okay() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	if(rec->rec_ring)
		rec->rec_ring->file_pos = 0;
	else {
		newchain = cmyth_livetv_chain_create(rec->rec_livetv_chain->chainid);
		newchain->progs = rec->rec_livetv_chain->progs;
		ref_release(rec->rec_livetv_file);
		rec->rec_livetv_file = NULL;
		ref_release(rec->rec_livetv_chain);
		rec->rec_livetv_chain = newchain;
	}

	ret = 0;

    fail:
	pthread_mutex_unlock(&mutex);

	return ret;
}
Exemple #5
0
/*
 * cmyth_file_destroy()
 *
 * Scope: PRIVATE (static)
 *
 * Description
 *
 * Tear down and release storage associated with a file connection.
 * This should only be called by ref_release().  All others
 * should call ref_release() to release a file connection.
 *
 * Return Value:
 *
 * None.
 */
static void
cmyth_file_destroy(cmyth_file_t file)
{
	int err;
	char msg[256];

	cmyth_dbg(CMYTH_DBG_DEBUG, "%s {\n", __FUNCTION__);
	if (!file) {
		cmyth_dbg(CMYTH_DBG_DEBUG, "%s }!\n", __FUNCTION__);
		return;
	}
	if (file->file_control) {
		pthread_mutex_lock(&mutex);

		/*
		 * Try to shut down the file transfer.  Can't do much
		 * if it fails other than log it.
		 */
		snprintf(msg, sizeof(msg),
			 "QUERY_FILETRANSFER %"PRIu32"[]:[]DONE", file->file_id);

		if ((err = cmyth_send_message(file->file_control, msg)) < 0) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: cmyth_send_message() failed (%d)\n",
				  __FUNCTION__, err);
			goto fail;
		}

		if ((err=cmyth_rcv_okay(file->file_control)) < 0) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: cmyth_rcv_okay() failed (%d)\n",
				  __FUNCTION__, err);
			goto fail;
		}
	    fail:
		pthread_mutex_unlock(&mutex);
		ref_release(file->file_control);
	}
	if (file->closed_callback) {
	    (file->closed_callback)(file);
	}
	if (file->file_data) {
		ref_release(file->file_data);
	}

	cmyth_dbg(CMYTH_DBG_DEBUG, "%s }\n", __FUNCTION__);
}
Exemple #6
0
int
cmyth_recorder_done_ringbuf(cmyth_recorder_t rec)
{
	int err;
	int ret = -1;
	char msg[256];

	if (!rec) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n",
			  __FUNCTION__);
		return -ENOSYS;
	}

	if (!rec->rec_connected) {
		return -EINVAL;
	}

	if(rec->rec_conn->conn_version >= 26)
		return 0;

	pthread_mutex_lock(&rec->rec_conn->conn_mutex);

	snprintf(msg, sizeof(msg), "QUERY_RECORDER %d[]:[]DONE_RINGBUF",
		 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);
		goto fail;
	}

	if ((err=cmyth_rcv_okay(rec->rec_conn)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_okay() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	ret = 0;

    fail:
	pthread_mutex_unlock(&rec->rec_conn->conn_mutex);

	return ret;
}
Exemple #7
0
/*
 * cmyth_recorder_change_channel(cmyth_recorder_t rec,
 *                               cmyth_channeldir_t direction)
 * 
 * Scope: PUBLIC
 *
 * Description
 *
 * Request that the recorder 'rec' change channels in one of the
 * followin
 *
 * CHANNEL_DIRECTION_UP       - Go up one channel in the listing
 * 
 * CHANNEL_DIRECTION_DOWN     - Go down one channel in the listing
 * 
 * CHANNEL_DIRECTION_FAVORITE - Go to the next favorite channel
 * 
 * CHANNEL_DIRECTION_SAME     - Stay on the same (current) channel
 *
 * Note that the recorder must not be actively recording when this
 * request is made or bad things may happen to the server (i.e. it may
 * segfault).
 *
 * Return Value:
 *
 * Success: 0
 *
 * Failure: -(ERRNO)
 */
int
cmyth_recorder_change_channel(cmyth_recorder_t rec,
			      cmyth_channeldir_t direction)
{
	int err;
	int ret = -1;
	char msg[256];

	if (!rec) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n",
			  __FUNCTION__);
		return -ENOSYS;
	}

	pthread_mutex_lock(&mutex);

	snprintf(msg, sizeof(msg),
		 "QUERY_RECORDER %d[]:[]CHANGE_CHANNEL[]:[]%d",
		 rec->rec_id, direction);

	if ((err=cmyth_send_message(rec->rec_conn, msg)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	if ((err=cmyth_rcv_okay(rec->rec_conn, "ok")) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_okay() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	if(rec->rec_ring)
		rec->rec_ring->file_pos = 0;
	else
		rec->rec_livetv_file->file_pos = 0;

	ret = 0;

    fail:
	pthread_mutex_unlock(&mutex);

	return ret;
}
Exemple #8
0
int
cmyth_recorder_set_live_recording(cmyth_recorder_t rec, uint8_t recording)
{
	int err;
	int ret = -1;
	char msg[256];

	if (!rec) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n",
			  __FUNCTION__);
		return -ENOSYS;
	}

	pthread_mutex_lock(&rec->rec_conn->conn_mutex);

	if (rec->rec_conn->conn_version >= 26)
	{
		snprintf(msg, sizeof(msg), "QUERY_RECORDER %d[]:[]SET_LIVE_RECORDING[]:[]%u", rec->rec_id, recording);

		if ((err=cmyth_send_message(rec->rec_conn, msg)) < 0) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: cmyth_send_message() failed (%d)\n",
				  __FUNCTION__, err);
			goto fail;
		}

		if ((err=cmyth_rcv_okay(rec->rec_conn)) < 0) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: cmyth_rcv_okay() failed (%d)\n",
				  __FUNCTION__, err);
			goto fail;
		}

		ret = recording;
	}
	else
	{
		ret = -EPERM;
	}

fail:
	pthread_mutex_unlock(&rec->rec_conn->conn_mutex);

	return ret;
}
Exemple #9
0
/*
 * cmyth_recorder_check_channel(cmyth_recorder_t rec, char *channame)
 * 
 * Scope: PUBLIC
 *
 * Description
 *
 * Request that the recorder 'rec' check the validity of the channel
 * specified by 'channame'.
 *
 * Return Value:
 *
 * Check the validity of a channel name.
 * Success: 1 - valid channel, 0 - invalid channel
 *
 * Failure: -(ERRNO)
 */
int
cmyth_recorder_check_channel(cmyth_recorder_t rec,
                             char *channame)
{
	int err;
	int ret = -1;
	char msg[256];

	if (!rec || !channame) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: invalid args "
			  "rec = %p, channame = %p\n",
			  __FUNCTION__, rec, channame);
		return -EINVAL;
	}

	pthread_mutex_lock(&mutex);

	snprintf(msg, sizeof(msg),
		 "QUERY_RECORDER %d[]:[]CHECK_CHANNEL[]:[]%s",
		 rec->rec_id, channame);

	if ((err=cmyth_send_message(rec->rec_conn, msg)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	if ((err=cmyth_rcv_okay(rec->rec_conn, "ok")) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_okay() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	ret = 0;

    fail:
	pthread_mutex_unlock(&mutex);

	return ret;
}
Exemple #10
0
/*
 * cmyth_recorder_pause(cmyth_recorder_t rec)
 * 
 * Scope: PUBLIC
 *
 * Description
 *
 * Request that the recorder 'rec' pause in the middle of the current
 * recording.  This will prevent the recorder from transmitting any
 * data until the recorder is unpaused.  At this moment, it is not
 * clear to me what will cause an unpause.
 *
 * Return Value:
 *
 * Success: 0
 *
 * Failure: -(ERRNO)
 */
int
cmyth_recorder_pause(cmyth_recorder_t rec)
{
	int ret = -EINVAL;
	char Buffer[255];

	if (rec == NULL) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: Invalid args rec = %p\n",
			  __FUNCTION__, rec);
		return -EINVAL;
	}

	if (!rec->rec_connected) {
		return -EINVAL;
	}

	pthread_mutex_lock(&rec->rec_conn->conn_mutex);

	sprintf(Buffer, "QUERY_RECORDER %ld[]:[]PAUSE", (long) rec->rec_id);
	if ((ret=cmyth_send_message(rec->rec_conn, Buffer)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message('%s') failed\n",
			  __FUNCTION__, Buffer);
		goto err;
	}

	if ((ret=cmyth_rcv_okay(rec->rec_conn)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_okay() failed\n",
			  __FUNCTION__);
		goto err;
	}

	ret = 0;

    err:
	pthread_mutex_unlock(&rec->rec_conn->conn_mutex);

	return ret;
}
Exemple #11
0
int
cmyth_recorder_stop_livetv(cmyth_recorder_t rec)
{
	int err;
	int ret = -1;
	char msg[256];

	if (!rec) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n",
			  __FUNCTION__);
		return -ENOSYS;
	}

	pthread_mutex_lock(&mutex);

	snprintf(msg, sizeof(msg), "QUERY_RECORDER %"PRIu32"[]:[]STOP_LIVETV",
		 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);
		goto fail;
	}

	if ((err=cmyth_rcv_okay(rec->rec_conn)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_okay() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	ret = 0;

    fail:
	pthread_mutex_unlock(&mutex);

	return ret;
}
Exemple #12
0
int cmyth_set_bookmark(cmyth_conn_t conn, cmyth_proginfo_t prog, int64_t bookmark)
{
	char *buf;
	unsigned int len = CMYTH_TIMESTAMP_LEN + CMYTH_INT64_LEN * 2 + 18 + 2;
	int ret;
	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;
	}
	if (conn->conn_version >= 66) {
		/*
		 * Since protocol 66 mythbackend expects a single 64 bit integer rather than two 32 bit
		 * hi and lo integers. Nevertheless the backend (at least up to 0.25) checks
		 * the existence of the 4th parameter, so adding a 0.
		 */
		sprintf(buf, "SET_BOOKMARK %"PRIu32" %s %"PRId64" 0", prog->proginfo_chanId,
				start_ts_dt, bookmark);
	}
	else {
		sprintf(buf, "SET_BOOKMARK %"PRIu32" %s %"PRId32" %"PRId32, prog->proginfo_chanId,
				start_ts_dt, (int32_t)(bookmark >> 32), (int32_t)(bookmark & 0xffffffff));
	}
	pthread_mutex_lock(&conn->conn_mutex);;
	if ((ret = cmyth_send_message(conn,buf)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			"%s: cmyth_send_message() failed (%d)\n",
			__FUNCTION__, ret);
		goto out;
	}
	if ((ret = cmyth_rcv_okay(conn)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_okay() failed\n",
			  __FUNCTION__);
	}
   out:
	pthread_mutex_unlock(&conn->conn_mutex);
	return ret;
}
Exemple #13
0
/*
 * cmyth_recorder_pause(cmyth_recorder_t rec)
 * 
 * Scope: PUBLIC
 *
 * Description
 *
 * Request that the recorder 'rec' pause in the middle of the current
 * recording.  This will prevent the recorder from transmitting any
 * data until the recorder is unpaused.  At this moment, it is not
 * clear to me what will cause an unpause.
 *
 * Return Value:
 *
 * Success: 0
 *
 * Failure: -(ERRNO)
 */
int
cmyth_recorder_pause(cmyth_recorder_t rec)
{
	int ret = -EINVAL;
	char Buffer[255];

	if (rec == NULL) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: Invalid args rec = %p\n",
			  __FUNCTION__, rec);
		return -EINVAL;
	}

	pthread_mutex_lock(&mutex);

	PRINTF("** SSDEBUG: trying to pause recorder:%p:%p\n",rec,rec->rec_conn);
	sprintf(Buffer, "QUERY_RECORDER %ld[]:[]PAUSE", (long) rec->rec_id);
	if ((ret=cmyth_send_message(rec->rec_conn, Buffer)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message('%s') failed\n",
			  __FUNCTION__, Buffer);
		goto err;
	}

	if ((ret=cmyth_rcv_okay(rec->rec_conn, "ok")) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_okay() failed\n",
			  __FUNCTION__);
		goto err;
	}

	ret = 0;

    err:
	PRINTF("** SSDEBUG: recorder paused:\n");
	pthread_mutex_unlock(&mutex);

	return ret;
}
Exemple #14
0
/*
 * cmyth_file_set_timeout()
 *
 * Scope: PUBLIC
 *
 * Description
 *
 * Set whether reading from a file should have a fast or slow timeout.
 * Slow timeouts are used for live TV ring buffers, and is three seconds.
 * Fast timeouts are used for static files, and are 0.12 seconds.
 *
 * Return Value:
 *
 * Sucess: 0
 *
 * Failure: an int containing -errno
 */
int
cmyth_file_set_timeout(cmyth_file_t file, int32_t fast)
{
	int ret;
	char msg[256];

	if (!file) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n",
			  __FUNCTION__);
		return -EINVAL;
	}

	pthread_mutex_lock (&mutex);

	snprintf(msg, sizeof(msg),
		 "QUERY_FILETRANSFER %"PRIu32"[]:[]SET_TIMEOUT[]:[]%"PRId32,
		 file->file_id, fast);
	if ((ret = cmyth_send_message(file->file_control, msg)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message() failed (%d)\n",
			  __FUNCTION__, ret);
		goto out;
	}

	if ((ret = cmyth_rcv_okay(file->file_control)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_okay() failed\n",
			  __FUNCTION__);
		goto out;
	}

	ret = 0;

out:
	pthread_mutex_unlock (&mutex);
	return ret;
}
Exemple #15
0
static cmyth_conn_t
cmyth_conn_connect(char *server, unsigned short port, unsigned buflen,
		   int tcp_rcvbuf, int event)
{
	cmyth_conn_t conn;
	char announcement[256];
	unsigned long tmp_ver;
	int attempt = 0;

    top:
	conn = cmyth_connect(server, port, buflen, tcp_rcvbuf);
	if (!conn) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_connect(%s, %d, %d) failed\n",
			  __FUNCTION__, server, port, buflen);
		return NULL;
	}

	/*
	 * Find out what the Myth Protocol Version is for this connection.
	 * Loop around until we get agreement from the server.
	 */
	if (attempt == 0)
		tmp_ver = conn->conn_version;
	conn->conn_version = tmp_ver;

	if (tmp_ver >= 62) {
		myth_protomap_t *map = protomap;
		while (map->version != 0 && map->version != tmp_ver)
			map++;
		if (map->version == 0) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: failed to connect with any version\n",
				  __FUNCTION__);
			goto shut;
		}
		sprintf(announcement, "MYTH_PROTO_VERSION %ld %04X", conn->conn_version, map->token);
	} else {
		sprintf(announcement, "MYTH_PROTO_VERSION %ld", conn->conn_version);
	}
	if (cmyth_send_message(conn, announcement) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message('%s') failed\n",
			  __FUNCTION__, announcement);
		goto shut;
	}
	if (cmyth_rcv_version(conn, &tmp_ver) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_version() failed\n",
			  __FUNCTION__);
		goto shut;
	}
	cmyth_dbg(CMYTH_DBG_ERROR,
		  "%s: asked for version %ld, got version %ld\n",
		  __FUNCTION__, conn->conn_version, tmp_ver);
	if (conn->conn_version != tmp_ver) {
		if (attempt == 1) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: failed to connect with any version\n",
				  __FUNCTION__);
			goto shut;
		}
		attempt = 1;
		ref_release(conn);
		goto top;
	}
	cmyth_dbg(CMYTH_DBG_PROTO, "%s: agreed on Version %ld protocol\n",
		  __FUNCTION__, conn->conn_version);

	sprintf(announcement, "ANN Playback %s %d", my_hostname, event);
	if (cmyth_send_message(conn, announcement) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message('%s') failed\n",
			  __FUNCTION__, announcement);
		goto shut;
	}
	if (cmyth_rcv_okay(conn, "OK") < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_okay() failed\n",
			  __FUNCTION__);
		goto shut;
	}
	return conn;

    shut:
	ref_release(conn);
	return NULL;
}
Exemple #16
0
/* Sergio: Added to support the new livetv protocol */
int
cmyth_recorder_spawn_chain_livetv(cmyth_recorder_t rec, char* channame)
{
	int err;
	int ret = -1;
	char msg[256];
	char myhostname[32];
	char datestr[32];
	time_t t;

	if (!rec) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n",
			  __FUNCTION__);
		return -ENOSYS;
	}

	pthread_mutex_lock(&mutex);


	/* Get our own IP address */
	gethostname(myhostname, 32);

	/* Get the current date and time to create a unique id */
	t = time(NULL);
	strftime(datestr, 32, "%Y-%m-%dT%H:%M:%S", localtime(&t));

	/* Now build the SPAWN_LIVETV message */
	if(rec->rec_conn->conn_version >= 34 && channame)
		snprintf(msg, sizeof(msg),
			"QUERY_RECORDER %"PRIu32"[]:[]SPAWN_LIVETV[]:[]live-%s-%s[]:[]%d[]:[]%s",
			 rec->rec_id, myhostname, datestr, 0, channame);
	else
		snprintf(msg, sizeof(msg),
			"QUERY_RECORDER %"PRIu32"[]:[]SPAWN_LIVETV[]:[]live-%s-%s[]:[]%d",
			 rec->rec_id, myhostname, datestr, 0);

	if ((err=cmyth_send_message(rec->rec_conn, msg)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	if ((err=cmyth_rcv_okay(rec->rec_conn)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_okay() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	/* Create an empty livetv chain with the ID used in the spawn command */
	snprintf(msg, sizeof(msg), "live-%s-%s", myhostname, datestr);
	rec->rec_livetv_chain = cmyth_livetv_chain_create(msg);

	ret = 0;

    fail:
	pthread_mutex_unlock(&mutex);

	return ret;
}
Exemple #17
0
/*
 * cmyth_recorder_set_channel(cmyth_recorder_t rec,
 *                            char *channame)
 * 
 * Scope: PUBLIC
 *
 * Description
 *
 * Request that the recorder 'rec' change channels to the channel
 * named 'channame'.
 *
 * Note that the recorder must not be actively recording when this
 * request is made or bad things may happen to the server (i.e. it may
 * segfault).
 *
 * Return Value:
 *
 * Success: 0
 *
 * Failure: -(ERRNO)
 */
int
cmyth_recorder_set_channel(cmyth_recorder_t rec, char *channame)
{
	int err;
	int ret = -1;
	char msg[256];
	cmyth_file_t file;

	if (!rec) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n",
			  __FUNCTION__);
		return -ENOSYS;
	}

	if (!rec->rec_connected) {
		return -EINVAL;
	}

	pthread_mutex_lock(&rec->rec_conn->conn_mutex);

	cmyth_chain_lock(rec->rec_chain);

	snprintf(msg, sizeof(msg),
		 "QUERY_RECORDER %d[]:[]SET_CHANNEL[]:[]%s",
		 rec->rec_id, channame);

	if ((err=cmyth_send_message(rec->rec_conn, msg)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	if ((err=cmyth_rcv_okay(rec->rec_conn)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_okay() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	pthread_mutex_unlock(&rec->rec_conn->conn_mutex);

	cmyth_chain_add_wait(rec->rec_chain);

	cmyth_chain_unlock(rec->rec_chain);

	if ((file=cmyth_livetv_current_file(rec)) == NULL) {
		goto fail_nolock;
	}

	cmyth_file_seek(file, 0, SEEK_SET);

	ref_release(file);

	ret = 0;

fail:
	pthread_mutex_unlock(&rec->rec_conn->conn_mutex);

fail_nolock:
	return ret;
}
Exemple #18
0
static cmyth_conn_t
cmyth_conn_connect(char *server, unsigned short port, unsigned buflen,
		   int tcp_rcvbuf, int event)
{
	cmyth_conn_t conn;
	char announcement[256];
	unsigned long tmp_ver;
	int attempt = 0;

    top:
	conn = cmyth_connect(server, port, buflen, tcp_rcvbuf);
	if (!conn) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_connect(%s, %d, %d) failed\n",
			  __FUNCTION__, server, port, buflen);
		return NULL;
	}

	/*
	 * Find out what the Myth Protocol Version is for this connection.
	 * Loop around until we get agreement from the server.
	 */
	if (attempt == 0)
		tmp_ver = conn->conn_version;
	conn->conn_version = tmp_ver;

	/*
	 * Myth 0.23.1 (Myth 0.23 + fixes) introduced an out of sequence protocol version number (23056)
	 * due to the next protocol version number having already been bumped in trunk.
	 *
	 * http://www.mythtv.org/wiki/Myth_Protocol
	 */
	if (tmp_ver >= 62 && tmp_ver != 23056) { // Treat protocol version number 23056 the same as protocol 56
		myth_protomap_t *map = protomap;
		while (map->version != 0 && map->version != tmp_ver)
			map++;
		if (map->version == 0) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: failed to connect with any version\n",
				  __FUNCTION__);
			goto shut;
		}
		sprintf(announcement, "MYTH_PROTO_VERSION %ld %s", conn->conn_version, map->token);
	} else {
		sprintf(announcement, "MYTH_PROTO_VERSION %ld", conn->conn_version);
	}
	if (cmyth_send_message(conn, announcement) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message('%s') failed\n",
			  __FUNCTION__, announcement);
		goto shut;
	}
	if (cmyth_rcv_version(conn, &tmp_ver) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_version() failed\n",
			  __FUNCTION__);
		goto shut;
	}
	cmyth_dbg(CMYTH_DBG_ERROR,
		  "%s: asked for version %ld, got version %ld\n",
		  __FUNCTION__, conn->conn_version, tmp_ver);
	if (conn->conn_version != tmp_ver) {
		if (attempt == 1) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: failed to connect with any version\n",
				  __FUNCTION__);
			goto shut;
		}
		attempt = 1;
		ref_release(conn);
		goto top;
	}
	cmyth_dbg(CMYTH_DBG_PROTO, "%s: agreed on Version %ld protocol\n",
		  __FUNCTION__, conn->conn_version);

	sprintf(announcement, "ANN Playback %s %d", my_hostname, event);
	if (cmyth_send_message(conn, announcement) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message('%s') failed\n",
			  __FUNCTION__, announcement);
		goto shut;
	}
	if (cmyth_rcv_okay(conn, "OK") < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_okay() failed\n",
			  __FUNCTION__);
		goto shut;
	}

	/*
	 * All of the downstream code in libcmyth assumes a monotonically increasing version number.
	 * This was not the case for Myth 0.23.1 (0.23 + fixes) where protocol version number 23056
	 * was used since 57 had already been used in trunk.
	 *
	 * Convert from protocol version number 23056 to version number 56 so subsequent code within
	 * libcmyth uses the same logic for the 23056 protocol as would be used for protocol version 56.
	 */
	if (conn->conn_version == 23056) {
		conn->conn_version = 56;
	}

	return conn;

    shut:
	ref_release(conn);
	return NULL;
}
Exemple #19
0
/* Sergio: Added to support the new livetv protocol */
int
cmyth_recorder_spawn_chain_livetv(cmyth_recorder_t rec)
{
	int err;
	int ret = -1;
	char msg[256], id[128];
	char myhostname[32];

	if (!rec) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: no recorder connection\n",
			  __FUNCTION__);
		return -ENOSYS;
	}

	if (!rec->rec_connected) {
		return -EINVAL;
	}

	pthread_mutex_lock(&rec->rec_conn->conn_mutex);


	/* Get our own IP address */
	gethostname(myhostname, 32);

	/* Create an empty livetv chain with a unique ID */
	snprintf(id, sizeof(id), "live-%s-%d-%p", myhostname, getpid(), rec);

	/* Now build the SPAWN_LIVETV message */
	if (rec->rec_conn->conn_version >=50) {
		snprintf(msg, sizeof(msg),
		"QUERY_RECORDER %d[]:[]SPAWN_LIVETV[]:[]%s[]:[]%d[]:[]",
		 rec->rec_id, id, 0);
	}
	else {
		snprintf(msg, sizeof(msg),
		"QUERY_RECORDER %d[]:[]SPAWN_LIVETV[]:[]%s[]:[]%d",
		 rec->rec_id, id, 0);
	}

	if ((err=cmyth_send_message(rec->rec_conn, msg)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	if ((err=cmyth_rcv_okay(rec->rec_conn)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_okay() failed (%d)\n",
			  __FUNCTION__, err);
		goto fail;
	}

	rec->rec_chain = cmyth_chain_create(rec, id);

	ret = 0;

    fail:
	pthread_mutex_unlock(&rec->rec_conn->conn_mutex);

	return ret;
}
Exemple #20
0
/*
 * cmyth_conn_connect_ring(char *server, unsigned short port, unsigned buflen
 *                         cmyth_recorder_t rec)
 *
 * Scope: PUBLIC
 *
 * Description:
 *
 * Create a new ring buffer connection for use transferring live-tv
 * using the MythTV protocol.  Return a pointer to the newly created
 * ring buffer connection.  The ring buffer connection is returned
 * held, and may be released using ref_release().
 *
 * Return Value:
 *
 * Success: Non-NULL cmyth_conn_t (this is a pointer type)
 *
 * Failure: NULL cmyth_conn_t
 */
int
cmyth_conn_connect_ring(cmyth_recorder_t rec, unsigned buflen, int tcp_rcvbuf)
{
	cmyth_conn_t conn;
	char *announcement;
	int ann_size = sizeof("ANN RingBuffer  ");
	char *server;
	unsigned short port;

	if (!rec) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: rec is NULL\n", __FUNCTION__);
		return -1;
	}

	server = rec->rec_server;
	port = rec->rec_port;

	cmyth_dbg(CMYTH_DBG_PROTO, "%s: connecting ringbuffer\n",
		  __FUNCTION__);
	conn = cmyth_connect(server, port, buflen, tcp_rcvbuf);
	cmyth_dbg(CMYTH_DBG_PROTO,
		  "%s: connecting ringbuffer, conn = %p\n",
		  __FUNCTION__, conn);
	if (!conn) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_connect(%s, %d, %d) failed\n",
			  __FUNCTION__, server, port, buflen);
		return -1;
	}

	ann_size += CMYTH_LONG_LEN + strlen(my_hostname);
	announcement = malloc(ann_size);
	if (!announcement) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: malloc(%d) failed for announcement\n",
			  __FUNCTION__, ann_size);
		goto shut;
	}
	sprintf(announcement,
		"ANN RingBuffer %s %d", my_hostname, rec->rec_id);
	if (cmyth_send_message(conn, announcement) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_send_message('%s') failed\n",
			  __FUNCTION__, announcement);
		free(announcement);
		goto shut;
	}
	free(announcement);
	if (cmyth_rcv_okay(conn, "OK") < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_okay() failed\n",
			  __FUNCTION__);
		goto shut;
	}

        rec->rec_ring->conn_data = conn;
	return 0;

    shut:
	ref_release(conn);
	return -1;
}