diff gui/win32/skinload.c @ 23077:17bf4f4b0715

Gui --> gui
author diego
date Mon, 23 Apr 2007 07:42:42 +0000
parents
children f81cd5be161b
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gui/win32/skinload.c	Mon Apr 23 07:42:42 2007 +0000
@@ -0,0 +1,809 @@
+/*
+  MPlayer Gui for win32
+  Copyright (c) 2003 Sascha Sommer <saschasommer@freenet.de>
+  Copyright (c) 2006 Erik Augustson <erik_27can@yahoo.com>
+  Copyright (c) 2006 Gianluigi Tiesi <sherpya@netfarm.it>
+
+  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., 51 Franklin St, Fifth Floor, Boston, MA 02111-1307 USA
+*/
+
+#include <stdlib.h>
+#include <inttypes.h>
+#include <windows.h>
+#include <png.h>
+
+#include <mp_msg.h>
+#include <cpudetect.h>
+#include <libswscale/rgb2rgb.h>
+#include <libswscale/swscale.h>
+
+#include "gui.h"
+
+#define MAX_LINESIZE 256
+
+typedef struct
+{
+    int msg;
+    char *name;
+} evName;
+
+static const evName evNames[] =
+{
+    {   evNone,                 "evNone"                },
+    {   evPlay,                 "evPlay"                },
+    {   evDropFile,             "evDropFile"            },
+    {   evStop,                 "evStop"                },
+    {   evPause,                "evPause"               },
+    {   evPrev,                 "evPrev"                },
+    {   evNext,                 "evNext"                },
+    {   evLoad,                 "evLoad"                },
+    {   evEqualizer,            "evEqualizer"           },
+    {   evEqualizer,            "evEqualeaser"          },
+    {   evPlayList,             "evPlaylist"            },
+    {   evExit,                 "evExit"                },
+    {   evIconify,              "evIconify"             },
+    {   evIncBalance,           "evIncBalance"          },
+    {   evDecBalance,           "evDecBalance"          },
+    {   evFullScreen,           "evFullScreen"          },
+    {   evFName,                "evFName"               },
+    {   evMovieTime,            "evMovieTime"           },
+    {   evAbout,                "evAbout"               },
+    {   evLoadPlay,             "evLoadPlay"            },
+    {   evPreferences,          "evPreferences"         },
+    {   evSkinBrowser,          "evSkinBrowser"         },
+    {   evBackward10sec,        "evBackward10sec"       },
+    {   evForward10sec,         "evForward10sec"        },
+    {   evBackward1min,         "evBackward1min"        },
+    {   evForward1min,          "evForward1min"         },
+    {   evBackward10min,        "evBackward10min"       },
+    {   evForward10min,         "evForward10min"        },
+    {   evIncVolume,            "evIncVolume"           },
+    {   evDecVolume,            "evDecVolume"           },
+    {   evMute,                 "evMute"                },
+    {   evIncAudioBufDelay,     "evIncAudioBufDelay"    },
+    {   evDecAudioBufDelay,     "evDecAudioBufDelay"    },
+    {   evPlaySwitchToPause,    "evPlaySwitchToPause"   },
+    {   evPauseSwitchToPlay,    "evPauseSwitchToPlay"   },
+    {   evNormalSize,           "evNormalSize"          },
+    {   evDoubleSize,           "evDoubleSize"          },
+    {   evSetMoviePosition,     "evSetMoviePosition"    },
+    {   evSetVolume,            "evSetVolume"           },
+    {   evSetBalance,           "evSetBalance"          },
+    {   evHelp,                 "evHelp"                },
+    {   evLoadSubtitle,         "evLoadSubtitle"        },
+    {   evPlayDVD,              "evPlayDVD"             },
+    {   evPlayVCD,              "evPlayVCD"             },
+    {   evSetURL,               "evSetURL"              },
+    {   evLoadAudioFile,        "evLoadAudioFile"       },
+    {   evDropSubtitle,         "evDropSubtitle"        },
+    {   evSetAspect,            "evSetAspect"           }
+};
+
+static const int evBoxs = sizeof(evNames) / sizeof(evName);
+
+static char *geteventname(int event)
+{
+    int i;
+    for(i=0; i<evBoxs; i++)
+        if(evNames[i].msg == event)
+            return evNames[i].name;
+    return NULL;
+}
+
+static inline int get_sws_cpuflags(void)
+{
+    return (gCpuCaps.hasMMX ? SWS_CPU_CAPS_MMX : 0) |
+           (gCpuCaps.hasMMX2 ? SWS_CPU_CAPS_MMX2 : 0) |
+           (gCpuCaps.has3DNow ? SWS_CPU_CAPS_3DNOW : 0);
+}
+
+/* reads a complete image as is into image buffer */
+static image *pngRead(skin_t *skin, unsigned char *fname)
+{
+    unsigned char header[8];
+    png_structp png;
+    png_infop info;
+    png_infop endinfo;
+    png_bytep *row_p;
+    int color, h;
+    png_uint_32 i;
+    int BPP;
+    char *img;
+    unsigned int imgsize;
+    image *bf;
+    char *filename;
+    FILE *fp;
+
+    if(!stricmp(fname, "NULL")) return 0;
+
+    /* find filename in order file file.png */
+    if(!(fp = fopen(fname, "rb")))
+    {
+        filename = calloc(1, strlen(skin->skindir) + strlen(fname) + 6);
+        sprintf(filename, "%s\\%s.png", skin->skindir, fname);
+        if(!(fp = fopen(filename, "rb")))
+        {
+            mp_msg(MSGT_GPLAYER, MSGL_ERR, "[png] cannot find image %s\n", filename);
+            free(filename);
+            return 0;
+        }
+        free(filename);
+    }
+
+    for (i=0; i < skin->imagecount; i++)
+        if(!strcmp(fname, skin->images[i]->name))
+        {
+#ifdef DEBUG
+            mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[png] skinfile %s already exists\n", fname);
+#endif
+            return skin->images[i];
+        }
+    (skin->imagecount)++;
+    skin->images = realloc(skin->images, sizeof(image *) * skin->imagecount);
+    bf = skin->images[(skin->imagecount) - 1] = calloc(1, sizeof(image));
+    bf->name = strdup(fname);
+    fread(header,1,8,fp);
+    if (!png_check_sig(header, 8)) return 0;
+    png = png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+    info = png_create_info_struct(png);
+    endinfo = png_create_info_struct(png);
+
+    png_init_io(png, fp);
+    png_set_sig_bytes(png, 8);
+    png_read_info(png, info);
+    png_get_IHDR(png, info, (png_uint_32*) &bf->width, (png_uint_32*) &bf->height, &BPP, &color, NULL, NULL, NULL);
+
+    if(color & PNG_COLOR_MASK_ALPHA)
+    {
+        if(color & PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY_ALPHA ) BPP *= 2;
+        else BPP *= 4;
+    }
+    else
+    {
+        if(color & PNG_COLOR_MASK_PALETTE || color == PNG_COLOR_TYPE_GRAY ) BPP *= 1;
+        else BPP *= 3;
+    }
+    row_p = (png_bytep *) malloc (sizeof(png_bytep) * bf->height);
+    img = (png_bytep) calloc(png_get_rowbytes(png, info), bf->height);
+    for (h=0; h < bf->height; h++)
+        row_p[h] = &img[png_get_rowbytes(png, info) * h];
+    png_read_image(png, row_p);
+    free(row_p);
+
+    png_read_end(png, endinfo);
+    png_destroy_read_struct(&png, &info, &endinfo);
+    fclose(fp);
+    imgsize=bf->width * bf->height * (BPP / 8);
+
+#ifdef DEBUG
+    mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[png] loaded image %s\n", fname);
+    mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[png] size: %dx%d bits: %d\n", bf->width, bf->height, BPP);
+    mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[png] imagesize: %u\n", imgsize);
+#endif
+
+    bf->size = bf->width * bf->height * skin->desktopbpp / 8;
+    bf->data = malloc(bf->size);
+    if(skin->desktopbpp == 16 && BPP == 24) rgb24tobgr15(img, bf->data, imgsize);
+    else if(skin->desktopbpp == 16 && BPP == 32) rgb32tobgr15(img, bf->data, imgsize);
+    else if(skin->desktopbpp == 24 && BPP == 24) rgb24tobgr24(img, bf->data, imgsize);
+    else if(skin->desktopbpp == 24 && BPP == 32) rgb32tobgr24(img, bf->data, imgsize);
+    else if(skin->desktopbpp == 32 && BPP == 24) rgb24tobgr32(img, bf->data, imgsize);
+    else if(skin->desktopbpp == 32 && BPP == 32) rgb32tobgr32(img, bf->data, imgsize);
+    free(img);
+    return bf;
+}
+
+/* frees all skin images */
+static void freeimages(skin_t *skin)
+{
+    unsigned int i;
+    for (i=0; i<skin->imagecount; i++)
+    {
+        if(skin->images && skin->images[i])
+        {
+            if(skin->images[i]->data) free(skin->images[i]->data);
+            if(skin->images[i]->name) free(skin->images[i]->name);
+            free(skin->images[i]);
+        }
+    }
+    free(skin->images);
+}
+
+#ifdef DEBUG
+void dumpwidgets(skin_t *skin)
+{
+    unsigned int i;
+    for (i=0; i<skin->widgetcount; i++)
+        mp_msg(MSGT_GPLAYER, MSGL_V, "widget %p id %i\n", skin->widgets[i], skin->widgets[i]->id);
+}
+#endif
+
+static int counttonextchar(const char *s1, char c)
+{
+    unsigned int i;
+    for (i=0; i<strlen(s1); i++)
+        if(s1[i] == c) return i;
+    return 0;
+}
+
+static char *findnextstring(char *temp, const char *desc, int *base)
+{
+    int len = counttonextchar(*base + desc, ',');
+    memset(temp, 0, strlen(desc) + 1);
+    if(!len) len = strlen(desc);
+    memcpy(temp, *base + desc, len);
+    *base += (len+1);
+    return temp;
+}
+
+static void freeskin(skin_t *skin)
+{
+    unsigned int i;
+    if(skin->skindir)
+    {
+        free(skin->skindir);
+        skin->skindir = NULL;
+    }
+
+    for (i=1; i<=skin->lastusedid; i++)
+        skin->removewidget(skin, i);
+
+    if(skin->widgets)
+    {
+        free(skin->widgets);
+        skin->widgets = NULL;
+    }
+
+    freeimages(skin);
+    for(i=0; i<skin->windowcount; i++)
+    {
+        if(skin->windows[i]->name)
+        {
+            free(skin->windows[i]->name);
+            skin->windows[i]->name = NULL;
+        }
+        free(skin->windows[i]);
+    }
+
+    free(skin->windows);
+    skin->windows = NULL;
+
+    for (i=0; i<skin->fontcount; i++)
+    {
+        unsigned int x;
+        if(skin->fonts[i]->name)
+        {
+            free(skin->fonts[i]->name);
+            skin->fonts[i]->name = NULL;
+        }
+
+        if(skin->fonts[i]->id)
+        {
+            free(skin->fonts[i]->id);
+            skin->fonts[i]->id = NULL;
+        }
+
+        for (x=0; x<skin->fonts[i]->charcount; x++)
+        {
+            free(skin->fonts[i]->chars[x]);
+            skin->fonts[i]->chars[x] = NULL;
+        }
+
+        if(skin->fonts[i]->chars)
+        {
+            free(skin->fonts[i]->chars);
+            skin->fonts[i]->chars = NULL;
+        }
+
+        free(skin->fonts[i]);
+        skin->fonts[i] = NULL;
+    }
+    free(skin->fonts);
+    skin->fonts = NULL;
+#ifdef DEBUG
+    mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN FREE] skin freed\n");
+#endif
+    free(skin);
+    skin = NULL;
+}
+
+static void removewidget(skin_t *skin, int id)
+{
+    unsigned int i;
+    unsigned int pos=0;
+    widget **temp = calloc(skin->widgetcount - 1, sizeof(widget *));
+
+    for (i=0; i<skin->widgetcount; i++)
+    {
+        if(skin->widgets[i]->id == id)
+        {
+            if(skin->widgets[i]->label)
+                free(skin->widgets[i]->label);
+            free(skin->widgets[i]);
+            skin->widgets[i] = NULL;
+        }
+        else
+        {
+            temp[pos] = skin->widgets[i];
+            pos++;
+        }
+    }
+    if (pos != i)
+    {
+        (skin->widgetcount)--;
+        free(skin->widgets);
+        skin->widgets = temp;
+#ifdef DEBUG
+        mp_msg(MSGT_GPLAYER, MSGL_DBG4, "removed widget %i\n", id);
+#endif
+        return;
+    }
+    free(temp);
+    mp_msg(MSGT_GPLAYER, MSGL_ERR, "widget %i not found\n", id);
+}
+
+static void addwidget(skin_t *skin, window *win, const char *desc)
+{
+    widget *mywidget;
+    char *temp = calloc(1, strlen(desc) + 1);
+    (skin->widgetcount)++;
+    (skin->lastusedid)++;
+    skin->widgets = realloc(skin->widgets, sizeof(widget *) * skin->widgetcount);
+    mywidget = skin->widgets[(skin->widgetcount) - 1] = calloc(1, sizeof(widget));
+    mywidget->id = skin->lastusedid;
+    mywidget->window = win->type;
+    /* parse and fill widget specific info */
+    if(!strncmp(desc, "base", 4))
+    {
+        int base = counttonextchar(desc, '=') + 1;
+        mywidget->type = tyBase;
+        mywidget->bitmap[0] = pngRead(skin, findnextstring(temp, desc, &base));
+        mywidget->wx = mywidget->x = atoi(findnextstring(temp, desc, &base));
+        mywidget->wy = mywidget->y = atoi(findnextstring(temp, desc, &base));
+        mywidget->wwidth = mywidget->width = atoi(findnextstring(temp, desc, &base));
+        mywidget->wheight = mywidget->height = atoi(findnextstring(temp, desc, &base));
+        win->base = mywidget;
+#ifdef DEBUG
+        mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [BASE] %s %i %i %i %i\n",
+              (mywidget->bitmap[0]) ? mywidget->bitmap[0]->name : NULL,
+               mywidget->x, mywidget->y, mywidget->width, mywidget->height);
+#endif
+    }
+    else if(!strncmp(desc, "button", 6))
+    {
+        int base = counttonextchar(desc, '=') + 1;
+        int i;
+        mywidget->type = tyButton;
+        mywidget->bitmap[0] = pngRead(skin, findnextstring(temp, desc, &base));
+        mywidget->wx = mywidget->x = atoi(findnextstring(temp, desc, &base));
+        mywidget->wy = mywidget->y = atoi(findnextstring(temp, desc, &base));
+        mywidget->wwidth = mywidget->width = atoi(findnextstring(temp, desc, &base));
+        mywidget->wheight = mywidget->height = atoi(findnextstring(temp, desc, &base));
+        findnextstring(temp, desc, &base);
+
+        /* Assign corresponding event to the widget */
+        mywidget->msg = evNone;
+        for (i=0; i<evBoxs; i++)
+        {
+            if(!strcmp(temp, evNames[i].name))
+            {
+                mywidget->msg = evNames[i].msg;
+                break;
+            }
+        }
+
+#ifdef DEBUG
+        mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [BUTTON] %s %i %i %i %i msg %i\n",
+              (mywidget->bitmap[0]) ? mywidget->bitmap[0]->name : NULL,
+               mywidget->x, mywidget->y, mywidget->width, mywidget->height, mywidget->msg);
+#endif
+    }
+    else if(!strncmp(desc, "hpotmeter", 9) || !strncmp(desc, "vpotmeter", 9))
+    {
+        int base = counttonextchar(desc, '=') + 1;
+        int i;
+        /* hpotmeter = button, bwidth, bheight, phases, numphases, default, X, Y, width, height, message */
+        if(!strncmp(desc, "hpotmeter", 9)) mywidget->type = tyHpotmeter;
+        else mywidget->type = tyVpotmeter;
+        mywidget->bitmap[0] = pngRead(skin, findnextstring(temp, desc, &base));
+        mywidget->width = atoi(findnextstring(temp, desc, &base));
+        mywidget->height = atoi(findnextstring(temp, desc, &base));
+        mywidget->bitmap[1] = pngRead(skin, findnextstring(temp, desc, &base));
+        mywidget->phases = 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));
+        mywidget->wwidth = atoi(findnextstring(temp, desc, &base));
+        mywidget->wheight = atoi(findnextstring(temp, desc, &base));
+        findnextstring(temp, desc, &base);
+        mywidget->msg = evNone;
+        for (i=0; i<evBoxs; i++)
+        {
+            if(!strcmp(temp, evNames[i].name))
+            {
+                mywidget->msg = evNames[i].msg;
+                break;
+            }
+        }
+#ifdef DEBUG
+        mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] %s %s %i %i %s %i %f %i %i %i %i msg %i\n",
+                (mywidget->type == tyHpotmeter) ? "[HPOTMETER]" : "[VPOTMETER]",
+                (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->wx, mywidget->wy, mywidget->wwidth, mywidget->wwidth,
+                mywidget->msg);
+#endif
+    }
+    else if(!strncmp(desc, "potmeter", 8))
+    {
+        int base = counttonextchar(desc, '=') + 1;
+        int i;
+        /* potmeter = phases, numphases, default, X, Y, width, height, message */
+        mywidget->type = tyPotmeter;
+        mywidget->bitmap[0] = pngRead(skin, findnextstring(temp, desc, &base));
+        mywidget->phases = atoi(findnextstring(temp, desc, &base));
+        mywidget->value = atof(findnextstring(temp, desc, &base));
+        mywidget->wx = mywidget->x = atoi(findnextstring(temp, desc, &base));
+        mywidget->wy = mywidget->y = atoi(findnextstring(temp, desc, &base));
+        mywidget->wwidth = mywidget->width = atoi(findnextstring(temp, desc, &base));
+        mywidget->wheight = mywidget->height = atoi(findnextstring(temp, desc, &base));
+        findnextstring(temp, desc, &base);
+        mywidget->msg = evNone;
+        for (i=0; i<evBoxs; i++)
+        {
+            if(!strcmp(temp, evNames[i].name))
+            {
+                mywidget->msg=evNames[i].msg;
+                break;
+            }
+        }
+#ifdef DEBUG
+        mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [POTMETER] %s %i %i %i %f %i %i msg %i\n",
+                (mywidget->bitmap[0]) ? mywidget->bitmap[0]->name : NULL,
+                mywidget->width, mywidget->height,
+                mywidget->phases, mywidget->value,
+                mywidget->x, mywidget->y,
+                mywidget->msg);
+#endif
+    }
+    else if(!strncmp(desc, "menu", 4))
+    {
+        int base = counttonextchar(desc, '=') + 1;
+        int i;
+        mywidget->type = tyMenu;
+        mywidget->wx=atoi(findnextstring(temp, desc, &base));
+        mywidget->x=0;
+        mywidget->wy=mywidget->y=atoi(findnextstring(temp, desc, &base));
+        mywidget->wwidth=mywidget->width=atoi(findnextstring(temp, desc, &base));
+        mywidget->wheight=mywidget->height=atoi(findnextstring(temp, desc, &base));
+        findnextstring(temp, desc, &base);
+        mywidget->msg = evNone;
+        for (i=0; i<evBoxs; i++)
+        {
+            if(!strcmp(temp, evNames[i].name))
+            {
+                mywidget->msg = evNames[i].msg;
+                break;
+            }
+        }
+#ifdef DEBUG
+        mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [MENU] %i %i %i %i msg %i\n",
+               mywidget->x, mywidget->y, mywidget->width, mywidget->height, mywidget->msg);
+#endif
+    }
+    else if(!strncmp(desc, "selected", 8))
+    {
+        win->base->bitmap[1] = pngRead(skin, (char *) desc + 9);
+#ifdef DEBUG
+        mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [BASE] added image %s\n", win->base->bitmap[1]->name);
+#endif
+    }
+    else if(!strncmp(desc, "slabel",6))
+    {
+        int base = counttonextchar(desc, '=') + 1;
+        unsigned int i;
+        mywidget->type = tySlabel;
+        mywidget->wx = mywidget->x = atoi(findnextstring(temp, desc, &base));
+        mywidget->wy = mywidget->y = atoi(findnextstring(temp, desc, &base));
+        findnextstring(temp, desc, &base);
+        mywidget->font = NULL;
+        for (i=0; i<skin->fontcount; i++)
+        {
+            if(!strcmp(temp, skin->fonts[i]->name))
+            {
+                mywidget->font = skin->fonts[i];
+                break;
+            }
+        }
+        mywidget->label = strdup(findnextstring(temp, desc, &base));
+#ifdef DEBUG
+        mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [SLABEL] %i %i %s %s\n",
+               mywidget->x, mywidget->y, mywidget->font->name, mywidget->label);
+#endif
+    }
+    else if(!strncmp(desc, "dlabel", 6))
+    {
+        int base = counttonextchar(desc, '=') + 1;
+        unsigned int i;
+        mywidget->type = tyDlabel;
+        mywidget->wx = mywidget->x = atoi(findnextstring(temp, desc, &base));
+        mywidget->wy = mywidget->y = atoi(findnextstring(temp, desc, &base));
+        mywidget->length = atoi(findnextstring(temp, desc, &base));
+        mywidget->align = atoi(findnextstring(temp, desc, &base));
+        findnextstring(temp, desc, &base);
+        mywidget->font = NULL;
+        for (i=0; i<skin->fontcount; i++)
+        {
+            if(!strcmp(temp, skin->fonts[i]->name))
+            {
+                mywidget->font=skin->fonts[i];
+                break;
+            }
+        }
+        mywidget->label=strdup(findnextstring(temp, desc, &base));
+#ifdef DEBUG
+        mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [ITEM] [DLABEL] %i %i %i %i %s \"%s\"\n",
+               mywidget->x, mywidget->y, mywidget->length, mywidget->align, mywidget->font->name, mywidget->label);
+#endif
+    }
+    free(temp);
+}
+
+static void loadfonts(skin_t* skin)
+{
+    unsigned int x;
+    for (x=0; x<skin->fontcount; x++)
+    {
+        FILE *fp;
+        int linenumber=0;
+        char *filename;
+        char *tmp = calloc(1, MAX_LINESIZE);
+        char *desc = calloc(1, MAX_LINESIZE);
+        filename = calloc(1, strlen(skin->skindir) + strlen(skin->fonts[x]->name) + 6);
+        sprintf(filename, "%s\\%s.fnt", skin->skindir, skin->fonts[x]->name);
+        if(!(fp = fopen(filename,"rb")))
+        {
+            mp_msg(MSGT_GPLAYER, MSGL_ERR, "[FONT LOAD] Font not found \"%s\"\n", skin->fonts[x]->name);
+            return;
+        }
+        while(!feof(fp))
+        {
+            int pos = 0;
+            unsigned int i;
+            fgets(tmp, MAX_LINESIZE, fp);
+            linenumber++;
+            memset(desc, 0, MAX_LINESIZE);
+            for (i=0; i<strlen(tmp); i++)
+            {
+                /* remove spaces and linebreaks */
+                if((tmp[i] == ' ') || (tmp[i] == '\n') || (tmp[i] == '\r')) continue;
+                /* remove comments */
+                if((tmp[i] == ';') &&  ((i < 1) || (tmp[i-1] != '\"')))
+                {
+#ifdef DEBUG
+                    mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[FONT LOAD] Comment: %s", tmp + i + 1);
+#endif
+                    break;
+                }
+                desc[pos] = tmp[i];
+                pos++;
+            }
+            if(!strlen(desc)) continue;
+            /* now we have "readable" output -> parse it */
+            if(!strncmp(desc, "image", 5))
+            {
+                skin->fonts[x]->image = pngRead(skin, desc + 6);
+#ifdef DEBUG
+                mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[FONT] [IMAGE] \"%s\"\n", desc + 6);
+#endif
+            }
+            else
+            {
+                int base = 4;
+                if(*desc != '"') break;
+                if(*(desc + 1) == 0) break;
+                (skin->fonts[x]->charcount)++;
+                skin->fonts[x]->chars = realloc(skin->fonts[x]->chars, sizeof(char_t *) *skin->fonts[x]->charcount);
+                skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]=calloc(1, sizeof(char_t));
+                skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->c = ((*(desc + 1) == '"') && (*(desc + 2) != '"')) ? ' ': *(desc + 1);
+                if((*(desc + 1) == '"') && (*(desc + 2) != '"')) base = 3;
+                skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->x = atoi(findnextstring(tmp, desc, &base));
+                skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->y = atoi(findnextstring(tmp, desc, &base));
+                skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->width = atoi(findnextstring(tmp, desc, &base));
+                skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->height = atoi(findnextstring(tmp, desc, &base));
+#ifdef DEBUG
+                mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[FONT] [CHAR] %c %i %i %i %i\n",
+                        skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->c,
+                        skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->x,
+                        skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->y,
+                        skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->width,
+                        skin->fonts[x]->chars[skin->fonts[x]->charcount - 1]->height);
+#endif
+            }
+        }
+        free(desc);
+        free(filename);
+        free(tmp);
+        fclose(fp);
+    }
+}
+
+skin_t* loadskin(char* skindir, int desktopbpp)
+{
+    FILE *fp;
+    int reachedendofwindow = 0;
+    int linenumber = 0;
+    skin_t *skin = calloc(1, sizeof(skin_t));
+    char *filename;
+    char *tmp = calloc(1, MAX_LINESIZE);
+    char *desc = calloc(1, MAX_LINESIZE);
+    window* mywindow = NULL;
+
+    /* init swscaler */
+    sws_rgb2rgb_init(get_sws_cpuflags());
+    /* setup funcs */
+    skin->freeskin = freeskin;
+    skin->pngRead = pngRead;
+    skin->addwidget = addwidget;
+    skin->removewidget = removewidget;
+    skin->geteventname = geteventname;
+    skin->desktopbpp = desktopbpp;
+    skin->skindir = strdup(skindir);
+
+    filename = calloc(1, strlen(skin->skindir) + strlen("skin") + 2);
+    sprintf(filename, "%s\\skin", skin->skindir);
+    if(!(fp = fopen(filename, "rb")))
+    {
+        mp_msg(MSGT_GPLAYER, MSGL_FATAL, "[SKIN LOAD] Skin \"%s\" not found\n", skindir);
+        skin->freeskin(skin);
+        return NULL;
+    }
+
+    while(!feof(fp))
+    {
+        int pos = 0;
+        unsigned int i;
+        int insidequote = 0;
+        fgets(tmp, MAX_LINESIZE, fp);
+        linenumber++;
+        memset(desc, 0, MAX_LINESIZE);
+        for (i=0; i<strlen(tmp); i++)
+        {
+            if((tmp[i] == '"') && !insidequote) { insidequote=1; continue; }
+            else if((tmp[i] == '"') && insidequote) { insidequote=0 ; continue; }
+            /* remove spaces and linebreaks */
+            if((!insidequote && (tmp[i] == ' ')) || (tmp[i] == '\n') || (tmp[i] == '\r')) continue;
+            /* remove comments */
+            else if(tmp[i] == ';')
+            {
+#ifdef DEBUG
+                mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN LOAD] Comment: %s", tmp + i + 1);
+#endif
+                break;
+            }
+            desc[pos] = tmp[i];
+            pos++;
+        }
+
+        if(!strlen(desc)) continue;
+        /* now we have "readable" output -> parse it */
+        /* parse window specific info */
+        if(!strncmp(desc, "section", 7))
+        {
+#ifdef DEBUG
+            mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [SECTION] \"%s\"\n", desc + 8);
+#endif
+        }
+        else if(!strncmp(desc, "window", 6))
+        {
+#ifdef DEBUG
+            mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [WINDOW] \"%s\"\n", desc + 7);
+#endif
+            reachedendofwindow = 0;
+            (skin->windowcount)++;
+            skin->windows = realloc(skin->windows, sizeof(window *) * skin->windowcount);
+            mywindow = skin->windows[(skin->windowcount) - 1] = calloc(1, sizeof(window));
+            mywindow->name = strdup(desc + 7);
+            if(!strncmp(desc + 7, "main", 4)) mywindow->type = wiMain;
+            else if(!strncmp(desc+7, "sub", 3))
+            {
+                mywindow->type = wiSub;
+                mywindow->decoration = 1;
+            }
+            else if(!strncmp(desc + 7, "menu", 4)) mywindow->type = wiMenu;
+            else if(!strncmp(desc + 7, "playbar", 7)) mywindow->type = wiPlaybar;
+            else mp_msg(MSGT_GPLAYER, MSGL_V, "[SKIN] warning found unknown windowtype");
+        }
+        else if(!strncmp(desc, "decoration", 10) && !strncmp(desc + 11, "enable", 6))
+        {
+            mywindow->decoration = 1;
+#ifdef DEBUG
+            mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [DECORATION] enabled decoration for window \"%s\"\n", mywindow->name);
+#endif
+        }
+        else if(!strncmp(desc, "background", 10))
+        {
+            int base = counttonextchar(desc, '=') + 1;
+            char temp[MAX_LINESIZE];
+            mywindow->backgroundcolor[0] = atoi(findnextstring(temp, desc, &base));
+            mywindow->backgroundcolor[1] = atoi(findnextstring(temp, desc, &base));
+            mywindow->backgroundcolor[2] = atoi(findnextstring(temp, desc, &base));
+#ifdef DEBUG
+            mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [BACKGROUND] window \"%s\" has backgroundcolor (%i,%i,%i)\n", mywindow->name,
+                    mywindow->backgroundcolor[0],
+                    mywindow->backgroundcolor[1],
+                    mywindow->backgroundcolor[2]);
+#endif
+        }
+        else if(!strncmp(desc, "end", 3))
+        {
+            if(reachedendofwindow)
+            {
+#ifdef DEBUG
+                mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [END] of section\n");
+#endif
+            }
+            else
+            {
+                reachedendofwindow = 1;
+#ifdef DEBUG
+                mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [END] of window \"%s\"\n", mywindow->name);
+#endif
+            }
+        }
+        else if(!strncmp(desc, "font", 4))
+        {
+            unsigned int i;
+            int id = 0;
+            char temp[MAX_LINESIZE];
+            int base = counttonextchar(desc, '=')+1;
+            findnextstring(temp, desc, &base);
+            findnextstring(temp, desc, &base);
+            for (i=0; i<skin->fontcount; i++)
+                if(!strcmp(skin->fonts[i]->id, temp))
+                {
+                    id = i;
+                    break;
+                }
+            if(!id)
+            {
+                int base = counttonextchar(desc, '=') + 1;
+                findnextstring(temp, desc, &base);
+                id = skin->fontcount;
+                (skin->fontcount)++;
+                skin->fonts = realloc(skin->fonts, sizeof(font_t *) * skin->fontcount);
+                skin->fonts[id]=calloc(1, sizeof(font_t));
+                skin->fonts[id]->name = strdup(temp);
+                skin->fonts[id]->id = strdup(findnextstring(temp, desc, &base));
+            }
+#ifdef DEBUG
+            mp_msg(MSGT_GPLAYER, MSGL_DBG4, "[SKIN] [FONT] id  \"%s\" name \"%s\"\n", skin->fonts[id]->name, skin->fonts[id]->id);
+#endif
+        }
+        else
+            skin->addwidget(skin, mywindow, desc);
+    }
+
+    free(desc);
+    free(filename);
+    free(tmp);
+    fclose(fp);
+    loadfonts(skin);
+    mp_msg(MSGT_GPLAYER, MSGL_V, "[SKIN LOAD] loaded skin \"%s\"\n", skin->skindir);
+    /* dumpwidgets(skin); */
+    return skin;
+}