static const void *
channel_class_get_number ( void *p )
{
- static int i;
+ static int64_t i;
i = channel_get_number(p);
return &i;
}
.get = channel_class_get_name,
},
{
- .type = PT_INT,
+ .type = PT_S64,
+ .intsplit = CHANNEL_SPLIT,
.id = "number",
.name = "Number",
.off = offsetof(channel_t, ch_number),
return blank;
}
-int
+int64_t
channel_get_number ( channel_t *ch )
{
int n;
const char *channel_get_name ( channel_t *ch );
int channel_set_name ( channel_t *ch, const char *s );
-int channel_get_number ( channel_t *ch );
+#define CHANNEL_SPLIT 1000000
+
+static inline uint32_t channel_get_major ( int64_t chnum ) { return chnum / CHANNEL_SPLIT; }
+static inline uint32_t channel_get_minor ( int64_t chnum ) { return chnum % CHANNEL_SPLIT; }
+
+int64_t channel_get_number ( channel_t *ch );
const char *channel_get_icon ( channel_t *ch );
int channel_set_icon ( channel_t *ch, const char *icon );
channel_tag_t *ct;
service_t *t;
epg_broadcast_t *now, *next = NULL;
+ int64_t chnum = channel_get_number(ch);
htsmsg_t *out = htsmsg_create_map();
htsmsg_t *tags = htsmsg_create_list();
htsmsg_t *services = htsmsg_create_list();
htsmsg_add_u32(out, "channelId", channel_get_id(ch));
- htsmsg_add_u32(out, "channelNumber", channel_get_number(ch));
+ htsmsg_add_u32(out, "channelNumber", channel_get_major(chnum));
+ if (channel_get_minor(chnum))
+ htsmsg_add_u32(out, "channelNumberMinor", channel_get_minor(chnum));
htsmsg_add_str(out, "channelName", channel_get_name(ch));
if(ch->ch_icon != NULL) {
uint16_t s_dvb_service_id;
uint16_t s_dvb_channel_num;
+ uint16_t s_dvb_channel_minor;
char *s_dvb_svcname;
char *s_dvb_provider;
char *s_dvb_cridauth;
*/
int s_dvb_eit_enable;
- uint16_t s_dvb_opentv_chnum;
+ uint64_t s_dvb_opentv_chnum;
/*
* Link to carrying multiplex and active adapter
tvh_str_set(&s->s_dvb_svcname, chname);
save = 1;
}
- if (s->s_dvb_channel_num != maj) {
- // TODO: ATSC channel numbering is plain weird!
- // could shift the major (*100 or something) and append
- // minor, but that'll probably confuse people, as will this!
+ if (s->s_dvb_channel_num != maj || s->s_dvb_channel_minor != min) {
s->s_dvb_channel_num = maj;
+ s->s_dvb_channel_minor = min;
save = 1;
}
#include <assert.h>
#include "service.h"
+#include "channels.h"
#include "input.h"
#include "settings.h"
#include "dvb_charset.h"
.opts = PO_RDONLY,
.off = offsetof(mpegts_service_t, s_dvb_channel_num),
},
+ {
+ .type = PT_U16,
+ .id = "lcn_minor",
+ .name = "Local Channel Minor",
+ .opts = PO_RDONLY,
+ .off = offsetof(mpegts_service_t, s_dvb_channel_minor),
+ },
{
.type = PT_U16,
.id = "lcn2",
/*
* Channel number
*/
-static int
+static int64_t
mpegts_service_channel_number ( service_t *s )
{
- int r = ((mpegts_service_t*)s)->s_dvb_channel_num;
+ int r = ((mpegts_service_t*)s)->s_dvb_channel_num * CHANNEL_SPLIT +
+ ((mpegts_service_t*)s)->s_dvb_channel_minor;
if (r <= 0)
- r = ((mpegts_service_t*)s)->s_dvb_opentv_chnum;
+ r = ((mpegts_service_t*)s)->s_dvb_opentv_chnum * CHANNEL_SPLIT;
return r;
}
break;
}
case PT_U32: {
- if (htsmsg_field_get_u32(f, &u32))
- continue;
+ if (p->intsplit) {
+ char *s;
+ if (!(new = htsmsg_field_get_str(f)))
+ continue;
+ u32 = atol(new) * p->intsplit;
+ if ((s = strchr(new, '.')) != NULL)
+ u32 += (atol(s + 1) % p->intsplit);
+ } else {
+ if (htsmsg_field_get_u32(f, &u32))
+ continue;
+ }
PROP_UPDATE(u32, uint32_t);
break;
}
case PT_S64: {
- if (htsmsg_field_get_s64(f, &s64))
- continue;
- i = s64;
- PROP_UPDATE(i, int64_t);
+ if (p->intsplit) {
+ char *s;
+ if (!(new = htsmsg_field_get_str(f)))
+ continue;
+ s64 = atol(new) * p->intsplit;
+ if ((s = strchr(new, '.')) != NULL)
+ s64 += (atol(s + 1) % p->intsplit);
+ } else {
+ if (htsmsg_field_get_s64(f, &s64))
+ continue;
+ }
+ PROP_UPDATE(s64, int64_t);
break;
}
case PT_DBL: {
const char *s;
const void *val = obj + p->off;
uint32_t u32;
- char buf[16];
+ char buf[24];
/* Ignore */
u32 = p->get_opts ? p->get_opts(obj) : p->opts;
htsmsg_add_u32(m, name, *(uint16_t *)val);
break;
case PT_U32:
- htsmsg_add_u32(m, name, *(uint32_t *)val);
+ if (p->intsplit) {
+ uint32_t maj = *(int64_t *)val / p->intsplit;
+ uint32_t min = *(int64_t *)val % p->intsplit;
+ if (min) {
+ snprintf(buf, sizeof(buf), "%u.%u", (unsigned int)maj, (unsigned int)min);
+ htsmsg_add_str(m, name, buf);
+ } else
+ htsmsg_add_s64(m, name, maj);
+ } else
+ htsmsg_add_u32(m, name, *(uint32_t *)val);
break;
case PT_S64:
- htsmsg_add_s64(m, name, *(int64_t *)val);
+ if (p->intsplit) {
+ int64_t maj = *(int64_t *)val / p->intsplit;
+ int64_t min = *(int64_t *)val % p->intsplit;
+ if (min) {
+ snprintf(buf, sizeof(buf), "%lu.%lu", (unsigned long)maj, (unsigned long)min);
+ htsmsg_add_str(m, name, buf);
+ } else
+ htsmsg_add_s64(m, name, maj);
+ } else
+ htsmsg_add_s64(m, name, *(int64_t *)val);
break;
case PT_STR:
if ((s = *(const char **)val))
if (pl->group)
htsmsg_add_u32(m, "group", pl->group);
+ /* Split integer value */
+ if (pl->intsplit)
+ htsmsg_add_u32(m, "intsplit", pl->intsplit);
+
/* Data */
if (obj)
prop_read_value(obj, pl, m, "value", optmask);
const char *id; ///< Property Key
const char *name; ///< Textual description
prop_type_t type; ///< Type
- int islist; ///< Is a list
+ uint8_t islist; ///< Is a list
+ uint8_t group; ///< Visual group ID (like ExtJS FieldSet)
size_t off; ///< Offset into object
uint32_t opts; ///< Options
- uint32_t group; ///< Visual group ID (like ExtJS FieldSet)
+ uint32_t intsplit; ///< integer/remainder boundary
/* String based processing */
const void *(*get) (void *ptr);
service_unref(t);
}
-static int
+static int64_t
service_channel_number ( service_t *s )
{
return 0;
/*
* Get number for service
*/
-int
+int64_t
service_get_channel_number ( service_t *s )
{
if (s->s_channel_number) return s->s_channel_number(s);
/**
* Channel info
*/
- int (*s_channel_number) (struct service *);
+ int64_t (*s_channel_number) (struct service *);
const char *(*s_channel_name) (struct service *);
const char *(*s_provider_name) (struct service *);
const char *service_get_channel_name (service_t *s);
const char *service_get_full_channel_name (service_t *s);
-int service_get_channel_number (service_t *s);
+int64_t service_get_channel_number (service_t *s);
#endif // SERVICE_H__
{
channel_t *ch;
outputtitle(hq, 0, "Channels");
+ int64_t chnum;
+ char chbuf[32];
CHANNEL_FOREACH(ch) {
htsbuf_qprintf(hq, "%s (%d)\n", channel_get_name(ch), channel_get_id(ch));
+ chnum = channel_get_number(ch);
+ if (channel_get_minor(chnum))
+ snprintf(chbuf, sizeof(chbuf), "%u.%u",
+ channel_get_major(chnum),
+ channel_get_minor(chnum));
+ else
+ snprintf(chbuf, sizeof(chbuf), "%u", channel_get_major(chnum));
htsbuf_qprintf(hq,
" refcount = %d\n"
" zombie = %d\n"
- " number = %d\n"
+ " number = %s\n"
" icon = %s\n\n",
ch->ch_refcount,
ch->ch_zombie,
- channel_get_number(ch),
+ chbuf,
ch->ch_icon ?: "<none set>");
}
}
this.hidden = conf.hidden || conf.advanced;
this.password = conf.password;
this.duration = conf.duration;
+ this.intsplit = conf.intsplit;
this.group = conf.group;
this.enum = conf.enum;
this.store = null;
case 'u16':
case 's64':
case 'dbl':
+ if (f.intsplit) {
+ /* this should be improved */
+ return new Ext.form.TextField({
+ fieldLabel: f.caption,
+ name: f.id,
+ value: value,
+ disabled: d,
+ width: 300,
+ maskRe: /[0-9\.]/,
+ });
+ }
return new Ext.form.NumberField({
fieldLabel: f.caption,
name: f.id,