summaryrefslogtreecommitdiff
path: root/xine/vo_osdreorder.c
blob: 6fed9e3c9c54661bd0b227b4984bcfb1eec1ff7f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
/*
 * vo_osdreorder.c: OSD re-ordering video-out post plugin
 *
 * See the main source file 'xineliboutput.c' for copyright information and
 * how to reach the author.
 *
 * $Id: vo_osdreorder.c,v 1.1 2009-03-17 12:14:41 phintuka Exp $
 *
 */

#include <stdlib.h>

#include <xine/video_out.h>

#include "vo_props.h"
#include "vo_hook.h"

/*
 *  osdreorder_hook_t
 */
typedef struct {
  vo_driver_hook_t h;

  /* currently showing OSDs in new drawing order */
  vo_overlay_t *overlay[50];

} osdreorder_hook_t;

/*
 *
 */

static int osd_level(vo_overlay_t *overlay)
{
  if (overlay->hili_rgb_clut != VDR_OSD_MAGIC /* not from vdr */) {
    return 9999;
  }

  /* VDR input plugin stores some control data in hili clut area */
  vdr_osd_extradata_t *data = (vdr_osd_extradata_t *)overlay->hili_color;
  return data->layer;
}

/*
 * interface
 */

/*
 * override overlay_blend()
 */
static void osdreorder_overlay_blend (vo_driver_t *self, vo_frame_t *frame, vo_overlay_t *overlay)
{
  osdreorder_hook_t *this = (osdreorder_hook_t*)self;
  int my_level = osd_level(overlay);
  int i;

  /* search position */
  for (i = 0; this->overlay[i] && osd_level(this->overlay[i]) >= my_level; i++)
    ;

  /* make room */
  if (this->overlay[i])
    memmove(&this->overlay[i+1], &this->overlay[i], (49-i)*sizeof(vo_overlay_t*));

  this->overlay[i] = overlay;
  return;
}

/*
 * override overlay_end()
 */
static void osdreorder_overlay_end (vo_driver_t *self, vo_frame_t *vo_img)
{
  osdreorder_hook_t *this = (osdreorder_hook_t*)self;
  int i;

  for (i = 0; this->overlay[i]; i++) {
    this->h.orig_driver->overlay_blend(this->h.orig_driver, vo_img, this->overlay[i]);
    this->overlay[i] = NULL;
  }

  /* redirect */
  if (this->h.orig_driver->overlay_end)
    this->h.orig_driver->overlay_end(this->h.orig_driver, vo_img);
}

/*
 * init()
 */
vo_driver_t *osd_reorder_init(void)
{
  osdreorder_hook_t *this = calloc(1, sizeof(osdreorder_hook_t));

  /* OSD interface */
  this->h.vo.overlay_blend    = osdreorder_overlay_blend;
  this->h.vo.overlay_end      = osdreorder_overlay_end;

  return &this->h.vo;
}