xosd.c 10.6 KB
Newer Older
1 2 3 4
/*****************************************************************************
 * xosd.c : X On Screen Display interface
 *****************************************************************************
 * Copyright (C) 2001 VideoLAN
5
 * $Id$
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
 *
 * Authors: Loc Minier <lool@videolan.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <stdlib.h>                                      /* malloc(), free() */
#include <string.h>

#include <xosd.h>

#include <vlc/intf.h>

#ifdef HAVE_UNISTD_H
#    include <unistd.h>
#endif

/*****************************************************************************
 * intf_sys_t: description and status of rc interface
 *****************************************************************************/
struct intf_sys_t
{
    xosd * p_osd;               /* libxosd handle */
Clément Stenac's avatar
Clément Stenac committed
44
    vlc_bool_t  b_need_update;   /* Update display ? */
45 46 47 48 49 50 51 52
};

#define MAX_LINE_LENGTH 256

/*****************************************************************************
 * Local prototypes.
 *****************************************************************************/
static int  Open         ( vlc_object_t * );
53
static void Close        ( vlc_object_t * );
54

55
static void Run          ( intf_thread_t * );
56

Clément Stenac's avatar
Clément Stenac committed
57 58 59
static int PlaylistNext( vlc_object_t *p_this, const char *psz_variable,
                vlc_value_t oval, vlc_value_t nval, void *param );

60 61 62
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
Christophe Massiot's avatar
Christophe Massiot committed
63
#define POSITION_TEXT N_("Flip vertical position")
64 65 66
#define POSITION_LONGTEXT N_("Display xosd output on the bottom of the " \
                             "screen instead of the top")

Christophe Massiot's avatar
Christophe Massiot committed
67
#define TXT_OFS_TEXT N_("Vertical offset")
68 69
#define TXT_OFS_LONGTEXT N_("Vertical offset in pixels of the displayed text")

Christophe Massiot's avatar
Christophe Massiot committed
70
#define SHD_OFS_TEXT N_("Shadow offset")
71 72
#define SHD_OFS_LONGTEXT N_("Offset in pixels of the shadow")

Christophe Massiot's avatar
Christophe Massiot committed
73
#define FONT_TEXT N_("Font")
74
#define FONT_LONGTEXT N_("Font used to display text in the xosd output")
Clément Stenac's avatar
Clément Stenac committed
75 76 77
/* FIXME FIXME FIXME: Gettextize */
#define COLOUR_TEXT ("Colour")
#define COLOUR_LONGTEXT ("Colour used to display text in the xosd output")
78 79

vlc_module_begin();
80 81
    set_category( CAT_INTERFACE );
    set_subcategory( SUBCAT_INTERFACE_CONTROL );
Gildas Bazin's avatar
 
Gildas Bazin committed
82
    set_description( _("XOSD interface") );
83
    add_bool( "xosd-position", 1, NULL, POSITION_TEXT, POSITION_LONGTEXT, VLC_TRUE );
Clément Stenac's avatar
Clément Stenac committed
84 85
    add_integer( "xosd-text-offset", 30, NULL, TXT_OFS_TEXT, TXT_OFS_LONGTEXT, VLC_TRUE );
    add_integer( "xosd-shadow-offset", 2, NULL,
86
                 SHD_OFS_TEXT, SHD_OFS_LONGTEXT, VLC_TRUE );
Clément Stenac's avatar
Clément Stenac committed
87 88
    add_string( "xosd-font",
                "-adobe-helvetica-bold-r-normal-*-*-160-*-*-p-*-iso8859-1",
89
                NULL, FONT_TEXT, FONT_LONGTEXT, VLC_TRUE );
Clément Stenac's avatar
Clément Stenac committed
90 91
    add_string( "xosd-colour", "LawnGreen",
                    NULL, COLOUR_TEXT, COLOUR_LONGTEXT, VLC_TRUE );
Gildas Bazin's avatar
 
Gildas Bazin committed
92
    set_capability( "interface", 10 );
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
    set_callbacks( Open, Close );
vlc_module_end();

/*****************************************************************************
 * Open: initialize and create stuff
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
    intf_thread_t *p_intf = (intf_thread_t *)p_this;

    /* Allocate instance and initialize some members */
    p_intf->p_sys = (intf_sys_t *)malloc( sizeof( intf_sys_t ) );
    if( p_intf->p_sys == NULL )
    {
        msg_Err( p_intf, "out of memory" );
108 109 110 111 112 113 114
        return VLC_ENOMEM;
    }

    if( getenv( "DISPLAY" ) == NULL )
    {
        msg_Err( p_intf, "no display, please set the DISPLAY variable" );
        return VLC_EGENERIC;
115 116 117 118
    }

    /* Initialize library */
    p_intf->p_sys->p_osd =
119
#if defined(HAVE_XOSD_VERSION_0) || defined(HAVE_XOSD_VERSION_1)
120
        xosd_init( config_GetPsz( p_intf, "xosd-font" ),
Clément Stenac's avatar
Clément Stenac committed
121 122
                   config_GetPsz( p_intf,"xosd-colour" ), 3,
                   XOSD_top, 0, 1 );
123
#else
124
        xosd_init( config_GetPsz( p_intf, "xosd-font" ),
Clément Stenac's avatar
Clément Stenac committed
125 126
                   config_GetPsz( p_intf,"xosd-colour" ), 3,
                    XOSD_top, 0, 0, 1 );
127
#endif
128

129 130 131 132 133 134
    if( p_intf->p_sys->p_osd == NULL )
    {
        msg_Err( p_intf, "couldn't initialize libxosd" );
        return VLC_EGENERIC;
    }

Clément Stenac's avatar
Clément Stenac committed
135 136 137 138 139 140 141 142 143 144
    playlist_t *p_playlist =
            (playlist_t *)vlc_object_find( p_intf, VLC_OBJECT_PLAYLIST,
                                           FIND_ANYWHERE );
    if( p_playlist == NULL )
    {
        return VLC_EGENERIC;
    }

    var_AddCallback( p_playlist, "playlist-current", PlaylistNext, p_this );
    var_AddCallback( p_playlist, "item-change", PlaylistNext, p_this );
145

Clément Stenac's avatar
Clément Stenac committed
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167
    vlc_object_release( p_playlist );

    /* Set user preferences */
    xosd_set_font( p_intf->p_sys->p_osd,
                    config_GetPsz( p_intf, "xosd-font" ) );
    xosd_set_outline_colour( p_intf->p_sys->p_osd,"black" );
#ifdef HAVE_XOSD_VERSION_2
    xosd_set_horizontal_offset( p_intf->p_sys->p_osd,
                    config_GetInt( p_intf, "xosd-text-offset" ) );
    xosd_set_vertical_offset( p_intf->p_sys->p_osd,
                    config_GetInt( p_intf, "xosd-text-offset" ) );
#else
    xosd_set_offset( p_intf->p_sys->p_osd,
                    config_GetInt( p_intf, "xosd-text-offset" ) );
#endif
    xosd_set_shadow_offset( p_intf->p_sys->p_osd,
                    config_GetInt( p_intf, "xosd-shadow-offset" ));
    xosd_set_pos( p_intf->p_sys->p_osd,
                    config_GetInt( p_intf, "xosd-position" ) ?
                                         XOSD_bottom: XOSD_top );

    /* Initialize to NULL */
168 169 170 171 172 173 174
    xosd_display( p_intf->p_sys->p_osd,
                  0,
                  XOSD_string,
                  "xosd interface initialized" );

    p_intf->pf_run = Run;

Clément Stenac's avatar
Clément Stenac committed
175 176
    p_intf->p_sys->b_need_update = VLC_TRUE;

177
    return VLC_SUCCESS;
178 179 180 181 182 183
}

/*****************************************************************************
 * Close: destroy interface stuff
 *****************************************************************************/
static void Close( vlc_object_t *p_this )
184
{
185 186 187
    intf_thread_t *p_intf = (intf_thread_t *)p_this;

    /* Uninitialize library */
Clément Stenac's avatar
Clément Stenac committed
188
    xosd_destroy( p_intf->p_sys->p_osd );
189 190 191 192 193 194 195 196 197 198 199 200

    /* Destroy structure */
    free( p_intf->p_sys );
}

/*****************************************************************************
 * Run: xosd thread
 *****************************************************************************
 * This part of the interface runs in a separate thread
 *****************************************************************************/
static void Run( intf_thread_t *p_intf )
{
Clément Stenac's avatar
Clément Stenac committed
201 202 203 204 205 206
    int i_size,i_index;
    playlist_t *p_playlist;
    playlist_item_t *p_item = NULL;
    input_item_t item;
    char psz_duration[MSTRTIME_MAX_SIZE+2];
    char *psz_display = NULL;
207 208 209

    while( !p_intf->b_die )
    {
Clément Stenac's avatar
Clément Stenac committed
210
        if( p_intf->p_sys->b_need_update == VLC_TRUE )
211
        {
Clément Stenac's avatar
Clément Stenac committed
212 213 214 215
            p_intf->p_sys->b_need_update = VLC_FALSE;
            p_playlist = (playlist_t *)vlc_object_find( p_intf,
                                      VLC_OBJECT_PLAYLIST, FIND_ANYWHERE );
            if( !p_playlist )
216
            {
Clément Stenac's avatar
Clément Stenac committed
217 218
                continue;
            }
219

Clément Stenac's avatar
Clément Stenac committed
220 221 222 223
            if( p_playlist->i_size < 0 || p_playlist->i_index < 0 )
            {
                vlc_object_release( p_playlist );
                continue;
224
            }
Clément Stenac's avatar
Clément Stenac committed
225 226 227 228 229
            if( psz_display )
            {
                free( psz_display );
                psz_display = NULL;
            }
Clément Stenac's avatar
Clément Stenac committed
230
            if( p_playlist->status.i_status == PLAYLIST_STOPPED )
Clément Stenac's avatar
Clément Stenac committed
231 232 233 234 235
            {
                psz_display = (char *)malloc( sizeof(char )*strlen(_("Stop")));
                sprintf( psz_display,_("Stop") );
                vlc_object_release( p_playlist );
            }
Clément Stenac's avatar
Clément Stenac committed
236
            else if( p_playlist->status.i_status == PLAYLIST_PAUSED )
Clément Stenac's avatar
Clément Stenac committed
237 238 239 240 241 242 243 244
            {
                psz_display = (char *)malloc( sizeof(char )*strlen(_("Pause")));
                sprintf( psz_display,_("Pause") );
                vlc_object_release( p_playlist );
            }
            else
            {
    //           vlc_mutex_lock(&p_playlist->object_lock );
245
                 p_item = p_playlist->status.p_item;
Clément Stenac's avatar
Clément Stenac committed
246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281
                item = p_item->input;
                if( !p_item )
                {
                    vlc_object_release( p_playlist );
     //            vlc_mutex_unlock(&p_playlist->object_lock );
                    continue;
                }
                i_size = p_playlist->i_size;
                i_index = p_playlist->i_index+1;
    //            vlc_mutex_unlock(&p_playlist->object_lock );

                vlc_object_release( p_playlist );

                if( item.i_duration != -1 )
                {
                    char psz_durationstr[MSTRTIME_MAX_SIZE];
                    secstotimestr( psz_durationstr, item.i_duration/1000000 );
                    sprintf( psz_duration, "(%s)", psz_durationstr );
                }
                else
                {
                    sprintf( psz_duration," " );
                }

                psz_display = (char *)malloc( sizeof(char )*
                                          (strlen( item.psz_name ) +
                                          MSTRTIME_MAX_SIZE + 2+6 + 10 +10 ));
                sprintf( psz_display," %i/%i - %s %s",
                         i_index,i_size, item.psz_name, psz_duration);
            }

            /* Display */
            xosd_display( p_intf->p_sys->p_osd,
                            0,                               /* first line */
                            XOSD_string,
                            psz_display );
282 283 284 285
        }

        msleep( INTF_IDLE_SLEEP );
    }
Clément Stenac's avatar
Clément Stenac committed
286
}
287

Clément Stenac's avatar
Clément Stenac committed
288 289 290 291
static int PlaylistNext( vlc_object_t *p_this, const char *psz_variable,
                vlc_value_t oval, vlc_value_t nval, void *param )
{
    intf_thread_t *p_intf = (intf_thread_t *)param;
292

Clément Stenac's avatar
Clément Stenac committed
293 294
    p_intf->p_sys->b_need_update = VLC_TRUE;
    return VLC_SUCCESS;
295 296
}