]> git.sesse.net Git - vlc/blob - modules/gui/skins2/src/theme_repository.cpp
8b150f6fc9298122a43196bbc550629df4dc9bee
[vlc] / modules / gui / skins2 / src / theme_repository.cpp
1 /*****************************************************************************
2  * theme_repository.cpp
3  *****************************************************************************
4  * Copyright (C) 2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Cyril Deguet     <asmax@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 #include "theme_repository.hpp"
25 #include "os_factory.hpp"
26 #include "../commands/async_queue.hpp"
27 #include "../commands/cmd_dialogs.hpp"
28 #ifdef HAVE_UNISTD_H
29 #   include <unistd.h>
30 #elif defined( WIN32 ) && !defined( UNDER_CE )
31 #   include <direct.h>
32 #endif
33 #ifdef HAVE_DIRENT_H
34 #   include <dirent.h>
35 #endif
36
37
38
39 ThemeRepository *ThemeRepository::instance( intf_thread_t *pIntf )
40 {
41     if( pIntf->p_sys->p_repository == NULL )
42     {
43         pIntf->p_sys->p_repository = new ThemeRepository( pIntf );
44     }
45
46     return pIntf->p_sys->p_repository;
47 }
48
49
50 void ThemeRepository::destroy( intf_thread_t *pIntf )
51 {
52     delete pIntf->p_sys->p_repository;
53     pIntf->p_sys->p_repository = NULL;
54 }
55
56
57 ThemeRepository::ThemeRepository( intf_thread_t *pIntf ): SkinObject( pIntf )
58 {
59     vlc_value_t val, text;
60
61     // Create a variable to add items in wxwindows popup menu
62     var_Create( pIntf, "intf-skins", VLC_VAR_STRING |
63                 VLC_VAR_HASCHOICE | VLC_VAR_ISCOMMAND );
64     text.psz_string = _("Select skin");
65     var_Change( pIntf, "intf-skins", VLC_VAR_SETTEXT, &text, NULL );
66
67     // Scan vlt files in the resource path
68     OSFactory *pOsFactory = OSFactory::instance( pIntf );
69     list<string> resPath = pOsFactory->getResourcePath();
70     list<string>::const_iterator it;
71     for( it = resPath.begin(); it != resPath.end(); it++ )
72     {
73         parseDirectory( *it );
74     }
75
76     // retrieve skins from skins directories and locate default skins
77     map<string,string>::const_iterator itmap, itdefault;
78     for( itmap = m_skinsMap.begin(); itmap != m_skinsMap.end(); itmap++ )
79     {
80         string path = itmap->first;
81         string name = itmap->second;
82         val.psz_string = (char*) path.c_str();
83         text.psz_string = (char*) name.c_str();
84         var_Change( getIntf(), "intf-skins", VLC_VAR_ADDCHOICE, &val,
85                     &text );
86
87         if( name == "default" )
88             itdefault = itmap;
89     }
90
91     // retrieve last skins stored or skins requested by user
92     char* psz_current = config_GetPsz( getIntf(), "skins2-last" );
93     string current = string( psz_current ? psz_current : "" );
94
95     // set the default skins if no skins provided
96     if( current.size() == 0 )
97     {
98         current = itdefault->first;
99         config_PutPsz( getIntf(), "skins2-last", current.c_str() );
100     }
101
102     free( psz_current );
103
104     // Update repository
105     updateRepository();
106
107     // Set the callback
108     var_AddCallback( pIntf, "intf-skins", changeSkin, this );
109
110     // variable for opening a dialog box to change skins
111     var_Create( pIntf, "intf-skins-interactive", VLC_VAR_VOID |
112                 VLC_VAR_ISCOMMAND );
113     text.psz_string = _("Open skin ...");
114     var_Change( pIntf, "intf-skins-interactive", VLC_VAR_SETTEXT, &text, NULL );
115
116     // Set the callback
117     var_AddCallback( pIntf, "intf-skins-interactive", changeSkin, this );
118
119 }
120
121
122 ThemeRepository::~ThemeRepository()
123 {
124     m_skinsMap.clear();
125
126     var_DelCallback( getIntf(), "intf-skins", changeSkin, this );
127     var_DelCallback( getIntf(), "intf-skins-interactive", changeSkin, this );
128
129     var_Destroy( getIntf(), "intf-skins" );
130     var_Destroy( getIntf(), "intf-skins-interactive" );
131 }
132
133
134 void ThemeRepository::parseDirectory( const string &rDir_locale )
135 {
136     DIR *pDir;
137     char *pszDirContent;
138     vlc_value_t val, text;
139     // Path separator
140     const string &sep = OSFactory::instance( getIntf() )->getDirSeparator();
141
142     // Open the dir
143     // FIXME: parseDirectory should be invoked with UTF-8 input instead!!
144     string rDir = sFromLocale( rDir_locale );
145     pDir = utf8_opendir( rDir.c_str() );
146
147     if( pDir == NULL )
148     {
149         // An error occurred
150         msg_Dbg( getIntf(), "cannot open directory %s", rDir.c_str() );
151         return;
152     }
153
154     // While we still have entries in the directory
155     while( ( pszDirContent = utf8_readdir( pDir ) ) != NULL )
156     {
157         string name = pszDirContent;
158         string extension;
159         if( name.size() > 4 )
160         {
161             extension = name.substr( name.size() - 4, 4 );
162         }
163         if( extension == ".vlt" || extension == ".wsz" )
164         {
165             string path = rDir + sep + name;
166             string shortname = name.substr( 0, name.size() - 4 );
167             m_skinsMap[path] = shortname;
168
169             msg_Dbg( getIntf(), "found skin %s", path.c_str() );
170         }
171
172         free( pszDirContent );
173     }
174
175     closedir( pDir );
176 }
177
178
179
180 int ThemeRepository::changeSkin( vlc_object_t *pIntf, char const *pVariable,
181                                  vlc_value_t oldval, vlc_value_t newval,
182                                  void *pData )
183 {
184     ThemeRepository *pThis = (ThemeRepository*)(pData);
185
186     if( !strcmp( pVariable, "intf-skins-interactive" ) )
187     {
188         CmdDlgChangeSkin cmd( pThis->getIntf() );
189         cmd.execute();
190     }
191     else if( !strcmp( pVariable, "intf-skins" ) )
192     {
193         // Try to load the new skin
194         CmdChangeSkin *pCmd = new CmdChangeSkin( pThis->getIntf(),
195                                                  newval.psz_string );
196         AsyncQueue *pQueue = AsyncQueue::instance( pThis->getIntf() );
197         pQueue->push( CmdGenericPtr( pCmd ) );
198     }
199
200     return VLC_SUCCESS;
201 }
202
203
204 void ThemeRepository::updateRepository()
205 {
206     vlc_value_t val, text;
207
208     // retrieve the current skin
209     char* psz_current = config_GetPsz( getIntf(), "skins2-last" );
210     if( !psz_current )
211         return;
212
213     val.psz_string = psz_current;
214     text.psz_string = psz_current;
215
216     // add this new skins if not yet present in repository
217     string current( psz_current );
218     if( m_skinsMap.find( current ) == m_skinsMap.end() )
219     {
220         var_Change( getIntf(), "intf-skins", VLC_VAR_ADDCHOICE, &val,
221                     &text );
222     }
223
224     // mark this current skins as 'checked' in list
225     var_Change( getIntf(), "intf-skins", VLC_VAR_SETVALUE, &val, NULL );
226
227     free( psz_current );
228 }
229