[prev in list] [next in list] [prev in thread] [next in thread]
List: xine-devel
Subject: [xine-devel] [PATCH] xine-ui OSD enhancement (color/fontsize/menu)
From: Richard van Paasen <rvpaasen () t3i ! nl>
Date: 2008-12-09 22:45:32
Message-ID: 493EF50C.7070603 () t3i ! nl
[Download RAW message or body]
Hi,
Note: I submitted this patch last week, but forgot to add the [PATCH] tag in the \
subject line of the email. If this is not the right place to submit xine-ui patches, \
please let me know.
I have implemented some OSD functionality in xine-ui:
* Added a custom OSD menu to stdctl interface. Available commands are
"OSDShowCustomMenu" and "OSDHideCustomMenu". This provides clients
to display a menu with options.
* Made OSD font sizes and color scheme configurable. New config entries:
gui.osd.fontsize (range: 8..36)
gui.osd.fontcolor (range: white, yellow, cyan, green)
gui.osd.background (range: true, false)
* Moved many magic numbers of OSD objects (positioning, margins,
indentation
to constants.
A patch to current xine-ui CVS is attached. I implemented this stuff for
Freevo to add some (osd) interactivity. Maybe this is usefull for others too.
Regards,
Richard.
["xine-ui.patch" (text/plain)]
Index: ChangeLog
===================================================================
RCS file: /cvsroot/xine/xine-ui/ChangeLog,v
retrieving revision 1.121
diff -u -r1.121 ChangeLog
--- ChangeLog 27 Nov 2008 17:55:50 -0000 1.121
+++ ChangeLog 1 Dec 2008 19:34:00 -0000
@@ -1,6 +1,18 @@
xine-ui (0.99.6) unstable; urgency=low
(write here, newest entry on top)
+ * Added a custom OSD menu to stdctl interface. Available commands are
+ "OSDShowCustomMenu" and "OSDHideCustomMenu". This provides clients
+ to display a menu with options.
+ Contributed by Richard van Paasen.
+ * Made OSD font sizes and color scheme configurable. New config entries:
+ gui.osd.fontsize (range: 8..36)
+ gui.osd.fontcolor (range: white, yellow, cyan, green)
+ gui.osd.background (range: true, false)
+ Contributed by Richard van Paasen.
+ * Moved many magic numbers of OSD objects (positioning, margins, indentation
+ to constants.
+ Contributed by Richard van Paasen.
* Automatically load opensubtitle-like filenames <name>.*.<subext>
* New/updated spanish manpage translations from Carlos E. Robinson
* Fixed possible corruption and overflow of keybindings table
Index: src/xitk/common.h
===================================================================
RCS file: /cvsroot/xine/xine-ui/src/xitk/common.h,v
retrieving revision 1.105
diff -u -r1.105 common.h
--- src/xitk/common.h 12 Mar 2008 12:16:59 -0000 1.105
+++ src/xitk/common.h 1 Dec 2008 19:34:00 -0000
@@ -237,7 +237,7 @@
osd_object_t bar;
osd_object_t status;
osd_object_t info;
-
+ osd_object_t menu;
} osd;
int experience_level;
Index: src/xitk/event.c
===================================================================
RCS file: /cvsroot/xine/xine-ui/src/xitk/event.c,v
retrieving revision 1.312
diff -u -r1.312 event.c
--- src/xitk/event.c 26 Mar 2008 23:30:39 -0000 1.312
+++ src/xitk/event.c 1 Dec 2008 19:34:01 -0000
@@ -959,6 +959,35 @@
}
break;
+ case ACTID_OSD_SHOWCUSTOMMENU:
+ if(gGui->alphanum.set) {
+ char *title, *options[OSD_CUSTMENU_MAXOPT];
+ int i;
+
+ title = strtok(gGui->alphanum.arg, "~");
+
+ if (title) {
+ for (i=0; i<OSD_CUSTMENU_MAXOPT; i++) {
+ options[i] = strtok(NULL, "~");
+ if (options[i] == NULL)
+ break;
+ }
+ }
+
+ if (title == NULL || i == 0)
+ osd_display_info(_("No menu to display!"));
+ else
+ osd_display_menu(title, options, i);
+
+ }
+ else
+ osd_display_info(_("No menu to display!"));
+ break;
+
+ case ACTID_OSD_HIDECUSTOMMENU:
+ osd_hide_menu();
+ break;
+
case ACTID_OSD_MENU:
oxine_menu();
break;
Index: src/xitk/kbindings.h
===================================================================
RCS file: /cvsroot/xine/xine-ui/src/xitk/kbindings.h,v
retrieving revision 1.68
diff -u -r1.68 kbindings.h
--- src/xitk/kbindings.h 16 Jan 2008 16:29:42 -0000 1.68
+++ src/xitk/kbindings.h 1 Dec 2008 19:34:01 -0000
@@ -127,6 +127,8 @@
ACTID_SKINDOWNLOAD,
ACTID_OSD_SINFOS,
ACTID_OSD_WTEXT,
+ ACTID_OSD_SHOWCUSTOMMENU,
+ ACTID_OSD_HIDECUSTOMMENU,
ACTID_FILESELECTOR,
ACTID_SUBSELECT,
ACTID_SV_SYNC_p,
Index: src/xitk/kbindings_common.c
===================================================================
RCS file: /cvsroot/xine/xine-ui/src/xitk/kbindings_common.c,v
retrieving revision 1.6
diff -u -r1.6 kbindings_common.c
--- src/xitk/kbindings_common.c 16 Nov 2008 17:06:36 -0000 1.6
+++ src/xitk/kbindings_common.c 1 Dec 2008 19:34:01 -0000
@@ -223,6 +223,10 @@
"OSDStreamInfos", ACTID_OSD_SINFOS , "i", \
KEYMOD_CONTROL , 0 , 0}, { "display information using OSD",
"OSDWriteText", ACTID_OSD_WTEXT , "VOID", \
KEYMOD_CONTROL , 0 , 0}, + { "display custom OSD menu",
+ "OSDShowCustomMenu", ACTID_OSD_SHOWCUSTOMMENU , "VOID", \
KEYMOD_CONTROL , 0 , 0}, + { "hide custom OSD menu",
+ "OSDHideCustomMenu", ACTID_OSD_HIDECUSTOMMENU , "VOID", \
KEYMOD_CONTROL , 0 , 0}, { "show OSD menu",
"OSDMenu", ACTID_OSD_MENU , "O", \
KEYMOD_NOMOD , 0 , 0}, { "enter key binding editor",
Index: src/xitk/osd.c
===================================================================
RCS file: /cvsroot/xine/xine-ui/src/xitk/osd.c,v
retrieving revision 1.48
diff -u -r1.48 osd.c
--- src/xitk/osd.c 12 Mar 2008 11:58:10 -0000 1.48
+++ src/xitk/osd.c 1 Dec 2008 19:34:01 -0000
@@ -43,43 +43,112 @@
#define CLUT_Y_CR_CB_INIT(_y,_cr,_cb) { (_cb), (_cr), (_y) }
#endif
+#define MIN(a, b) ( (a) < (b) ? (a) : (b) )
+#define MAX(a, b) ( (a) > (b) ? (a) : (b) )
+
+/*
+ Xine OSD objects have a 256-entry palette. This pallette is used to
+ render the OSD object. For drawing text, xine needs 11 entries. A block
+ of 11 entires is refered to as a text color. The 11 palette entries that
+ define a text color describe the following:
+
+ 0: not used by font, always transparent
+ 1: font background, usually transparent, may be used to implement
+ translucid boxes where the font will be printed.
+ 2-5: transition between background and border (usually only alpha
+ value changes).
+ 6: font border. if the font is to be displayed without border this
+ will probably be adjusted to font background or near.
+ 7-9: transition between border and foreground
+ 10: font color (foreground)
+
+ Each block of 11 entries is refered to as XINE_OSD_TEXT# (where the #
+ stands for 1, 2, 3, ...) The default xine-internal) palette can be
+ restored on a per textcolor (11 entries) basis with the function
+ xine_osd_set_text_palette(). The function xine_osd_set_palette() just
+ installs an entire palette.
+*/
+
static const struct { /* CLUT == Color LookUp Table */
uint8_t cb : 8;
uint8_t cr : 8;
uint8_t y : 8;
uint8_t foo : 8;
} __attribute__ ((packed)) textpalettes_color[] = {
- /* white, no border, translucid */
+
+ /* white palette */
CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), //0
- CLUT_Y_CR_CB_INIT(0x60, 0x80, 0x80), //1
- CLUT_Y_CR_CB_INIT(0x70, 0x80, 0x80), //2
- CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), //3
- CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), //4
- CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), //5
+ CLUT_Y_CR_CB_INIT(0x20, 0x80, 0x80), //1
+ CLUT_Y_CR_CB_INIT(0x33, 0x80, 0x80), //2
+ CLUT_Y_CR_CB_INIT(0x46, 0x80, 0x80), //3
+ CLUT_Y_CR_CB_INIT(0x59, 0x80, 0x80), //4
+ CLUT_Y_CR_CB_INIT(0x6c, 0x80, 0x80), //5
CLUT_Y_CR_CB_INIT(0x80, 0x80, 0x80), //6
- CLUT_Y_CR_CB_INIT(0xa0, 0x80, 0x80), //7
- CLUT_Y_CR_CB_INIT(0xc0, 0x80, 0x80), //8
- CLUT_Y_CR_CB_INIT(0xe0, 0x80, 0x80), //9
+ CLUT_Y_CR_CB_INIT(0x9f, 0x80, 0x80), //7
+ CLUT_Y_CR_CB_INIT(0xbf, 0x80, 0x80), //8
+ CLUT_Y_CR_CB_INIT(0xdf, 0x80, 0x80), //9
CLUT_Y_CR_CB_INIT(0xff, 0x80, 0x80), //10
- /* yellow, black border, transparent */
+
+ /* yellow palette */
+ CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), //0
+ CLUT_Y_CR_CB_INIT(0x20, 0x80, 0x80), //1
+ CLUT_Y_CR_CB_INIT(0x31, 0x81, 0x76), //2
+ CLUT_Y_CR_CB_INIT(0x42, 0x83, 0x6c), //3
+ CLUT_Y_CR_CB_INIT(0x53, 0x84, 0x63), //4
+ CLUT_Y_CR_CB_INIT(0x64, 0x86, 0x59), //5
+ CLUT_Y_CR_CB_INIT(0x75, 0x87, 0x50), //6
+ CLUT_Y_CR_CB_INIT(0x92, 0x89, 0x44), //7
+ CLUT_Y_CR_CB_INIT(0xaf, 0x8b, 0x38), //8
+ CLUT_Y_CR_CB_INIT(0xcc, 0x8d, 0x2c), //9
+ CLUT_Y_CR_CB_INIT(0xe9, 0x8f, 0x20), //10
+
+ /* cyan palette */
+ CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), //0
+ CLUT_Y_CR_CB_INIT(0x23, 0x7d, 0x90), //1
+ CLUT_Y_CR_CB_INIT(0x30, 0x74, 0x90), //2
+ CLUT_Y_CR_CB_INIT(0x3c, 0x6b, 0x90), //3
+ CLUT_Y_CR_CB_INIT(0x49, 0x62, 0x90), //4
+ CLUT_Y_CR_CB_INIT(0x56, 0x59, 0x90), //5
+ CLUT_Y_CR_CB_INIT(0x63, 0x50, 0x90), //6
+ CLUT_Y_CR_CB_INIT(0x79, 0x40, 0x95), //7
+ CLUT_Y_CR_CB_INIT(0x8f, 0x30, 0x9b), //8
+ CLUT_Y_CR_CB_INIT(0xa5, 0x20, 0xa0), //9
+ CLUT_Y_CR_CB_INIT(0xbc, 0x10, 0xa5), //10
+
+ /* green palette */
CLUT_Y_CR_CB_INIT(0x00, 0x00, 0x00), //0
- CLUT_Y_CR_CB_INIT(0x80, 0x80, 0xe0), //1
- CLUT_Y_CR_CB_INIT(0x80, 0x80, 0xc0), //2
- CLUT_Y_CR_CB_INIT(0x60, 0x80, 0xa0), //3
- CLUT_Y_CR_CB_INIT(0x40, 0x80, 0x80), //4
- CLUT_Y_CR_CB_INIT(0x20, 0x80, 0x80), //5
- CLUT_Y_CR_CB_INIT(0x00, 0x80, 0x80), //6
- CLUT_Y_CR_CB_INIT(0x40, 0x84, 0x60), //7
- CLUT_Y_CR_CB_INIT(0xd0, 0x88, 0x40), //8
- CLUT_Y_CR_CB_INIT(0xe0, 0x8a, 0x00), //9
- CLUT_Y_CR_CB_INIT(0xff, 0x90, 0x00), //10
+ CLUT_Y_CR_CB_INIT(0x20, 0x80, 0x80), //1
+ CLUT_Y_CR_CB_INIT(0x2b, 0x77, 0x79), //2
+ CLUT_Y_CR_CB_INIT(0x36, 0x6f, 0x73), //3
+ CLUT_Y_CR_CB_INIT(0x41, 0x67, 0x6c), //4
+ CLUT_Y_CR_CB_INIT(0x4d, 0x5f, 0x66), //5
+ CLUT_Y_CR_CB_INIT(0x58, 0x57, 0x60), //6
+ CLUT_Y_CR_CB_INIT(0x6b, 0x4a, 0x55), //7
+ CLUT_Y_CR_CB_INIT(0x7e, 0x3d, 0x4b), //8
+ CLUT_Y_CR_CB_INIT(0x90, 0x2f, 0x40), //9
+ CLUT_Y_CR_CB_INIT(0xa3, 0x22, 0x36), //10
};
-static const uint8_t textpalettes_trans[] = {
- /* white, no border, translucid */
- 0, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15,
- /* yellow, black border, transparent */
- 0, 8, 9, 10, 11, 12, 13, 14, 15, 15, 15,
+static uint8_t textpalettes_trans[] = {
+ /* white palette */
+ 0, 11, 9, 10, 11, 12, 13, 14, 15, 15, 15,
+ /* yellow palette */
+ 0, 11, 9, 10, 11, 12, 13, 14, 15, 15, 15,
+ /* cyan palette */
+ 0, 11, 9, 10, 11, 12, 13, 14, 15, 15, 15,
+ /* green palette */
+ 0, 11, 9, 10, 11, 12, 13, 14, 15, 15, 15,
+};
+
+static uint32_t color[OVL_PALETTE_SIZE];
+static uint8_t trans[OVL_PALETTE_SIZE];
+
+static char *osd_fontcolors[] = {
+ "white",
+ "yellow",
+ "cyan",
+ "green",
+ NULL
};
static const struct {
@@ -104,16 +173,42 @@
{ ">$$", XINE_SPEED_FAST_4 }
};
+/* minimum width of the stream else
+ osd objects are not shown */
+#define MINIMUM_WIN_WIDTH 300
+
+/* dimensions of the bar */
#define BAR_WIDTH 336
#define BAR_HEIGHT 25
-#define MINIMUM_WIN_WIDTH 300
-#define FONT_SIZE 20
-#define UNSCALED_FONT_SIZE 24
+/* fontsize range */
+#define DEF_OSD_FONTSIZE 24
+#define MIN_ODS_FONTSIZE 8
+#define MAX_OSD_FONTSIZE 36
+#define MAX_OSD_FONTHEIGHT (MAX_OSD_FONTSIZE + (MAX_OSD_FONTSIZE>>1))
+
+/* margins and indentation */
+#define OSD_MARGIN_W 15
+#define OSD_MARGIN_H 15
+#define OSD_TEXTMARGIN_W 6
+#define OSD_TEXTMARGIN_H 4
+#define OSD_TEXTINDENT " "
+
+/* font faces */
+#define OSD_FONTFACE_REGULAR "sans"
+#define OSD_FONTFACE_SYMBOLS "cetus"
+
+/* default color and background */
+#define DEF_OSD_BACKGROUND 1
+#define DEF_OSD_FONTCOLOR 0
+
+static int osd_fontsize = DEF_OSD_FONTSIZE;
+static int osd_fontcolor = DEF_OSD_FONTCOLOR;
+static int osd_background = DEF_OSD_BACKGROUND;
static pthread_mutex_t osd_mutex;
-static void _xine_osd_show(xine_osd_t *osd, int64_t vpts) {
+static void _xine_osd_show(xine_osd_t *osd, int64_t vpts) {
if( gGui->osd.use_unscaled && gGui->osd.unscaled_available )
xine_osd_show_unscaled(osd, vpts);
else
@@ -121,10 +216,9 @@
}
static void _osd_get_output_size(int *w, int *h) {
- if( gGui->osd.use_unscaled && gGui->osd.unscaled_available )
+ video_window_get_frame_size(w, h);
+ if( (*w==0) || (*h==0) || (gGui->osd.use_unscaled && gGui->osd.unscaled_available) \
) video_window_get_output_size(w, h);
- else
- video_window_get_frame_size(w, h);
}
static char *_osd_get_speed_sym(int speed) {
@@ -148,34 +242,125 @@
return NULL;
}
-void osd_init(void) {
- int fonth = FONT_SIZE;
+static int _get_xine_color(int fontcolor) {
- gGui->osd.sinfo.osd[0] = xine_osd_new(gGui->stream, 0, 0, 900, (fonth * 6) + (5 * \
3));
- xine_osd_set_font(gGui->osd.sinfo.osd[0], "sans", fonth);
- xine_osd_set_text_palette(gGui->osd.sinfo.osd[0],
- XINE_TEXTPALETTE_WHITE_BLACK_TRANSPARENT, XINE_OSD_TEXT1);
+ switch(fontcolor) {
+ case 0: return XINE_OSD_TEXT1;
+ case 1: return XINE_OSD_TEXT2;
+ case 2: return XINE_OSD_TEXT3;
+ case 3: return XINE_OSD_TEXT4;
+ default: return XINE_OSD_TEXT1;
+ }
+}
- gGui->osd.bar.osd[0] = xine_osd_new(gGui->stream, 0, 0, BAR_WIDTH + 1, BAR_HEIGHT \
+ 1);
-
- xine_osd_set_palette(gGui->osd.bar.osd[0], textpalettes_color, \
textpalettes_trans); +static void _osd_ltrim_text(xine_osd_t *osd, char *buf, int \
maxw, int *tw, int *th) {
- gGui->osd.bar.osd[1] = xine_osd_new(gGui->stream, 0, 0, BAR_WIDTH + 1, BAR_HEIGHT \
+ 1);
- xine_osd_set_font(gGui->osd.bar.osd[1], "sans", fonth);
- xine_osd_set_text_palette(gGui->osd.bar.osd[1],
- XINE_TEXTPALETTE_WHITE_BLACK_TRANSPARENT, XINE_OSD_TEXT1);
-
- gGui->osd.status.osd[0] = xine_osd_new(gGui->stream, 0, 0, 300, 2 * fonth);
- xine_osd_set_text_palette(gGui->osd.status.osd[0],
- XINE_TEXTPALETTE_WHITE_BLACK_TRANSPARENT, XINE_OSD_TEXT1);
-
- gGui->osd.info.osd[0] = xine_osd_new(gGui->stream, 0, 0, 2048, fonth + (fonth >> \
1));
- xine_osd_set_font(gGui->osd.info.osd[0], "sans", fonth);
- xine_osd_set_text_palette(gGui->osd.info.osd[0],
- XINE_TEXTPALETTE_WHITE_BLACK_TRANSPARENT, XINE_OSD_TEXT1);
+ /* Trim text until it fits in "maxw". The
+ text is cut off at the left side */
+
+ char *p = buf;
+ xine_osd_get_text_size(osd, buf, tw, th);
+
+ while(*tw > maxw) {
+ *(p++) = '\0';
+ *(p) = '.';
+ *(p+1) = '.';
+ *(p+2) = '.';
+ xine_osd_get_text_size(osd, p, tw, th);
+ }
+
+ if(p > buf) {
+ memmove(buf, p, strlen(p) + 1);
+ }
+}
+
+static void _osd_rtrim_text(xine_osd_t *osd, char *buf, int maxw, int *tw, int *th) \
{ +
+ /* Trim text until it fits in "maxw". The
+ text is cut off at the right side */
+ xine_osd_get_text_size(osd, buf, tw, th);
+
+ while(*tw > maxw) {
+ int i = strlen(buf);
+ buf[i-1] = '\0';
+ buf[i-2] = '.';
+ buf[i-3] = '.';
+ buf[i-4] = '.';
+ xine_osd_get_text_size(osd, buf, tw, th);
+ }
+}
+
+static void _osd_fontsize_cb(void *user_data, xine_cfg_entry_t *entry) {
+
+ osd_fontsize = entry->num_value;
+}
+
+static void _osd_fontcolor_cb(void *user_data, xine_cfg_entry_t *entry) {
+
+ osd_fontcolor = _get_xine_color(entry->num_value);
+}
+
+static void _osd_background_cb(void *user_data, xine_cfg_entry_t *entry) {
+
+ osd_background = entry->num_value;
+}
+
+void osd_init(void) {
+
+ osd_fontsize = xine_config_register_range(
+ __xineui_global_xine_instance, "gui.osd.fontsize",
+ DEF_OSD_FONTSIZE, MIN_ODS_FONTSIZE, MAX_OSD_FONTSIZE,
+ _("font size for OSD text"),
+ CONFIG_NO_HELP, CONFIG_LEVEL_ADV, _osd_fontsize_cb, CONFIG_NO_DATA
+ );
+
+ osd_fontcolor = _get_xine_color(
+ xine_config_register_enum(
+ __xineui_global_xine_instance, "gui.osd.fontcolor",
+ DEF_OSD_FONTCOLOR,
+ osd_fontcolors,
+ _("OSD font colors: white, yellow, green"),
+ CONFIG_NO_HELP, CONFIG_LEVEL_ADV, _osd_fontcolor_cb, CONFIG_NO_DATA
+ )
+ );
+
+ osd_background = xine_config_register_bool(
+ __xineui_global_xine_instance, "gui.osd.background",
+ DEF_OSD_BACKGROUND,
+ _("draw background to increase readibility of text"),
+ CONFIG_NO_HELP, CONFIG_LEVEL_ADV, _osd_background_cb, CONFIG_NO_DATA
+ );
+
+ memcpy(color, textpalettes_color, sizeof(textpalettes_color));
+ memcpy(trans, textpalettes_trans, sizeof(textpalettes_trans));
+
+ /* create STREAM INFO */
+ gGui->osd.sinfo.osd = xine_osd_new(gGui->stream,
+ 0, 0, 2048, (MAX_OSD_FONTHEIGHT * 10) + (OSD_TEXTMARGIN_H * 2) + 1);
+ xine_osd_set_palette(gGui->osd.sinfo.osd, color, trans);
+
+ /* create BAR */
+ gGui->osd.bar.osd = xine_osd_new(gGui->stream,
+ 0, 0, 2048, MAX_OSD_FONTHEIGHT + BAR_HEIGHT + (OSD_TEXTMARGIN_H * 3) + 1);
+ xine_osd_set_palette(gGui->osd.bar.osd, color, trans);
+
+ /* create STATUS */
+ gGui->osd.status.osd = xine_osd_new(gGui->stream,
+ 0, 0, 2048, MAX_OSD_FONTHEIGHT + (OSD_TEXTMARGIN_H * 2) + 1);
+ xine_osd_set_palette(gGui->osd.status.osd, color, trans);
+
+ /* create INFO */
+ gGui->osd.info.osd = xine_osd_new(gGui->stream,
+ 0, 0, 2048, MAX_OSD_FONTHEIGHT + (OSD_TEXTMARGIN_H * 2) + 1);
+ xine_osd_set_palette(gGui->osd.info.osd, color, trans);
+
+ /* create MENU */
+ gGui->osd.menu.osd = xine_osd_new(gGui->stream,
+ 0, 0, 2048, (MAX_OSD_FONTHEIGHT * 10) + (OSD_TEXTMARGIN_H * 2) + 1);
+ xine_osd_set_palette(gGui->osd.menu.osd, color, trans);
gGui->osd.unscaled_available =
- (xine_osd_get_capabilities(gGui->osd.status.osd[0]) & XINE_OSD_CAP_UNSCALED );
+ (xine_osd_get_capabilities(gGui->osd.status.osd) & XINE_OSD_CAP_UNSCALED );
pthread_mutex_init(&osd_mutex, NULL);
}
@@ -185,7 +370,7 @@
pthread_mutex_lock(&osd_mutex);
if(gGui->osd.sinfo.visible) {
gGui->osd.sinfo.visible = 0;
- xine_osd_hide(gGui->osd.sinfo.osd[0], 0);
+ xine_osd_hide(gGui->osd.sinfo.osd, 0);
}
pthread_mutex_unlock(&osd_mutex);
}
@@ -195,9 +380,8 @@
pthread_mutex_lock(&osd_mutex);
if(gGui->osd.bar.visible) {
gGui->osd.bar.visible = 0;
- xine_osd_hide(gGui->osd.bar.osd[0], 0);
- xine_osd_hide(gGui->osd.bar.osd[1], 0);
- }
+ xine_osd_hide(gGui->osd.bar.osd, 0);
+ }
pthread_mutex_unlock(&osd_mutex);
}
@@ -206,7 +390,7 @@
pthread_mutex_lock(&osd_mutex);
if(gGui->osd.status.visible) {
gGui->osd.status.visible = 0;
- xine_osd_hide(gGui->osd.status.osd[0], 0);
+ xine_osd_hide(gGui->osd.status.osd, 0);
}
pthread_mutex_unlock(&osd_mutex);
}
@@ -216,7 +400,17 @@
pthread_mutex_lock(&osd_mutex);
if(gGui->osd.info.visible) {
gGui->osd.info.visible = 0;
- xine_osd_hide(gGui->osd.info.osd[0], 0);
+ xine_osd_hide(gGui->osd.info.osd, 0);
+ }
+ pthread_mutex_unlock(&osd_mutex);
+}
+
+void osd_hide_menu(void) {
+
+ pthread_mutex_lock(&osd_mutex);
+ if(gGui->osd.menu.visible) {
+ gGui->osd.menu.visible = 0;
+ xine_osd_hide(gGui->osd.menu.osd, 0);
}
pthread_mutex_unlock(&osd_mutex);
}
@@ -227,17 +421,18 @@
osd_hide_bar();
osd_hide_status();
osd_hide_info();
+ osd_hide_menu();
}
void osd_deinit(void) {
osd_hide();
- xine_osd_free(gGui->osd.sinfo.osd[0]);
- xine_osd_free(gGui->osd.bar.osd[0]);
- xine_osd_free(gGui->osd.bar.osd[1]);
- xine_osd_free(gGui->osd.status.osd[0]);
- xine_osd_free(gGui->osd.info.osd[0]);
+ xine_osd_free(gGui->osd.sinfo.osd);
+ xine_osd_free(gGui->osd.bar.osd);
+ xine_osd_free(gGui->osd.status.osd);
+ xine_osd_free(gGui->osd.info.osd);
+ xine_osd_free(gGui->osd.menu.osd);
pthread_mutex_destroy(&osd_mutex);
}
@@ -249,47 +444,66 @@
if(gGui->osd.sinfo.visible) {
gGui->osd.sinfo.visible--;
if(!gGui->osd.sinfo.visible) {
- xine_osd_hide(gGui->osd.sinfo.osd[0], 0);
+ xine_osd_hide(gGui->osd.sinfo.osd, 0);
}
}
if(gGui->osd.bar.visible) {
gGui->osd.bar.visible--;
if(!gGui->osd.bar.visible) {
- xine_osd_hide(gGui->osd.bar.osd[0], 0);
- xine_osd_hide(gGui->osd.bar.osd[1], 0);
+ xine_osd_hide(gGui->osd.bar.osd, 0);
}
}
if(gGui->osd.status.visible) {
gGui->osd.status.visible--;
if(!gGui->osd.status.visible) {
- xine_osd_hide(gGui->osd.status.osd[0], 0);
+ xine_osd_hide(gGui->osd.status.osd, 0);
}
}
if(gGui->osd.info.visible) {
gGui->osd.info.visible--;
if(!gGui->osd.info.visible) {
- xine_osd_hide(gGui->osd.info.osd[0], 0);
+ xine_osd_hide(gGui->osd.info.osd, 0);
}
}
-
pthread_mutex_unlock(&osd_mutex);
}
+static void osd_show_sinfo(int settimer) {
+
+ int x, y, wwidth, wheight;
+ _osd_get_output_size(&wwidth, &wheight);
+
+ x = OSD_MARGIN_W;
+ y = MAX_OSD_FONTHEIGHT + OSD_MARGIN_H + OSD_TEXTMARGIN_H;
+
+ xine_osd_set_position(gGui->osd.sinfo.osd, (x >= 0) ? x : 0, (y >= 0) ? y : 0);
+
+ if( wwidth > MINIMUM_WIN_WIDTH ) {
+ pthread_mutex_lock(&osd_mutex);
+ _xine_osd_show(gGui->osd.sinfo.osd, 0);
+ if (settimer)
+ gGui->osd.sinfo.visible = gGui->osd.timeout;
+ pthread_mutex_unlock(&osd_mutex);
+ }
+}
+
void osd_stream_infos(void) {
if(gGui->osd.enabled) {
int vwidth, vheight, asrate;
int wwidth, wheight;
const char *vcodec, *acodec;
- char buffer[256], *p;
- int x, y;
- int w, h, osdw;
+ int i, x, y, w, h, tw, th;
int playedtime, playeddays, totaltime, pos;
int audiochannel, spuchannel, len;
+ /* streaminfo has 10 lines */
+ #define NUMLINES 10
+ char b[NUMLINES][256];
+
vcodec = xine_get_meta_info(gGui->stream, XINE_META_INFO_VIDEOCODEC);
acodec = xine_get_meta_info(gGui->stream, XINE_META_INFO_AUDIOCODEC);
vwidth = xine_get_stream_info(gGui->stream, XINE_STREAM_INFO_VIDEO_WIDTH);
@@ -304,7 +518,7 @@
playedtime /= 1000;
totaltime /= 1000;
- xine_osd_clear(gGui->osd.sinfo.osd[0]);
+ xine_osd_clear(gGui->osd.sinfo.osd);
/* We're in visual animation mode */
if((vwidth == 0) && (vheight == 0)) {
@@ -327,114 +541,135 @@
_osd_get_output_size(&wwidth, &wheight);
- y = x = 0;
+ xine_osd_set_font(gGui->osd.sinfo.osd, OSD_FONTFACE_REGULAR, osd_fontsize);
- strlcpy(buffer, (gGui->is_display_mrl) ? gGui->mmk.mrl : gGui->mmk.ident, \
sizeof(buffer));
- xine_osd_get_text_size(gGui->osd.sinfo.osd[0], buffer, &osdw, &h);
- p = buffer;
- while(osdw > (wwidth - 40)) {
- *(p++) = '\0';
- *(p) = '.';
- *(p+1) = '.';
- *(p+2) = '.';
- xine_osd_get_text_size(gGui->osd.sinfo.osd[0], p, &osdw, &h);
- }
- xine_osd_draw_text(gGui->osd.sinfo.osd[0], x, y, p, XINE_OSD_TEXT1);
-
- y += h;
-
+ /* GET MRL */
+ snprintf(b[0], sizeof(b[0]), "%s:", _("Stream MRL"));
+ snprintf(b[1], sizeof(b[1]), OSD_TEXTINDENT "%s", (gGui->is_display_mrl) ? \
gGui->mmk.mrl : gGui->mmk.ident); + _osd_ltrim_text(
+ gGui->osd.sinfo.osd, b[1], (wwidth - (OSD_MARGIN_W << 1) - (OSD_TEXTMARGIN_W \
<< 1)), &w, &h); +
+ /* GET VCODEC */
+ snprintf(b[2], sizeof(b[2]), "%s:", _("Video Codec"));
if(vcodec && vwidth && vheight) {
- snprintf(buffer, sizeof(buffer), "%s: %dX%d", vcodec, vwidth, vheight);
- xine_osd_draw_text(gGui->osd.sinfo.osd[0], x, y, buffer, XINE_OSD_TEXT1);
- xine_osd_get_text_size(gGui->osd.sinfo.osd[0], buffer, &w, &h);
- if(w > osdw)
- osdw = w;
- y += h;
+ snprintf(b[3], sizeof(b[3]), OSD_TEXTINDENT "%s, %dX%d", vcodec, vwidth, \
vheight); + }
+ else {
+ snprintf(b[3], sizeof(b[3]), OSD_TEXTINDENT "%s", _("none"));
}
+ /* GET ACODEC */
+ snprintf(b[4], sizeof(b[4]), "%s:", _("Audio Codec"));
if(acodec && asrate) {
- snprintf(buffer, sizeof(buffer), "%s: %d%s", acodec, asrate, "Hz");
- xine_osd_draw_text(gGui->osd.sinfo.osd[0], x, y, buffer, XINE_OSD_TEXT1);
- xine_osd_get_text_size(gGui->osd.sinfo.osd[0], buffer, &w, &h);
- if(w > osdw)
- osdw = w;
- y += h;
+ snprintf(b[5], sizeof(b[5]), OSD_TEXTINDENT "%s, %d%s", acodec, asrate, "Hz");
}
-
- strlcpy(buffer, _("Audio: "), sizeof(buffer));
- len = strlen(buffer);
+ else {
+ snprintf(b[5], sizeof(b[5]), OSD_TEXTINDENT "%s", _("none"));
+ }
+
+ /* GET AUDIO PARMS*/
+ snprintf(b[6], sizeof(b[6]), "%s:", _("Audio Parameters"));
+
+ snprintf(b[7], sizeof(b[7]), OSD_TEXTINDENT "%s: ", _("Audio"));
+ len = strlen(b[7]);
+
switch(audiochannel) {
case -2:
- strlcat(buffer, "off", sizeof(buffer));
+ strlcat(b[7], _("off"), sizeof(b[7]));
break;
case -1:
- if(!xine_get_audio_lang (gGui->stream, audiochannel, &buffer[len]))
- strlcat(buffer, "auto", sizeof(buffer));
+ if(!xine_get_audio_lang (gGui->stream, audiochannel, &b[7][len]))
+ strlcat(b[7], _("auto"), sizeof(b[7]));
break;
default:
- if(!xine_get_audio_lang (gGui->stream, audiochannel, &buffer[len]))
- snprintf(buffer+strlen(buffer), sizeof(buffer)-strlen(buffer), "%3d", \
audiochannel); + if(!xine_get_audio_lang (gGui->stream, audiochannel, \
&b[7][len])) + snprintf(b[7]+strlen(b[7]), sizeof(b[7])-strlen(b[7]), "%3d", \
audiochannel); break;
}
- strlcat(buffer, ", Spu: ", sizeof(buffer));
- len = strlen(buffer);
+ snprintf(b[7]+strlen(b[7]), sizeof(b[7])-strlen(b[7]), ", %s: ", _("Spu"));
+ len = strlen(b[7]);
switch (spuchannel) {
case -2:
- strlcat(buffer, "off", sizeof(buffer));
+ strlcat(b[7], _("off"), sizeof(b[7]));
break;
case -1:
- if(!xine_get_spu_lang (gGui->stream, spuchannel, &buffer[len]))
- strlcat(buffer, "auto", sizeof(buffer));
+ if(!xine_get_spu_lang (gGui->stream, spuchannel, &b[7][len]))
+ strlcat(b[7], _("auto"), sizeof(b[7]));
break;
default:
- if(!xine_get_spu_lang (gGui->stream, spuchannel, &buffer[len]))
- snprintf(buffer+strlen(buffer), sizeof(buffer)-strlen(buffer), "%3d", \
spuchannel); + if(!xine_get_spu_lang (gGui->stream, spuchannel, &b[7][len]))
+ snprintf(b[7]+strlen(b[7]), sizeof(b[7])-strlen(b[7]), "%3d", spuchannel);
break;
}
- strlcat(buffer, ".", sizeof(buffer));
- xine_osd_draw_text(gGui->osd.sinfo.osd[0], x, y, buffer, XINE_OSD_TEXT1);
- xine_osd_get_text_size(gGui->osd.sinfo.osd[0], buffer, &w, &h);
- if(w > osdw)
- osdw = w;
-
- y += (h);
+ strlcat(b[7], ".", sizeof(b[7]));
+ /* GET PLAYTIME */
+ snprintf(b[8], sizeof(b[8]), "%s:", _("Play Time"));
playeddays = playedtime / (3600 * 24);
-
+
if(playeddays > 0)
- sprintf(buffer, "%d::%02d ", playeddays, playedtime / 3600);
+ sprintf(b[9], OSD_TEXTINDENT "%d::%02d ", playeddays, playedtime / 3600);
else
- sprintf(buffer, "%d:%02d:%02d ", playedtime / 3600, (playedtime % 3600) / 60, \
playedtime % 60); + sprintf(b[9], OSD_TEXTINDENT "%d:%02d:%02d ", playedtime / \
3600, (playedtime % 3600) / 60, playedtime % 60);
if(totaltime > 0) {
int totaldays;
totaldays = totaltime / (3600 * 24);
- sprintf(buffer+strlen(buffer), "(%.0f%%) %s ", ((float)playedtime / \
(float)totaltime) * 100, _("of")); + sprintf(b[9]+strlen(b[9]), "(%.0f%%) %s ", \
((float)playedtime / (float)totaltime) * 100, _("of"));
if(totaldays > 0)
- sprintf(buffer+strlen(buffer), "%d::%02d", totaldays, totaltime / 3600);
+ sprintf(b[9]+strlen(b[9]), "%d::%02d", totaldays, totaltime / 3600);
else
- sprintf(buffer+strlen(buffer), "%d:%02d:%02d", totaltime / 3600, (totaltime % 3600) \
/ 60, totaltime % 60); + sprintf(b[9]+strlen(b[9]), "%d:%02d:%02d", totaltime / 3600, \
(totaltime % 3600) / 60, totaltime % 60); }
-
- xine_osd_draw_text(gGui->osd.sinfo.osd[0], x, y, buffer, XINE_OSD_TEXT1);
- xine_osd_get_text_size(gGui->osd.sinfo.osd[0], buffer, &w, &h);
- if(w > osdw)
- osdw = w;
-
- osd_stream_position(pos);
-
- x = (wwidth - osdw) - 40;
- xine_osd_set_position(gGui->osd.sinfo.osd[0], (x >= 0) ? x : 0, 15);
- gGui->osd.sinfo.x = (x >= 0) ? x : 0;
- gGui->osd.sinfo.y = 15;
- gGui->osd.sinfo.w = osdw;
+ /* DETERMINE DIMENSIONS */
+ tw = 0;
+ th = 0;
+
+ for(i = 0; i < NUMLINES; i++) {
+ _osd_rtrim_text(
+ gGui->osd.sinfo.osd, b[i], (wwidth - (OSD_MARGIN_W << 1) - (OSD_TEXTMARGIN_W \
<< 1)), &w, &h); + tw = (tw < w ? w : tw); th = (th < h ? h : th);
+ }
+
+ /* DRAW */
+ h = th;
+ tw = tw + (OSD_TEXTMARGIN_W << 1);
+ th = 10 * (h + OSD_TEXTMARGIN_H) + OSD_TEXTMARGIN_H;
+ x = OSD_TEXTMARGIN_W;
+ y = OSD_TEXTMARGIN_H;
+
+ if (osd_background) {
+ xine_osd_draw_rect(gGui->osd.sinfo.osd, 0, 0, tw + 1, th + 1, osd_fontcolor + \
1, 1); + }
+
+ for(i = 0; i < NUMLINES; i++) {
+ xine_osd_draw_text(gGui->osd.sinfo.osd, x, y + (h + OSD_TEXTMARGIN_H) * i, \
b[i], osd_fontcolor); + }
+
+ gGui->osd.sinfo.w = tw;
+ gGui->osd.sinfo.h = th;
+
+ osd_show_sinfo(1);
+ }
+}
+
+static void osd_show_bar(int settimer) {
+
+ int x, wwidth, wheight;
+ _osd_get_output_size(&wwidth, &wheight);
+
+ x = (wwidth - gGui->osd.bar.w) >> 1;
+ xine_osd_set_position(gGui->osd.bar.osd, (x >= 0) ? x : 0, (wheight - \
gGui->osd.bar.h) - (OSD_MARGIN_H * 3)); +
+ if( wwidth > MINIMUM_WIN_WIDTH ) {
pthread_mutex_lock(&osd_mutex);
- _xine_osd_show(gGui->osd.sinfo.osd[0], 0);
- gGui->osd.sinfo.visible = gGui->osd.timeout;
+ _xine_osd_show(gGui->osd.bar.osd, 0);
+ if (settimer)
+ gGui->osd.bar.visible = gGui->osd.timeout;
pthread_mutex_unlock(&osd_mutex);
}
}
@@ -444,10 +679,11 @@
if(gGui->osd.enabled) {
int wwidth, wheight;
int bar_color[40];
- int i, x;
+ int i, x, y;
float _val = (int) val;
float _min = (int) min;
float _max = (int) max;
+ int bw, bh, tw, th, offsetx, offsety;
int pos;
if(max <= min)
@@ -461,98 +697,147 @@
pos = (int) (_val + -_min) / ((_max + -_min) / 40);
- _osd_get_output_size(&wwidth, &wheight);
-
- xine_osd_clear(gGui->osd.bar.osd[0]);
- xine_osd_clear(gGui->osd.bar.osd[1]);
-
+ /* initialize the bar color to XINE_OSD_TEXT1 */
memset(&bar_color, (XINE_OSD_TEXT1 + 7), sizeof(int) * 40);
-
+
switch(type) {
case OSD_BAR_PROGRESS:
case OSD_BAR_STEPPER:
- if(pos)
- memset(bar_color, (XINE_OSD_TEXT1 + 21), sizeof(int) * pos);
+ if(pos) {
+ /* set the first 'pos' entries to osd_fontcolor */
+ memset(bar_color, osd_fontcolor + 7 , sizeof(int) * pos);
+ }
break;
case OSD_BAR_POS:
case OSD_BAR_POS2:
- if(pos)
- bar_color[pos - 1] = (XINE_OSD_TEXT1 + 21);
+ if(pos) {
+ /* set the current 'pos' entry to osd_fontcolor */
+ bar_color[pos - 1] = osd_fontcolor + 10;
+ }
break;
}
-
+
+ _osd_get_output_size(&wwidth, &wheight);
+
+ xine_osd_clear(gGui->osd.bar.osd);
+
+ /* bar dimensions */
+ bw = BAR_WIDTH + (OSD_TEXTMARGIN_W << 1);
+ bh = BAR_HEIGHT + (OSD_TEXTMARGIN_H << 1);
+
+ /* DRAW TITLE */
+ if(title) {
+
+ /* prepare for drawing text */
+ xine_osd_set_font(gGui->osd.bar.osd, OSD_FONTFACE_REGULAR, osd_fontsize);
+ xine_osd_get_text_size(gGui->osd.bar.osd, title, &tw, &th);
+
+ /* text dimensions */
+ tw = tw + (OSD_TEXTMARGIN_W << 1);
+ th = th + OSD_TEXTMARGIN_H;
+
+ if (tw < bw) {
+ /* bar is wider than title */
+ offsetx = ((bw - tw) >> 1) + OSD_TEXTMARGIN_W;
+ }
+ else {
+ offsetx = OSD_TEXTMARGIN_W;
+ }
+
+ offsety = OSD_TEXTMARGIN_H;
+
+ if (osd_background) {
+ xine_osd_draw_rect(gGui->osd.bar.osd, 0, 0, MAX(tw, bw) + 1, th + 1, \
osd_fontcolor + 1, 1); + }
+
+ xine_osd_draw_text(gGui->osd.bar.osd, offsetx, offsety, title, osd_fontcolor);
+ }
+ else {
+ th = 0;
+ tw = 0;
+ }
+
+ /* DRAW BAR */
+ if (tw > bw) {
+ /* title is wider than bar */
+ offsetx = ((tw - bw) >> 1) + OSD_TEXTMARGIN_W;
+ }
+ else {
+ offsetx = OSD_TEXTMARGIN_W;
+ }
+
+ /* position bar below title */
+ offsety = th + OSD_TEXTMARGIN_H;
+
+ if (osd_background) {
+ xine_osd_draw_rect(gGui->osd.bar.osd, 0, th, MAX(tw, bw) + 1, th + bh + 1, \
osd_fontcolor + 1, 1); + }
+
if((type == OSD_BAR_PROGRESS) || (type == OSD_BAR_POS)) {
- x = 3;
- xine_osd_draw_rect(gGui->osd.bar.osd[0], x, 2, x + 3, BAR_HEIGHT - 2, \
XINE_OSD_TEXT1 + 9, 1); +
+ /* draw bar with left size of
+ 'pos' in foreground color */
+
+ x = offsetx + 3;
+ y = offsety;
+ xine_osd_draw_rect(gGui->osd.bar.osd,
+ x, y + 2, x + 3, y + BAR_HEIGHT - 2, osd_fontcolor + 9, 1);
x += 8;
-
+
for(i = 0; i < 40; i++, x += 8) {
- xine_osd_draw_rect(gGui->osd.bar.osd[0],
- x, 6, x + 3, BAR_HEIGHT - 2, bar_color[i], 1);
+ xine_osd_draw_rect(gGui->osd.bar.osd,
+ x, y + 6, x + 3, y + BAR_HEIGHT - 2, bar_color[i], 1);
}
-
- xine_osd_draw_rect(gGui->osd.bar.osd[0],
- x, 2, x + 3, BAR_HEIGHT - 2, XINE_OSD_TEXT1 + 9, 1);
+
+ xine_osd_draw_rect(gGui->osd.bar.osd,
+ x, y + 2, x + 3, y + BAR_HEIGHT - 2, osd_fontcolor + 9, 1);
}
else if(type == OSD_BAR_POS2) {
- x = 3;
- xine_osd_draw_rect(gGui->osd.bar.osd[0], x, 2, x + 3, BAR_HEIGHT - 2, \
XINE_OSD_TEXT1 + 9, 1); +
+ /* draw bar with the current
+ 'pos' in foreground color */
+
+ x = offsetx + 3;
+ y = offsety;
+ xine_osd_draw_rect(gGui->osd.bar.osd,
+ x, y + 2, x + 3, y + BAR_HEIGHT - 2, osd_fontcolor + 9, 1);
x += 8;
-
+
for(i = 0; i < 40; i++, x += 8) {
if(i == (pos - 1))
- xine_osd_draw_rect(gGui->osd.bar.osd[0],
- x, 2, x + 3, BAR_HEIGHT - 2, bar_color[i], 1);
+ xine_osd_draw_rect(gGui->osd.bar.osd,
+ x - 1, y + 2, x + 4, y + BAR_HEIGHT - 2, bar_color[i], 1);
else
- xine_osd_draw_rect(gGui->osd.bar.osd[0],
- x, 6, x + 3, BAR_HEIGHT - 6, bar_color[i], 1);
+ xine_osd_draw_rect(gGui->osd.bar.osd,
+ x, y + 6, x + 3, y + BAR_HEIGHT - 6, bar_color[i], 1);
}
- xine_osd_draw_rect(gGui->osd.bar.osd[0],
- x, 2, x + 3, BAR_HEIGHT - 2, XINE_OSD_TEXT1 + 9, 1);
+ xine_osd_draw_rect(gGui->osd.bar.osd,
+ x, y + 2, x + 3, y + BAR_HEIGHT - 2, osd_fontcolor + 9, 1);
}
else if(type == OSD_BAR_STEPPER) {
- int y = BAR_HEIGHT - 4;
- int step = y / 20;
-
- x = 11;
+
+ /* draw bar with left size of
+ 'pos' in foreground color */
+
+ int step = 0;
+ x = offsetx + 11;
+ y = offsety + BAR_HEIGHT;
for(i = 0; i < 40; i++, x += 8) {
- xine_osd_draw_rect(gGui->osd.bar.osd[0],
- x, y, x + 3, BAR_HEIGHT - 2, bar_color[i], 1);
+ xine_osd_draw_rect(gGui->osd.bar.osd,
+ x, y - 4 - step, x + 3, offsety + BAR_HEIGHT - 2, bar_color[i], 1);
if(!(i % 2))
- y -= step;
+ step += ((BAR_HEIGHT - 4) / 20);
}
}
-
- if(title) {
- int tw, th;
-
- gGui->osd.bar.have_text = 1;
-
- xine_osd_get_text_size(gGui->osd.bar.osd[1], title, &tw, &th);
- xine_osd_draw_text(gGui->osd.bar.osd[1], (BAR_WIDTH - tw) >> 1, 0, title, \
XINE_OSD_TEXT1);
- }
- else
- gGui->osd.bar.have_text = 0;
-
- x = (wwidth - BAR_WIDTH) >> 1;
- xine_osd_set_position(gGui->osd.bar.osd[0], (x >= 0) ? x : 0, (wheight - \
BAR_HEIGHT) - 40);
- xine_osd_set_position(gGui->osd.bar.osd[1], (x >= 0) ? x : 0, (wheight - \
(BAR_HEIGHT * 2)) - 40);
-
- /* don't even bother drawing osd over those small streams.
- * it would look pretty bad.
- */
- if( wwidth > MINIMUM_WIN_WIDTH ) {
- pthread_mutex_lock(&osd_mutex);
- _xine_osd_show(gGui->osd.bar.osd[0], 0);
- if(title)
- _xine_osd_show(gGui->osd.bar.osd[1], 0);
- gGui->osd.bar.visible = gGui->osd.timeout;
- pthread_mutex_unlock(&osd_mutex);
- }
+
+ gGui->osd.bar.w = MAX(tw, bw);
+ gGui->osd.bar.h = th + bh;
+
+ osd_show_bar(1);
}
}
@@ -560,16 +845,34 @@
osd_draw_bar(_("Position in Stream"), 0, 65535, pos, OSD_BAR_POS2);
}
+static void osd_show_info(int settimer) {
+
+ int wwidth, wheight;
+ _osd_get_output_size(&wwidth, &wheight);
+
+ xine_osd_set_position(gGui->osd.info.osd, 0, OSD_MARGIN_H);
+
+ if( wwidth > MINIMUM_WIN_WIDTH ) {
+ pthread_mutex_lock(&osd_mutex);
+ _xine_osd_show(gGui->osd.info.osd, 0);
+ if (settimer)
+ gGui->osd.info.visible = gGui->osd.timeout;
+ pthread_mutex_unlock(&osd_mutex);
+ }
+}
+
void osd_display_info(char *info, ...) {
if(gGui->osd.enabled && !gGui->on_quit) {
- va_list args;
+ va_list args;
char *buf;
- int n, size = 100;
+ int n, size = 100;
+ int tw, th;
+ int wwidth, wheight;
if((buf = xine_xmalloc(size)) == NULL)
return;
-
+
while(1) {
va_start(args, info);
@@ -588,30 +891,164 @@
return;
}
- xine_osd_clear(gGui->osd.info.osd[0]);
+ _osd_get_output_size(&wwidth, &wheight);
+
+ xine_osd_clear(gGui->osd.info.osd);
+ xine_osd_set_font(gGui->osd.info.osd, OSD_FONTFACE_REGULAR, osd_fontsize);
+
+ _osd_rtrim_text(
+ gGui->osd.info.osd, buf, (wwidth - (OSD_MARGIN_W << 1) - (OSD_TEXTMARGIN_W << \
1)), &tw, &th); +
+ tw = tw + (OSD_TEXTMARGIN_W << 1);
+ th = th + (OSD_TEXTMARGIN_H << 1);
- xine_osd_draw_text(gGui->osd.info.osd[0], 0, 0, buf, XINE_OSD_TEXT1);
- xine_osd_set_position(gGui->osd.info.osd[0], 20, 10 + 30);
+ if (osd_background) {
+ xine_osd_draw_rect(gGui->osd.info.osd, 0, 0, wwidth + 1, th + 1, osd_fontcolor \
+ 1, 1); + }
+
+ xine_osd_draw_text(gGui->osd.info.osd, OSD_MARGIN_W + OSD_TEXTMARGIN_W, \
OSD_TEXTMARGIN_H, buf, osd_fontcolor);
+ gGui->osd.info.w = tw;
+ gGui->osd.info.h = th;
+
+ osd_show_info(1);
+ SAFE_FREE(buf);
+ }
+}
+
+static void osd_show_menu() {
+
+ int w, h, wwidth, wheight;
+ _osd_get_output_size(&wwidth, &wheight);
+
+ w = (wwidth - gGui->osd.menu.w) >> 1;
+ h = (wheight - gGui->osd.menu.h) >> 1;
+
+ xine_osd_set_position(gGui->osd.menu.osd, w, h);
+
+ if( wwidth > MINIMUM_WIN_WIDTH ) {
pthread_mutex_lock(&osd_mutex);
- _xine_osd_show(gGui->osd.info.osd[0], 0);
- gGui->osd.info.visible = gGui->osd.timeout;
+ _xine_osd_show(gGui->osd.menu.osd, 0);
+ gGui->osd.menu.visible = 1;
pthread_mutex_unlock(&osd_mutex);
+ }
+}
- SAFE_FREE(buf);
+void osd_display_menu(char* title, char **items, int n) {
+
+/*
+ Title
+ -----------
+ 1. Option A
+ 2. Option B
+ 3. Option C
+ ...
+*/
+
+ if(gGui->osd.enabled && !gGui->on_quit) {
+ int tw = 0, th = 0;
+ int w_title = 0, h_title = 0;
+ int w_index = 0, h_index = 0;
+ int w_item = 0, h_item = 0;
+ int i, w, h, x, y, maxwidth, wwidth, wheight;
+ char buf[4];
+
+ if (n <= 0)
+ return;
+
+ n = MIN(n, OSD_CUSTMENU_MAXOPT);
+
+ _osd_get_output_size(&wwidth, &wheight);
+
+ xine_osd_clear(gGui->osd.menu.osd);
+ xine_osd_set_font(gGui->osd.menu.osd, OSD_FONTFACE_REGULAR, osd_fontsize);
+
+ /* TITLE DIMENSINS */
+ if (title) {
+ xine_osd_get_text_size(gGui->osd.menu.osd, title, &w_title, &h_title);
+ th += h_title + (OSD_TEXTMARGIN_H << 1);
+ }
+
+ /* INDEX NUMBER DIMENSIONS */
+ for(i = 0; i < n; i++) {
+ sprintf(buf, "%d.", i+1);
+ xine_osd_get_text_size(gGui->osd.menu.osd, buf, &w, &h);
+ w_index = MAX(w, w_index);
+ h_index = MAX(h, h_index);
+ }
+
+ /* DETERMINE ITEM DIMENSIONS */
+ maxwidth = (wwidth - (w_index << 1) - (OSD_MARGIN_W << 1) - (OSD_TEXTMARGIN_W << \
1)); + for(i = 0; i < n; i++) {
+ xine_osd_get_text_size(gGui->osd.menu.osd, items[i], &w, &h);
+ w_item = MAX(w, w_item);
+ h_item = MAX(h, h_item);
+ th += MAX(h_index, h_item);
+ }
+
+ th += (OSD_TEXTMARGIN_H << 1);
+ tw = MAX(w_title, (w_index << 1) + w_item) + (OSD_TEXTMARGIN_W << 1);
+
+ /* DRAW */
+ x = OSD_TEXTMARGIN_W;
+ y = OSD_TEXTMARGIN_H;
+
+ if (osd_background) {
+ xine_osd_draw_rect(gGui->osd.menu.osd, 0, 0, tw + 1, th + 1, osd_fontcolor + \
1, 1); + xine_osd_draw_rect(gGui->osd.menu.osd, 0, 0, tw, th, XINE_OSD_TEXT1 + \
10, 0); + }
+
+ if (title) {
+ xine_osd_draw_text(gGui->osd.menu.osd, x, y, title, osd_fontcolor);
+ xine_osd_draw_line(gGui->osd.menu.osd,
+ x, y + h_title + OSD_TEXTMARGIN_H,
+ tw - (OSD_TEXTMARGIN_W << 1) + 1, y + h_title + \
OSD_TEXTMARGIN_H, + XINE_OSD_TEXT1 + 10);
+ y += h_title + (OSD_TEXTMARGIN_H << 1);
+ }
+
+ for(i = 0; i < n; i++) {
+ sprintf(buf, "%d.", i + 1);
+ xine_osd_draw_text(gGui->osd.menu.osd, x, y, buf, osd_fontcolor);
+ xine_osd_draw_text(gGui->osd.menu.osd, x + (w_index << 1), y, items[i], \
osd_fontcolor); + y += h_item;
+ }
+
+ gGui->osd.menu.w = tw;
+ gGui->osd.menu.h = th;
+
+ osd_show_menu();
}
}
+static void osd_show_status(int settimer) {
+
+ int x, y, wwidth, wheight;
+ _osd_get_output_size(&wwidth, &wheight);
+
+ x = wwidth - gGui->osd.status.w - OSD_MARGIN_W;
+ y = MAX_OSD_FONTHEIGHT + OSD_MARGIN_H + OSD_TEXTMARGIN_H;
+
+ xine_osd_set_position(gGui->osd.status.osd, x, y);
+
+ if( wwidth > MINIMUM_WIN_WIDTH ) {
+ pthread_mutex_lock(&osd_mutex);
+ _xine_osd_show(gGui->osd.status.osd, 0);
+ if (settimer)
+ gGui->osd.status.visible = gGui->osd.timeout;
+ pthread_mutex_unlock(&osd_mutex);
+ }
+}
void osd_update_status(void) {
if(gGui->osd.enabled) {
int status;
char buffer[256];
- int wwidth, wheight;
+ int tw, th;
status = xine_get_status(gGui->stream);
- xine_osd_clear(gGui->osd.status.osd[0]);
+ xine_osd_clear(gGui->osd.status.osd);
/*
{ : eject
@@ -655,30 +1092,28 @@
break;
}
- if( gGui->osd.use_unscaled && gGui->osd.unscaled_available )
- xine_osd_set_font(gGui->osd.status.osd[0], "cetus", UNSCALED_FONT_SIZE);
- else
- xine_osd_set_font(gGui->osd.status.osd[0], "cetus", FONT_SIZE);
/* set latin1 encoding (NULL) for status text with special characters,
* then switch back to locale encoding ("")
*/
- xine_osd_set_encoding(gGui->osd.status.osd[0], NULL);
- xine_osd_draw_text(gGui->osd.status.osd[0], 0, 0, buffer, XINE_OSD_TEXT1);
- xine_osd_set_encoding(gGui->osd.status.osd[0], "");
- xine_osd_set_position(gGui->osd.status.osd[0], 20, 10);
+ xine_osd_set_font(gGui->osd.status.osd, OSD_FONTFACE_SYMBOLS, osd_fontsize);
+ xine_osd_set_encoding(gGui->osd.status.osd, NULL);
+ xine_osd_get_text_size(gGui->osd.status.osd, buffer, &tw, &th);
- _osd_get_output_size(&wwidth, &wheight);
+ tw = tw + (OSD_TEXTMARGIN_W << 1);
+ th = th + (OSD_TEXTMARGIN_H << 1);
- /* don't even bother drawing osd over those small streams.
- * it would look pretty bad.
- */
- if( wwidth > MINIMUM_WIN_WIDTH ) {
- pthread_mutex_lock(&osd_mutex);
- _xine_osd_show(gGui->osd.status.osd[0], 0);
- gGui->osd.status.visible = gGui->osd.timeout;
- pthread_mutex_unlock(&osd_mutex);
+ if (osd_background) {
+ xine_osd_draw_rect(gGui->osd.status.osd, 0, 0, tw + 1, th + 1, osd_fontcolor + \
1, 1); }
+
+ xine_osd_draw_text(gGui->osd.status.osd, OSD_TEXTMARGIN_W, OSD_TEXTMARGIN_H, \
buffer, osd_fontcolor); + xine_osd_set_encoding(gGui->osd.status.osd, "");
+
+ gGui->osd.status.w = tw;
+ gGui->osd.status.h = th;
+
+ osd_show_status(1);
}
}
@@ -692,7 +1127,7 @@
switch(channel) {
case -2:
- lang = "off";
+ lang = "off";
break;
case -1:
if(!xine_get_spu_lang(gGui->stream, channel, &lang_buffer[0]))
@@ -741,58 +1176,22 @@
}
void osd_update_osd(void) {
- int vwidth, vheight, wwidth, wheight;
- int x;
- if(!gGui->osd.sinfo.visible && !gGui->osd.bar.visible)
- return;
-
- vwidth = xine_get_stream_info(gGui->stream, XINE_STREAM_INFO_VIDEO_WIDTH);
- vheight = xine_get_stream_info(gGui->stream, XINE_STREAM_INFO_VIDEO_HEIGHT);
-
- if((vwidth == 0) && (vheight == 0)) {
- if(gGui->visual_anim.running) {
- if(gGui->visual_anim.enabled == 1)
- video_window_get_frame_size(&vwidth, &vheight);
- else if(gGui->visual_anim.enabled == 2)
- vwidth = xine_get_stream_info(gGui->visual_anim.stream, \
XINE_STREAM_INFO_VIDEO_WIDTH);
- }
- else
- video_window_get_frame_size(&vwidth, &vheight);
-
- }
-
- _osd_get_output_size(&wwidth, &wheight);
-
- pthread_mutex_lock(&osd_mutex);
+ /* The info and sinfo objects are aligned relative to
+ the top/left corner and do not need to be repositioned
+ when the window has been resized. The status object
+ is aligned relative to the top/right corner, the
+ bar object is aligned relative to the center/bottom
+ and the menu is centered horizontally and vertically.
+ These thus need to be repositioned [if visible].
+ */
- if(gGui->osd.sinfo.visible) {
- xine_osd_hide(gGui->osd.sinfo.osd[0], 0);
-
- x = (wwidth - gGui->osd.sinfo.w) - 40;
- xine_osd_set_position(gGui->osd.sinfo.osd[0], (x >= 0) ? x : 0, \
gGui->osd.sinfo.y);
- _xine_osd_show(gGui->osd.sinfo.osd[0], 0);
- }
+ if(gGui->osd.status.visible)
+ osd_show_sinfo(0);
- if(gGui->osd.bar.visible) {
- xine_osd_hide(gGui->osd.bar.osd[0], 0);
- xine_osd_hide(gGui->osd.bar.osd[1], 0);
-
- x = (wwidth - BAR_WIDTH) >> 1;
- xine_osd_set_position(gGui->osd.bar.osd[0], (x >= 0) ? x : 0, (wheight - \
BAR_HEIGHT) - 40);
- xine_osd_set_position(gGui->osd.bar.osd[1], (x >= 0) ? x : 0, (wheight - \
(BAR_HEIGHT * 2)) - 40);
-
- /* don't even bother drawing osd over those small streams.
- * it would look pretty bad.
- */
- if(wwidth > MINIMUM_WIN_WIDTH) {
- _xine_osd_show(gGui->osd.bar.osd[0], 0);
-
- if(gGui->osd.bar.have_text)
- _xine_osd_show(gGui->osd.bar.osd[1], 0);
- }
+ if (gGui->osd.bar.visible)
+ osd_show_bar(0);
- }
-
- pthread_mutex_unlock(&osd_mutex);
+ if (gGui->osd.menu.visible)
+ osd_show_menu();
}
Index: src/xitk/osd.h
===================================================================
RCS file: /cvsroot/xine/xine-ui/src/xitk/osd.h,v
retrieving revision 1.16
diff -u -r1.16 osd.h
--- src/xitk/osd.h 13 Nov 2007 21:12:18 -0000 1.16
+++ src/xitk/osd.h 1 Dec 2008 19:34:01 -0000
@@ -27,9 +27,8 @@
#include <stdarg.h>
typedef struct {
- xine_osd_t *osd[2];
+ xine_osd_t *osd;
int visible;
- int have_text;
int x, y;
int w, h;
} osd_object_t;
@@ -39,11 +38,14 @@
#define OSD_BAR_POS2 3
#define OSD_BAR_STEPPER 4
+#define OSD_CUSTMENU_MAXOPT 9
+
void osd_init(void);
void osd_hide_sinfo(void);
void osd_hide_bar(void);
void osd_hide_status(void);
void osd_hide_info(void);
+void osd_hide_menu(void);
void osd_hide(void);
void osd_deinit(void);
void osd_update(void);
@@ -53,6 +55,7 @@
void osd_update_status(void);
void osd_stream_position(int pos);
void osd_display_info(char *info, ...) __attribute__ ((format (printf, 1, 2)));
+void osd_display_menu(char* title, char **options, int n);
/* see OSD_BAR_* */
void osd_draw_bar(char *title, int min, int max, int val, int type);
Index: src/xitk/stdctl.c
===================================================================
RCS file: /cvsroot/xine/xine-ui/src/xitk/stdctl.c,v
retrieving revision 1.11
diff -u -r1.11 stdctl.c
--- src/xitk/stdctl.c 12 Mar 2008 11:58:11 -0000 1.11
+++ src/xitk/stdctl.c 1 Dec 2008 19:34:01 -0000
@@ -33,6 +33,9 @@
#include <unistd.h>
#include <string.h>
+/* input_pvr functionality needs this */
+#define XINE_ENABLE_EXPERIMENTAL_FEATURES
+
#include "common.h"
#define DEBUG_STDCTL 0
@@ -83,7 +86,7 @@
fprintf(stderr, "Command Received = '%s'\n", c);
#endif
- /* Handle optional parameter */
+ /* Handle optional parameter */
/* alphanum: separated from the command by a '$' */
/* syntax: "command$parameter" */
@@ -162,9 +165,8 @@
last_secs = secs;
}
}
-
}
-
+
pthread_exit(NULL);
}
@@ -196,9 +198,19 @@
void stdctl_event(const xine_event_t *event)
{
switch(event->type) {
- case XINE_EVENT_UI_PLAYBACK_FINISHED:
- fprintf(stdctl.fbk, "PlaybackFinished\n");
- break;
+ case XINE_EVENT_UI_PLAYBACK_FINISHED:
+ fprintf(stdctl.fbk, "PlaybackFinished\n");
+ break;
+
+ case XINE_EVENT_PVR_REPORT_NAME: {
+ xine_pvr_save_data_t *data = (xine_pvr_save_data_t*) event->data;
+ fprintf(stdctl.fbk, "PVRStreamSaved=%s\n", data->name);
+ break;
+ }
+
+ default:
+ //fprintf(stdctl.fbk, "event: %d\n", event->type);
+ break;
}
}
------------------------------------------------------------------------------
_______________________________________________
xine-devel mailing list
xine-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/xine-devel
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic