Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

htsp: misc cleanup

  • Loading branch information...
commit 9bc3c3dd52efabd55e842056fcc5ef0616e5935f 1 parent 15a0d79
@andoma authored
View
1  glwthemes/default/pages/directory.view
@@ -17,6 +17,7 @@ multiopt($view.path,
translate($page.model.contents, void,
"album", link(_("Album"), "album.view"),
+ "tvchannels", link(_("Tvchannels"), "tvchannels.view"),
"images", link(_("Images"), "images.view")
),
select($page.model.contents == "images",
View
41 glwthemes/default/pages/iteminfo/tvchannel.view
@@ -0,0 +1,41 @@
+
+widget(container_y, {
+ .spacing = 4;
+ widget(label, {
+ .caption = $args.metadata.title;
+ .ellipsize = true;
+ .sizeScale = 1.5;
+ .filterConstraintX = true;
+ shadow: true;
+ outline: true;
+ });
+
+
+ widget(list_y, {
+ &view.focused = focusedChild();
+
+ cloner($args.metadata.events.list, container_x, {
+
+ widget(label, {
+ .filterConstraintX = true;
+ .weight = 0.3;
+ .caption = strftime($self.start, "%H:%M");
+ shadow: true;
+ outline: true;
+ });
+
+ widget(label, {
+ .caption = $self.title;
+ .ellipsize = true;
+ .focusable = true;
+ .focusOnClick = true;
+ .color = select(isFocused(), 1.0, 0.6);
+ shadow: true;
+ outline: true;
+ });
+
+ });
+ });
+});
+
+
View
3  glwthemes/default/pages/list.view
@@ -43,6 +43,7 @@ widget(keyintercept, {
"action", "action",
"info", "info",
"plugin", "plugin",
+ "tvchannel", "tvchannel",
"keymapentry", "keymapentry"
)
+ ".view";
@@ -81,6 +82,7 @@ widget(keyintercept, {
source: translate($clone.focused.type, "",
"video", "iteminfo/video.view",
"image", "iteminfo/image.view",
+ "tvchannel", "iteminfo/tvchannel.view",
"plugin", "iteminfo/plugin.view");
.args ?= $clone.focused;
});
@@ -88,6 +90,7 @@ widget(keyintercept, {
$view.showRightPane = translate($clone.focused.type, 0,
"video", 1,
"plugin", 1,
+ "tvchannel", 1,
"image", 1
);
});
View
29 glwthemes/default/pages/listitems/tvchannel.view
@@ -0,0 +1,29 @@
+#import "theme://common.view"
+
+widget(backdrop, {
+
+ source: "highlight.png";
+ autoRefocusable: true;
+ focusable: true;
+ focusOnClick: true;
+ onEvent(activate, navOpen($self.url, void, void, $parent.model));
+
+ alphaSelf: iir(isFocused() * 1, 8) + isHovered() * 0.1;
+
+ widget(container_x, {
+ spacing: 13;
+ widget(icon, {
+ align: left;
+ color: select(isFocused(), 1.0, 0.6);
+ source: "dataroot://resources/svg/Display.svg";
+ shadow: true;
+ });
+
+ widget(label, {
+ filterConstraintX: true;
+ TextStyleItem();
+ color: select(isFocused(), 1.0, 0.6);
+ caption: $self.metadata.title;
+ });
+ });
+});
View
37 glwthemes/default/pages/smallitems/tvchannel.view
@@ -0,0 +1,37 @@
+widget(container_z, {
+ autoRefocusable: true;
+ focusable: true;
+ width: $ui.size * 8;
+
+
+ widget(stencil, {
+ source: "theme://graphics/stencil.png";
+ widget(container_z, {
+ widget(quad, {
+ color: 0;
+ });
+
+ widget(image, {
+ align: bottom;
+ width: $ui.size * 8;
+ $clone.ready = isReady();
+ source: "thumb://" + $self.url;
+ color: isFocused() + 0.5;
+ });
+
+ widget(container_y, {
+ space(1);
+ widget(throbber, {
+ alpha: iir(!$clone.ready, 8);
+ });
+ space(1);
+ });
+ });
+ });
+
+ widget(backdrop, {
+ source: "theme://graphics/border32.png";
+ border: 16;
+ alpha: iir(isFocused(), 8) + 0.1;
+ });
+});
View
88 glwthemes/default/pages/tvchannels.view
@@ -0,0 +1,88 @@
+#import "theme://common.view"
+
+widget(container_y, {
+
+ alpha: 1 - iir(clamp(getLayer(), 0, 1), 7) * 0.5;
+ blur: iir(clamp(getLayer(), 0, 1), 7);
+
+ PageTitle($page.model.metadata.title);
+ VerticalSeparator();
+
+ widget(dummy, {
+ height: $ui.size * 2;
+ });
+
+ widget(container_x, {
+ weight: 2;
+ });
+
+ widget(dummy, {
+ height: $ui.size * 2;
+ });
+
+ widget(fader, {
+ filterConstraintY: true;
+ weight: 1;
+ plane: [0,1,0,1];
+ alphaFallOff: 1;
+ blurFallOff: 0.2;
+ widget(mirror, {
+ alpha: 0.4;
+
+ widget(list_x, {
+ spacing: 5;
+
+ scrollThreshold: $ui.width / 10;
+
+
+ &self.focused = focusedChild();
+
+ cloner($page.model.nodes, container_z, {
+ autoRefocusable: true;
+ focusable: true;
+ width: $ui.size * 12;
+ $clone.fd = focusDistance();
+
+ widget(stencil, {
+ source: "theme://graphics/stencil.png";
+ widget(container_z, {
+ widget(quad, {
+ color: 0;
+ alpha: 0.5;
+ });
+
+ widget(image, {
+ align: bottom;
+ width: $ui.size * 8;
+ $clone.ready = isReady();
+ source: $self.metadata.icon;
+ color: isFocused() + 0.5;
+ });
+
+
+ widget(label, {
+ padding: [0,0,0,$ui.size*0.5];
+ align: bottom;
+ caption: $self.metadata.title;
+ shadow: true;
+ outline: true;
+ });
+
+ });
+ });
+
+ widget(backdrop, {
+ source: "theme://graphics/border32.png";
+ border: 16;
+ alpha: iir(isFocused(), 8) + 0.1;
+ });
+ });
+ });
+ });
+ });
+
+ widget(dummy, {
+ height: $ui.size * 4;
+ });
+});
+
View
5 src/backend/backend.c
@@ -86,7 +86,8 @@ backend_play_video(const char *url, struct media_pipe *mp,
int flags, int priority,
char *errbuf, size_t errlen,
const char *mimetype,
- const char *canonical_url)
+ const char *canonical_url,
+ video_queue_t *vq)
{
backend_t *nb = backend_canhandle(url);
@@ -98,7 +99,7 @@ backend_play_video(const char *url, struct media_pipe *mp,
mp_set_url(mp, canonical_url);
return nb->be_play_video(url, mp, flags, priority, errbuf, errlen, mimetype,
- canonical_url);
+ canonical_url, vq);
}
View
7 src/backend/backend.h
@@ -26,6 +26,7 @@ struct media_pipe;
struct navigator;
struct event;
struct image_meta;
+typedef struct video_queue video_queue_t;
typedef int (be_load_cb_t)(void *opaque, int loaded, int total);
@@ -73,7 +74,8 @@ typedef struct backend {
int flags, int priority,
char *errbuf, size_t errlen,
const char *mimetype,
- const char *canonical_url);
+ const char *canonical_url,
+ video_queue_t *vq);
struct event *(*be_play_audio)(const char *url, struct media_pipe *mp,
char *errbuf, size_t errlen, int paused,
@@ -111,7 +113,8 @@ struct event *backend_play_video(const char *url, struct media_pipe *mp,
int flags, int priority,
char *errbuf, size_t errlen,
const char *mimetype,
- const char *canonical_url)
+ const char *canonical_url,
+ video_queue_t *vq)
__attribute__ ((warn_unused_result));
View
3  src/backend/dvd/linux_dvd.c
@@ -183,7 +183,8 @@ be_dvd_play(const char *url, media_pipe_t *mp,
int flags, int priority,
char *errstr, size_t errlen,
const char *mimetype,
- const char *canonical_url)
+ const char *canonical_url,
+ struct video_queue *vq)
{
event_t *e;
if(strncmp(url, "dvd:", strlen("dvd:"))) {
View
383 src/backend/htsp/htsp.c
@@ -37,6 +37,7 @@
#include "media.h"
#include "misc/string.h"
#include "misc/sha.h"
+#include "video/video_playback.h"
#define EPG_TAIL 20 // How many EPG entries to keep per channel
@@ -49,7 +50,7 @@ TAILQ_HEAD(htsp_msg_queue, htsp_msg);
LIST_HEAD(htsp_subscription_list, htsp_subscription);
LIST_HEAD(htsp_subscription_stream_list, htsp_subscription_stream);
LIST_HEAD(htsp_tag_list, htsp_tag);
-TAILQ_HEAD(htsp_channel_queue, htsp_channel);
+LIST_HEAD(htsp_channel_list, htsp_channel);
static struct htsp_connection_list htsp_connections;
@@ -70,10 +71,9 @@ typedef struct htsp_tag {
*
*/
typedef struct htsp_channel {
- TAILQ_ENTRY(htsp_channel) ch_link;
+ LIST_ENTRY(htsp_channel) ch_link;
int ch_id;
char *ch_title;
- int ch_channel_num;
prop_t *ch_root;
prop_t *ch_prop_icon;
@@ -123,7 +123,7 @@ typedef struct htsp_connection {
hts_mutex_t hc_meta_mutex;
struct htsp_tag_list hc_tags;
- struct htsp_channel_queue hc_channels;
+ struct htsp_channel_list hc_channels;
} htsp_connection_t;
@@ -195,7 +195,7 @@ htsp_recv(htsp_connection_t *hc)
if(l > 16 * 1024 * 1024)
return NULL;
- buf = malloc(l);
+ buf = mymalloc(l);
if(buf == NULL || tc->read(tc, buf, l, 1, NULL, NULL) < 0) {
free(buf);
@@ -268,10 +268,6 @@ htsp_reqreply(htsp_connection_t *hc, htsmsg_t *m)
free(password);
}
-
-
-
-
if(htsmsg_binary_serialize(m, &buf, &len, -1) < 0) {
htsmsg_destroy(m);
return NULL;
@@ -400,9 +396,8 @@ update_events(htsp_connection_t *hc, prop_t *metadata, int id, int next)
prop_t *events = prop_create(metadata, "list");
prop_t *current_event = prop_create(metadata, "current");
prop_t *next_event = prop_create(metadata, "next");
- char buf[10];
- uint32_t u32;
int linkstate = 0;
+ htsmsg_field_t *f;
if(id == 0) {
@@ -416,40 +411,55 @@ update_events(htsp_connection_t *hc, prop_t *metadata, int id, int next)
linkstate = 1;
}
+ m = htsmsg_create_map();
+ htsmsg_add_str(m, "method", "getEvents");
+ htsmsg_add_u32(m, "eventId", id);
+ htsmsg_add_u32(m, "numFollowing", EPG_TAIL);
+
+ if((m = htsp_reqreply(hc, m)) != NULL) {
+
+ htsmsg_t *events = htsmsg_get_list(m, "events");
+ f = events ? TAILQ_FIRST(&events->hm_fields) : NULL;
+
+ } else {
+ f = NULL;
+ }
+
+
for(i = 0; i < EPG_TAIL; i++) {
- snprintf(buf, sizeof(buf), "id%d", i);
+ char buf[10];
+ uint32_t u32;
+ snprintf(buf, sizeof(buf), "%d", i);
- if(id != 0) {
- m = htsmsg_create_map();
- htsmsg_add_str(m, "method", "getEvent");
- htsmsg_add_u32(m, "eventId", id);
-
- if((m = htsp_reqreply(hc, m)) != NULL) {
-
- prop_t *e = prop_create(events, buf);
- prop_set_string(prop_create(e, "title"), htsmsg_get_str(m, "title"));
- prop_set_string(prop_create(e, "description"),
- htsmsg_get_str(m, "description"));
- if(!htsmsg_get_u32(m, "start", &u32))
- prop_set_int(prop_create(e, "start"), u32);
-
- if(!htsmsg_get_u32(m, "stop", &u32))
- prop_set_int(prop_create(e, "stop"), u32);
-
- switch(linkstate) {
- case 0:
- prop_link(e, current_event);
- break;
- case 1:
- prop_link(e, next_event);
- break;
- }
- linkstate++;
- id = htsmsg_get_u32_or_default(m, "nextEventId", 0);
- continue;
- } else {
- id = 0;
+ if(f != NULL && f->hmf_type != HMF_MAP)
+ f = NULL;
+
+ if(f != NULL) {
+
+ m = htsmsg_get_map_by_field(f);
+
+ prop_t *e = prop_create(events, buf);
+ prop_set_string(prop_create(e, "title"), htsmsg_get_str(m, "title"));
+ prop_set_string(prop_create(e, "description"),
+ htsmsg_get_str(m, "description"));
+ if(!htsmsg_get_u32(m, "start", &u32))
+ prop_set_int(prop_create(e, "start"), u32);
+
+ if(!htsmsg_get_u32(m, "stop", &u32))
+ prop_set_int(prop_create(e, "stop"), u32);
+
+ switch(linkstate) {
+ case 0:
+ prop_link(e, current_event);
+ break;
+ case 1:
+ prop_link(e, next_event);
+ break;
}
+ linkstate++;
+
+ f = TAILQ_NEXT(f, hmf_link);
+ continue;
}
prop_destroy_by_name(events, buf);
@@ -470,30 +480,37 @@ update_events(htsp_connection_t *hc, prop_t *metadata, int id, int next)
*
*/
static htsp_channel_t *
-htsp_channel_get(htsp_connection_t *hc, int id)
+htsp_channel_get(htsp_connection_t *hc, int id, int create)
{
htsp_channel_t *ch;
-
- TAILQ_FOREACH(ch, &hc->hc_channels, ch_link)
+ char txt[256];
+ LIST_FOREACH(ch, &hc->hc_channels, ch_link)
if(ch->ch_id == id)
- break;
- return ch;
-}
+ return ch;
+ if(!create)
+ return NULL;
-/**
- *
- */
-static int
-channel_compar(htsp_channel_t *a, htsp_channel_t *b)
-{
- if(a->ch_channel_num == b->ch_channel_num)
- return dictcmp(a->ch_title ?: "", b->ch_title ?: "");
- if(a->ch_channel_num < b->ch_channel_num)
- return -1;
- if(a->ch_channel_num > b->ch_channel_num)
- return 1;
- return 0;
+ ch = calloc(1, sizeof(htsp_channel_t));
+
+ snprintf(txt, sizeof(txt), "%d", id);
+ prop_t *p = ch->ch_root = prop_create_root(txt);
+
+ snprintf(txt, sizeof(txt), "htsp://%s:%d/channel/%d",
+ hc->hc_hostname, hc->hc_port, id);
+ prop_set_string(prop_create(ch->ch_root, "url"), txt);
+
+ prop_t *m = prop_create(p, "metadata");
+ ch->ch_prop_icon = prop_create(m, "icon");
+ ch->ch_prop_title = prop_create(m, "title");
+ ch->ch_prop_channelNumber = prop_create(m, "channelNumber");
+ ch->ch_prop_events = prop_create(m, "events");
+
+ prop_set_string(prop_create(ch->ch_root, "type"), "tvchannel");
+
+ LIST_INSERT_HEAD(&hc->hc_channels, ch, ch_link);
+ ch->ch_id = id;
+ return ch;
}
@@ -505,10 +522,9 @@ htsp_channelAddUpdate(htsp_connection_t *hc, htsmsg_t *m, int create)
{
uint32_t id, next;
int chnum;
- prop_t *p;
char txt[200];
const char *title, *icon;
- htsp_channel_t *ch, *n;
+ htsp_channel_t *ch;
if(htsmsg_get_u32(m, "channelId", &id))
return;
@@ -516,80 +532,34 @@ htsp_channelAddUpdate(htsp_connection_t *hc, htsmsg_t *m, int create)
title = htsmsg_get_str(m, "channelName");
icon = htsmsg_get_str(m, "channelIcon");
chnum = htsmsg_get_s32_or_default(m, "channelNumber", -1);
-
- if(chnum == 0)
- chnum = INT32_MAX;
-
snprintf(txt, sizeof(txt), "%d", id);
hts_mutex_lock(&hc->hc_meta_mutex);
if(create) {
- ch = calloc(1, sizeof(htsp_channel_t));
- p = ch->ch_root = prop_create_root(txt);
-
- prop_t *m = prop_create(p, "metadata");
- ch->ch_prop_icon = prop_create(m, "icon");
- ch->ch_prop_title = prop_create(m, "title");
- ch->ch_prop_channelNumber = prop_create(m, "channelNumber");
- ch->ch_prop_events = prop_create(m, "events");
-
- ch->ch_id = id;
-
- snprintf(txt, sizeof(txt), "htsp://%s:%d/channel/%d",
- hc->hc_hostname, hc->hc_port, id);
-
- prop_set_string(prop_create(p, "url"), txt);
- prop_set_string(prop_create(p, "type"), "tvchannel");
-
- ch->ch_channel_num = chnum;
- mystrset(&ch->ch_title, title);
-
- TAILQ_INSERT_SORTED(&hc->hc_channels, ch, ch_link, channel_compar);
- n = TAILQ_NEXT(ch, ch_link);
-
- if(prop_set_parent_ex(p, hc->hc_channels_nodes,
- n ? n->ch_root : NULL, NULL))
+ ch = htsp_channel_get(hc, id, 1);
+ if(prop_set_parent(ch->ch_root, hc->hc_channels_nodes))
abort();
} else {
- int move = 0;
-
- ch = htsp_channel_get(hc, id);
+ ch = htsp_channel_get(hc, id, 0);
if(ch == NULL) {
TRACE(TRACE_ERROR, "HTSP", "Got update for unknown channel %d", id);
hts_mutex_unlock(&hc->hc_meta_mutex);
return;
}
-
- p = ch->ch_root;
-
- if(title != NULL) {
- move = 1;
- mystrset(&ch->ch_title, title);
- }
-
- if(chnum != -1) {
- move = 1;
- ch->ch_channel_num = chnum;
- }
-
- if(move) {
- TAILQ_REMOVE(&hc->hc_channels, ch, ch_link);
- TAILQ_INSERT_SORTED(&hc->hc_channels, ch, ch_link, channel_compar);
- n = TAILQ_NEXT(ch, ch_link);
- prop_move(p, n ? n->ch_root : NULL);
- }
}
hts_mutex_unlock(&hc->hc_meta_mutex);
if(icon != NULL)
prop_set_string(ch->ch_prop_icon, icon);
- if(title != NULL)
+ if(title != NULL) {
+ mystrset(&ch->ch_title, title);
prop_set_string(ch->ch_prop_title, title);
+ }
if(chnum != -1)
prop_set_int(ch->ch_prop_channelNumber, chnum);
@@ -606,10 +576,10 @@ htsp_channelAddUpdate(htsp_connection_t *hc, htsmsg_t *m, int create)
*
*/
static void
-channel_destroy(htsp_connection_t *hc, htsp_channel_t *ch)
+channel_destroy(htsp_channel_t *ch)
{
prop_destroy(ch->ch_root);
- TAILQ_REMOVE(&hc->hc_channels, ch, ch_link);
+ LIST_REMOVE(ch, ch_link);
free(ch->ch_title);
free(ch);
}
@@ -629,8 +599,8 @@ htsp_channelDelete(htsp_connection_t *hc, htsmsg_t *m)
hts_mutex_lock(&hc->hc_meta_mutex);
- if((ch = htsp_channel_get(hc, id)) != NULL)
- channel_destroy(hc, ch);
+ if((ch = htsp_channel_get(hc, id, 0)) != NULL)
+ channel_destroy(ch);
hts_mutex_unlock(&hc->hc_meta_mutex);
}
@@ -643,8 +613,8 @@ static void
channel_delete_all(htsp_connection_t *hc)
{
htsp_channel_t *ch;
- while((ch = TAILQ_FIRST(&hc->hc_channels)) != NULL)
- channel_destroy(hc, ch);
+ while((ch = LIST_FIRST(&hc->hc_channels)) != NULL)
+ channel_destroy(ch);
}
@@ -752,8 +722,9 @@ htsp_tagAddUpdate(htsp_connection_t *hc, htsmsg_t *m, int create)
prop_set_string(prop_create(ch, "type"), "tvchannel");
prop_set_stringf(prop_create(ch, "url"),
- "htsp://%s:%d/tagchannel/%s/%" PRId64,
- hc->hc_hostname, hc->hc_port, id, f->hmf_s64);
+ "htsp://%s:%d/channel/%" PRId64,
+ hc->hc_hostname, hc->hc_port, f->hmf_s64);
+
prop_t *orig = prop_create(hc->hc_channels_nodes, txt);
prop_link(prop_create(orig, "metadata"), prop_create(ch, "metadata"));
@@ -1136,7 +1107,7 @@ htsp_connection_find(const char *url, char *path, size_t pathlen,
hts_mutex_init(&hc->hc_subscription_mutex);
hts_mutex_init(&hc->hc_meta_mutex);
- TAILQ_INIT(&hc->hc_channels);
+ LIST_INIT(&hc->hc_channels);
hc->hc_tc = tc;
hc->hc_seq_generator = 1;
@@ -1163,7 +1134,8 @@ htsp_connection_find(const char *url, char *path, size_t pathlen,
*
*/
static void
-make_model(prop_t *parent, const char *title, prop_t *nodes)
+make_model(prop_t *parent, const char *title, prop_t *nodes,
+ const char *contents)
{
prop_t *model = prop_create(parent, "model");
prop_t *meta;
@@ -1176,6 +1148,7 @@ make_model(prop_t *parent, const char *title, prop_t *nodes)
prop_create(model, "filter"),
PROP_NF_AUTODESTROY);
prop_set_int(prop_create(model, "canFilter"), 1);
+ prop_set_string(prop_create(model, "contents"), contents);
prop_nf_release(pnf);
@@ -1188,7 +1161,7 @@ make_model(prop_t *parent, const char *title, prop_t *nodes)
*
*/
static void
-make_model2(prop_t *parent, prop_t *sourcemodel)
+make_model2(prop_t *parent, prop_t *sourcemodel, const char *contents)
{
prop_t *model = prop_create(parent, "model");
prop_t *meta;
@@ -1201,6 +1174,7 @@ make_model2(prop_t *parent, prop_t *sourcemodel)
prop_create(model, "filter"),
PROP_NF_AUTODESTROY);
prop_set_int(prop_create(model, "canFilter"), 1);
+ prop_set_string(prop_create(model, "contents"), contents);
prop_nf_release(pnf);
@@ -1226,22 +1200,21 @@ be_htsp_open(prop_t *page, const char *url)
TRACE(TRACE_DEBUG, "HTSP", "Open %s", url);
- if(!strncmp(path, "/channel/", strlen("/channel/")) ||
- !strncmp(path, "/tagchannel/", strlen("/tagchannel/")))
+ if(!strncmp(path, "/channel/", strlen("/channel/")))
return backend_open_video(page, url);
if(!strcmp(path, "/channels")) {
- make_model(page, "Channels", hc->hc_channels_nodes);
+ make_model(page, "Channels", hc->hc_channels_nodes, "tvchannels");
} else if(!strncmp(path, "/tag/", strlen("/tag/"))) {
prop_t *model;
model = prop_create(hc->hc_tags_nodes, path + strlen("/tag/"));
- make_model2(page, model);
+ make_model2(page, model, "tvchannels");
} else if(!strcmp(path, "")) {
- make_model(page, "Tags", hc->hc_tags_nodes);
+ make_model(page, "Tags", hc->hc_tags_nodes, NULL);
} else {
nav_open_errorf(page, _("Invalid HTSP URL"));
@@ -1298,12 +1271,11 @@ set_channel(htsp_connection_t *hc, htsp_subscription_t *hs, int chid,
htsp_channel_t *ch;
hts_mutex_lock(&hc->hc_meta_mutex);
- if((ch = htsp_channel_get(hc, chid)) != NULL) {
+ if((ch = htsp_channel_get(hc, chid, 1)) != NULL) {
prop_t *m = hs->hs_mp->mp_prop_metadata;
-
+
TRACE(TRACE_DEBUG, "HTSP", "Subscribing to channel %s", ch->ch_title);
-
prop_link(ch->ch_prop_title, prop_create(m, "title"));
prop_link(ch->ch_prop_icon, prop_create(m, "icon"));
prop_link(ch->ch_prop_channelNumber, prop_create(m, "channelNumber"));
@@ -1322,71 +1294,20 @@ set_channel(htsp_connection_t *hc, htsp_subscription_t *hs, int chid,
*/
static int
zap_channel(htsp_connection_t *hc, htsp_subscription_t *hs,
- int chid, char *errbuf, size_t errlen, const char *tag, int delta,
- char **name)
+ char *errbuf, size_t errlen, int reverse,
+ char **name, video_queue_t *vq, rstr_t **url)
{
- htsp_tag_t *ht;
- htsp_channel_t *ch;
- int p, newch;
htsmsg_t *m;
const char *err;
- hts_mutex_lock(&hc->hc_meta_mutex);
-
- if(tag != NULL) {
-
- LIST_FOREACH(ht, &hc->hc_tags, ht_link)
- if(!strcmp(ht->ht_id, tag))
- break;
-
- if(ht == NULL) {
- hts_mutex_unlock(&hc->hc_meta_mutex);
- return chid;
- }
-
- for(p = 0; p < ht->ht_num_channels; p++)
- if(ht->ht_channels[p] == chid)
- break;
-
- if(p == ht->ht_num_channels) {
- hts_mutex_unlock(&hc->hc_meta_mutex);
- return chid;
- }
-
- p += delta;
- if(p == -1)
- p = ht->ht_num_channels - 1;
- else if(p == ht->ht_num_channels)
- p = 0;
-
- newch = ht->ht_channels[p];
-
- } else {
-
- if((ch = htsp_channel_get(hc, chid)) == NULL) {
- hts_mutex_unlock(&hc->hc_meta_mutex);
- return chid;
- }
-
- if(delta == 1) {
- if((ch = TAILQ_NEXT(ch, ch_link)) == NULL)
- ch = TAILQ_FIRST(&hc->hc_channels);
- } else {
- if((ch = TAILQ_PREV(ch, htsp_channel_queue, ch_link)) == NULL)
- ch = TAILQ_LAST(&hc->hc_channels, htsp_channel_queue);
- }
-
- if(ch == NULL) {
- hts_mutex_unlock(&hc->hc_meta_mutex);
- return chid;
- }
-
- newch = ch->ch_id;
- }
-
-
+ rstr_t *tmp = video_queue_find_next(vq, rstr_get(*url), reverse, 1);
+ if(tmp == NULL)
+ return 0;
+ const char *q = strstr(rstr_get(tmp), "/channel/");
+ if(q == NULL)
+ return 0;
- hts_mutex_unlock(&hc->hc_meta_mutex);
+ int newch = atoi(q + strlen("/channel/"));
// Stop current
@@ -1424,12 +1345,15 @@ zap_channel(htsp_connection_t *hc, htsp_subscription_t *hs,
return -1;
}
+ rstr_set(url, tmp);
+
htsmsg_destroy(m);
set_channel(hc, hs, newch, name);
- return newch;
+ return 0;
}
+
/**
*
*/
@@ -1453,8 +1377,9 @@ prio_to_weight(int p)
*/
static event_t *
htsp_subscriber(htsp_connection_t *hc, htsp_subscription_t *hs,
- int chid, char *errbuf, size_t errlen, const char *tag,
- int primary, int priority)
+ char *errbuf, size_t errlen,
+ int primary, int priority, video_queue_t *vq,
+ const char *url)
{
event_t *e;
htsmsg_t *m;
@@ -1462,6 +1387,11 @@ htsp_subscriber(htsp_connection_t *hc, htsp_subscription_t *hs,
const char *err;
char *name = NULL;
+ const char *q = strstr(url, "/channel/");
+ if(q == NULL)
+ return NULL;
+ int chid = atoi(q + strlen("/channel/"));
+
m = htsmsg_create_map();
htsmsg_add_str(m, "method", "subscribe");
@@ -1484,7 +1414,7 @@ htsp_subscriber(htsp_connection_t *hc, htsp_subscription_t *hs,
prop_set_string(mp->mp_prop_playstatus, "play");
- mp_configure(mp, 0, MP_BUFFER_DEEP);
+ mp_configure(mp, 0, MP_BUFFER_SHALLOW);
if(primary)
mp_become_primary(mp);
@@ -1493,6 +1423,8 @@ htsp_subscriber(htsp_connection_t *hc, htsp_subscription_t *hs,
set_channel(hc, hs, chid, &name);
+ rstr_t *rurl = rstr_alloc(url);
+
while(1) {
e = mp_dequeue_event(mp);
@@ -1522,12 +1454,14 @@ htsp_subscriber(htsp_connection_t *hc, htsp_subscription_t *hs,
if((m = htsp_reqreply(hc, m)) == NULL) {
snprintf(errbuf, errlen, "Connection with server lost");
+ rstr_release(rurl);
return NULL;
}
if((err = htsmsg_get_str(m, "error")) != NULL) {
snprintf(errbuf, errlen, "From server: %s", err);
htsmsg_destroy(m);
+ rstr_release(rurl);
return NULL;
}
@@ -1536,24 +1470,28 @@ htsp_subscriber(htsp_connection_t *hc, htsp_subscription_t *hs,
} else if(event_is_action(e, ACTION_PREV_CHANNEL) ||
event_is_action(e, ACTION_SKIP_BACKWARD)) {
- chid = zap_channel(hc, hs, chid, errbuf, errlen, tag, -1, &name);
+ if(zap_channel(hc, hs, errbuf, errlen, 1, &name, vq, &rurl)) {
+ rstr_release(rurl);
+ return NULL;
+ }
} else if(event_is_action(e, ACTION_NEXT_CHANNEL) ||
event_is_action(e, ACTION_SKIP_FORWARD)) {
- chid = zap_channel(hc, hs, chid, errbuf, errlen, tag, 1, &name);
+ if(zap_channel(hc, hs, errbuf, errlen, 0, &name, vq, &rurl)) {
+ rstr_release(rurl);
+ return NULL;
+ }
} else if(event_is_type(e, EVENT_EXIT) ||
event_is_type(e, EVENT_PLAY_URL))
break;
event_release(e);
-
- if(chid == -1)
- return NULL;
-
}
+ rstr_release(rurl);
+
prop_set_string(mp->mp_prop_playstatus, "stop");
m = htsmsg_create_map();
@@ -1593,14 +1531,13 @@ be_htsp_playvideo(const char *url, media_pipe_t *mp,
int flags, int priority,
char *errbuf, size_t errlen,
const char *mimetype,
- const char *canonical_url)
+ const char *canonical_url,
+ video_queue_t *vq)
{
htsp_connection_t *hc;
char path[URL_MAX];
htsp_subscription_t *hs;
event_t *e;
- char *tag = NULL;
- int chid;
int primary = !!(flags & BACKEND_VIDEO_PRIMARY);
TRACE(TRACE_DEBUG, "HTSP",
@@ -1612,24 +1549,6 @@ be_htsp_playvideo(const char *url, media_pipe_t *mp,
return NULL;
}
- if(!strncmp(path, "/channel/", strlen("/channel/"))) {
- chid = atoi(path + strlen("/channel/"));
- tag = NULL;
- } else if(!strncmp(path, "/tagchannel/", strlen("/tagchannel/"))) {
- tag = mystrdupa(path + strlen("/tagchannel/"));
- char *x = strrchr(tag, '/');
- if(x == NULL) {
- snprintf(errbuf, errlen, "Invalid URL");
- return NULL;
- }
- *x++ = 0;
- chid = atoi(x);
- } else {
- snprintf(errbuf, errlen, "Invalid URL");
- return NULL;
- }
-
-
hs = calloc(1, sizeof(htsp_subscription_t));
hs->hs_sid = atomic_add(&hc->hc_sid_generator, 1);
@@ -1641,7 +1560,7 @@ be_htsp_playvideo(const char *url, media_pipe_t *mp,
LIST_INSERT_HEAD(&hc->hc_subscriptions, hs, hs_link);
hts_mutex_unlock(&hc->hc_subscription_mutex);
- e = htsp_subscriber(hc, hs, chid, errbuf, errlen, tag, primary, priority);
+ e = htsp_subscriber(hc, hs, errbuf, errlen, primary, priority, vq, url);
mp_flush(mp, 0);
mp_shutdown(mp);
@@ -1775,18 +1694,10 @@ htsp_subscriptionStart(htsp_connection_t *hc, htsmsg_t *m)
mp = hs->hs_mp;
TRACE(TRACE_DEBUG, "HTSP", "Got start notitification");
-
- prop_destroy_childs(mp->mp_prop_audio_tracks);
- prop_destroy_childs(mp->mp_prop_subtitle_tracks);
-
- mp_add_track_off(mp->mp_prop_audio_tracks, "audio:off");
- mp_add_track_off(mp->mp_prop_subtitle_tracks, "sub:off");
-
mp->mp_audio.mq_stream = -1;
mp->mp_video.mq_stream2 = -1;
-
- prop_set_string(mp->mp_prop_audio_track_current, "spu:off");
- prop_set_string(mp->mp_prop_audio_track_current, "audio:off");
+
+ mp_reinit_streams(mp);
if((sourceinfo = htsmsg_get_map(m, "sourceinfo")) != NULL) {
View
3  src/backend/rtmp/rtmp.c
@@ -673,7 +673,8 @@ rtmp_playvideo(const char *url0, media_pipe_t *mp,
int flags, int priority,
char *errbuf, size_t errlen,
const char *mimetype,
- const char *canonical_url)
+ const char *canonical_url,
+ video_queue_t *vq)
{
rtmp_t r = {0};
event_t *e;
View
80 src/fileaccess/fa_video.c
@@ -74,12 +74,6 @@ static void attachment_load(struct attachment_list *alist,
static void attachment_unload_all(struct attachment_list *alist);
-
-
-static event_t *playlist_play(fa_handle_t *fh, media_pipe_t *mp, int primary,
- int flags, char *errbuf, size_t errlen);
-
-
/**
*
*/
@@ -666,7 +660,8 @@ be_file_playvideo(const char *url, media_pipe_t *mp,
int flags, int priority,
char *errbuf, size_t errlen,
const char *mimetype,
- const char *canonical_url)
+ const char *canonical_url,
+ video_queue_t *vq)
{
AVFormatContext *fctx;
AVCodecContext *ctx;
@@ -674,7 +669,6 @@ be_file_playvideo(const char *url, media_pipe_t *mp,
int i;
media_codec_t **cwvec;
event_t *e;
- uint8_t buf[64];
uint64_t hash;
int64_t fsize;
@@ -716,13 +710,6 @@ be_file_playvideo(const char *url, media_pipe_t *mp,
if(fh == NULL)
return NULL;
- if(fa_read(fh, buf, sizeof(buf)) == sizeof(buf)) {
- if(!memcmp(buf, "<showtimeplaylist", strlen("<showtimeplaylist"))) {
- return playlist_play(fh, mp, flags, priority, errbuf, errlen);
- }
- }
-
-
if(flags & BACKEND_VIDEO_SET_TITLE) {
char tmp[1024];
fa_url_get_last_component(tmp, sizeof(tmp), canonical_url);
@@ -914,69 +901,6 @@ be_file_playvideo(const char *url, media_pipe_t *mp,
}
-/**
- *
- */
-static event_t *
-playlist_play(fa_handle_t *fh, media_pipe_t *mp, int flags,
- int priority, char *errbuf, size_t errlen)
-{
- void *mem;
- htsmsg_t *xml, *urls, *c;
- event_t *e;
- const char *s, *url;
- int loop;
- htsmsg_field_t *f;
- int played_something;
-
- mem = fa_load_and_close(fh, NULL);
-
- if((xml = htsmsg_xml_deserialize(mem, errbuf, errlen)) == NULL)
- return NULL;
-
- s = htsmsg_get_str_multi(xml, "tags", "showtimeplaylist",
- "attrib", "loop", NULL);
- loop = s != NULL && atoi(s);
-
- urls = htsmsg_get_map_multi(xml, "tags", "showtimeplaylist", "tags", NULL);
-
- if(urls == NULL) {
- htsmsg_destroy(xml);
- snprintf(errbuf, errlen, "No <url> tags in playlist");
- return NULL;
- }
-
- do {
- played_something = 0;
-
- HTSMSG_FOREACH(f, urls) {
- if(strcmp(f->hmf_name, "url") ||
- (c = htsmsg_get_map_by_field(f)) == NULL)
- continue;
- int flags2 = flags;
-
- s = htsmsg_get_str_multi(c, "attrib", "noaudio", NULL);
-
- if(s && atoi(s))
- flags2 |= BACKEND_VIDEO_NO_AUDIO;
-
- url = htsmsg_get_str(c, "cdata");
- if(url == NULL)
- continue;
- e = backend_play_video(url, mp, flags2, priority, errbuf, errlen, NULL,
- url);
- if(!event_is_type(e, EVENT_EOF)) {
- htsmsg_destroy(xml);
- return e;
- }
- played_something = 1;
- }
- } while(played_something && loop);
-
- htsmsg_destroy(xml);
- return event_create_type(EVENT_EOF);
-}
-
/**
*
View
5 src/fileaccess/fa_video.h
@@ -21,9 +21,12 @@
#include "media.h"
+struct video_queue;
+
event_t *be_file_playvideo(const char *url, media_pipe_t *mp,
int flags, int priority,
char *errbuf, size_t errlen,
- const char *mimetype, const char *canonical_url);
+ const char *mimetype, const char *canonical_url,
+ struct video_queue *vq);
#endif /* FA_VIDEO_H */
View
5 src/prop/prop_core.c
@@ -543,6 +543,11 @@ trampoline_rstr(prop_sub_t *s, prop_event_t event, ...)
if(event == PROP_SET_RSTRING) {
cb(s->hps_opaque, va_arg(ap, rstr_t *));
+ } else if(event == PROP_SET_CSTRING) {
+ const char *str = va_arg(ap, const char *);
+ rstr_t *t = rstr_alloc(str);
+ cb(s->hps_opaque, t);
+ rstr_release(t);
} else if(event == PROP_SET_RLINK) {
cb(s->hps_opaque, va_arg(ap, rstr_t *));
} else if(!(s->hps_flags & PROP_SUB_IGNORE_VOID)) {
View
60 src/ui/glw/glw_list.c
@@ -538,6 +538,63 @@ scroll_to_me(glw_list_t *l, glw_t *c)
+
+/**
+ *
+ */
+static void
+glw_flood_focus_distance(glw_t *w, int v)
+{
+ glw_t *c;
+
+ if(w->glw_focus_distance != v) {
+ w->glw_focus_distance = v;
+ glw_signal0(w, GLW_SIGNAL_FOCUS_DISTANCE_CHANGED, NULL);
+ }
+
+ TAILQ_FOREACH(c, &w->glw_childs, glw_parent_link)
+ glw_flood_focus_distance(c, v);
+}
+
+/**
+ *
+ */
+static void
+update_focus_distance(glw_t *w, glw_t *ign)
+{
+ glw_t *c, *p, *n;
+ int d = 0;
+
+ if((c = w->glw_focused) == NULL)
+ return;
+
+ p = n = c;
+
+ glw_flood_focus_distance(c, 0);
+
+ while(1) {
+ p = p ? glw_prev_widget(p) : NULL;
+ n = n ? glw_next_widget(n) : NULL;
+
+ if(p == ign)
+ p = p ? glw_prev_widget(p) : NULL;
+
+ if(n == ign)
+ n = n ? glw_next_widget(n) : NULL;
+
+ if(p == NULL && n == NULL)
+ break;
+
+ d++;
+ if(p != NULL)
+ glw_flood_focus_distance(p, d);
+ if(n != NULL)
+ glw_flood_focus_distance(n, d);
+ }
+}
+
+
+
/**
*
*/
@@ -554,6 +611,7 @@ glw_list_callback(glw_t *w, void *opaque, glw_signal_t signal, void *extra)
scroll_to_me(l, extra);
l->suggest_cnt = 0;
w->glw_flags2 &= ~GLW2_FLOATING_FOCUS;
+ update_focus_distance(w, NULL);
return 0;
case GLW_SIGNAL_CHILD_DESTROYED:
@@ -569,6 +627,7 @@ glw_list_callback(glw_t *w, void *opaque, glw_signal_t signal, void *extra)
l->current_pos = 0;
l->filtered_pos = 0;
}
+ update_focus_distance(w, extra);
break;
case GLW_SIGNAL_POINTER_EVENT:
@@ -582,6 +641,7 @@ glw_list_callback(glw_t *w, void *opaque, glw_signal_t signal, void *extra)
case GLW_SIGNAL_CHILD_CREATED:
case GLW_SIGNAL_CHILD_MOVED:
scroll_to_me(l, w->glw_focused);
+ update_focus_distance(w, NULL);
break;
case GLW_SIGNAL_CHILD_CONSTRAINTS_CHANGED:
View
4 src/ui/glw/glw_x11.c
@@ -746,8 +746,8 @@ static const struct {
{ XK_Left, ShiftMask | ControlMask, ACTION_SKIP_BACKWARD},
{ XK_Right, ShiftMask | ControlMask, ACTION_SKIP_FORWARD},
- { XK_Prior, 0, ACTION_PAGE_UP},
- { XK_Next, 0, ACTION_PAGE_DOWN},
+ { XK_Prior, 0, ACTION_PAGE_UP, ACTION_PREV_CHANNEL},
+ { XK_Next, 0, ACTION_PAGE_DOWN, ACTION_NEXT_CHANNEL},
{ XK_Home, 0, ACTION_TOP},
{ XK_End, 0, ACTION_BOTTOM},
View
50 src/video/video_playback.c
@@ -41,10 +41,10 @@ TAILQ_HEAD(video_queue_entry_queue, video_queue_entry);
/**
*
*/
-typedef struct video_queue {
+struct video_queue {
prop_sub_t *vq_node_sub;
struct video_queue_entry_queue vq_entries;
-} video_queue_t;
+};
/**
@@ -173,7 +173,8 @@ vsource_load_hls(struct vsource_list *list, const char *url,
static event_t *
play_video(const char *url, struct media_pipe *mp,
int flags, int priority,
- char *errbuf, size_t errlen)
+ char *errbuf, size_t errlen,
+ video_queue_t *vq)
{
htsmsg_t *subs, *sources;
const char *str;
@@ -185,7 +186,7 @@ play_video(const char *url, struct media_pipe *mp,
if(strncmp(url, "videoparams:", strlen("videoparams:")))
return backend_play_video(url, mp, flags | BACKEND_VIDEO_SET_TITLE,
- priority, errbuf, errlen, NULL, url);
+ priority, errbuf, errlen, NULL, url, vq);
url += strlen("videoparams:");
htsmsg_t *m = htsmsg_json_deserialize(url);
@@ -258,15 +259,6 @@ play_video(const char *url, struct media_pipe *mp,
if(htsmsg_get_u32_or_default(m, "no_fs_scan", 0))
flags |= BACKEND_VIDEO_NO_FS_SCAN;
-
- LIST_FOREACH(vs, &vsources, vs_link) {
- printf("%10d: %s: %s\n",
- vs->vs_bitrate,
- vs->vs_mimetype,
- vs->vs_url);
- }
-
-
vs = LIST_FIRST(&vsources);
if(canonical_url == NULL)
@@ -276,7 +268,7 @@ play_video(const char *url, struct media_pipe *mp,
e = backend_play_video(vs->vs_url, mp, flags, priority,
errbuf, errlen, vs->vs_mimetype,
- canonical_url);
+ canonical_url, vq);
vsource_cleanup(&vsources);
@@ -510,8 +502,9 @@ video_queue_destroy(video_queue_t *vq)
/**
*
*/
-static rstr_t *
-video_queue_find_next(video_queue_t *vq, const char *url, int reverse)
+rstr_t *
+video_queue_find_next(video_queue_t *vq, const char *url, int reverse,
+ int wrap)
{
rstr_t *r = NULL;
video_queue_entry_t *vqe;
@@ -520,13 +513,25 @@ video_queue_find_next(video_queue_t *vq, const char *url, int reverse)
hts_mutex_lock(&video_queue_mutex);
TAILQ_FOREACH(vqe, &vq->vq_entries, vqe_link) {
if(vqe->vqe_url != NULL && !strcmp(url, rstr_get(vqe->vqe_url)) &&
- vqe->vqe_type != NULL && !strcmp("video", rstr_get(vqe->vqe_type)))
+ vqe->vqe_type != NULL &&
+ (!strcmp("video", rstr_get(vqe->vqe_type)) ||
+ !strcmp("tvchannel", rstr_get(vqe->vqe_type))))
break;
}
- if(vqe != NULL)
- vqe = reverse ? TAILQ_PREV(vqe, video_queue_entry_queue, vqe_link) :
- TAILQ_NEXT(vqe, vqe_link);
+ if(vqe != NULL) {
+
+ if(reverse) {
+ vqe = TAILQ_PREV(vqe, video_queue_entry_queue, vqe_link);
+ if(vqe == NULL)
+ vqe = TAILQ_LAST(&vq->vq_entries, video_queue_entry_queue);
+ } else {
+ vqe = TAILQ_NEXT(vqe, vqe_link);
+ if(vqe == NULL)
+ vqe = TAILQ_FIRST(&vq->vq_entries);
+ }
+ }
+
if(vqe != NULL)
r = rstr_dup(vqe->vqe_url);
hts_mutex_unlock(&video_queue_mutex);
@@ -556,7 +561,7 @@ video_player_idle(void *aux)
if(play_url != NULL) {
e = play_video(rstr_get(play_url), mp,
play_flags, play_priority,
- errbuf, sizeof(errbuf));
+ errbuf, sizeof(errbuf), vq);
if(e == NULL)
prop_set_string(errprop, errbuf);
}
@@ -605,7 +610,8 @@ video_player_idle(void *aux)
event_is_action(e, ACTION_SKIP_BACKWARD);
if(vq && (video_settings.continuous_playback || force_continuous || skp))
next = video_queue_find_next(vq, rstr_get(play_url),
- event_is_action(e, ACTION_SKIP_BACKWARD));
+ event_is_action(e, ACTION_SKIP_BACKWARD),
+ 0);
if(skp)
play_flags |= BACKEND_VIDEO_START_FROM_BEGINNING;
View
6 src/video/video_playback.h
@@ -21,8 +21,14 @@
#include "media.h"
+struct rstr;
+struct video_queue;
void video_playback_create(media_pipe_t *mp);
void video_playback_destroy(media_pipe_t *mp);
+struct rstr *video_queue_find_next(struct video_queue *vq,
+ const char *url, int reverse,
+ int wrap);
+
#endif /* PLAY_VIDEO_H */
Please sign in to comment.
Something went wrong with that request. Please try again.