📄 theme_loader.cpp
字号:
/***************************************************************************** * theme_loader.cpp ***************************************************************************** * Copyright (C) 2003 the VideoLAN team * $Id: theme_loader.cpp 19663 2007-04-04 14:21:33Z lool $ * * Authors: Cyril Deguet <asmax@via.ecp.fr> * Olivier Teulière <ipkiss@via.ecp.fr> * * 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 Street, Fifth Floor, Boston MA 02110-1301, USA. *****************************************************************************/#include "theme_loader.hpp"#include "theme.hpp"#include "../parser/builder.hpp"#include "../parser/skin_parser.hpp"#include "../src/os_factory.hpp"#include "../src/vlcproc.hpp"#include "../src/window_manager.hpp"#include <cctype>#ifdef HAVE_FCNTL_H# include <fcntl.h>#endif#ifdef HAVE_SYS_STAT_H# include <sys/stat.h>#endif#ifdef HAVE_UNISTD_H# include <unistd.h>#elif defined( WIN32 ) && !defined( UNDER_CE )# include <direct.h>#endif#ifdef HAVE_DIRENT_H# include <dirent.h>#endif#if defined( HAVE_ZLIB_H )# include <zlib.h># include <errno.h>int gzopen_frontend ( char *pathname, int oflags, int mode );int gzclose_frontend( int );int gzread_frontend ( int, void *, size_t );int gzwrite_frontend( int, const void *, size_t );#if defined( HAVE_LIBTAR_H )# include <libtar.h>#elsetypedef gzFile TAR;int tar_open ( TAR **t, char *pathname, int oflags );int tar_extract_all ( TAR *t, char *prefix );int tar_close ( TAR *t );int getoct( char *p, int width );#endifint makedir( const char *newdir );#endif#define DEFAULT_XML_FILE "theme.xml"#define WINAMP2_XML_FILE "winamp2.xml"#define ZIP_BUFFER_SIZE 4096bool ThemeLoader::load( const string &fileName ){ // First, we try to un-targz the file, and if it fails we hope it's a XML // file... string path = getFilePath( fileName );#if defined( HAVE_ZLIB_H ) if( ! extract( sToLocale( fileName ) ) && ! parse( path, fileName ) ) return false;#else if( ! parse( path, fileName ) ) return false;#endif Theme *pNewTheme = getIntf()->p_sys->p_theme; if( !pNewTheme ) { return false; } // Check if the skin to load is in the config file, to load its config char *skin_last = config_GetPsz( getIntf(), "skins2-last" ); if( skin_last != NULL && fileName == (string)skin_last ) { // Restore the theme configuration getIntf()->p_sys->p_theme->loadConfig(); // Used to anchor the windows at the beginning pNewTheme->getWindowManager().stopMove(); } else { config_PutPsz( getIntf(), "skins2-last", fileName.c_str() ); // Show the windows pNewTheme->getWindowManager().showAll( true ); } if( skin_last ) free( skin_last ); // The new theme cannot embed a video output yet VlcProc::instance( getIntf() )->dropVout(); return true;}#if defined( HAVE_ZLIB_H )bool ThemeLoader::extractTarGz( const string &tarFile, const string &rootDir ){ TAR *t;#if defined( HAVE_LIBTAR_H ) tartype_t gztype = { (openfunc_t) gzopen_frontend, (closefunc_t) gzclose_frontend, (readfunc_t) gzread_frontend, (writefunc_t) gzwrite_frontend }; if( tar_open( &t, (char *)tarFile.c_str(), &gztype, O_RDONLY, 0, TAR_GNU ) == -1 )#else if( tar_open( &t, (char *)tarFile.c_str(), O_RDONLY ) == -1 )#endif { return false; } if( tar_extract_all( t, (char *)rootDir.c_str() ) != 0 ) { tar_close( t ); return false; } if( tar_close( t ) != 0 ) { return false; } return true;}bool ThemeLoader::extractZip( const string &zipFile, const string &rootDir ){ // Try to open the ZIP file unzFile file = unzOpen( zipFile.c_str() ); unz_global_info info; if( unzGetGlobalInfo( file, &info ) != UNZ_OK ) { return false; } // Extract all the files in the archive for( unsigned long i = 0; i < info.number_entry; i++ ) { if( !extractFileInZip( file, rootDir ) ) { msg_Warn( getIntf(), "error while unzipping %s", zipFile.c_str() ); unzClose( file ); return false; } if( i < info.number_entry - 1 ) { // Go the next file in the archive if( unzGoToNextFile( file ) !=UNZ_OK ) { msg_Warn( getIntf(), "error while unzipping %s", zipFile.c_str() ); unzClose( file ); return false; } } } unzClose( file ); return true;}bool ThemeLoader::extractFileInZip( unzFile file, const string &rootDir ){ // Read info for the current file char filenameInZip[256]; unz_file_info fileInfo; if( unzGetCurrentFileInfo( file, &fileInfo, filenameInZip, sizeof( filenameInZip), NULL, 0, NULL, 0 ) != UNZ_OK ) { return false; } // Convert the file name to lower case, because some winamp skins // use the wrong case... for( size_t i=0; i< strlen( filenameInZip ); i++) { filenameInZip[i] = tolower( filenameInZip[i] ); } // Allocate the buffer void *pBuffer = malloc( ZIP_BUFFER_SIZE ); if( !pBuffer ) { msg_Err( getIntf(), "failed to allocate memory" ); return false; } // Get the path of the file OSFactory *pOsFactory = OSFactory::instance( getIntf() ); string fullPath = rootDir + pOsFactory->getDirSeparator() + fixDirSeparators( filenameInZip ); string basePath = getFilePath( fullPath ); // Extract the file if is not a directory if( basePath != fullPath ) { if( unzOpenCurrentFile( file ) ) { free( pBuffer ); return false; } makedir( basePath.c_str() ); FILE *fout = fopen( fullPath.c_str(), "wb" ); if( fout == NULL ) { msg_Err( getIntf(), "error opening %s", fullPath.c_str() ); free( pBuffer ); return false; } // Extract the current file int n; do { n = unzReadCurrentFile( file, pBuffer, ZIP_BUFFER_SIZE ); if( n < 0 ) { msg_Err( getIntf(), "error while reading zip file" ); free( pBuffer ); return false; } else if( n > 0 ) { if( fwrite( pBuffer, n , 1, fout) != 1 ) { msg_Err( getIntf(), "error while writing %s", fullPath.c_str() ); free( pBuffer ); return false; } } } while( n > 0 ); fclose(fout); if( unzCloseCurrentFile( file ) != UNZ_OK ) { free( pBuffer ); return false; } } free( pBuffer ); return true;}bool ThemeLoader::extract( const string &fileName ){ bool result = true; char *tmpdir = tempnam( NULL, "vlt" ); string tempPath = tmpdir; free( tmpdir ); // Extract the file in a temporary directory if( ! extractTarGz( fileName, tempPath ) && ! extractZip( fileName, tempPath ) ) { deleteTempFiles( tempPath ); return false; } string path; string xmlFile; OSFactory *pOsFactory = OSFactory::instance( getIntf() ); // Find the XML file in the theme if( findFile( tempPath, DEFAULT_XML_FILE, xmlFile ) ) { path = getFilePath( xmlFile ); } else { // No XML file, check if it is a winamp2 skin string mainBmp; if( findFile( tempPath, "main.bmp", mainBmp ) ) { msg_Dbg( getIntf(), "trying to load a winamp2 skin" ); path = getFilePath( mainBmp ); // Look for winamp2.xml in the resource path list<string> resPath = pOsFactory->getResourcePath(); list<string>::const_iterator it; for( it = resPath.begin(); it != resPath.end(); it++ ) { if( findFile( sToLocale( *it ), WINAMP2_XML_FILE, xmlFile ) ) break; } } } if( !xmlFile.empty() ) { // Parse the XML file if (! parse( path, xmlFile ) ) { msg_Err( getIntf(), "error while parsing %s", xmlFile.c_str() ); result = false; } } else { msg_Err( getIntf(), "no XML found in theme %s", fileName.c_str() ); result = false; } // Clean-up deleteTempFiles( tempPath ); return result;}void ThemeLoader::deleteTempFiles( const string &path ){ OSFactory::instance( getIntf() )->rmDir( path );}#endif // HAVE_ZLIB_Hbool ThemeLoader::parse( const string &path, const string &xmlFile ){ // File loaded msg_Dbg( getIntf(), "using skin file: %s", xmlFile.c_str() ); // Start the parser SkinParser parser( getIntf(), xmlFile, path ); if( ! parser.parse() ) { msg_Err( getIntf(), "failed to parse %s", xmlFile.c_str() ); return false; } // Build and store the theme Builder builder( getIntf(), parser.getData(), path ); getIntf()->p_sys->p_theme = builder.build(); return true;}string ThemeLoader::getFilePath( const string &rFullPath ){ OSFactory *pOsFactory = OSFactory::instance( getIntf() ); const string &sep = pOsFactory->getDirSeparator(); // Find the last separator ('/' or '\') string::size_type p = rFullPath.rfind( sep, rFullPath.size() ); string basePath; if( p != string::npos ) { if( p < rFullPath.size() - 1) { basePath = rFullPath.substr( 0, p ); } else { basePath = rFullPath; } } return basePath;}string ThemeLoader::fixDirSeparators( const string &rPath ){ OSFactory *pOsFactory = OSFactory::instance( getIntf() ); const string &sep = pOsFactory->getDirSeparator(); string::size_type p = rPath.find( "/", 0 ); string newPath = rPath; while( p != string::npos )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -