Пример #1
0
static int o_files(int f, struct path_info *info, struct fuse_file_info *fi)
{
	int i;
	cmyth_conn_t control;
	cmyth_proglist_t list;
	int count;
	int ret = -ENOENT;

	pthread_mutex_lock(&mutex);

	if ((i=lookup_server(info->host)) < 0) {
		pthread_mutex_unlock(&mutex);
		return -ENOENT;
	}

	control = ref_hold(conn[i].control);

	if (conn[i].list == NULL) {
		list = cmyth_proglist_get_all_recorded(control);
		conn[i].list = list;
		parse_progs(conn+i);
	} else {
		list = conn[i].list;
	}

	list = ref_hold(list);

	pthread_mutex_unlock(&mutex);

	count = cmyth_proglist_get_count(list);

	for (i=0; i<count; i++) {
		cmyth_proginfo_t prog;
		char *pn;

		prog = cmyth_proglist_get_item(list, i);
		pn = cmyth_proginfo_pathname(prog);

		if (strcmp(pn+1, info->file) == 0) {
			if (do_open(prog, fi, f) < 0) {
				ref_release(pn);
				ref_release(prog);
				goto out;
			}
			ref_release(pn);
			ref_release(prog);
			ret = 0;
			goto out;
		}

		ref_release(pn);
		ref_release(prog);
	}

out:
	ref_release(control);
	ref_release(list);

	return ret;
}
Пример #2
0
static int
rd_files(struct path_info *info, void *buf, fuse_fill_dir_t filler,
	 off_t offset, struct fuse_file_info *fi)
{
	int i;
	cmyth_conn_t control;
	cmyth_proglist_t list;
	int count;

	pthread_mutex_lock(&mutex);

	if ((i=lookup_server(info->host)) < 0) {
		pthread_mutex_unlock(&mutex);
		return 0;
	}

	control = ref_hold(conn[i].control);

	if (conn[i].list == NULL) {
		list = cmyth_proglist_get_all_recorded(control);
		conn[i].list = list;
	} else {
		list = conn[i].list;
	}

	list = ref_hold(list);

	pthread_mutex_unlock(&mutex);

	count = cmyth_proglist_get_count(list);

	for (i=0; i<count; i++) {
		cmyth_proginfo_t prog;
		long long len;
		char *fn, *pn;
		struct stat st;

		prog = cmyth_proglist_get_item(list, i);
		pn = cmyth_proginfo_pathname(prog);
		len = cmyth_proginfo_length(prog);

		fn = pn+1;

		memset(&st, 0, sizeof(st));
		st.st_mode = S_IFREG | 0444;
		st.st_size = len;

		debug("%s(): file '%s' len %lld\n", __FUNCTION__, fn, len);
		filler(buf, fn, &st, 0);

		ref_release(prog);
		ref_release(pn);
	}

	ref_release(control);
	ref_release(list);

	return 0;
}
Пример #3
0
static void
parse_progs(struct myth_conn *c)
{
	int i, j, count;
	struct prog_map *progs;

	count = cmyth_proglist_get_count(c->list);

	progs = ref_alloc(sizeof(*progs)*count);

	for (i=0; i<count; i++) {
		cmyth_proginfo_t prog;
		char *title, *subtitle;
		prog = cmyth_proglist_get_item(c->list, i);
		title = cmyth_proginfo_title(prog);
		subtitle = cmyth_proginfo_subtitle(prog);
		progs[i].prog = ref_hold(prog);
		progs[i].suffix = 0;
		for (j=0; j<i; j++) {
			char *t, *s;
			t = cmyth_proginfo_title(progs[j].prog);
			s = cmyth_proginfo_subtitle(progs[j].prog);
			if ((strcmp(title, t) == 0) &&
			    (strcmp(subtitle, s) == 0)) {
				progs[i].suffix++;
			}
			ref_release(t);
			ref_release(s);
		}
		ref_release(title);
		ref_release(subtitle);
		ref_release(prog);
	}

	for (i=0; i<c->nprogs; i++) {
		ref_release(c->progs[i].prog);
	}
	ref_release(c->progs);
	c->progs = progs;
}
Пример #4
0
/* proginfo.c */
int
cmyth_get_delete_list_deprecated(cmyth_conn_t conn, char * msg, cmyth_proglist_t prog)
{
 int err=0;
 int count;
 int prog_count=0;

 if (!conn) {
 cmyth_dbg(CMYTH_DBG_ERROR, "%s: no connection\n", __FUNCTION__);
 return -1;
 }
 pthread_mutex_lock(&conn->conn_mutex);
 if ((err = cmyth_send_message(conn, msg)) < 0) {
 fprintf (stderr, "ERROR %d \n",err);
 cmyth_dbg(CMYTH_DBG_ERROR,
 "%s: cmyth_send_message() failed (%d)\n",__FUNCTION__,err);
 return err;
 }
 count = cmyth_rcv_length(conn);
 cmyth_rcv_proglist(conn, &err, prog, count);
 prog_count=cmyth_proglist_get_count(prog);
 pthread_mutex_unlock(&conn->conn_mutex);
 return prog_count;
}
Пример #5
0
static int ga_all(struct path_info *info, struct stat *stbuf)
{
	cmyth_conn_t control;
	cmyth_proglist_t list;
	int count;
	int i;

	pthread_mutex_lock(&mutex);

	if ((i=lookup_server(info->host)) < 0) {
		pthread_mutex_unlock(&mutex);
		return -ENOENT;
	}

	control = ref_hold(conn[i].control);

	if (conn[i].list == NULL) {
		list = cmyth_proglist_get_all_recorded(control);
		conn[i].list = list;
	} else {
		list = conn[i].list;
	}

	list = ref_hold(list);

	pthread_mutex_unlock(&mutex);

	stbuf->st_mode = S_IFLNK | 0444;
	stbuf->st_nlink = 1;

	count = cmyth_proglist_get_count(list);

	debug("%s(): file '%s'\n", __FUNCTION__, info->file);

	for (i=0; i<count; i++) {
		cmyth_proginfo_t prog;
		long long len;
		char *title, *s;
		char tmp[512];

		prog = cmyth_proglist_get_item(list, i);
		title = cmyth_proginfo_title(prog);
		s = cmyth_proginfo_subtitle(prog);

		snprintf(tmp, sizeof(tmp), "%s - %s.nuv", title, s);

		if (strcmp(tmp, info->file) == 0) {
			cmyth_timestamp_t ts;
			time_t t;
			char *pn;

			len = cmyth_proginfo_length(prog);
			pn = cmyth_proginfo_pathname(prog);
			debug("%s(): file '%s' len %lld\n",
			      __FUNCTION__, tmp, len);
			stbuf->st_size = strlen(pn) + 8;
			ts = cmyth_proginfo_rec_end(prog);
			t = cmyth_timestamp_to_unixtime(ts);
			stbuf->st_atime = t;
			stbuf->st_mtime = t;
			stbuf->st_ctime = t;
			ref_release(pn);
			ref_release(prog);
			ref_release(ts);
			ref_release(title);
			ref_release(s);
			ref_release(control);
			ref_release(list);
			return 0;
		}
		ref_release(prog);
		ref_release(title);
		ref_release(s);
	}

	ref_release(control);
	ref_release(list);

	return -ENOENT;
}
Пример #6
0
static int myth_readlink(const char *path, char *buf, size_t size)
{
	struct path_info info;
	int n;
	int i;
	cmyth_conn_t control;
	cmyth_proglist_t list;
	int count;

	debug("%s(): path '%s' size %lld\n", __FUNCTION__, path,
	      (long long)size);

	memset(&info, 0, sizeof(info));
	if (lookup_path(path, &info) < 0) {
		return -ENOENT;
	}

	if (strcmp(info.dir, "all") != 0) {
		return -ENOENT;
	}

	pthread_mutex_lock(&mutex);

	if ((i=lookup_server(info.host)) < 0) {
		pthread_mutex_unlock(&mutex);
		return -ENOENT;
	}

	control = ref_hold(conn[i].control);

	if (conn[i].list == NULL) {
		list = cmyth_proglist_get_all_recorded(control);
		conn[i].list = list;
	} else {
		list = conn[i].list;
	}

	list = ref_hold(list);

	pthread_mutex_unlock(&mutex);

	count = cmyth_proglist_get_count(list);

	for (i=0; i<count; i++) {
		cmyth_proginfo_t prog;
		char tmp[512];
		char *t, *s, *pn;

		prog = cmyth_proglist_get_item(list, i);
		t = cmyth_proginfo_title(prog);
		s = cmyth_proginfo_subtitle(prog);
		pn = cmyth_proginfo_pathname(prog);

		snprintf(tmp, sizeof(tmp), "%s - %s.nuv", t, s);

		if (strcmp(tmp, info.file) == 0) {
			snprintf(tmp, sizeof(tmp), "../files%s", pn);

			n = (strlen(tmp) > size) ? size : strlen(tmp);
			strncpy(buf, tmp, n);

			debug("%s(): link '%s' %d bytes\n", __FUNCTION__,
			      tmp, n);

			ref_release(t);
			ref_release(s);
			ref_release(pn);
			ref_release(prog);
			ref_release(control);
			ref_release(list);

			return 0;
		}

		ref_release(t);
		ref_release(s);
		ref_release(pn);
		ref_release(prog);
	}

	ref_release(control);
	ref_release(list);

	return -ENOENT;
}
Пример #7
0
cmyth_proginfo_t
cmyth_proginfo_get_from_timeslot(cmyth_conn_t control, uint32_t chanid, const cmyth_timestamp_t recstartts)
{
	int err = 0;
	int count, i;
	char msg[4096];
	cmyth_proginfo_t prog = NULL;
	cmyth_proglist_t list = NULL;
	char time[15];

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

	if ((err = cmyth_timestamp_to_numstring(time, recstartts)) < 0) {
		cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_timestamp_to_numstring() failed (%d)\n",
			  __FUNCTION__, err);
		return NULL;
	}

	if(control->conn_version >= 32) {
		pthread_mutex_lock(&control->conn_mutex);

		snprintf(msg, sizeof(msg), "QUERY_RECORDING TIMESLOT %"PRIu32" %s",
			chanid, time);

		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 (count < 0) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: cmyth_rcv_length() failed (%d)\n",
				  __FUNCTION__, count);
			goto out;
		}

		i = cmyth_rcv_string(control, &err, msg, sizeof(msg), count);
		if (err) {
			cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed\n",
				  __FUNCTION__);
			goto out;
		}
		count -= i;

		if (strcmp(msg, "OK") != 0) {
			cmyth_dbg(CMYTH_DBG_ERROR, "%s: didn't recieve OK as response\n",
				  __FUNCTION__);
			goto out;
		}

		prog = cmyth_proginfo_create();
		if (cmyth_rcv_proginfo(control, &err, prog, count) != count) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: cmyth_rcv_proginfo() < count\n", __FUNCTION__);
			goto out;
		}

		pthread_mutex_unlock(&control->conn_mutex);
		return prog;
		out:
		pthread_mutex_unlock(&control->conn_mutex);
		if(prog)
			ref_release(prog);
		return NULL;

	} else {

		list = cmyth_proglist_get_all_recorded(control);
		if (!list) {
			cmyth_dbg(CMYTH_DBG_ERROR, "%s: no program list\n",
				  __FUNCTION__);
		}

		count = cmyth_proglist_get_count(list);
		for (i = 0;i < count; i++) {
			prog = cmyth_proglist_get_item(list, i);
			if (!prog) {
				cmyth_dbg(CMYTH_DBG_DEBUG, "%s: no program info\n",
					  __FUNCTION__);
				continue;
			}
			if (cmyth_timestamp_compare(prog->proginfo_rec_start_ts, recstartts) != 0 ||
					prog->proginfo_chanId != chanid) {
				ref_release(prog);
				prog = NULL;
				continue;
			}
			break;
		}
		ref_release(list);
		return prog;
	}

}
Пример #8
0
cmyth_proginfo_t
cmyth_proginfo_get_from_basename(cmyth_conn_t control, const char* basename)
{
	int err = 0;
	int count, i;
	char msg[4096];
	char *base;
	cmyth_proginfo_t prog = NULL;
	cmyth_proglist_t list = NULL;

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

	/*
	 * mythbackend doesn't support spaces in basenames
	 * when doing QUERY_RECORDING.  If there are spaces, fallback
	 * to enumerating all recordings
	 */
	if(control->conn_version >= 32 && strchr(basename, ' ') == NULL) {
		pthread_mutex_lock(&control->conn_mutex);

		snprintf(msg, sizeof(msg), "QUERY_RECORDING BASENAME %s",
			 basename);

		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 (count < 0) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: cmyth_rcv_length() failed (%d)\n",
				  __FUNCTION__, count);
			goto out;
		}

		i = cmyth_rcv_string(control, &err, msg, sizeof(msg), count);
		if (err) {
			cmyth_dbg(CMYTH_DBG_ERROR, "%s: cmyth_rcv_string() failed\n",
				  __FUNCTION__);
			goto out;
		}
		count -= i;

		if (strcmp(msg, "OK") != 0) {
			cmyth_dbg(CMYTH_DBG_ERROR, "%s: didn't recieve OK as response\n",
				  __FUNCTION__);
			goto out;
		}

		prog = cmyth_proginfo_create();
		if (cmyth_rcv_proginfo(control, &err, prog, count) != count) {
			cmyth_dbg(CMYTH_DBG_ERROR,
				  "%s: cmyth_rcv_proginfo() < count\n", __FUNCTION__);
			goto out;
		}

		pthread_mutex_unlock(&control->conn_mutex);
		return prog;
		out:
		pthread_mutex_unlock(&control->conn_mutex);
		if(prog)
			ref_release(prog);
		return NULL;

	} else {

		list = cmyth_proglist_get_all_recorded(control);
		if (!list) {
			cmyth_dbg(CMYTH_DBG_ERROR, "%s: no program list\n",
				  __FUNCTION__);
		}

		count = cmyth_proglist_get_count(list);
		for (i = 0;i < count; i++) {
			prog = cmyth_proglist_get_item(list, i);
			if (!prog) {
				cmyth_dbg(CMYTH_DBG_DEBUG, "%s: no program info\n",
					  __FUNCTION__);
				continue;
			}
			base = strrchr(prog->proginfo_pathname, '/');
			if (!base || strcmp(base+1, basename) !=0) {
				ref_release(prog);
				prog = NULL;
				continue;
			}
			break;
		}
		ref_release(list);
		return prog;
	}

}
Пример #9
0
static int
show_proglist(cmyth_proglist_t episodes, int level, int show_card)
{
	int count, i;

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

	count = cmyth_proglist_get_count(episodes);

	for (i=0; i<count; i++) {
		char *title;
		char *subtitle=NULL, *channel = NULL;
		char *description=NULL, *category=NULL, *recgroup=NULL;
		char *pathname=NULL;
		cmyth_proginfo_t prog;
		int rec;

		prog = cmyth_proglist_get_item(episodes, i);

		title = cmyth_proginfo_title(prog);

		rec = cmyth_proginfo_check_recording(control, prog);

		if (level > 2) {
			subtitle = cmyth_proginfo_subtitle(prog);
			channel = cmyth_proginfo_channame(prog);
		}

		if (level > 3) {
			description = cmyth_proginfo_description(prog);
			category = cmyth_proginfo_category(prog);
			recgroup = cmyth_proginfo_recgroup(prog);
		}

		if (level > 4) {
			pathname = cmyth_proginfo_pathname(prog);
		}

		if (channel) {
			printf("\tChannel:         %s\n", channel);
		}
		if (title) {
			printf("\tTitle:           %s\n", title);
			if (rec > 0) {
				cmyth_timestamp_t end;
				char str[32];

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

				printf("\t                 RECORDING on %d until %s\n",
				       rec, str);

				ref_release(end);
			}
		}
		if (subtitle) {
			printf("\tSubtitle:        %s\n", subtitle);
		}
		if (description) {
			printf("\tDescription:     %s\n", description);
		}
		if (category) {
			printf("\tCategory:        %s\n", category);
		}
		if (recgroup) {
			printf("\tRecording Group: %s\n", recgroup);
		}
		if (pathname) {
			printf("\tPathname:        %s\n", pathname);
		}

		if (level > 4) {
			printf("\tBytes:           %lld\n",
			       cmyth_proginfo_length(prog));
		}

		if (level > 1 && show_card) {
			long card = cmyth_proginfo_card_id(prog);

			if (card == 0) {
				printf("\tRecorder:        will not record\n");
			} else {
				printf("\tRecorder:        %ld\n", card);
			}
		}

		ref_release(channel);
		ref_release(title);
		ref_release(subtitle);
		ref_release(description);
		ref_release(category);
		ref_release(recgroup);
		ref_release(pathname);

		ref_release(prog);
	}

	ref_release(episodes);

	return count;
}
Пример #10
0
int
main(int argc, char **argv)
{
	int c, opt_index;
	int verbose = 0;
	int opt_e = 0, opt_r = 0, opt_s = 0, opt_u = 0;
	char *server;

	while ((c=getopt_long(argc, argv, "hersuv", opts, &opt_index)) != -1) {
		switch (c) {
		case 'h':
			print_help(argv[0]);
			exit(0);
			break;
		case 'e':
			opt_e = 1;
			break;
		case 'r':
			opt_r = 1;
			break;
		case 's':
			opt_s = 1;
			break;
		case 'u':
			opt_u = 1;
			break;
		case 'v':
			verbose++;
			break;
		default:
			print_help(argv[0]);
			exit(1);
			break;
		}
	}

	if (optind == argc) {
		fprintf(stderr, "no server given!\n");
		return -1;
	}

	server = argv[optind];

	if (!is_alive(server)) {
		printf("%s is not responding.\n", server);
		return 1;
	}

	printf("%s is alive.\n", server);

	if (cmyth_conn_block_shutdown(control) < 0) {
		printf("Failed to block backend shutdown!\n");
	}

	if (verbose) {
		int version, count;
		cmyth_proglist_t list;
		long long total, used;

		printf("libcmyth version %s\n", cmyth_version());
		printf("librefmem version %s\n", ref_version());

		version = cmyth_conn_get_protocol_version(control);

		printf("\tprotocol version: %d\n", version);

		list = cmyth_proglist_get_all_recorded(control);
		count = cmyth_proglist_get_count(list);

		printf("\trecordings: %d\n", count);

		if (cmyth_conn_get_freespace(control, &total, &used) == 0) {
			printf("\ttotal space: %lld bytes\n", total);
			printf("\tused space:  %lld bytes\n", used);
		}

		get_event(server);

		ref_release(list);
	}

	if (opt_e) {
		get_recordings(verbose);
	}

	if (opt_r) {
		get_recorders(verbose);
	}

	if (opt_s) {
		get_scheduled(verbose);
	}

	if (opt_u) {
		get_upcoming(verbose);
	}

	if (cmyth_conn_allow_shutdown(control) < 0) {
		printf("Failed to allow backend shutdown!\n");
	}

	ref_release(control);

	if (verbose > 1) {
		unsigned int refs, bytes;

		ref_get_usage(&refs, &bytes);

		printf("Refmem: refs  %d\n", refs);
		printf("Refmem: bytes %d\n", bytes);

		if (refs > 0) {
			ref_alloc_show();
		}
	}

	return 0;
}
Пример #11
0
static int ga_files(struct path_info *info, struct stat *stbuf)
{
	cmyth_conn_t control;
	cmyth_proglist_t list;
	int count;
	int i;

	pthread_mutex_lock(&mutex);

	if ((i=lookup_server(info->host)) < 0) {
		pthread_mutex_unlock(&mutex);
		return -ENOENT;
	}

	control = ref_hold(conn[i].control);

	if (conn[i].list == NULL) {
		list = cmyth_proglist_get_all_recorded(control);
		conn[i].list = list;
		parse_progs(conn+i);
	} else {
		list = conn[i].list;
	}

	list = ref_hold(list);

	pthread_mutex_unlock(&mutex);

	stbuf->st_mode = S_IFREG | 0444;
	stbuf->st_nlink = 1;

	count = cmyth_proglist_get_count(list);

	debug("%s(): file '%s'\n", __FUNCTION__, info->file);

	for (i=0; i<count; i++) {
		cmyth_proginfo_t prog;
		long long len;
		char *pn;

		prog = cmyth_proglist_get_item(list, i);
		pn = cmyth_proginfo_pathname(prog);

		if (strcmp(pn+1, info->file) == 0) {
			cmyth_timestamp_t ts;
			time_t t;
			len = cmyth_proginfo_length(prog);
			debug("%s(): file '%s' len %lld\n",
			      __FUNCTION__, pn+1, len);
			stbuf->st_size = len;
			stbuf->st_blksize = MAX_BSIZE;
			stbuf->st_blocks = len / MAX_BSIZE;
			if ((len * MAX_BSIZE) != stbuf->st_blocks) {
				stbuf->st_blocks++;
			}
			ts = cmyth_proginfo_rec_end(prog);
			t = cmyth_timestamp_to_unixtime(ts);
			stbuf->st_atime = t;
			stbuf->st_mtime = t;
			stbuf->st_ctime = t;
			ref_release(prog);
			ref_release(pn);
			ref_release(ts);
			ref_release(control);
			ref_release(list);
			return 0;
		}
		ref_release(prog);
		ref_release(pn);
	}

	ref_release(control);
	ref_release(list);

	return -ENOENT;
}
Пример #12
0
static int
rd_all(struct path_info *info, void *buf, fuse_fill_dir_t filler,
       off_t offset, struct fuse_file_info *fi)
{
	int i;
	cmyth_conn_t control;
	cmyth_proglist_t list;
	int count;
	struct myth_conn *mc;

	pthread_mutex_lock(&mutex);

	if ((i=lookup_server(info->host)) < 0) {
		pthread_mutex_unlock(&mutex);
		return 0;
	}

	control = ref_hold(conn[i].control);

	if (conn[i].list == NULL) {
		list = cmyth_proglist_get_all_recorded(control);
		conn[i].list = list;
		parse_progs(conn+i);
	} else {
		list = conn[i].list;
	}

	mc = conn+i;

	list = ref_hold(list);

	pthread_mutex_unlock(&mutex);

	count = cmyth_proglist_get_count(list);

	char *name[count];

	for (i=0; i<count; i++) {
		cmyth_proginfo_t prog;
		long long len;
		char *fn, *pn, *t, *s;

		prog = cmyth_proglist_get_item(list, i);
		pn = cmyth_proginfo_pathname(prog);
		t = cmyth_proginfo_title(prog);
		s = cmyth_proginfo_subtitle(prog);
		len = cmyth_proginfo_length(prog);

		if (mc->progs[i].suffix == 0) {
			name[i] = ref_sprintf("%s - %s.nuv", t, s);
		} else {
			name[i] = ref_sprintf("%s - %s (%d).nuv", t, s,
					      mc->progs[i].suffix);
		}

		fn = pn+1;

		debug("%s(): file '%s' len %lld\n", __FUNCTION__, fn, len);
		filler(buf, name[i], NULL, 0);

		ref_release(prog);
		ref_release(pn);
		ref_release(t);
		ref_release(s);
	}

	for (i=0; i<count; i++) {
		ref_release(name[i]);
	}

	ref_release(control);
	ref_release(list);

	return 0;
}
Пример #13
0
static int
rd_shows(struct path_info *info, void *buf, fuse_fill_dir_t filler,
       off_t offset, struct fuse_file_info *fi)
{
	int i;
	cmyth_conn_t control;
	cmyth_proglist_t list;
	int count;

	pthread_mutex_lock(&mutex);

	if ((i=lookup_server(info->host)) < 0) {
		pthread_mutex_unlock(&mutex);
		return 0;
	}

	control = ref_hold(conn[i].control);

	if (conn[i].list == NULL) {
		list = cmyth_proglist_get_all_recorded(control);
		conn[i].list = list;
	} else {
		list = conn[i].list;
	}

	list = ref_hold(list);

	pthread_mutex_unlock(&mutex);

	count = cmyth_proglist_get_count(list);
  if(info->subdir) {
    for (i=0; i<count; i++) {
      cmyth_proginfo_t prog;
      long long len;
      char *fn, *pn, *t, *s;
      struct stat st;
      char tmp[512];

      prog = cmyth_proglist_get_item(list, i);
      t = cmyth_proginfo_title(prog);
      if(strcmp(t, info->subdir) == 0) {
        pn = cmyth_proginfo_pathname(prog);
        s = cmyth_proginfo_subtitle(prog);
        len = cmyth_proginfo_length(prog);
      
        fn = pn+1;

        snprintf(tmp, sizeof(tmp), "%s.nuv", s);      
        memset(&st, 0, sizeof(st));
        st.st_mode = S_IFLNK | 0444;
        st.st_size = strlen(pn) + 8;
        
        debug("%s(): file '%s' len %lld\n", __FUNCTION__, fn, len);
        filler(buf, tmp, &st, 0);

        snprintf(tmp, sizeof(tmp), "%s.nuv.png", s);      
        memset(&st, 0, sizeof(st));
        st.st_mode = S_IFLNK | 0444;
        st.st_size = strlen(pn) + 8;
        
        debug("%s(): file '%s' len %lld\n", __FUNCTION__, fn, len);
        filler(buf, tmp, &st, 0);

        ref_release(pn);
        ref_release(s);
      }
      ref_release(prog);
      ref_release(t);
    }
  } else {
    char** seen = malloc(sizeof(char*) * count);
    int seen_counter, k;

    seen_counter = 0;
    memset(seen, count, sizeof(char*));
    
    for (i=0; i<count; i++) {
      cmyth_proginfo_t prog;
      char *t;
      struct stat st;
      char found;
      prog = cmyth_proglist_get_item(list, i);
      t = cmyth_proginfo_title(prog);
      
      found = 0;
      for(k=0; k<seen_counter; k++) {
        if(strcmp(seen[k], t) == 0) {
          found = 1;
          break;
        }
      }
      
      if(!found) {
        seen[seen_counter] = strdup(t);
        seen_counter++;
        
        st.st_mode = S_IFDIR | 0555;
        st.st_nlink = 2;
        
        debug("%s(): dir '%s'\n", __FUNCTION__, t);
        filler(buf, t, &st, 0);
      }
      ref_release(prog);
      ref_release(t);
    }
    
    for(i=0; i<seen_counter; i++) {
      free(seen[i]);
    }
    free(seen);
  }

	ref_release(control);
	ref_release(list);

	return 0;
}