예제 #1
0
/*
 * cmyth_livetv_chain_setup(cmyth_recorder_t old_rec)
 *
 * Scope: PUBLIC
 *
 * Description
 *
 * Set up the file information the recorder needs to watch live
 * tv.  The recorder is supplied.  This will be duplicated and
 * released, so the caller can re-use the same variable to hold the
 * return.  The new copy of the recorder will have a livetv chain
 * within it.
 *
 * Return Value:
 *
 * Success: A pointer to a new recorder structure with a livetvchain
 *
 * Failure: NULL but the recorder passed in is not released the
 *					caller needs to do this on a failure.
 */
cmyth_recorder_t
cmyth_livetv_chain_setup(cmyth_recorder_t rec, int tcp_rcvbuf,
                         void (*prog_update_callback)(cmyth_proginfo_t))
{

    cmyth_recorder_t new_rec = NULL;
    char url[1024];
    cmyth_conn_t control;
    cmyth_proginfo_t loc_prog;
    cmyth_file_t ft;

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

    control = rec->rec_conn;
    /* Get the current recording information */
    loc_prog = cmyth_recorder_get_cur_proginfo(rec);

    if (loc_prog == NULL) {
        cmyth_dbg(CMYTH_DBG_DEBUG, "%s: could not get current filename\n",
                  __FUNCTION__);
        goto out;
    }

    pthread_mutex_lock(&mutex);

    new_rec = cmyth_recorder_dup(rec);
    if (new_rec == NULL) {
        cmyth_dbg(CMYTH_DBG_DEBUG, "%s: cannot create recorder\n",
                  __FUNCTION__);
        goto out;
    }
    ref_release(rec);

    if(new_rec->rec_livetv_chain == NULL) {
        cmyth_dbg(CMYTH_DBG_DEBUG, "%s: error no livetv_chain\n",
                  __FUNCTION__);
        new_rec = NULL;
        goto out;
    }

    sprintf(url, "myth://%s:%d%s", loc_prog->proginfo_hostname, rec->rec_port,
            loc_prog->proginfo_pathname);

    if(cmyth_livetv_chain_has_url(new_rec, url) == -1) {
        new_rec->rec_livetv_chain->livetv_tcp_rcvbuf = tcp_rcvbuf;
        ft = cmyth_conn_connect_file(loc_prog, new_rec->rec_conn, 4096, new_rec->rec_livetv_chain->livetv_tcp_rcvbuf);
        if (!ft) {
            cmyth_dbg(CMYTH_DBG_ERROR,
                      "%s: cmyth_conn_connect_file(%s) failed\n",
                      __FUNCTION__, url);
            new_rec = NULL;
            goto out;
        }
    }
    if(cmyth_livetv_chain_add(new_rec, url, ft, loc_prog) == -1) {
        cmyth_dbg(CMYTH_DBG_ERROR,
                  "%s: cmyth_livetv_chain_add(%s) failed\n",
                  __FUNCTION__, url);
        new_rec = NULL;
        ref_release(ft);
        goto out;
    }

    new_rec->rec_livetv_chain->prog_update_callback = prog_update_callback;
    ref_release(ft);

    /* JLB: Manage program breaks
     * Switch ON watch signal
     */
    new_rec->rec_livetv_chain->livetv_watch = 1;

    cmyth_livetv_chain_switch(new_rec, 0);


out:
    pthread_mutex_unlock(&mutex);
    ref_release(loc_prog);

    return new_rec;
}
예제 #2
0
파일: livetv.c 프로젝트: Castlecard/plex
/*
 * cmyth_livetv_chain_setup(cmyth_recorder_t old_rec)
 * 
 * Scope: PUBLIC
 *
 * Description
 *
 * Set up the file information the recorder needs to watch live
 * tv.  The recorder is supplied.  This will be duplicated and
 * released, so the caller can re-use the same variable to hold the
 * return.  The new copy of the recorder will have a livetv chain
 * within it.
 *
 * Return Value:
 *
 * Success: A pointer to a new recorder structure with a livetvchain
 *
 * Failure: NULL but the recorder passed in is not released the
 *					caller needs to do this on a failure.
 */
cmyth_recorder_t
cmyth_livetv_chain_setup(cmyth_recorder_t rec, int tcp_rcvbuf,
			 void (*prog_update_callback)(cmyth_proginfo_t))
{

	cmyth_recorder_t new_rec = NULL;
	char url[1024];
	cmyth_conn_t control;
	cmyth_proginfo_t loc_prog, loc_prog2;
	cmyth_file_t ft;
	int i=0;


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

	control = rec->rec_conn;
	/* Get the current recording information */
	loc_prog = cmyth_recorder_get_cur_proginfo(rec);

	/* Since backend will pretty much lockup when trying to open an *
	 * empty file, like the dummy file first generated by dvd       */
	loc_prog2 = (cmyth_proginfo_t)ref_hold(loc_prog);
	while(i++<5 && (loc_prog2 == NULL || (loc_prog2 && loc_prog2->proginfo_Length == 0))) {
		usleep(200000);
		if(loc_prog2)
			ref_release(loc_prog2);
		loc_prog2 = cmyth_recorder_get_cur_proginfo(rec);
		loc_prog2 = cmyth_proginfo_get_detail(control, loc_prog2);
	}

	if (loc_prog == NULL) {
		cmyth_dbg(CMYTH_DBG_DEBUG, "%s: could not get current filename\n",
			  __FUNCTION__);
		goto out;
	}

	pthread_mutex_lock(&mutex);

	sprintf(url, "myth://%s:%d%s",loc_prog->proginfo_hostname, rec->rec_port,
					loc_prog->proginfo_pathname);

	new_rec = cmyth_recorder_dup(rec);
	if (new_rec == NULL) {
		cmyth_dbg(CMYTH_DBG_DEBUG, "%s: cannot create recorder\n",
			  __FUNCTION__);
		goto out;
	}
	ref_release(rec);

	if(new_rec->rec_livetv_chain == NULL) {
		cmyth_dbg(CMYTH_DBG_DEBUG, "%s: error no livetv_chain\n",
			  __FUNCTION__);
		new_rec = NULL;
		goto out;
	}

	if(cmyth_livetv_chain_has_url(new_rec, url) == -1) {
		ft = cmyth_conn_connect_file(loc_prog, new_rec->rec_conn, 16*1024, tcp_rcvbuf);
		if (!ft) {
			cmyth_dbg(CMYTH_DBG_ERROR,
	  			"%s: cmyth_conn_connect_file(%s) failed\n",
	  			__FUNCTION__, url);
			new_rec = NULL;
			goto out;
		}
		if(cmyth_livetv_chain_add(new_rec, url, ft, loc_prog) == -1) {
			cmyth_dbg(CMYTH_DBG_ERROR,
		 			"%s: cmyth_livetv_chain_add(%s) failed\n",
		 			__FUNCTION__, url);
			new_rec = NULL;
			goto out;
		}
		new_rec->rec_livetv_chain->prog_update_callback = prog_update_callback;
		ref_release(ft);
		cmyth_livetv_chain_switch(new_rec, 0);
	}


	ref_release(loc_prog);
    out:
	pthread_mutex_unlock(&mutex);

	return new_rec;
}
예제 #3
0
파일: ringbuf.c 프로젝트: AWilco/xbmc
/*
 * cmyth_ringbuf_setup(cmyth_recorder_t old_rec)
 * 
 * Scope: PUBLIC
 *
 * Description
 *
 * Set up the ring buffer inside a recorder for use in playing live
 * tv.  The recorder is supplied.  This will be duplicated and
 * released, so the caller can re-use the same variable to hold the
 * return.  The new copy of the recorder will have a ringbuffer set up
 * within it.
 *
 * Return Value:
 *
 * Success: A pointer to a new recorder structure with a ringbuffer
 *
 * Faiure: NULL
 */
cmyth_recorder_t
cmyth_ringbuf_setup(cmyth_recorder_t rec)
{
	static const char service[]="rbuf://";
	cmyth_recorder_t new_rec = NULL;
	char *host = NULL;
	char *port = NULL;
	char *path = NULL;
	char tmp;

	int err, count;
	int r;
	long long size, fill;
	char msg[256];
	char url[1024];
	char buf[32];
	cmyth_conn_t control;

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

	control = rec->rec_conn;

	pthread_mutex_lock(&mutex);

	snprintf(msg, sizeof(msg),
		 "QUERY_RECORDER %u[]:[]SETUP_RING_BUFFER[]:[]0",
		 rec->rec_id);

	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 (control->conn_version >= 16) {
		r = cmyth_rcv_string(control, &err, buf, sizeof(buf)-1, count);
		count -= r;
	}
	r = cmyth_rcv_string(control, &err, url, sizeof(url)-1, count); 
	count -= r;

	if ((r=cmyth_rcv_long_long(control, &err, &size, count)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_length() failed (%d)\n",
			  __FUNCTION__, r);
		goto out;
	}
	count -= r;

	if ((r=cmyth_rcv_long_long(control, &err, &fill, count)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR,
			  "%s: cmyth_rcv_length() failed (%d)\n",
			  __FUNCTION__, r);
		goto out;
	}

	cmyth_dbg(CMYTH_DBG_DEBUG, "%s: url is: '%s'\n",
		  __FUNCTION__, url);
	path = url;
	if (strncmp(url, service, sizeof(service) - 1) == 0) {
		/*
		 * The URL starts with rbuf://.  The rest looks like
		 * <host>:<port>/<filename>.
		 */
		host = url + strlen(service);
		port = strchr(host, ':');
		if (!port) {
			/*
			 * This does not seem to be a proper URL, so just
			 * assume it is a filename, and get out.
			 */
			cmyth_dbg(CMYTH_DBG_DEBUG,
				  "%s: 1 port %s, host = %s\n",
				  __FUNCTION__, port, host);
			goto out;
		}
		port = port + 1;
		path = strchr(port, '/');
		if (!path) {
			/*
			 * This does not seem to be a proper URL, so just
			 * assume it is a filename, and get out.
			 */
			cmyth_dbg(CMYTH_DBG_DEBUG, "%s: no path\n",
				  __FUNCTION__);
			goto out;
		}
	}

	new_rec = cmyth_recorder_dup(rec);
	if (new_rec == NULL) {
		cmyth_dbg(CMYTH_DBG_DEBUG, "%s: cannot create recorder\n",
			  __FUNCTION__);
		goto out;
	}
	ref_release(rec);
        new_rec->rec_ring = cmyth_ringbuf_create();
        
	tmp = *(port - 1);
	*(port - 1) = '\0';
	new_rec->rec_ring->ringbuf_hostname = ref_strdup(host);
	*(port - 1) = tmp;
	tmp = *(path);
	*(path) = '\0';
	new_rec->rec_ring->ringbuf_port = atoi(port);
	*(path) = tmp;
	new_rec->rec_ring->ringbuf_url = ref_strdup(url);
	new_rec->rec_ring->ringbuf_size = size;
	new_rec->rec_ring->ringbuf_fill = fill;

    out:
	pthread_mutex_unlock(&mutex);

	return new_rec;
}