[MPlayer-cvslog] r37149 - in trunk: Changelog DOCS/xml/de/skin.xml DOCS/xml/en/skin.xml gui/app/app.c gui/app/app.h gui/app/gui.h gui/skin/skin.c gui/ui/main.c gui/ui/playbar.c gui/ui/render.c gui/ui/ui.h gui/win32...

ib subversion at mplayerhq.hu
Sun Apr 13 01:29:30 CEST 2014


Author: ib
Date: Sun Apr 13 01:29:29 2014
New Revision: 37149

Log:
Add new item 'rpotmeter'.

This is the missing counterpart to hpotmeter and vpotmeter
allowing rotary control elements in a GUI skin now.

Based on an idea and a realization by Hans-Dieter Kosch,
hdkosch kabelbw de.

Additionally, update (and revise) documentation.

Modified:
   trunk/Changelog
   trunk/gui/app/app.c
   trunk/gui/app/app.h
   trunk/gui/app/gui.h
   trunk/gui/skin/skin.c
   trunk/gui/ui/main.c
   trunk/gui/ui/playbar.c
   trunk/gui/ui/render.c
   trunk/gui/ui/ui.h
   trunk/gui/win32/gui.c
   trunk/gui/win32/gui.h
   trunk/gui/win32/skinload.c
   trunk/gui/win32/skinload.h
   trunk/gui/win32/widgetrender.c

Changes in other areas also in this revision:
Modified:
   trunk/DOCS/xml/de/skin.xml
   trunk/DOCS/xml/en/skin.xml

Modified: trunk/Changelog
==============================================================================
--- trunk/Changelog	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/Changelog	Sun Apr 13 01:29:29 2014	(r37149)
@@ -40,7 +40,7 @@ MPlayer
     * Console message with information on deprecated (but still supported)
       entries in the skin configuration file
     * New symbol character (r) and new dynamic label variables ($D, $U, $P)
-    * New item: pimage
+    * New items (pimage, rpotmeter)
 
   1.1: "We gave up on 1.0"
 

Modified: trunk/gui/app/app.c
==============================================================================
--- trunk/gui/app/app.c	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/app/app.c	Sun Apr 13 01:29:29 2014	(r37149)
@@ -21,6 +21,8 @@
  * @brief GUI application helpers
  */
 
+#include <math.h>
+
 #include "app.h"
 #include "gui.h"
 #include "gui/skin/font.h"
@@ -180,6 +182,31 @@ guiItem *appFindItem(int event)
 }
 
 /**
+ * @brief Calculate the radian of a point inside the visual representation
+ *        of an item.
+ *
+ * @param item pointer to the item
+ * @param x x position of the point
+ * @param y y position of the point
+ *
+ * @return radian of the point
+ *
+ * @note The return value is a @a clockwise radian.
+ */
+double appRadian(guiItem *item, int x, int y)
+{
+    double tx, ty;
+
+    // transform the center to (0,0)
+    tx = x - item->width / 2.0;
+    ty = y - item->height / 2.0;
+
+    // the y-axis is upside down and must be mirrored
+    // the x-axis is being mirrored for a clockwise radian
+    return (tx == 0.0 && ty == 0.0 ? 0.0 : atan2(-ty, -tx) + M_PI);
+}
+
+/**
  * @brief Modify the value of the item belonging to an event.
  *
  * @param event event

Modified: trunk/gui/app/app.h
==============================================================================
--- trunk/gui/app/app.h	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/app/app.h	Sun Apr 13 01:29:29 2014	(r37149)
@@ -102,6 +102,7 @@ enum {
     itDLabel,
     itHPotmeter,
     itVPotmeter,
+    itRPotmeter,
     itPimage,
     itMenu,
     itPLMButton = 100,
@@ -132,6 +133,7 @@ typedef struct {
     int pbwidth, pbheight;
     int numphases;
     float value;
+    double zeropoint, arclength;
 
     int message;
 
@@ -180,6 +182,7 @@ extern guiItems guiApp;
 guiItem *appFindItem(int event);
 int appFindMessage(const char *name);
 void appFreeStruct(void);
+double appRadian(guiItem *item, int x, int y);
 void btnModify(int event, float value);
 void btnSet(int event, int state);
 void btnValue(int event, float *value);

Modified: trunk/gui/app/gui.h
==============================================================================
--- trunk/gui/app/gui.h	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/app/gui.h	Sun Apr 13 01:29:29 2014	(r37149)
@@ -48,9 +48,9 @@
 #define isInside(x, y, tx, ty, bx, by) ((x) > (tx) && (y) > (ty) && (x) < (bx) && (y) < (by))
 
 /// Check whether #guiItem @a item has a button (and thus a pressed state).
-#define hasButton(item) (item.type == itButton || item.type == itHPotmeter || item.type == itVPotmeter)
+#define hasButton(item) (item.type == itButton || item.type == itHPotmeter || item.type == itVPotmeter || item.type == itRPotmeter)
 
 /// Check whether #guiItem @a item utilizes member 'value'
-#define hasValue(item) (item.type == itHPotmeter || item.type == itVPotmeter || item.type == itPimage)
+#define hasValue(item) (item.type == itHPotmeter || item.type == itVPotmeter || item.type == itRPotmeter || item.type == itPimage)
 
 #endif /* MPLAYER_GUI_GUI_H */

Modified: trunk/gui/skin/skin.c
==============================================================================
--- trunk/gui/skin/skin.c	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/skin/skin.c	Sun Apr 13 01:29:29 2014	(r37149)
@@ -21,6 +21,7 @@
  * @brief Skin parser
  */
 
+#include <math.h>
 #include <stdio.h>
 #include <string.h>
 
@@ -35,6 +36,7 @@
 
 #include "help_mp.h"
 #include "mp_msg.h"
+#include "libavutil/attributes.h"
 #include "libavutil/avstring.h"
 #include "libavutil/common.h"
 
@@ -589,13 +591,15 @@ static int item_menu(char *in)
 }
 
 /**
- * @brief Parse a hpotmeter or vpotmeter definition.
+ * @brief Parse a hpotmeter, vpotmeter or rpotmeter definition.
  *
- *        Parameters: button,bwidth,bheight,phases,numphases,default,x,y,width,height,message
+ *        Parameters: button,bwidth,bheight,phases,numphases,[x0,y0,x1,y1,]default,x,y,width,height,message
  *
  * @param item pointer to item to store the parameters in
  * @param in definition to be analyzed
  *
+ * @note item->type is already available.
+ *
  * @return 0 (ok) or 1 (error)
  */
 static int parse_potmeter(guiItem *item, char *in)
@@ -603,6 +607,7 @@ static int parse_potmeter(guiItem *item,
     unsigned char bfname[256];
     unsigned char phfname[256];
     unsigned char buf[512];
+    int i = 0, av_uninit(x0), av_uninit(y0), av_uninit(x1), av_uninit(y1);
     int bwidth, bheight, num, d, x, y, w, h, message;
 
     if (!window_item(currItem))
@@ -613,17 +618,25 @@ static int parse_potmeter(guiItem *item,
     if (in_window("menu"))
         return 1;
 
-    cutStr(in, bfname, ',', 0);
-    bwidth  = cutInt(in, ',', 1);
-    bheight = cutInt(in, ',', 2);
-    cutStr(in, phfname, ',', 3);
-    num = cutInt(in, ',', 4);
-    d   = cutInt(in, ',', 5);
-    x   = cutInt(in, ',', 6);
-    y   = cutInt(in, ',', 7);
-    w   = cutInt(in, ',', 8);
-    h   = cutInt(in, ',', 9);
-    cutStr(in, buf, ',', 10);
+    cutStr(in, bfname, ',', i++);
+    bwidth  = cutInt(in, ',', i++);
+    bheight = cutInt(in, ',', i++);
+    cutStr(in, phfname, ',', i++);
+    num = cutInt(in, ',', i++);
+
+    if (item->type == itRPotmeter) {
+        x0 = cutInt(in, ',', i++);
+        y0 = cutInt(in, ',', i++);
+        x1 = cutInt(in, ',', i++);
+        y1 = cutInt(in, ',', i++);
+    }
+
+    d = cutInt(in, ',', i++);
+    x = cutInt(in, ',', i++);
+    y = cutInt(in, ',', i++);
+    w = cutInt(in, ',', i++);
+    h = cutInt(in, ',', i++);
+    cutStr(in, buf, ',', i++);
 
     message = appFindMessage(buf);
 
@@ -656,6 +669,19 @@ static int parse_potmeter(guiItem *item,
     item->message   = message;
     item->pressed   = btnReleased;
 
+    if (item->type == itRPotmeter) {
+        mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[skin]     start: %d,%d / stop: %d,%d\n", x0, y0, x1, y1);
+
+        item->zeropoint = appRadian(item, x0, y0);
+        item->arclength = appRadian(item, x1, y1) - item->zeropoint;
+
+        if (item->arclength < 0.0)
+            item->arclength += 2 * M_PI;
+        // else check if radians of (x0,y0) and (x1,y1) only differ below threshold
+        else if (item->arclength < 0.05)
+            item->arclength = 2 * M_PI;
+    }
+
     item->Bitmap.Image = NULL;
 
     if (strcmp(phfname, "NULL") != 0) {
@@ -735,6 +761,29 @@ static int item_vpotmeter(char *in)
 }
 
 /**
+ * @brief Parse a @a rpotmeter definition.
+ *
+ *        Syntax: rpotmeter=button,bwidth,bheight,phases,numphases,x0,y0,x1,y1,default,x,y,width,height,message
+ *
+ * @param in definition to be analyzed
+ *
+ * @return 0 (ok) or 1 (error)
+ */
+static int item_rpotmeter(char *in)
+{
+    guiItem *item;
+
+    item = next_item();
+
+    if (!item)
+        return 1;
+
+    item->type = itRPotmeter;
+
+    return parse_potmeter(item, in);
+}
+
+/**
  * @brief Parse a @a potmeter definition.
  *
  *        Syntax: potmeter=phases,numphases,default,x,y,width,height,message
@@ -1075,6 +1124,7 @@ static _item skinItem[] = {
     { "menu",       item_menu       },
     { "pimage",     item_pimage     },
     { "potmeter",   item_potmeter   }, // legacy
+    { "rpotmeter",  item_rpotmeter  },
     { "section",    item_section    },
     { "selected",   item_selected   },
     { "slabel",     item_slabel     },

Modified: trunk/gui/ui/main.c
==============================================================================
--- trunk/gui/ui/main.c	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/ui/main.c	Sun Apr 13 01:29:29 2014	(r37149)
@@ -18,6 +18,7 @@
 
 /* main window */
 
+#include <math.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/stat.h>
@@ -95,10 +96,13 @@ static void uiMainMouse( int Button,int 
  static int     itemtype = 0;
         int     i;
         guiItem * item = NULL;
+ static double  prev_point;
+        double  point;
         float   value = 0.0f;
 
  static int     SelectedItem = -1;
         int     currentselected = -1;
+ static int     endstop;
 
  for ( i=0;i <= guiApp.IndexOfMainItems;i++ )
   if ( ( guiApp.mainItems[i].pressed != btnDisabled )&&
@@ -135,6 +139,13 @@ static void uiMainMouse( int Button,int 
                   { item->pressed=btnDisabled; }
                  break;
            }*/
+          if ( itemtype == itRPotmeter )
+           {
+            prev_point=appRadian( item, X - item->x, Y - item->y ) - item->zeropoint;
+            if ( prev_point < 0.0 ) prev_point+=2*M_PI;
+            if ( prev_point <= item->arclength ) endstop=False;
+            else endstop=STOPPED_AT_0 + STOPPED_AT_100;   // block movement
+           }
           break;
    case wsRLMouseButton:
           boxMoved=False;
@@ -154,6 +165,12 @@ static void uiMainMouse( int Button,int 
             case itVPotmeter:
                  value=100.0 - 100.0 * ( Y - item->y ) / item->height;
                  break;
+            case itRPotmeter:
+                 if ( endstop ) { itemtype=0; return; }
+                 point=appRadian( item, X - item->x, Y - item->y ) - item->zeropoint;
+                 if ( point < 0.0 ) point+=2*M_PI;
+                 value=100.0 * point / item->arclength;
+                 break;
            }
           uiEvent( item->message,value );
           itemtype=0;
@@ -170,7 +187,7 @@ rollerhandled:
           if (currentselected != - 1)
            {
             item=&guiApp.mainItems[currentselected];
-            if ( ( item->type == itHPotmeter )||( item->type == itVPotmeter ) )
+            if ( ( item->type == itHPotmeter )||( item->type == itVPotmeter )||( item->type == itRPotmeter ) )
              {
               item->value=constrain(item->value + value);
               uiEvent( item->message,item->value );
@@ -189,6 +206,45 @@ rollerhandled:
             case itPRMButton:
                  if (guiApp.menuIsPresent) guiApp.menuWindow.MouseHandler( 0,RX,RY,0,0 );
                  break;
+            case itRPotmeter:
+                 point=appRadian( item, X - item->x, Y - item->y ) - item->zeropoint;
+                 if ( point < 0.0 ) point+=2*M_PI;
+                 if ( item->arclength < 2 * M_PI )
+                 /* a potmeter with separated 0% and 100% positions */
+                  {
+                   value=item->value;
+                   if ( point - prev_point > M_PI )
+                   /* turned beyond the 0% position */
+                    {
+                     if ( !endstop )
+                      {
+                       endstop=STOPPED_AT_0;
+                       value=0.0f;
+                      }
+                    }
+                   else if ( prev_point - point > M_PI )
+                   /* turned back from beyond the 0% position */
+                    {
+                     if ( endstop == STOPPED_AT_0 ) endstop=False;
+                    }
+                   else if ( prev_point <= item->arclength && point > item->arclength )
+                   /* turned beyond the 100% position */
+                    {
+                     if ( !endstop )
+                      {
+                       endstop=STOPPED_AT_100;
+                       value=100.0f;
+                      }
+                    }
+                   else if ( prev_point > item->arclength && point <= item->arclength )
+                   /* turned back from beyond the 100% position */
+                    {
+                     if ( endstop == STOPPED_AT_100 ) endstop=False;
+                    }
+                  }
+                 if ( !endstop ) value=100.0 * point / item->arclength;
+                 prev_point=point;
+                 goto potihandled;
             case itVPotmeter:
                  value=100.0 - 100.0 * ( Y - item->y ) / item->height;
                  goto potihandled;

Modified: trunk/gui/ui/playbar.c
==============================================================================
--- trunk/gui/ui/playbar.c	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/ui/playbar.c	Sun Apr 13 01:29:29 2014	(r37149)
@@ -18,6 +18,7 @@
 
 /* playbar window */
 
+#include <math.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <sys/stat.h>
@@ -123,10 +124,13 @@ static void uiPlaybarMouse( int Button, 
  static int     itemtype = 0;
         int     i;
         guiItem * item = NULL;
+ static double  prev_point;
+        double  point;
         float   value = 0.0f;
 
  static int     SelectedItem = -1;
         int     currentselected = -1;
+ static int     endstop;
 
  for ( i=0;i <= guiApp.IndexOfPlaybarItems;i++ )
    if ( ( guiApp.playbarItems[i].pressed != btnDisabled )&&
@@ -162,6 +166,12 @@ static void uiPlaybarMouse( int Button, 
                  ( ( item->message == evPauseSwitchToPlay && item->message == evPlaySwitchToPause ) ) ) )
                  { item->pressed=btnDisabled; }
                break;
+          case itRPotmeter:
+               prev_point=appRadian( item, X - item->x, Y - item->y ) - item->zeropoint;
+               if ( prev_point < 0.0 ) prev_point+=2*M_PI;
+               if ( prev_point <= item->arclength ) endstop=False;
+               else endstop=STOPPED_AT_0 + STOPPED_AT_100;   // block movement
+               break;
          }
 
         break;
@@ -183,6 +193,12 @@ static void uiPlaybarMouse( int Button, 
           case itVPotmeter:
                value=100.0 - 100.0 * ( Y - item->y ) / item->height;
                break;
+          case itRPotmeter:
+               if ( endstop ) { itemtype=0; return; }
+               point=appRadian( item, X - item->x, Y - item->y ) - item->zeropoint;
+               if ( point < 0.0 ) point+=2*M_PI;
+               value=100.0 * point / item->arclength;
+               break;
          }
         uiEvent( item->message,value );
 
@@ -195,7 +211,7 @@ rollerhandled:
         if (currentselected != - 1)
          {
           item=&guiApp.playbarItems[currentselected];
-          if ( ( item->type == itHPotmeter )||( item->type == itVPotmeter ) )
+          if ( ( item->type == itHPotmeter )||( item->type == itVPotmeter )||( item->type == itRPotmeter ) )
            {
             item->value=constrain(item->value + value);
             uiEvent( item->message,item->value );
@@ -210,6 +226,45 @@ rollerhandled:
           case itPRMButton:
                if (guiApp.menuIsPresent) guiApp.menuWindow.MouseHandler( 0,RX,RY,0,0 );
                break;
+          case itRPotmeter:
+               point=appRadian( item, X - item->x, Y - item->y ) - item->zeropoint;
+               if ( point < 0.0 ) point+=2*M_PI;
+               if ( item->arclength < 2 * M_PI )
+               /* a potmeter with separated 0% and 100% positions */
+                {
+                 value=item->value;
+                 if ( point - prev_point > M_PI )
+                 /* turned beyond the 0% position */
+                  {
+                   if ( !endstop )
+                    {
+                     endstop=STOPPED_AT_0;
+                     value=0.0f;
+                    }
+                  }
+                 else if ( prev_point - point > M_PI )
+                 /* turned back from beyond the 0% position */
+                  {
+                   if ( endstop == STOPPED_AT_0 ) endstop=False;
+                  }
+                 else if ( prev_point <= item->arclength && point > item->arclength )
+                 /* turned beyond the 100% position */
+                  {
+                   if ( !endstop )
+                    {
+                     endstop=STOPPED_AT_100;
+                     value=100.0f;
+                    }
+                  }
+                 else if ( prev_point > item->arclength && point <= item->arclength )
+                 /* turned back from beyond the 100% position */
+                  {
+                   if ( endstop == STOPPED_AT_100 ) endstop=False;
+                  }
+                }
+               if ( !endstop ) value=100.0 * point / item->arclength;
+               prev_point=point;
+               goto potihandled;
           case itVPotmeter:
                value=100.0 - 100.0 * ( Y - item->y ) / item->height;
                goto potihandled;

Modified: trunk/gui/ui/render.c
==============================================================================
--- trunk/gui/ui/render.c	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/ui/render.c	Sun Apr 13 01:29:29 2014	(r37149)
@@ -21,6 +21,7 @@
  * @brief GUI rendering
  */
 
+#include <math.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -35,6 +36,7 @@
 #include "access_mpcontext.h"
 #include "help_mp.h"
 #include "libavutil/avstring.h"
+#include "libavutil/common.h"
 #include "osdep/timer.h"
 #include "stream/stream.h"
 
@@ -479,6 +481,29 @@ void RenderAll(wsWindow *window, guiItem
             PutImage(item->x, item->y + (item->height - item->pbheight) * (1.0 - item->value / 100.0), db, dw, &item->Mask, 3, index, True);
             break;
 
+        case itRPotmeter:
+
+            PutImage(item->x, item->y, db, dw, &item->Bitmap, item->numphases, (item->numphases - 1) * item->value / 100.0, True);
+
+            if (item->Mask.Image) {
+                double radius, radian;
+                int y;
+
+                // keep the button inside the potmeter outline
+                radius = (FFMIN(item->width, item->height) - FFMAX(item->pbwidth, item->pbheight)) / 2.0;
+
+                radian = item->value / 100.0 * item->arclength + item->zeropoint;
+
+                // coordinates plus a correction for a non-square item
+                // (remember: both axes are mirrored, we have a clockwise radian)
+                x = radius * (1 + cos(radian)) + FFMAX(0, (item->width - item->height) / 2.0) + 0.5;
+                y = radius * (1 + sin(radian)) + FFMAX(0, (item->height - item->width) / 2.0) + 0.5;
+
+                PutImage(item->x + x, item->y + y, db, dw, &item->Mask, 3, index, True);
+            }
+
+            break;
+
         case itSLabel:
 
             if (item->width == -1)

Modified: trunk/gui/ui/ui.h
==============================================================================
--- trunk/gui/ui/ui.h	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/ui/ui.h	Sun Apr 13 01:29:29 2014	(r37149)
@@ -19,6 +19,14 @@
 #ifndef MPLAYER_GUI_UI_H
 #define MPLAYER_GUI_UI_H
 
+/// End stops of a rotary potentiometer (::itRPotmeter)
+enum
+{
+  NOT_STOPPED,
+  STOPPED_AT_0,
+  STOPPED_AT_100
+};
+
 extern unsigned char * menuDrawBuffer;
 extern int             mainVisible;
 

Modified: trunk/gui/win32/gui.c
==============================================================================
--- trunk/gui/win32/gui.c	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/win32/gui.c	Sun Apr 13 01:29:29 2014	(r37149)
@@ -25,6 +25,7 @@
 #include <stdlib.h>
 #include <ctype.h>
 #include <fcntl.h>
+#include <math.h>
 #include <windows.h>
 #include <windowsx.h>
 #include <shlobj.h>
@@ -117,6 +118,19 @@ LPSTR acp (LPCSTR utf8)
     return "?";
 }
 
+double appRadian (widget *item, int x, int y)
+{
+  double tx, ty;
+
+  // transform the center to (0,0)
+  tx = x - item->wwidth / 2.0;
+  ty = y - item->wheight / 2.0;
+
+  // the y-axis is upside down and must be mirrored
+  // the x-axis is being mirrored for a clockwise radian
+  return (tx == 0.0 && ty == 0.0 ? 0.0 : atan2(-ty, -tx) + M_PI);
+}
+
 static void console_toggle(gui_t *gui)
 {
     if (console_state)
@@ -304,10 +318,10 @@ static void updatedisplay(gui_t *gui, HW
 
     if(!hwnd) return;
 
-    /* load all hpotmeters vpotmeters pimages */
+    /* load all hpotmeters vpotmeters rpotmeters pimages */
     for(i=0; i<gui->skin->widgetcount; i++)
     {
-        if(gui->skin->widgets[i]->type == tyHpotmeter || gui->skin->widgets[i]->type == tyVpotmeter || gui->skin->widgets[i]->type == tyPimage)
+        if(gui->skin->widgets[i]->type == tyHpotmeter || gui->skin->widgets[i]->type == tyVpotmeter || gui->skin->widgets[i]->type == tyRpotmeter || gui->skin->widgets[i]->type == tyPimage)
         {
             if(gui->skin->widgets[i]->msg == evSetVolume)
                 gui->skin->widgets[i]->value = guiInfo.Volume;
@@ -695,6 +709,8 @@ static LRESULT CALLBACK VideoProc(HWND h
 /* Window Proc for the gui Window */
 static LRESULT CALLBACK EventProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
 {
+    static double prev_point;
+    static int endstop;
     gui_t *gui = (gui_t *) GetWindowLongPtr(hWnd, GWLP_USERDATA);
 
     /* Avoid processing when then window doesn't match gui mainwindow */
@@ -833,6 +849,14 @@ static LRESULT CALLBACK EventProc(HWND h
                 renderwidget(gui->skin, get_drawground(hWnd), gui->activewidget, 0);
                 RedrawWindow(hWnd, NULL, NULL, RDW_INVALIDATE);
                 handlemsg(hWnd, gui->activewidget->msg);
+
+                if(gui->activewidget->type == tyRpotmeter)
+                {
+                    prev_point = appRadian(gui->activewidget, gui->mousewx, gui->mousewy) - gui->activewidget->zeropoint;
+                    if(prev_point < 0.0) prev_point += 2 * M_PI;
+                    if(prev_point <= gui->activewidget->arclength) endstop=FALSE;
+                    else endstop=STOPPED_AT_0 + STOPPED_AT_100;   // block movement
+                }
             }
             break;
         }
@@ -942,8 +966,49 @@ static LRESULT CALLBACK EventProc(HWND h
                         item->y = GET_Y_LPARAM(lParam) - gui->mousewy;
                         item->value = 100.0 - 100.0 * (item->y - item->wy) / (item->wheight - item->height);
                     }
+                    if(item->type == tyRpotmeter)
+                    {
+                        double point;
 
-                    if((item->type == tyHpotmeter) || (item->type == tyVpotmeter))
+                        point = appRadian(item, GET_X_LPARAM(lParam) - gui->activewidget->x, GET_Y_LPARAM(lParam) - gui->activewidget->y) - item->zeropoint;
+                        if(point < 0.0) point += 2 * M_PI;
+                        if(item->arclength < 2 * M_PI)
+                        /* a potmeter with separated 0% and 100% positions */
+                        {
+                            if(point - prev_point > M_PI)
+                            /* turned beyond the 0% position */
+                            {
+                                if(!endstop)
+                                {
+                                    endstop = STOPPED_AT_0;
+                                    item->value = 0.0f;
+                                }
+                            }
+                            else if(prev_point - point > M_PI)
+                            /* turned back from beyond the 0% position */
+                            {
+                                if(endstop == STOPPED_AT_0) endstop = FALSE;
+                            }
+                            else if(prev_point <= item->arclength && point > item->arclength)
+                            /* turned beyond the 100% position */
+                            {
+                                if (!endstop)
+                                {
+                                    endstop = STOPPED_AT_100;
+                                    item->value = 100.0f;
+                                }
+                            }
+                            else if(prev_point > item->arclength && point <= item->arclength)
+                            /* turned back from beyond the 100% position */
+                            {
+                                if(endstop == STOPPED_AT_100) endstop = FALSE;
+                            }
+                        }
+                        if(!endstop) item->value = 100.0 * point / item->arclength;
+                        prev_point = point;
+                    }
+
+                    if((item->type == tyHpotmeter) || (item->type == tyVpotmeter) || (item->type == tyRpotmeter))
                     {
                         /* Bound checks */
                         if(item->value > 100.0f)

Modified: trunk/gui/win32/gui.h
==============================================================================
--- trunk/gui/win32/gui.h	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/win32/gui.h	Sun Apr 13 01:29:29 2014	(r37149)
@@ -107,6 +107,7 @@ int create_videowindow(gui_t *gui);
 int parse_filename(char *file, play_tree_t *playtree, m_config_t *mconfig, int clear);
 void capitalize(char *fname);
 LPSTR acp(LPCSTR utf8);
+double appRadian(widget *item, int x, int y);
 
 void renderinfobox(skin_t *skin, window_priv_t *priv);
 void renderwidget(skin_t *skin, image *dest, widget *item, int state);

Modified: trunk/gui/win32/skinload.c
==============================================================================
--- trunk/gui/win32/skinload.c	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/win32/skinload.c	Sun Apr 13 01:29:29 2014	(r37149)
@@ -25,12 +25,15 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <inttypes.h>
+#include <math.h>
 #include <windows.h>
 
 #include "mp_msg.h"
 #include "help_mp.h"
 #include "cpudetect.h"
 #include "libswscale/swscale.h"
+#include "libavutil/attributes.h"
+#include "libavutil/common.h"
 #include "libavutil/imgutils.h"
 #include "gui.h"
 #include "gui/util/mem.h"
@@ -364,12 +367,13 @@ static void addwidget(skin_t *skin, wind
               (mywidget->bitmap[0]) ? mywidget->bitmap[0]->name : NULL,
                mywidget->x, mywidget->y, mywidget->width, mywidget->height, mywidget->msg);
     }
-    else if(!strncmp(desc, "hpotmeter", 9) || !strncmp(desc, "vpotmeter", 9) || /* legacy */ !strncmp(desc, "potmeter", 8))
+    else if(!strncmp(desc, "hpotmeter", 9) || !strncmp(desc, "vpotmeter", 9) || !strncmp(desc, "rpotmeter", 9) || /* legacy */ !strncmp(desc, "potmeter", 8))
     {
         int base = counttonextchar(desc, '=') + 1;
-        int i;
+        int i, av_uninit(x0), av_uninit(y0), av_uninit(x1), av_uninit(y1);
         /* hpotmeter = button, bwidth, bheight, phases, numphases, default, X, Y, width, height, message */
         if(!strncmp(desc, "vpotmeter", 9)) mywidget->type = tyVpotmeter;
+        else if(!strncmp(desc, "rpotmeter", 9)) mywidget->type = tyRpotmeter;
         else mywidget->type = tyHpotmeter;
         if (*desc == 'p')
         {
@@ -388,6 +392,15 @@ static void addwidget(skin_t *skin, wind
         }
         mywidget->bitmap[1] = pngRead(skin, findnextstring(temp, desc, &base));
         mywidget->phases = atoi(findnextstring(temp, desc, &base));
+
+        if (*desc == 'r')
+        {
+            x0 = atoi(findnextstring(temp, desc, &base));
+            y0 = atoi(findnextstring(temp, desc, &base));
+            x1 = atoi(findnextstring(temp, desc, &base));
+            y1 = atoi(findnextstring(temp, desc, &base));
+        }
+
         mywidget->value = atof(findnextstring(temp, desc, &base));
         mywidget->x = mywidget->wx = atoi(findnextstring(temp, desc, &base));
         mywidget->y = mywidget->wy = atoi(findnextstring(temp, desc, &base));
@@ -406,12 +419,24 @@ static void addwidget(skin_t *skin, wind
                 break;
             }
         }
-        mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[SKIN] [ITEM] %s %s %i %i %s %i %f %i %i %i %i msg %i\n",
-                (mywidget->type == tyHpotmeter) ? "[HPOTMETER]" : "[VPOTMETER]",
+        if (*desc == 'r')
+        {
+            mywidget->zeropoint = appRadian(mywidget, x0, y0);
+            mywidget->arclength = appRadian(mywidget, x1, y1) - mywidget->zeropoint;
+
+            if (mywidget->arclength < 0.0) mywidget->arclength += 2 * M_PI;
+            // else check if radians of (x0,y0) and (x1,y1) only differ below threshold
+            else if (mywidget->arclength < 0.05) mywidget->arclength = 2 * M_PI;
+        }
+        mp_msg(MSGT_GPLAYER, MSGL_DBG2, "[SKIN] [ITEM] %s %s %i %i %s %i ",
+                (mywidget->type == tyHpotmeter) ? "[HPOTMETER]" : (mywidget->type == tyVpotmeter) ? "[VPOTMETER]" : "[RPOTMETER]",
                 (mywidget->bitmap[0]) ? mywidget->bitmap[0]->name : NULL,
                 mywidget->width, mywidget->height,
                 (mywidget->bitmap[1]) ? mywidget->bitmap[1]->name : NULL,
-                mywidget->phases, mywidget->value,
+                mywidget->phases);
+        if (*desc == 'r')
+            mp_msg(MSGT_GPLAYER, MSGL_DBG2, "%i,%i %i,%i ", x0, y0, x1, y1);
+        mp_msg(MSGT_GPLAYER, MSGL_DBG2, "%f %i %i %i %i msg %i\n", mywidget->value,
                 mywidget->wx, mywidget->wy, mywidget->wwidth, mywidget->wwidth,
                 mywidget->msg);
         if (mywidget->bitmap[0] == NULL || mywidget->width == 0 || mywidget->height == 0)
@@ -420,6 +445,14 @@ static void addwidget(skin_t *skin, wind
             mywidget->width = mywidget->wwidth;
             mywidget->height = mywidget->wheight;
         }
+        if (*desc == 'r')
+        {
+            mywidget->maxwh = FFMAX(mywidget->width, mywidget->height);
+
+            // clickedinsidewidget() checks with width/height, so set it
+            mywidget->width = mywidget->wwidth;
+            mywidget->height = mywidget->wheight;
+        }
     }
     else if(!strncmp(desc, "pimage", 6))
     {

Modified: trunk/gui/win32/skinload.h
==============================================================================
--- trunk/gui/win32/skinload.h	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/win32/skinload.h	Sun Apr 13 01:29:29 2014	(r37149)
@@ -61,12 +61,15 @@ typedef struct
     int width, height;              /* width and height of the button */
     int wwidth, wheight;            /* width and height of the widget */
     // ---
+    int maxwh;
     // ---
     int msg, msg2;
     int pressed, tmp;
     int key, key2;
     int phases;
     float value;
+    double zeropoint;
+    double arclength;
     image *bitmap[2];               /* Associated image(s) in imagepool */
     // ---
     font_t *font;
@@ -121,6 +124,7 @@ skin_t *loadskin(char *skindir, int desk
 #define tyMenu          6
 #define tySlabel        7
 #define tyDlabel        8
+#define tyRpotmeter     9
 
 /* --- Window types --- */
 

Modified: trunk/gui/win32/widgetrender.c
==============================================================================
--- trunk/gui/win32/widgetrender.c	Fri Apr 11 11:34:31 2014	(r37148)
+++ trunk/gui/win32/widgetrender.c	Sun Apr 13 01:29:29 2014	(r37149)
@@ -24,6 +24,7 @@
 #include <stdio.h>
 #include <string.h>
 #include <ctype.h>
+#include <math.h>
 #include <windows.h>
 
 #include "gui/util/bitmap.h"
@@ -34,6 +35,7 @@
 #include "access_mpcontext.h"
 #include "help_mp.h"
 #include "libavutil/avstring.h"
+#include "libavutil/common.h"
 #include "stream/stream.h"
 
 #define MAX_LABELSIZE 250
@@ -409,11 +411,13 @@ void renderwidget(skin_t *skin, image *d
     if(!dest) return;
     if((item->type == tyButton) || (item->type == tyHpotmeter) || (item->type == tyVpotmeter) || (item->type == tyPimage))
         img = item->bitmap[0];
+    if(item->type == tyRpotmeter)
+        img = item->bitmap[1];
 
     if(!img) return;
 
     y = item->y;
-    if(item->type == tyPimage || /* legacy (potmeter) */ (item->type == tyHpotmeter && item->width == item->wwidth))
+    if(item->type == tyPimage || /* legacy (potmeter) */ (item->type == tyHpotmeter && item->width == item->wwidth) || item->type == tyRpotmeter)
     {
         height = img->height / item->phases;
         y =  height * (int)(item->value * item->phases / 100);
@@ -430,7 +434,7 @@ void renderwidget(skin_t *skin, image *d
     if(item->type == tyButton)
         render(skin->desktopbpp, dest, find_background(skin,item), item->x, item->y, item->x, item->y, img->width, height, 1);
 
-    if((item->type == tyHpotmeter) || (item->type == tyVpotmeter) || (item->type == tyPimage))
+    if((item->type == tyHpotmeter) || (item->type == tyVpotmeter) || (item->type == tyRpotmeter) || (item->type == tyPimage))
     {
         if(item->type == tyVpotmeter)
         {
@@ -438,6 +442,13 @@ void renderwidget(skin_t *skin, image *d
             render(skin->desktopbpp, dest, find_background(skin, item), item->wx, item->wy, item->wx, item->wy, item->width, item->wheight, 1);
             item->y = (100 - item->value) * (item->wheight-item->height) / 100 + item->wy;
         }
+        else if(item->type == tyRpotmeter)
+        {
+            /* repaint the area behind the rpotmeter */
+            render(skin->desktopbpp, dest, find_background(skin, item), item->wx, item->wy, item->wx, item->wy, item->wwidth, item->wheight, 1);
+            item->x = item->wx;
+            item->y = item->wy;
+        }
         else
         {
             /* repaint the area behind the slider */
@@ -446,4 +457,31 @@ void renderwidget(skin_t *skin, image *d
         }
     }
     render(skin->desktopbpp, dest, img, item->x, item->y, 0, y, img->width, height, 1);
+
+    /* rpotmeter button */
+    if(item->type == tyRpotmeter && item->bitmap[0] != item->bitmap[1])
+    {
+        img = item->bitmap[0];
+
+        if(img)
+        {
+            double radius, radian;
+            int ix, iy;
+
+            // keep the button inside the potmeter outline
+            radius = (FFMIN(item->wwidth, item->wheight) - item->maxwh) / 2.0;
+
+            radian = item->value / 100.0 * item->arclength + item->zeropoint;
+
+            // coordinates plus a correction for a non-square item
+            // (remember: both axes are mirrored, we have a clockwise radian)
+            ix = item->wx + radius * (1 + cos(radian)) + FFMAX(0, (item->wwidth - item->wheight) / 2.0) + 0.5;
+            iy = item->wy + radius * (1 + sin(radian)) + FFMAX(0, (item->wheight - item->wwidth) / 2.0) + 0.5;
+
+            height = img->height / 3;
+            y = state * height;
+
+            render(skin->desktopbpp, dest, img, ix, iy, 0, y, img->width, height, 1);
+        }
+    }
 }


More information about the MPlayer-cvslog mailing list