]> git.sesse.net Git - vlc/blobdiff - src/video_output/video_widgets.c
Support for multiple OSD channels :
[vlc] / src / video_output / video_widgets.c
index 9024f9024682f7bc8e4a274973fcafe3c30c5ef6..674f4f92fd9677452a07493f2d338dd2f3eab203 100644 (file)
@@ -28,8 +28,8 @@
 #include <vlc/vout.h>
 #include <osd.h>
 
-#define RECT_EMPTY 0
-#define RECT_FILLED 1
+#define STYLE_EMPTY 0
+#define STYLE_FILLED 1
 
 /*****************************************************************************
  * Local prototypes
@@ -45,7 +45,7 @@ static void RenderYUY2( vout_thread_t *, picture_t *, const subpicture_t *,
                         int );
 static void RenderRV32( vout_thread_t *, picture_t *, const subpicture_t *,
                         int );
-static subpicture_t *vout_CreateWidget( vout_thread_t * );
+static subpicture_t *vout_CreateWidget( vout_thread_t *, int );
 static void FreeWidget( subpicture_t * );
 
 /**
@@ -62,7 +62,7 @@ struct subpicture_sys_t
 
 /*****************************************************************************
  * Draws a rectangle at the given position in the subpic.
- * It may be filled (fill == RECT_FILLED) or empty (fill == RECT_EMPTY).
+ * It may be filled (fill == STYLE_FILLED) or empty (fill == STYLE_EMPTY).
  *****************************************************************************/
 static void DrawRect( vout_thread_t *p_vout, subpicture_t *p_subpic,
                       int i_x1, int i_y1, int i_x2, int i_y2, short fill )
@@ -70,7 +70,7 @@ static void DrawRect( vout_thread_t *p_vout, subpicture_t *p_subpic,
     int x, y;
     subpicture_sys_t *p_widget = p_subpic->p_sys;
 
-    if( fill == RECT_FILLED )
+    if( fill == STYLE_FILLED )
     {
         for( y = i_y1; y <= i_y2; y++ )
         {
@@ -97,7 +97,7 @@ static void DrawRect( vout_thread_t *p_vout, subpicture_t *p_subpic,
 
 /*****************************************************************************
  * Draws a triangle at the given position in the subpic.
- * It may be filled (fill == RECT_FILLED) or empty (fill == RECT_EMPTY).
+ * It may be filled (fill == STYLE_FILLED) or empty (fill == STYLE_EMPTY).
  *****************************************************************************/
 static void DrawTriangle( vout_thread_t *p_vout, subpicture_t *p_subpic,
                           int i_x1, int i_y1, int i_x2, int i_y2, short fill )
@@ -107,35 +107,64 @@ static void DrawTriangle( vout_thread_t *p_vout, subpicture_t *p_subpic,
 
     i_mid = i_y1 + ( ( i_y2 - i_y1 ) >> 1 );
 
-    if( fill == RECT_FILLED )
+    if( i_x2 >= i_x1 )
     {
-        for( y = i_y1; y <= i_mid; y++ )
+        if( fill == STYLE_FILLED )
         {
-            h = y - i_y1;
-            for( x = i_x1; x <= i_x1 + h && x <= i_x2; x++ )
+            for( y = i_y1; y <= i_mid; y++ )
             {
-                p_widget->p_pic[ x + p_widget->i_width * y ] = 1;
-                p_widget->p_pic[ x + p_widget->i_width * ( i_y2 - h ) ] = 1;
+                h = y - i_y1;
+                for( x = i_x1; x <= i_x1 + h && x <= i_x2; x++ )
+                {
+                    p_widget->p_pic[ x + p_widget->i_width * y ] = 1;
+                    p_widget->p_pic[ x + p_widget->i_width * ( i_y2 - h ) ] = 1;
+                }
+            }
+        }
+        else
+        {
+            for( y = i_y1; y <= i_mid; y++ )
+            {
+                h = y - i_y1;
+                p_widget->p_pic[ i_x1 + p_widget->i_width * y ] = 1;
+                p_widget->p_pic[ i_x1 + h + p_widget->i_width * y ] = 1;
+                p_widget->p_pic[ i_x1 + p_widget->i_width * ( i_y2 - h ) ] = 1;
+                p_widget->p_pic[ i_x1 + h + p_widget->i_width * ( i_y2 - h ) ] = 1;
             }
         }
     }
     else
     {
-        for( y = i_y1; y <= i_mid; y++ )
+        if( fill == STYLE_FILLED )
         {
-            h = y - i_y1;
-            p_widget->p_pic[ i_x1 + p_widget->i_width * y ] = 1;
-            p_widget->p_pic[ i_x1 + h + p_widget->i_width * y ] = 1;
-            p_widget->p_pic[ i_x1 + p_widget->i_width * ( i_y2 - h ) ] = 1;
-            p_widget->p_pic[ i_x1 + h + p_widget->i_width * ( i_y2 - h ) ] = 1;
+            for( y = i_y1; y <= i_mid; y++ )
+            {
+                h = y - i_y1;
+                for( x = i_x1; x >= i_x1 - h && x >= i_x2; x-- )
+                {
+                    p_widget->p_pic[ x + p_widget->i_width * y ] = 1;
+                    p_widget->p_pic[ x + p_widget->i_width * ( i_y2 - h ) ] = 1;
+                }
+            }
+        }
+        else
+        {
+            for( y = i_y1; y <= i_mid; y++ )
+            {
+                h = y - i_y1;
+                p_widget->p_pic[ i_x1 + p_widget->i_width * y ] = 1;
+                p_widget->p_pic[ i_x1 - h + p_widget->i_width * y ] = 1;
+                p_widget->p_pic[ i_x1 + p_widget->i_width * ( i_y2 - h ) ] = 1;
+                p_widget->p_pic[ i_x1 - h + p_widget->i_width * ( i_y2 - h ) ] = 1;
+            }
         }
     }
 }
 
 /*****************************************************************************
- * Render: place string in picture
+ * Render: place widget in picture
  *****************************************************************************
- * This function merges the previously rendered freetype glyphs into a picture
+ * This function merges the previously drawn widget into a picture
  *****************************************************************************/
 static void Render( vout_thread_t *p_vout, picture_t *p_pic,
                     const subpicture_t *p_subpic )
@@ -343,7 +372,7 @@ static void RenderRV32( vout_thread_t *p_vout, picture_t *p_pic,
 /*****************************************************************************
  * Creates and initializes an OSD widget.
  *****************************************************************************/
-subpicture_t *vout_CreateWidget( vout_thread_t *p_vout )
+subpicture_t *vout_CreateWidget( vout_thread_t *p_vout, int i_channel )
 {
     subpicture_t *p_subpic;
     subpicture_sys_t *p_widget;
@@ -353,7 +382,8 @@ subpicture_t *vout_CreateWidget( vout_thread_t *p_vout )
     p_widget = 0;
 
     /* Create and initialize a subpicture */
-    p_subpic = vout_CreateSubPicture( p_vout, MEMORY_SUBPICTURE );
+    p_subpic = vout_CreateSubPicture( p_vout, i_channel, GRAPH_CONTENT,
+                                      MEMORY_SUBPICTURE );
     if( p_subpic == NULL )
     {
         return NULL;
@@ -378,9 +408,10 @@ subpicture_t *vout_CreateWidget( vout_thread_t *p_vout )
 
 /*****************************************************************************
  * Displays an OSD slider.
- * Type 0 is position slider-like, and type 1 is volume slider-like.
+ * Types are: OSD_HOR_SLIDER and OSD_VERT_SLIDER.
  *****************************************************************************/
-void vout_OSDSlider( vlc_object_t *p_caller, int i_position, short i_type )
+void vout_OSDSlider( vlc_object_t *p_caller, int i_channel, int i_position,
+                     short i_type )
 {
     vout_thread_t *p_vout = vlc_object_find( p_caller, VLC_OBJECT_VOUT,
                                              FIND_ANYWHERE );
@@ -393,7 +424,7 @@ void vout_OSDSlider( vlc_object_t *p_caller, int i_position, short i_type )
         return;
     }
 
-    p_subpic = vout_CreateWidget( p_vout );
+    p_subpic = vout_CreateWidget( p_vout, i_channel );
     if( p_subpic == NULL )
     {
         return;
@@ -402,7 +433,7 @@ void vout_OSDSlider( vlc_object_t *p_caller, int i_position, short i_type )
 
     i_y_margin = p_vout->render.i_height / 10;
     i_x_margin = i_y_margin;
-    if( i_type == 0 )
+    if( i_type == OSD_HOR_SLIDER )
     {
         p_widget->i_width = p_vout->render.i_width - 2 * i_x_margin;
         p_widget->i_height = p_vout->render.i_height / 20;
@@ -429,47 +460,38 @@ void vout_OSDSlider( vlc_object_t *p_caller, int i_position, short i_type )
     }
     memset( p_widget->p_pic, 0, p_widget->i_width * p_widget->i_height );
 
-    if( i_type == 0 )
+    if( i_type == OSD_HOR_SLIDER )
     {
         int i_x_pos = ( p_widget->i_width - 2 ) * i_position / 100;
         int i_y_pos = p_widget->i_height / 2;
         DrawRect( p_vout, p_subpic, i_x_pos - 1, 2, i_x_pos + 1,
-                  p_widget->i_height - 3, RECT_FILLED );
+                  p_widget->i_height - 3, STYLE_FILLED );
         DrawRect( p_vout, p_subpic, 0, 0, p_widget->i_width - 1,
-                  p_widget->i_height - 1, RECT_EMPTY );
+                  p_widget->i_height - 1, STYLE_EMPTY );
     }
-    else if( i_type == 1 )
+    else if( i_type == OSD_VERT_SLIDER )
     {
         int i_y_pos = p_widget->i_height / 2;
         DrawRect( p_vout, p_subpic, 2, p_widget->i_height -
                   ( p_widget->i_height - 2 ) * i_position / 100,
                   p_widget->i_width - 3, p_widget->i_height - 3,
-                  RECT_FILLED );
-        DrawRect( p_vout, p_subpic, 1, i_y_pos, 1, i_y_pos, RECT_FILLED );
+                  STYLE_FILLED );
+        DrawRect( p_vout, p_subpic, 1, i_y_pos, 1, i_y_pos, STYLE_FILLED );
         DrawRect( p_vout, p_subpic, p_widget->i_width - 2, i_y_pos,
-                  p_widget->i_width - 2, i_y_pos, RECT_FILLED );
+                  p_widget->i_width - 2, i_y_pos, STYLE_FILLED );
         DrawRect( p_vout, p_subpic, 0, 0, p_widget->i_width - 1,
-                  p_widget->i_height - 1, RECT_EMPTY );
+                  p_widget->i_height - 1, STYLE_EMPTY );
     }
 
-    vlc_mutex_lock( &p_vout->change_lock );
-
-    if( p_vout->p_last_osd_message )
-    {
-        vout_DestroySubPicture( p_vout, p_vout->p_last_osd_message );
-    }
-    p_vout->p_last_osd_message = p_subpic;
     vout_DisplaySubPicture( p_vout, p_subpic );
 
-    vlc_mutex_unlock( &p_vout->change_lock );
-
     vlc_object_release( p_vout );
     return;
 }
 
 /*****************************************************************************
  * Displays an OSD icon.
- * Types are: OSD_PLAY_ICON, OSD_PAUSE_ICON
+ * Types are: OSD_PLAY_ICON, OSD_PAUSE_ICON, OSD_SPEAKER_ICON, OSD_MUTE_ICON
  *****************************************************************************/
 void vout_OSDIcon( vlc_object_t *p_caller, short i_type )
 {
@@ -477,14 +499,24 @@ void vout_OSDIcon( vlc_object_t *p_caller, short i_type )
                                              FIND_ANYWHERE );
     subpicture_t *p_subpic;
     subpicture_sys_t *p_widget;
-    int i_x_margin, i_y_margin;
+    int i_x_margin, i_y_margin, i_channel;
 
     if( p_vout == NULL || !config_GetInt( p_caller, "osd" ) )
     {
         return;
     }
 
-    p_subpic = vout_CreateWidget( p_vout );
+    switch( i_type )
+    {
+        case OSD_SPEAKER_ICON:
+            i_channel = VOLUME_CHAN;
+            break;
+        default:
+            i_channel = SOLO_CHAN;
+            break;
+    }
+
+    p_subpic = vout_CreateWidget( p_vout, i_channel );
     if( p_subpic == NULL )
     {
         return;
@@ -493,7 +525,7 @@ void vout_OSDIcon( vlc_object_t *p_caller, short i_type )
 
     i_y_margin = p_vout->render.i_height / 15;
     i_x_margin = i_y_margin;
-    p_widget->i_width = p_vout->render.i_width / 22;
+    p_widget->i_width = p_vout->render.i_width / 20;
     p_widget->i_height = p_widget->i_width;
     p_widget->i_x = p_vout->render.i_width - i_x_margin -
                     p_widget->i_width;
@@ -513,9 +545,9 @@ void vout_OSDIcon( vlc_object_t *p_caller, short i_type )
     {
         int i_bar_width = p_widget->i_width / 3;
         DrawRect( p_vout, p_subpic, 0, 0, i_bar_width - 1,
-                  p_widget->i_height - 1, RECT_FILLED );
+                  p_widget->i_height - 1, STYLE_FILLED );
         DrawRect( p_vout, p_subpic, p_widget->i_width - i_bar_width, 0,
-                  p_widget->i_width - 1, p_widget->i_height - 1, RECT_FILLED );
+                  p_widget->i_width - 1, p_widget->i_height - 1, STYLE_FILLED );
     }
     else if( i_type == OSD_PLAY_ICON )
     {
@@ -523,19 +555,30 @@ void vout_OSDIcon( vlc_object_t *p_caller, short i_type )
         int i_delta = ( p_widget->i_width - i_mid ) >> 1;
         int i_y2 = ( ( p_widget->i_height - 1 ) >> 1 ) * 2;
         DrawTriangle( p_vout, p_subpic, i_delta, 0,
-                      p_widget->i_width - i_delta, i_y2, RECT_FILLED );
+                      p_widget->i_width - i_delta, i_y2, STYLE_FILLED );
     }
-
-    vlc_mutex_lock( &p_vout->change_lock );
-
-    if( p_vout->p_last_osd_message )
+    else if( i_type == OSD_SPEAKER_ICON || i_type == OSD_MUTE_ICON )
     {
-        vout_DestroySubPicture( p_vout, p_vout->p_last_osd_message );
+        int i_mid = p_widget->i_height >> 1;
+        int i_delta = ( p_widget->i_width - i_mid ) >> 1;
+        int i_y2 = ( ( p_widget->i_height - 1 ) >> 1 ) * 2;
+        DrawRect( p_vout, p_subpic, i_delta, i_mid / 2,
+                  p_widget->i_width - i_delta,
+                  p_widget->i_height - 1 - i_mid / 2, STYLE_FILLED );
+        DrawTriangle( p_vout, p_subpic, p_widget->i_width - i_delta, 0,
+                      i_delta, i_y2, STYLE_FILLED );
+        if( i_type == OSD_MUTE_ICON )
+        {
+            int i;
+            for( i = 1; i < p_widget->i_width; i++ )
+            {
+                int k = i + ( p_widget->i_height - i - 1 ) * p_widget->i_width;
+                p_widget->p_pic[ k ] = 1 - p_widget->p_pic[ k ];
+            }
+        }
     }
-    p_vout->p_last_osd_message = p_subpic;
-    vout_DisplaySubPicture( p_vout, p_subpic );
 
-    vlc_mutex_unlock( &p_vout->change_lock );
+    vout_DisplaySubPicture( p_vout, p_subpic );
 
     vlc_object_release( p_vout );
     return;