]> git.sesse.net Git - vlc/blob - modules/gui/skins/src/themeloader.cpp
* Gtk2 skins: it doesn't work but it runs without any segfault, so
[vlc] / modules / gui / skins / src / themeloader.cpp
1 /*****************************************************************************
2  * themeloader.cpp: ThemeLoader class
3  *****************************************************************************
4  * Copyright (C) 2003 VideoLAN
5  * $Id: themeloader.cpp,v 1.5 2003/04/13 17:46:23 asmax Exp $
6  *
7  * Authors: Olivier Teulière <ipkiss@via.ecp.fr>
8  *          Emmanuel Puig    <karibu@via.ecp.fr>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111,
23  * USA.
24  *****************************************************************************/
25
26
27 //--- GENERAL ---------------------------------------------------------------
28 #include <string>
29 #include <fcntl.h>
30 #if !defined WIN32
31 #include <unistd.h>
32 #endif
33
34 //--- VLC -------------------------------------------------------------------
35 #include <vlc/vlc.h>
36 #include <vlc/intf.h>
37
38 #if defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )
39 #   include <zlib.h>
40 #   include <libtar.h>
41 #endif
42
43 //--- SKIN ------------------------------------------------------------------
44 #include "os_api.h"
45 #include "theme.h"
46 #include "os_theme.h"
47 #include "themeloader.h"
48 #include "skin_common.h"
49
50 #include "anchor.h"
51 #include "window.h"
52
53 #define DEFAULT_XML_FILE "theme.xml"
54
55 //---------------------------------------------------------------------------
56 extern "C"
57 {
58     extern FILE *yyin;
59     int yylex();
60 }
61
62 //---------------------------------------------------------------------------
63 ThemeLoader::ThemeLoader( intf_thread_t *_p_intf )
64 {
65     p_intf = _p_intf;
66 }
67 //---------------------------------------------------------------------------
68 ThemeLoader::~ThemeLoader()
69 {
70 }
71 //---------------------------------------------------------------------------
72 int gzopen_frontend( char *pathname, int oflags, int mode )
73 {
74 #if defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )
75     char *gzflags;
76     gzFile gzf;
77     int fd;
78
79     switch( oflags & O_ACCMODE )
80     {
81         case O_WRONLY:
82             gzflags = "wb";
83             break;
84         case O_RDONLY:
85             gzflags = "rb";
86             break;
87         case O_RDWR:
88         default:
89             errno = EINVAL;
90             return -1;
91     }
92
93     fd = open( pathname, oflags, mode );
94     if( fd == -1 )
95         return -1;
96
97 //    if( ( oflags & O_CREAT ) && fchmod( fd, mode ) )
98 //        return -1;
99
100     gzf = gzdopen( fd, gzflags );
101     if( !gzf )
102     {
103         errno = ENOMEM;
104         return -1;
105     }
106
107     return (int)gzf;
108 #else
109     return 0;
110 #endif
111 }
112 //---------------------------------------------------------------------------
113 #if defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )
114 bool ThemeLoader::ExtractTarGz( const string tarfile, const string rootdir )
115 {
116     TAR *t;
117     tartype_t gztype = { (openfunc_t) gzopen_frontend, (closefunc_t) gzclose,
118         (readfunc_t) gzread, (writefunc_t) gzwrite };
119
120     if( tar_open( &t, (char *)tarfile.c_str(), &gztype, O_RDONLY, 0,
121                   TAR_GNU ) == -1 )
122     {
123         return false;
124     }
125
126     if( tar_extract_all( t, (char *)rootdir.c_str() ) != 0 )
127     {
128         return false;
129     }
130
131     if( tar_close( t ) != 0 )
132     {
133         return false;
134     }
135
136     return true;
137 }
138 //---------------------------------------------------------------------------
139 bool ThemeLoader::Extract( const string FileName )
140 {
141     char *tmpdir = tempnam( NULL, "vlt" );
142     string TempPath = tmpdir;
143     free( tmpdir );
144
145     if( ! ExtractTarGz( FileName, TempPath ) )
146         return false;
147
148     if( ! Parse( TempPath + DIRECTORY_SEPARATOR + string( DEFAULT_XML_FILE ) ) )
149     {
150         DeleteTempFiles( TempPath );
151         return false;
152     }
153
154     DeleteTempFiles( TempPath );
155     return true;
156 }
157 //---------------------------------------------------------------------------
158 void ThemeLoader::DeleteTempFiles( const string Path )
159 {
160     OSAPI_RmDir( Path );
161 }
162 #endif
163 //---------------------------------------------------------------------------
164 void ThemeLoader::CleanTheme()
165 {
166     delete (OSTheme *)p_intf->p_sys->p_theme;
167     p_intf->p_sys->p_theme = (Theme *)new OSTheme( p_intf );
168 }
169 //---------------------------------------------------------------------------
170 bool ThemeLoader::Parse( const string XmlFile )
171 {
172     // Things to do before loading theme
173     p_intf->p_sys->p_theme->OnLoadTheme();
174
175     // Set the file to parse
176     yyin = fopen( XmlFile.c_str(), "r" );
177     if( yyin == NULL )
178     {
179         // Skin cannot be opened
180         msg_Warn( p_intf, "Cannot open the specified skin file: %s",
181                   XmlFile.c_str() );
182         return false;
183     }
184
185     // File loaded
186     msg_Dbg( p_intf, "Using skin file: %s", XmlFile.c_str() );
187
188     // Save current working directory
189 #ifdef WIN32    
190     char *cwd = new char[MAX_PATH];
191     getcwd( cwd, MAX_PATH );
192 #else
193     char *cwd = new char[PATH_MAX];
194     getcwd( cwd, PATH_MAX );
195 #endif
196
197     // Directory separator is different in each OS !
198     int p = XmlFile.rfind( DIRECTORY_SEPARATOR, XmlFile.size() );
199
200     // Change current working directory to xml file
201     string path = "";
202     if( p > 0 )
203         path = XmlFile.substr( 0, p );
204     chdir( path.c_str() );
205
206     p_intf->p_sys->b_all_win_closed = false;
207
208     // Start the parser
209     int lex = yylex();
210     
211     fclose( yyin );
212     if( lex )
213     {
214         // Set old working directory to current
215         chdir( cwd );
216         delete[] cwd;
217
218         msg_Warn( p_intf, "yylex failed: %i", lex );
219         CleanTheme();
220         return false;
221     }
222
223     // Set old working directory to current
224     chdir( cwd );
225     delete[] cwd;
226
227     return true;
228 }
229 //---------------------------------------------------------------------------
230 bool ThemeLoader::Load( const string FileName )
231 {
232     // First, we try to un-targz the file, and if it fails we hope it's a XML
233     // file...
234 #if defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )
235     if( ! Extract( FileName ) && ! Parse( FileName ) )
236         return false;
237 #else
238     if( ! Parse( FileName ) )
239         return false;
240 #endif
241
242     // Check if the skin to load is in the config file, to load its config
243     char *skin_last = config_GetPsz( p_intf, "skin_last" );
244     if( skin_last != NULL && FileName == (string)skin_last )
245     {
246         p_intf->p_sys->p_theme->LoadConfig();
247     }
248     else
249     {
250         config_PutPsz( p_intf, "skin_last", FileName.c_str() );
251         config_SaveConfigFile( p_intf, "skins" );
252     }
253
254     return true;
255 }
256 //---------------------------------------------------------------------------