/**************************************************************************** * Theme_Downloader * USB Loader GX 2009 * * Theme downloader for USB Loader GX * * Theme_Downloader.cpp ***************************************************************************/ #include #include #include "language/gettext.h" #include "libwiigui/gui.h" #include "prompts/PromptWindows.h" #include "prompts/ProgressWindow.h" #include "homebrewboot/HomebrewBrowse.h" #include "network/networkops.h" #include "themes/Theme_List.h" #include "menu.h" #include "filelist.h" #include "listfiles.h" #include "sys.h" #include "network/http.h" #include "ZipFile.h" #include "gecko.h" /*** Extern functions ***/ extern void ResumeGui(); extern void HaltGui(); /*** Extern variables ***/ extern GuiWindow * mainWindow; extern GuiSound * bgMusic; extern GuiImage * bgImg; extern u8 shutdown; extern u8 reset; int DownloadTheme( const char *url, const char *title ) { if ( !url ) return 0; char filename[255]; memset( filename, 0, sizeof( filename ) ); int filesize = download_request( url, ( char * ) & filename ); if ( filesize <= 0 ) { WindowPrompt( tr( "Download request failed." ), 0, tr( "OK" ) ); return 0; } char path[300]; char filepath[300]; snprintf( path, sizeof( path ), "%s%s", Settings.theme_downloadpath, title ); subfoldercreate( path ); snprintf( filepath, sizeof( filepath ), "%s/%s", path, filename ); FILE *file = fopen( filepath, "wb" ); if ( !file ) { WindowPrompt( tr( "Download failed." ), tr( "Can't create file" ), tr( "OK" ) ); return 0; } u32 done = 0; int blocksize = 1024 * 5; u8 *buffer = new u8[blocksize]; while ( done < ( u32 ) filesize ) { if ( ( u32 ) blocksize > filesize - done ) blocksize = filesize - done; ShowProgress( tr( "Downloading file" ), 0, ( char* ) filename, done, filesize, true ); int ret = network_read( buffer, blocksize ); if ( ret < 0 ) { free( buffer ); fclose( file ); remove( path ); ProgressStop(); WindowPrompt( tr( "Download failed." ), tr( "Transfer failed." ), tr( "OK" ) ); return 0; } else if ( ret == 0 ) break; fwrite( buffer, 1, blocksize, file ); done += ret; } delete [] buffer; fclose( file ); ProgressStop(); if ( done != ( u32 ) filesize ) { remove( filepath ); WindowPrompt( tr( "Download failed." ), tr( "Connection lost..." ), tr( "OK" ) ); return 0; } ZipFile zipfile( filepath ); int result = zipfile.ExtractAll( path ); if ( result ) { remove( filepath ); int choice = WindowPrompt( tr( "Successfully extracted theme." ), tr( "Do you want to apply it now?" ), tr( "Yes" ), tr( "No" ) ); if ( choice ) { char real_themepath[1024]; sprintf( real_themepath, "%s", CFG.theme_path ); if ( SearchFile( path, "GXtheme.cfg", real_themepath ) == true ) { char *ptr = strrchr( real_themepath, '/' ); if ( ptr ) { ptr++; ptr[0] = '\0'; } snprintf( CFG.theme_path, sizeof( CFG.theme_path ), "%s", real_themepath ); cfg_save_global(); CFG_Load(); CFG_LoadGlobal(); result = 2; } else WindowPrompt( tr( "ERROR: Can't set up theme." ), tr( "GXtheme.cfg not found in any subfolder." ), tr( "OK" ) ); } } else WindowPrompt( tr( "Failed to extract." ), tr( "Unsupported format, try to extract manually." ), tr( "OK" ) ); return result; } static int Theme_Prompt( const char *title, const char *author, GuiImageData *thumbimageData, const char *downloadlink ) { gprintf( "\nTheme_Prompt(%s ,%s, , %s)", title, author, downloadlink ); bool leave = false; int result = 0; GuiSound btnSoundOver( button_over_pcm, button_over_pcm_size, Settings.sfxvolume ); // because destroy GuiSound must wait while sound playing is finished, we use a global sound if ( !btnClick2 ) btnClick2 = new GuiSound( button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume ); // GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume); char imgPath[100]; snprintf( imgPath, sizeof( imgPath ), "%sbutton_dialogue_box.png", CFG.theme_path ); GuiImageData btnOutline( imgPath, button_dialogue_box_png ); snprintf( imgPath, sizeof( imgPath ), "%stheme_dialogue_box.png", CFG.theme_path ); GuiImageData dialogBox( imgPath, theme_dialogue_box_png ); GuiImage dialogBoxImg( &dialogBox ); GuiWindow promptWindow( dialogBox.GetWidth(), dialogBox.GetHeight() ); promptWindow.SetAlignment( ALIGN_CENTRE, ALIGN_MIDDLE ); promptWindow.SetPosition( 0, -10 ); GuiTrigger trigA; trigA.SetSimpleTrigger( -1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A ); GuiTrigger trigB; trigB.SetButtonOnlyTrigger( -1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B ); GuiText titleTxt( tr( "Theme Title:" ), 18, THEME.prompttext ); titleTxt.SetAlignment( ALIGN_LEFT, ALIGN_TOP ); titleTxt.SetPosition( 230, 30 ); GuiText titleTxt2( title, 18, THEME.prompttext ); titleTxt2.SetAlignment( ALIGN_LEFT, ALIGN_TOP ); titleTxt2.SetPosition( 230, 50 ); titleTxt2.SetMaxWidth( dialogBox.GetWidth() - 220, WRAP ); GuiText authorTxt( tr( "Author:" ), 18, THEME.prompttext ); authorTxt.SetAlignment( ALIGN_LEFT, ALIGN_TOP ); authorTxt.SetPosition( 230, 100 ); GuiText authorTxt2( author, 18, THEME.prompttext ); authorTxt2.SetAlignment( ALIGN_LEFT, ALIGN_TOP ); authorTxt2.SetPosition( 230, 120 ); authorTxt2.SetMaxWidth( dialogBox.GetWidth() - 220, DOTTED ); GuiText downloadBtnTxt( tr( "Download" ) , 22, THEME.prompttext ); downloadBtnTxt.SetMaxWidth( btnOutline.GetWidth() - 30 ); GuiImage downloadBtnImg( &btnOutline ); if ( Settings.wsprompt == yes ) { downloadBtnTxt.SetWidescreen( CFG.widescreen ); downloadBtnImg.SetWidescreen( CFG.widescreen ); } GuiButton downloadBtn( &downloadBtnImg, &downloadBtnImg, ALIGN_RIGHT, ALIGN_TOP, -5, 170, &trigA, &btnSoundOver, btnClick2, 1 ); downloadBtn.SetLabel( &downloadBtnTxt ); downloadBtn.SetScale( 0.9 ); GuiText backBtnTxt( tr( "Back" ) , 22, THEME.prompttext ); backBtnTxt.SetMaxWidth( btnOutline.GetWidth() - 30 ); GuiImage backBtnImg( &btnOutline ); if ( Settings.wsprompt == yes ) { backBtnTxt.SetWidescreen( CFG.widescreen ); backBtnImg.SetWidescreen( CFG.widescreen ); } GuiButton backBtn( &backBtnImg, &backBtnImg, ALIGN_RIGHT, ALIGN_TOP, -5, 220, &trigA, &btnSoundOver, btnClick2, 1 ); backBtn.SetLabel( &backBtnTxt ); backBtn.SetTrigger( &trigB ); backBtn.SetScale( 0.9 ); GuiImage ThemeImage( thumbimageData ); ThemeImage.SetAlignment( ALIGN_LEFT, ALIGN_TOP ); ThemeImage.SetPosition( 20, 10 ); ThemeImage.SetScale( 0.8 ); ThemeImage.SetScale( 0.8 ); promptWindow.Append( &dialogBoxImg ); promptWindow.Append( &ThemeImage ); promptWindow.Append( &titleTxt ); promptWindow.Append( &titleTxt2 ); promptWindow.Append( &authorTxt ); promptWindow.Append( &authorTxt2 ); promptWindow.Append( &downloadBtn ); promptWindow.Append( &backBtn ); HaltGui(); promptWindow.SetEffect( EFFECT_SLIDE_TOP | EFFECT_SLIDE_IN, 50 ); mainWindow->SetState( STATE_DISABLED ); mainWindow->Append( &promptWindow ); mainWindow->ChangeFocus( &promptWindow ); ResumeGui(); while ( !leave ) { VIDEO_WaitVSync(); if ( shutdown == 1 ) Sys_Shutdown(); else if ( reset == 1 ) Sys_Reboot(); if ( downloadBtn.GetState() == STATE_CLICKED ) { int choice = WindowPrompt( tr( "Do you want to download this theme?" ), title, tr( "Yes" ), tr( "Cancel" ) ); if ( choice ) { result = DownloadTheme( downloadlink, title ); if ( result == 2 ) leave = true; } mainWindow->SetState( STATE_DISABLED ); promptWindow.SetState( STATE_DEFAULT ); mainWindow->ChangeFocus( &promptWindow ); downloadBtn.ResetState(); } else if ( backBtn.GetState() == STATE_CLICKED ) { leave = true; backBtn.ResetState(); } } promptWindow.SetEffect( EFFECT_SLIDE_TOP | EFFECT_SLIDE_OUT, 50 ); while ( promptWindow.GetEffect() > 0 ) usleep( 50 ); HaltGui(); mainWindow->Remove( &promptWindow ); mainWindow->SetState( STATE_DEFAULT ); ResumeGui(); return result; } int Theme_Downloader() { int pagesize = 4; int menu = MENU_NONE; bool listchanged = false; char THEME_LINK[70]; sprintf( THEME_LINK, "http://wii.spiffy360.com/themes.php?xml=1&category=1&adult=%d", Settings.godmode ); //gprintf("\nTHEME_LINK: %s", THEME_LINK); //const char THEME_LINK_ADULT[70] = "http://wii.spiffy360.com/themes.php?xml=1&category=1&adult=1"; /*** Sound Variables ***/ GuiSound btnSoundOver( button_over_pcm, button_over_pcm_size, Settings.sfxvolume ); // because destroy GuiSound must wait while sound playing is finished, we use a global sound if ( !btnClick2 ) btnClick2 = new GuiSound( button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume ); // GuiSound btnClick(button_click2_pcm, button_click2_pcm_size, Settings.sfxvolume); GuiSound btnClick1( button_click_pcm, button_click_pcm_size, Settings.sfxvolume ); /*** Image Variables ***/ char imgPath[150]; snprintf( imgPath, sizeof( imgPath ), "%sbutton_dialogue_box.png", CFG.theme_path ); GuiImageData btnOutline( imgPath, button_dialogue_box_png ); snprintf( imgPath, sizeof( imgPath ), "%stheme_box.png", CFG.theme_path ); GuiImageData theme_box_Data( imgPath, theme_box_png ); snprintf( imgPath, sizeof( imgPath ), "%ssettings_background.png", CFG.theme_path ); GuiImageData bgData( imgPath, settings_background_png ); snprintf( imgPath, sizeof( imgPath ), "%sstartgame_arrow_left.png", CFG.theme_path ); GuiImageData arrow_left( imgPath, startgame_arrow_left_png ); snprintf( imgPath, sizeof( imgPath ), "%sstartgame_arrow_right.png", CFG.theme_path ); GuiImageData arrow_right( imgPath, startgame_arrow_right_png ); snprintf( imgPath, sizeof( imgPath ), "%sWifi_btn.png", CFG.theme_path ); GuiImageData wifiImgData( imgPath, Wifi_btn_png ); snprintf( imgPath, sizeof( imgPath ), "%spageindicator.png", CFG.theme_path ); GuiImageData PageindicatorImgData( imgPath, pageindicator_png ); GuiImage background( &bgData ); /*** Trigger Variables ***/ GuiTrigger trigA; trigA.SetSimpleTrigger( -1, WPAD_BUTTON_A | WPAD_CLASSIC_BUTTON_A, PAD_BUTTON_A ); GuiTrigger trigHome; trigHome.SetButtonOnlyTrigger( -1, WPAD_BUTTON_HOME | WPAD_CLASSIC_BUTTON_HOME, 0 ); GuiTrigger trigB; trigB.SetButtonOnlyTrigger( -1, WPAD_BUTTON_B | WPAD_CLASSIC_BUTTON_B, PAD_BUTTON_B ); GuiTrigger trigL; trigL.SetButtonOnlyTrigger( -1, WPAD_BUTTON_LEFT | WPAD_CLASSIC_BUTTON_LEFT, PAD_BUTTON_LEFT ); GuiTrigger trigR; trigR.SetButtonOnlyTrigger( -1, WPAD_BUTTON_RIGHT | WPAD_CLASSIC_BUTTON_RIGHT, PAD_BUTTON_RIGHT ); GuiTrigger trigMinus; trigMinus.SetButtonOnlyTrigger( -1, WPAD_BUTTON_MINUS | WPAD_CLASSIC_BUTTON_MINUS, 0 ); GuiTrigger trigPlus; trigPlus.SetButtonOnlyTrigger( -1, WPAD_BUTTON_PLUS | WPAD_CLASSIC_BUTTON_PLUS, 0 ); GuiText titleTxt( tr( "Theme Downloader" ), 28, ( GXColor ) {0, 0, 0, 255} ); titleTxt.SetAlignment( ALIGN_CENTRE, ALIGN_TOP ); titleTxt.SetPosition( 0, 40 ); GuiImageData *ImageData[pagesize]; GuiImage *Image[pagesize]; GuiImage *theme_box_img[pagesize]; GuiButton *MainButton[pagesize]; GuiText *MainButtonTxt[pagesize]; Theme_List *Theme = NULL; /*** Buttons ***/ for ( int i = 0; i < pagesize; i++ ) { ImageData[i] = NULL; Image[i] = NULL; MainButtonTxt[i] = NULL; theme_box_img[i] = new GuiImage( &theme_box_Data ); MainButton[i] = new GuiButton( theme_box_Data.GetWidth(), theme_box_Data.GetHeight() ); MainButton[i]->SetAlignment( ALIGN_LEFT, ALIGN_TOP ); MainButton[i]->SetSoundOver( &btnSoundOver ); MainButton[i]->SetSoundClick( &btnClick1 ); MainButton[i]->SetImage( theme_box_img[i] ); MainButton[i]->SetEffectGrow(); MainButton[i]->SetTrigger( &trigA ); } /*** Positions ***/ MainButton[0]->SetPosition( 90, 75 ); MainButton[1]->SetPosition( 340, 75 ); MainButton[2]->SetPosition( 90, 230 ); MainButton[3]->SetPosition( 340, 230 ); GuiText backBtnTxt( tr( "Back" ) , 22, THEME.prompttext ); backBtnTxt.SetMaxWidth( btnOutline.GetWidth() - 30 ); GuiImage backBtnImg( &btnOutline ); if ( Settings.wsprompt == yes ) { backBtnTxt.SetWidescreen( CFG.widescreen ); backBtnImg.SetWidescreen( CFG.widescreen ); } GuiButton backBtn( &backBtnImg, &backBtnImg, 2, 3, -180, 400, &trigA, &btnSoundOver, btnClick2, 1 ); backBtn.SetLabel( &backBtnTxt ); backBtn.SetTrigger( &trigB ); GuiButton HomeBtn( 1, 1 ); HomeBtn.SetTrigger( &trigHome ); GuiImage GoLeftImg( &arrow_left ); GuiButton GoLeftBtn( GoLeftImg.GetWidth(), GoLeftImg.GetHeight() ); GoLeftBtn.SetAlignment( ALIGN_LEFT, ALIGN_MIDDLE ); GoLeftBtn.SetPosition( 25, -25 ); GoLeftBtn.SetImage( &GoLeftImg ); GoLeftBtn.SetSoundOver( &btnSoundOver ); GoLeftBtn.SetSoundClick( btnClick2 ); GoLeftBtn.SetEffectGrow(); GoLeftBtn.SetTrigger( &trigA ); GoLeftBtn.SetTrigger( &trigL ); GoLeftBtn.SetTrigger( &trigMinus ); GuiImage GoRightImg( &arrow_right ); GuiButton GoRightBtn( GoRightImg.GetWidth(), GoRightImg.GetHeight() ); GoRightBtn.SetAlignment( ALIGN_RIGHT, ALIGN_MIDDLE ); GoRightBtn.SetPosition( -25, -25 ); GoRightBtn.SetImage( &GoRightImg ); GoRightBtn.SetSoundOver( &btnSoundOver ); GoRightBtn.SetSoundClick( btnClick2 ); GoRightBtn.SetEffectGrow(); GoRightBtn.SetTrigger( &trigA ); GoRightBtn.SetTrigger( &trigR ); GoRightBtn.SetTrigger( &trigPlus ); GuiImage PageindicatorImg( &PageindicatorImgData ); GuiText PageindicatorTxt( ( char * ) NULL, 22, ( GXColor ) { 0, 0, 0, 255} ); GuiButton PageIndicatorBtn( PageindicatorImg.GetWidth(), PageindicatorImg.GetHeight() ); PageIndicatorBtn.SetAlignment( ALIGN_CENTRE, ALIGN_TOP ); PageIndicatorBtn.SetPosition( 110, 400 ); PageIndicatorBtn.SetImage( &PageindicatorImg ); PageIndicatorBtn.SetLabel( &PageindicatorTxt ); PageIndicatorBtn.SetSoundOver( &btnSoundOver ); PageIndicatorBtn.SetSoundClick( &btnClick1 ); PageIndicatorBtn.SetTrigger( &trigA ); PageIndicatorBtn.SetEffectGrow(); GuiImage wifiImg( &wifiImgData ); if ( Settings.wsprompt == yes ) { wifiImg.SetWidescreen( CFG.widescreen ); } GuiButton wifiBtn( wifiImg.GetWidth(), wifiImg.GetHeight() ); wifiBtn.SetImage( &wifiImg ); wifiBtn.SetPosition( 500, 400 ); wifiBtn.SetSoundOver( &btnSoundOver ); wifiBtn.SetSoundClick( &btnClick1 ); wifiBtn.SetEffectGrow(); wifiBtn.SetTrigger( &trigA ); GuiWindow w( screenwidth, screenheight ); HaltGui(); w.Append( &background ); mainWindow->Append( &w ); ResumeGui(); if ( !IsNetworkInit() ) NetworkInitPrompt(); char url[300]; int currentpage = 1; int currenttheme = 0; HaltGui(); w.RemoveAll(); w.Append( &background ); w.Append( &titleTxt ); w.Append( &backBtn ); w.Append( &GoLeftBtn ); w.Append( &GoRightBtn ); w.Append( &PageIndicatorBtn ); w.Append( &wifiBtn ); w.Append( &HomeBtn ); ResumeGui(); ShowProgress( tr( "Downloading Page List:" ), "", ( char * ) tr( "Please wait..." ), 0, pagesize ); Theme = new Theme_List( THEME_LINK ); int ThemesOnPage = Theme->GetThemeCount(); if ( !ThemesOnPage ) { WindowPrompt( tr( "No themes found on the site." ), 0, "OK" ); menu = MENU_SETTINGS; } while ( menu == MENU_NONE ) { HaltGui(); w.RemoveAll(); w.Append( &background ); w.Append( &titleTxt ); w.Append( &backBtn ); w.Append( &GoLeftBtn ); w.Append( &GoRightBtn ); w.Append( &PageIndicatorBtn ); w.Append( &wifiBtn ); w.Append( &HomeBtn ); ResumeGui(); sprintf( url, "%i", currentpage ); PageindicatorTxt.SetText( url ); int n = 0; for ( int i = currenttheme; ( i < ( currenttheme + pagesize ) ); i++ ) { ShowProgress( tr( "Downloading image:" ), 0, ( char * ) Theme->GetThemeTitle( i ), n, pagesize ); if ( MainButtonTxt[n] ) delete MainButtonTxt[n]; if ( ImageData[n] ) delete ImageData[n]; if ( Image[n] ) delete Image[n]; MainButtonTxt[n] = NULL; ImageData[n] = NULL; Image[n] = NULL; if ( i < ThemesOnPage ) { MainButtonTxt[n] = new GuiText( Theme->GetThemeTitle( i ), 18, ( GXColor ) { 0, 0, 0, 255} ); MainButtonTxt[n]->SetAlignment( ALIGN_CENTER, ALIGN_TOP ); MainButtonTxt[n]->SetPosition( 0, 10 ); MainButtonTxt[n]->SetMaxWidth( theme_box_Data.GetWidth() - 10, DOTTED ); sprintf( url, "%s", Theme->GetImageLink( i ) ); char filepath[300]; snprintf( filepath, sizeof( filepath ), "%s/tmp/%s.jpg", Settings.theme_downloadpath, Theme->GetThemeTitle( i ) ); FILE * storefile = fopen( filepath, "rb" ); if ( !storefile ) { struct block file = downloadfile( url ); char storepath[300]; snprintf( storepath, sizeof( storepath ), "%s/tmp/", Settings.theme_downloadpath ); subfoldercreate( storepath ); if ( file.data ) { storefile = fopen( filepath, "wb" ); fwrite( file.data, 1, file.size, storefile ); fclose( storefile ); } ImageData[n] = new GuiImageData( file.data, file.size ); free( file.data ); } else { fseek( storefile, 0, SEEK_END ); u32 filesize = ftell( storefile ); u8 *buffer = ( u8* ) malloc( filesize ); rewind( storefile ); fread( buffer, 1, filesize, storefile ); fclose( storefile ); ImageData[n] = new GuiImageData( buffer, filesize ); free( buffer ); buffer = NULL; } Image[n] = new GuiImage( ImageData[n] ); Image[n]->SetScale( 0.4 ); Image[n]->SetPosition( 50, -45 ); MainButton[n]->SetIcon( Image[n] ); MainButton[n]->SetLabel( MainButtonTxt[n] ); } n++; } ProgressStop(); HaltGui(); for ( int i = 0; i < pagesize; i++ ) { if ( MainButtonTxt[i] ) w.Append( MainButton[i] ); } ResumeGui(); listchanged = false; while ( !listchanged ) { VIDEO_WaitVSync (); if ( shutdown == 1 ) Sys_Shutdown(); else if ( reset == 1 ) Sys_Reboot(); else if ( wifiBtn.GetState() == STATE_CLICKED ) { Initialize_Network(); wifiBtn.ResetState(); } else if ( backBtn.GetState() == STATE_CLICKED ) { listchanged = true; menu = MENU_SETTINGS; backBtn.ResetState(); break; } else if ( GoRightBtn.GetState() == STATE_CLICKED ) { listchanged = true; currenttheme += pagesize; currentpage++; if ( currenttheme >= ThemesOnPage ) { currentpage = 1; currenttheme = 0; } GoRightBtn.ResetState(); } else if ( GoLeftBtn.GetState() == STATE_CLICKED ) { listchanged = true; currenttheme -= pagesize; currentpage--; if ( currenttheme < 0 ) { currentpage = roundup( ( ThemesOnPage + 1.0f ) / pagesize ); currenttheme = currentpage * pagesize - pagesize; } GoLeftBtn.ResetState(); } for ( int i = 0; i < pagesize; i++ ) { if ( MainButton[i]->GetState() == STATE_CLICKED ) { snprintf( url, sizeof( url ), "%s", Theme->GetDownloadLink( currenttheme + i ) ); int ret = Theme_Prompt( Theme->GetThemeTitle( currenttheme + i ), Theme->GetThemeAuthor( currenttheme + i ), ImageData[i], url ); MainButton[i]->ResetState(); if ( ret == 2 ) { listchanged = true; menu = MENU_THEMEDOWNLOADER; } } } } } w.SetEffect( EFFECT_FADE, -20 ); while ( w.GetEffect() > 0 ) usleep( 100 ); HaltGui(); mainWindow->Remove( &w ); for ( int i = 0; i < pagesize; i++ ) { if ( MainButton[i] ) delete MainButton[i]; if ( theme_box_img[i] ) delete theme_box_img[i]; if ( ImageData[i] ) delete ImageData[i]; if ( Image[i] ) delete Image[i]; if ( MainButtonTxt[i] ) delete MainButtonTxt[i]; } if ( Theme ) delete Theme; Theme = NULL; ResumeGui(); return menu; }