]> git.sesse.net Git - vlc/blob - modules/gui/skins/src/themeloader.cpp
96659dbc301c9825e152cd9382bcfef3d0f3c855
[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.4 2003/04/12 21:43:27 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 #define DEFAULT_XML_FILE "theme.xml"
51
52 //---------------------------------------------------------------------------
53 extern "C"
54 {
55     extern FILE *yyin;
56     int yylex();
57 }
58
59 //---------------------------------------------------------------------------
60 ThemeLoader::ThemeLoader( intf_thread_t *_p_intf )
61 {
62     p_intf = _p_intf;
63 }
64 //---------------------------------------------------------------------------
65 ThemeLoader::~ThemeLoader()
66 {
67 }
68 //---------------------------------------------------------------------------
69 int gzopen_frontend( char *pathname, int oflags, int mode )
70 {
71 #if defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )
72     char *gzflags;
73     gzFile gzf;
74     int fd;
75
76     switch( oflags & O_ACCMODE )
77     {
78         case O_WRONLY:
79             gzflags = "wb";
80             break;
81         case O_RDONLY:
82             gzflags = "rb";
83             break;
84         case O_RDWR:
85         default:
86             errno = EINVAL;
87             return -1;
88     }
89
90     fd = open( pathname, oflags, mode );
91     if( fd == -1 )
92         return -1;
93
94 //    if( ( oflags & O_CREAT ) && fchmod( fd, mode ) )
95 //        return -1;
96
97     gzf = gzdopen( fd, gzflags );
98     if( !gzf )
99     {
100         errno = ENOMEM;
101         return -1;
102     }
103
104     return (int)gzf;
105 #else
106     return 0;
107 #endif
108 }
109 //---------------------------------------------------------------------------
110 #if defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )
111 bool ThemeLoader::ExtractTarGz( const string tarfile, const string rootdir )
112 {
113     TAR *t;
114     tartype_t gztype = { (openfunc_t) gzopen_frontend, (closefunc_t) gzclose,
115         (readfunc_t) gzread, (writefunc_t) gzwrite };
116
117     if( tar_open( &t, (char *)tarfile.c_str(), &gztype, O_RDONLY, 0,
118                   TAR_GNU ) == -1 )
119     {
120         return false;
121     }
122
123     if( tar_extract_all( t, (char *)rootdir.c_str() ) != 0 )
124     {
125         return false;
126     }
127
128     if( tar_close( t ) != 0 )
129     {
130         return false;
131     }
132
133     return true;
134 }
135 //---------------------------------------------------------------------------
136 bool ThemeLoader::Extract( const string FileName )
137 {
138     char *tmpdir = tempnam( NULL, "vlt" );
139     string TempPath = tmpdir;
140     free( tmpdir );
141
142     if( ! ExtractTarGz( FileName, TempPath ) )
143         return false;
144
145     if( ! Parse( TempPath + DIRECTORY_SEPARATOR + string( DEFAULT_XML_FILE ) ) )
146     {
147         DeleteTempFiles( TempPath );
148         return false;
149     }
150
151     DeleteTempFiles( TempPath );
152     return true;
153 }
154 //---------------------------------------------------------------------------
155 void ThemeLoader::DeleteTempFiles( const string Path )
156 {
157     OSAPI_RmDir( Path );
158 }
159 #endif
160 //---------------------------------------------------------------------------
161 void ThemeLoader::CleanTheme()
162 {
163     delete (OSTheme *)p_intf->p_sys->p_theme;
164     p_intf->p_sys->p_theme = (Theme *)new OSTheme( p_intf );
165 }
166 //---------------------------------------------------------------------------
167 bool ThemeLoader::Parse( const string XmlFile )
168 {
169     // Things to do before loading theme
170     p_intf->p_sys->p_theme->OnLoadTheme();
171
172     // Set the file to parse
173     yyin = fopen( XmlFile.c_str(), "r" );
174     if( yyin == NULL )
175     {
176         // Skin cannot be opened
177         msg_Warn( p_intf, "Cannot open the specified skin file: %s",
178                   XmlFile.c_str() );
179         return false;
180     }
181
182     // File loaded
183     msg_Dbg( p_intf, "Using skin file: %s", XmlFile.c_str() );
184
185     // Save current working directory
186 #ifdef WIN32    
187     char *cwd = new char[MAX_PATH];
188     getcwd( cwd, MAX_PATH );
189 #else
190     char *cwd = new char[PATH_MAX];
191     getcwd( cwd, PATH_MAX );
192 #endif
193
194     // Directory separator is different in each OS !
195     int p = XmlFile.rfind( DIRECTORY_SEPARATOR, XmlFile.size() );
196
197     // Change current working directory to xml file
198     string path = "";
199     if( p > 0 )
200         path = XmlFile.substr( 0, p );
201     chdir( path.c_str() );
202
203     p_intf->p_sys->b_all_win_closed = false;
204
205     // Start the parser
206     int lex = yylex();
207     fclose( yyin );
208     if( lex )
209     {
210         // Set old working directory to current
211         chdir( cwd );
212         delete[] cwd;
213
214         msg_Warn( p_intf, "yylex failed: %i", lex );
215         CleanTheme();
216         return false;
217     }
218
219     // Set old working directory to current
220     chdir( cwd );
221     delete[] cwd;
222
223     return true;
224 }
225 //---------------------------------------------------------------------------
226 bool ThemeLoader::Load( const string FileName )
227 {
228     // First, we try to un-targz the file, and if it fails we hope it's a XML
229     // file...
230 #if defined( HAVE_LIBTAR_H ) && defined( HAVE_ZLIB_H )
231     if( ! Extract( FileName ) && ! Parse( FileName ) )
232         return false;
233 #else
234     if( ! Parse( FileName ) )
235         return false;
236 #endif
237
238     // Check if the skin to load is in the config file, to load its config
239     char *skin_last = config_GetPsz( p_intf, "skin_last" );
240     if( skin_last != NULL && FileName == (string)skin_last )
241     {
242         p_intf->p_sys->p_theme->LoadConfig();
243     }
244     else
245     {
246         config_PutPsz( p_intf, "skin_last", FileName.c_str() );
247         config_SaveConfigFile( p_intf, "skins" );
248     }
249
250     return true;
251 }
252 //---------------------------------------------------------------------------