Esempio n. 1
0
/*
 * cmyth_livetv_wait()
 *
 * After starting live TV or after a channel change wait here until some
 * recording data is available.
 */
static int
cmyth_livetv_wait(cmyth_recorder_t rec)
{
    int i = 0, rc = -1;
    cmyth_conn_t conn;
    static int failures = 0;

    usleep(250000*failures);

    conn = cmyth_conn_reconnect(rec->rec_conn);

    while (i++ < 10) {
        int len;
        cmyth_proginfo_t prog;
        cmyth_file_t file;

        if (!cmyth_recorder_is_recording(rec)) {
            usleep(1000);
            continue;
        }

        prog = cmyth_recorder_get_cur_proginfo(rec);

        if (prog == NULL) {
            usleep(1000);
            continue;
        }

        file = cmyth_conn_connect_file(prog, conn, 4096, 4096);

        ref_release(prog);

        if (file == NULL) {
            if (failures < 4) {
                failures++;
            }
            usleep(1000);
            continue;
        }

        len = cmyth_file_request_block(file, 512);

        ref_release(file);

        if (len == 512) {
            rc = 0;
            break;
        }

        if (failures < 4) {
            failures++;
        }
        usleep(1000);
    }

    ref_release(conn);

    return rc;
}
Esempio n. 2
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, 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;
}
Esempio n. 3
0
/*
 * cmyth_livetv_chain_update(cmyth_recorder_t rec, char * chainid, int buff)
 * 
 * Scope: PUBLIC
 *
 * Description
 *
 * Called in response to the backend's notification of a chain update.
 * The recorder is supplied and will be queried for the current recording
 * to determine if a new file needs to be added to the chain of files
 * in the live tv instance.
 *
 * Return Value:
 *
 * Success: 0
 *
 * Failure: -1
 */
int
cmyth_livetv_chain_update(cmyth_recorder_t rec, char * chainid,
													int tcp_rcvbuf)
{
	int ret=0;
	char url[1024];
	cmyth_conn_t control;
	cmyth_proginfo_t loc_prog;
	cmyth_file_t ft;

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

	control = rec->rec_conn;

	loc_prog = cmyth_recorder_get_cur_proginfo(rec);
	pthread_mutex_lock(&mutex);

	if(rec->rec_livetv_chain) {
		if(strncmp(rec->rec_livetv_chain->chainid, chainid, strlen(chainid)) == 0) {
			sprintf(url, "myth://%s:%d%s",loc_prog->proginfo_hostname, rec->rec_port,
					loc_prog->proginfo_pathname);

			/*
				 Now check if this file is in the recorder chain and if not
				 then open a new file transfer and add it to the chain.
			*/

			if(cmyth_livetv_chain_has_url(rec, url) == -1) {
				ft = cmyth_conn_connect_file(loc_prog, rec->rec_conn, 16*1024, tcp_rcvbuf);
				if (!ft) {
					cmyth_dbg(CMYTH_DBG_ERROR,
			  			"%s: cmyth_conn_connect_file(%s) failed\n",
			  			__FUNCTION__, url);
					ret = -1;
					goto out;
				}
				if(cmyth_livetv_chain_add(rec, url, ft, loc_prog) == -1) {
					cmyth_dbg(CMYTH_DBG_ERROR,
			  			"%s: cmyth_livetv_chain_add(%s) failed\n",
			  			__FUNCTION__, url);
					ret = -1;
					goto out;
				}
				ref_release(ft);
				if(rec->rec_livetv_chain->chain_switch_on_create) {
					cmyth_livetv_chain_switch(rec, LAST);
					rec->rec_livetv_chain->chain_switch_on_create = 0;
				}
			}
		}
		else {
			cmyth_dbg(CMYTH_DBG_ERROR,
			 		"%s: chainid doesn't match recorder's chainid!!\n",
			 		__FUNCTION__, url);
			ret = -1;
		}
	}
	else {
		cmyth_dbg(CMYTH_DBG_ERROR,
		 		"%s: rec_livetv_chain is NULL!!\n",
		 		__FUNCTION__, url);
		ret = -1;
	}

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

	return ret;
}
Esempio n. 4
0
int
cmyth_recorder_add_chanlist(cmyth_recorder_t rec)
{
	cmyth_proginfo_t zero, first, prog;
	char *first_name;
	cmyth_chanlist_t list;
	cmyth_channel_t channel;

	/*
	 * Get a list of channels for the recorder by cycling through the
	 * current program guide.  For some reason, the first proginfo
	 * structure retrieved seems to be empty, so just ignore it.
	 */

	zero = cmyth_recorder_get_cur_proginfo(rec);

	if (zero == NULL) {
		return -1;
	}

	first = cmyth_recorder_get_next_proginfo(rec, zero,
						 BROWSE_DIRECTION_UP);

	ref_release(zero);

	first_name = cmyth_proginfo_channame(first);

	prog = ref_hold(first);

	list = cmyth_chanlist_create();

	while (1) {
		cmyth_proginfo_t prev = prog;
		char *name, *sign, *icon;
		char buf[128];

		prog = cmyth_recorder_get_next_proginfo(rec, prev,
							BROWSE_DIRECTION_UP);

		if (prog == NULL) {
			break;
		}

		name = cmyth_proginfo_channame(prog);
		sign = cmyth_proginfo_chansign(prog);

		snprintf(buf, sizeof(buf), "%s %s", name, sign);

		icon = cmyth_proginfo_chanicon(prog);
		channel = cmyth_channel_create(prog->proginfo_chanId,
					       name, sign, buf, icon);

		cmyth_chanlist_add(list, channel);

		ref_release(channel);
		ref_release(sign);
		ref_release(icon);
		ref_release(prev);

		if (strcmp(first_name, name) == 0) {
			ref_release(name);
			break;
		}

		ref_release(name);
	}

	rec->rec_chanlist = list;

	ref_release(first_name);
	ref_release(first);
	ref_release(prog);

	return 0;
}
Esempio n. 5
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;
}
Esempio n. 6
0
/*
 * cmyth_livetv_chain_update(cmyth_recorder_t rec, char * chainid, int buff)
 *
 * Scope: PUBLIC
 *
 * Description
 *
 * Called in response to the backend's notification of a chain update.
 * The recorder is supplied and will be queried for the current recording
 * to determine if a new file needs to be added to the chain of files
 * in the live tv instance.
 *
 * Return Value:
 *
 * Success: 0
 *
 * Failure: -1
 */
int
cmyth_livetv_chain_update(cmyth_recorder_t rec, char * chainid)
{
    int ret;
    char url[1024];
    cmyth_proginfo_t loc_prog;
    cmyth_file_t ft;

    ret = 0;

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

    /* JLB: Manage program break
     * Skip chain update, it will doing later
     */
    if (!rec->rec_livetv_chain) {
        cmyth_dbg(CMYTH_DBG_ERROR,
                  "%s: rec_livetv_chain is NULL\n",
                  __FUNCTION__, url);
        return -1;
    }
    else {
        if (rec->rec_livetv_chain->livetv_watch != 1) {
            cmyth_dbg(CMYTH_DBG_DEBUG,
                      "%s: skip chain update\n",
                      __FUNCTION__);
            return 0;
        }
    }

    loc_prog = cmyth_recorder_get_cur_proginfo(rec);
    if (!loc_prog) {
        cmyth_dbg(CMYTH_DBG_ERROR,
                  "%s: recorder is not recording\n",
                  __FUNCTION__);
        return -1;
    }

    pthread_mutex_lock(&mutex);

    if (strncmp(rec->rec_livetv_chain->chainid, chainid, strlen(chainid)) == 0) {
        sprintf(url, "myth://%s:%d%s", loc_prog->proginfo_hostname, rec->rec_port,
                loc_prog->proginfo_pathname);

        /*
        	  Now check if this file is in the recorder chain and if not
        	  then open a new file transfer and add it to the chain.
        */

        if (cmyth_livetv_chain_has_url(rec, url) == -1) {
            ft = cmyth_conn_connect_file(loc_prog, rec->rec_conn, 4096, rec->rec_livetv_chain->livetv_tcp_rcvbuf);
            if (!ft) {
                cmyth_dbg(CMYTH_DBG_ERROR,
                          "%s: cmyth_conn_connect_file(%s) failed\n",
                          __FUNCTION__, url);
                ret = -1;
                goto out;
            }
            if (cmyth_livetv_chain_add(rec, url, ft, loc_prog) == -1) {
                cmyth_dbg(CMYTH_DBG_ERROR,
                          "%s: cmyth_livetv_chain_add(%s) failed\n",
                          __FUNCTION__, url);
                ret = -1;
                ref_release(ft);
                goto out;
            }
            ref_release(ft);
            if (rec->rec_livetv_chain->chain_switch_on_create) {
                cmyth_livetv_chain_switch(rec, LAST);
                rec->rec_livetv_chain->chain_switch_on_create = 0;
            }
        }
    }
    else {
        cmyth_dbg(CMYTH_DBG_ERROR,
                  "%s: chainid doesn't match recorder's chainid!!\n",
                  __FUNCTION__, url);
        ret = -1;
    }

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

    return ret;
}
Esempio n. 7
0
static void
cmyth_chain_update(cmyth_chain_t chain, cmyth_recorder_t rec, char *msg)
{
	char *p;
	cmyth_proginfo_t prog = NULL;
	cmyth_chain_entry_t entry;
	int size, tip;
	long long offset;
	int start = 0;
	char *path;

	if ((p=strchr(msg, ' ')) != NULL) {
		*(p++) = '\0';

		if (strcmp(msg, "LIVETV_CHAIN UPDATE") != 0) {
			return;
		}
	} else {
		p = msg;
	}

	prog = cmyth_recorder_get_cur_proginfo(rec);

	if (prog == NULL) {
		return;
	}

	path = cmyth_proginfo_pathname(prog);

	if (path == NULL) {
		return;
	}

	if (strlen(path) == 0) {
		ref_release(path);
		ref_release(prog);
		return;
	}
	ref_release(path);

	pthread_mutex_lock(&chain->chain_mutex);

	if (!chain->chain_id || (strncmp(p, chain->chain_id, strlen(p)) != 0)) {
		goto out;
	}

	tip = chain->chain_count - 1;

	if (tip >= 0) {
		path = cmyth_proginfo_pathname(chain->chain_list[tip]->prog);
		ref_release(path);

		if (cmyth_proginfo_compare(prog,
					   chain->chain_list[tip]->prog) == 0) {
			ref_release(prog);
			goto out;
		}

		offset = chain->chain_list[tip]->offset +
			cmyth_proginfo_length(chain->chain_list[tip]->prog);
	} else {
		offset = 0;
		start = 1;
	}

	size = sizeof(*chain->chain_list) * (++chain->chain_count);

	chain->chain_list = ref_realloc(chain->chain_list, size);

	entry = ref_alloc(sizeof(*entry));

	entry->prog = prog;
	entry->file = NULL;
	entry->offset = offset;

	chain->chain_list[tip+1] = entry;

	pthread_cond_broadcast(&chain->chain_cond);

out:
	pthread_mutex_unlock(&chain->chain_mutex);

	if (start) {
		chain->chain_current = 0;
		cmyth_chain_switch(chain, 0);
	}
}
Esempio n. 8
0
static int
get_recorders(int level)
{
	int i, j;

	for (i=0; i<=32; i++) {
		cmyth_recorder_t rec;
		int state;

		rec = cmyth_conn_get_recorder(control, i);

		if (rec == NULL) {
			continue;
		}

		state = cmyth_recorder_is_recording(rec);

		if (state == 0) {
			printf("Recorder %d is idle\n", i);
		} else if (state == 1) {
			cmyth_proginfo_t prog;
			cmyth_timestamp_t end;
			char str[32];
			char *title;

			prog = cmyth_recorder_get_cur_proginfo(rec);

			end = cmyth_proginfo_rec_end(prog);
			cmyth_timestamp_to_string(str, end);

			printf("Recorder %d is recording until %s\n", i, str);

			if (prog && (level > 0)) {
				title = cmyth_proginfo_title(prog);
				if (title) {
					printf("\tTitle:           %s\n",
					       title);
				}
				ref_release(title);
			}

			ref_release(prog);
			ref_release(end);
		} else {
			printf("Recorder %d is in an unknown state\n", i);
		}

		if (level > 1) {
			cmyth_chanlist_t cl;
			cmyth_channel_t chan;
			char *name;

			cl = cmyth_recorder_get_chanlist(rec);

			for (j=0; j<cmyth_chanlist_get_count(cl); j++) {
				chan = cmyth_chanlist_get_item(cl, j);
				name = cmyth_channel_string(chan);
				printf("\tChannel: %s\n", name);
				ref_release(name);
				ref_release(chan);
			}

			ref_release(cl);
		}

		ref_release(rec);
	}

	return 0;
}