Index: guilib/GUIWindowManager.cpp =================================================================== --- guilib/GUIWindowManager.cpp (revision 24004) +++ guilib/GUIWindowManager.cpp (working copy) @@ -346,6 +346,18 @@ // destination path cannot be used with virtual window strPath1 = ""; } + + if (iWindowID == WINDOW_PROGRAMS) + { + iWindowID = g_stSettings.m_iProgramStartWindow; + // ensure the virtual video window only returns video windows + if (iWindowID != WINDOW_PROGRAM_NAV) + iWindowID = WINDOW_PROGRAM_FILES; + // destination path cannot be used with virtual window + strPath1 = ""; + } + + // Is the Library enabled? If not, go to Files view. if (iWindowID == WINDOW_MUSIC_NAV && !g_guiSettings.GetBool("musiclibrary.enabled")) { @@ -362,6 +374,15 @@ CLog::Log(LOGDEBUG, "Trying to activate Video Library, but its disabled. Switching to Files instead."); } + if (iWindowID == WINDOW_PROGRAM_NAV && !g_guiSettings.GetBool("programlibrary.enabled")) + { + iWindowID = WINDOW_PROGRAM_FILES; + // clear destination path + strPath1 = ""; + CLog::Log(LOGDEBUG, "Trying to activate Program Library, but its disabled. Switching to Files instead."); + } + + // debug CLog::Log(LOGDEBUG, "Activating window ID: %i", iWindowID); Index: guilib/Key.h =================================================================== --- guilib/Key.h (revision 24004) +++ guilib/Key.h (working copy) @@ -347,13 +347,20 @@ #define WINDOW_DIALOG_KARAOKE_SONGSELECT 10143 #define WINDOW_DIALOG_KARAOKE_SELECTOR 10144 #define WINDOW_DIALOG_SLIDER 10145 +#define WINDOW_DIALOG_PROGRAM_SCAN 10146 +#define WINDOW_DIALOG_PROGRAM_CONTENT_SETTINGS 10147 #define WINDOW_MUSIC_PLAYLIST 10500 #define WINDOW_MUSIC_FILES 10501 #define WINDOW_MUSIC_NAV 10502 #define WINDOW_MUSIC_PLAYLIST_EDITOR 10503 #define WINDOW_PROGRAM_NAV 10504 +#define WINDOW_PROGRAM_FILES 10505 +#define WINDOW_PROGRAM_GENRE 10506 +#define WINDOW_PROGRAM_DEVELOPER 10507 +#define WINDOW_PROGRAM_YEAR 10508 + //#define WINDOW_VIRTUAL_KEYBOARD 11000 #define WINDOW_DIALOG_SELECT 12000 #define WINDOW_MUSIC_INFO 12001 @@ -365,10 +372,12 @@ #define WINDOW_SLIDESHOW 12007 #define WINDOW_DIALOG_FILESTACKING 12008 #define WINDOW_KARAOKELYRICS 12009 +#define WINDOW_PROGRAM_INFO 12010 #define WINDOW_WEATHER 12600 #define WINDOW_SCREENSAVER 12900 #define WINDOW_OSD 12901 + #define WINDOW_VIDEO_MENU 12902 #define WINDOW_MUSIC_OVERLAY 12903 #define WINDOW_VIDEO_OVERLAY 12904 @@ -380,6 +389,9 @@ #define WINDOW_PYTHON_START 13000 #define WINDOW_PYTHON_END 13099 + + + #define ICON_TYPE_NONE 101 #define ICON_TYPE_PROGRAMS 102 #define ICON_TYPE_MUSIC 103 Index: language/English/strings.xml =================================================================== --- language/English/strings.xml (revision 24004) +++ language/English/strings.xml (working copy) @@ -1,4 +1,4 @@ - + Programs @@ -1315,9 +1315,7 @@ Games Program info Game info - - - + No programfiles found in this path Platform Developer Publisher @@ -1325,6 +1323,8 @@ No. of Players GameStandards Rating Synopsis + Perspectives + Recently added games Index: skin/PM3.HD/720p/Home.xml =================================================================== --- skin/PM3.HD/720p/Home.xml (revision 24004) +++ skin/PM3.HD/720p/Home.xml (working copy) @@ -501,12 +501,19 @@ special://skin/backgrounds/pictures.jpg $INFO[Skin.String(Home_Custom_Back_Pictures_Folder)] + + + ActivateWindow(Programs) + special://skin/backgrounds/programs.jpg + $INFO[Skin.String(Home_Custom_Back_Programs_Folder)] + Skin.HasSetting(ProgramsInHome) + Library.HasContent(Games) + - ActivateWindow(Programs) + ActivateWindow(ProgramFiles) special://skin/backgrounds/programs.jpg $INFO[Skin.String(Home_Custom_Back_Programs_Folder)] - Skin.HasSetting(ProgramsInHome) + Skin.HasSetting(ProgramsInHome) + !Library.HasContent(Games) Index: skin/PM3.HD/720p/includes.xml =================================================================== --- skin/PM3.HD/720p/includes.xml (revision 24004) +++ skin/PM3.HD/720p/includes.xml (working copy) @@ -3,6 +3,7 @@ + @@ -548,6 +549,7 @@ Conditional Conditional Conditional + Conditional Conditional Conditional Conditional @@ -575,6 +577,7 @@ + 44 280 Index: skin/PM3.HD/720p/MyPrograms.xml =================================================================== --- skin/PM3.HD/720p/MyPrograms.xml (revision 24004) +++ skin/PM3.HD/720p/MyPrograms.xml (working copy) @@ -1,15 +1,19 @@ 50 no + 50,51,54 CommonBackground Window_OpenClose_Right_Panel_Animation - ContentPanel - CommonRootView - CommonListView - ThumbnailView - WideIconView + + Conditional + Conditional + ContentPanel + CommonRootView + CommonListView + WideIconView + AllViewCommonPageControls CommonFileCount ScrollOffsetLabel @@ -20,6 +24,17 @@ 0 130 + Conditional + Conditional + + 0 + -30 + 320 + 470 + Panel2.png + Control.IsVisible(500) + VisibleFadeEffect + View As button 0 @@ -28,7 +43,7 @@ 50 50 - 99 + 611 3 @@ -52,42 +67,43 @@ 2 99 - + Library button 0 90 - ReplaceWindow(Programlibrary) - Window.IsVisible(Programlibrary) + ReplaceWindow(myprogramlibrary) + Window.IsVisible(myprogramlibrary) ButtonCommonValues 50 50 - 2 - 98 + 3 + 7 + Library.HasContent(Program) + System.GetBool(programlibrary.enabled) - - Gamesaves Button + + Stack Toggle 0 135 ButtonCommonValues - - ActivateWindow(35) + 50 50 - 3 + 99 610 - System.Platform.Xbox + conditional Fake Button to fix Player Controls Navigation - 98 + 7 603 false 0 180 - conditional + conditional CommonNowPlaying_Controls @@ -107,7 +123,7 @@ WindowTitleCommons - + \ No newline at end of file Index: skin/PM3.HD/720p/MyProgramsNav.xml =================================================================== --- skin/PM3.HD/720p/MyProgramsNav.xml (revision 24004) +++ skin/PM3.HD/720p/MyProgramsNav.xml (working copy) @@ -1,18 +1,30 @@ 50 no - 50 + 50,51,54,60,61 + CommonBackground + - Window_OpenClose_Right_Panel_Animation - ContentPanel - CommonRootView - CommonListView - ThumbnailView - AllViewCommonPageControls - CommonFileCount - ScrollOffsetLabel + Window_OpenClose_Right_Panel_Animation + + Conditional + Conditional + + + ContentPanel + CommonRootView + CommonListView + GamesListView + GamesFanartView + + WideIconView + + + Window_OpenClose_Animation + GameFanartView_Extras + Window_OpenClose_Left_Panel_Animation @@ -57,8 +69,8 @@ 0 90 - ReplaceWindow(Programs) - Window.IsVisible(Programlibrary) + ReplaceWindow(programs) + Window.IsVisible(programlibrary) ButtonCommonValues 50 50 Index: system/playercorefactory.xml =================================================================== --- system/playercorefactory.xml (revision 24004) +++ system/playercorefactory.xml (working copy) @@ -7,9 +7,13 @@ placeholder for MPlayer --> + + D:\emu\zsnesw151\snesw.exe + + Index: system/scrapers/programs/moby.gif =================================================================== Cannot display: file marked as a binary type. svn:mime-type = application/octet-stream Property changes on: system\scrapers\programs\moby.gif ___________________________________________________________________ Added: svn:mime-type + application/octet-stream Index: xbmc/AdvancedSettings.cpp =================================================================== --- xbmc/AdvancedSettings.cpp (revision 24004) +++ xbmc/AdvancedSettings.cpp (working copy) @@ -41,13 +41,13 @@ m_useMultipaths = true; m_audioHeadRoom = 0; - m_ac3Gain = 12.0f; + m_ac3Gain = 12.0f; m_audioApplyDrc = true; m_karaokeSyncDelayCDG = 0.0f; m_karaokeSyncDelayLRC = 0.0f; m_karaokeChangeGenreForKaraokeSongs = false; - m_karaokeKeepDelay = true; + m_karaokeKeepDelay = true; m_karaokeStartIndex = 1; m_karaokeAlwaysEmptyOnCdgs = 1; m_karaokeUseSongSpecificBackground = 0; @@ -106,6 +106,8 @@ m_songInfoDuration = 10; m_busyDialogDelay = 2000; + + #ifdef _DEBUG m_logLevel = LOG_LEVEL_DEBUG; m_logLevelHint = LOG_LEVEL_DEBUG; @@ -117,6 +119,8 @@ #ifdef HAS_HAL m_useHalMount = g_application.IsStandAlone(); #endif + + m_fullScreenOnMovieStart = true; m_noDVDROM = false; m_cachePath = "special://temp/"; @@ -128,6 +132,7 @@ m_videoCleanStringRegExps.push_back("(\\[.*\\])"); m_moviesExcludeFromScanRegExps.push_back("-trailer"); + m_gamesExcludeFromScanRegExps.push_back("-preview"); m_moviesExcludeFromScanRegExps.push_back("[-._ ]sample"); m_tvshowExcludeFromScanRegExps.push_back("[-._ ]sample[-._ ]"); @@ -150,22 +155,22 @@ m_tvshowMultiPartStackRegExp = "^[-EeXx]+([0-9]+)"; - m_remoteRepeat = 480; + m_remoteRepeat = 480; m_controllerDeadzone = 0.2f; m_playlistAsFolders = true; - m_detectAsUdf = false; + m_detectAsUdf = false; m_thumbSize = DEFAULT_THUMB_SIZE; m_sambaclienttimeout = 10; - m_sambadoscodepage = ""; - m_sambastatfiles = true; + m_sambadoscodepage = ""; + m_sambastatfiles = true; m_bHTTPDirectoryStatFilesize = false; m_musicThumbs = "folder.jpg|Folder.jpg|folder.JPG|Folder.JPG|cover.jpg|Cover.jpg|cover.jpeg"; - m_dvdThumbs = "folder.jpg|Folder.jpg|folder.JPG|Folder.JPG"; + m_dvdThumbs = "folder.jpg|Folder.jpg|folder.JPG|Folder.JPG"; m_bMusicLibraryHideAllItems = false; m_bMusicLibraryAllItemsOnBottom = false; @@ -176,7 +181,7 @@ m_prioritiseAPEv2tags = false; m_musicItemSeparator = " / "; m_videoItemSeparator = " / "; - + m_programItemSeparator = " / "; m_bVideoLibraryHideAllItems = false; m_bVideoLibraryAllItemsOnBottom = false; m_iVideoLibraryRecentlyAddedItems = 25; @@ -186,6 +191,12 @@ m_bVideoLibraryExportAutoThumbs = false; m_bVideoLibraryMyMoviesCategoriesToGenres = false; + m_bProgramLibraryHideAllItems = false; + m_bProgramLibraryAllItemsOnBottom = false; + m_iProgramLibraryRecentlyAddedItems = 25; + m_bProgramLibraryHideRecentlyAddedItems = false; + m_bProgramLibraryCleanOnUpdate = false; + m_bUseEvilB = true; m_bTuxBoxAudioChannelSelection = false; @@ -383,6 +394,26 @@ XMLUtils::GetString(pElement,"postprocessing",m_videoPPFFmpegType); } + + pElement = pRootElement->FirstChildElement("programfiles"); + if (pElement) + { + TiXmlElement* pProgramExcludes = pElement->FirstChildElement("excludefromlisting"); + if (pProgramExcludes) + GetCustomRegexps(pProgramExcludes, m_programExcludeFromListingRegExps); + + pProgramExcludes = pElement->FirstChildElement("excludefromscan"); + if (pProgramExcludes) + GetCustomRegexps(pProgramExcludes, m_gamesExcludeFromScanRegExps); + + + pProgramExcludes = pElement->FirstChildElement("cleanstrings"); + if (pProgramExcludes) + GetCustomRegexps(pProgramExcludes, m_programCleanStringRegExps); + + } + + pElement = pRootElement->FirstChildElement("musiclibrary"); if (pElement) { @@ -412,6 +443,18 @@ if (pMyMovies) XMLUtils::GetBoolean(pMyMovies, "categoriestogenres", m_bVideoLibraryMyMoviesCategoriesToGenres); } + + pElement = pRootElement->FirstChildElement("programlibrary"); + if (pElement) + { + XMLUtils::GetBoolean(pElement, "hideallitems", m_bProgramLibraryHideAllItems); + XMLUtils::GetBoolean(pElement, "allitemsonbottom", m_bProgramLibraryAllItemsOnBottom); + XMLUtils::GetInt(pElement, "recentlyaddeditems", m_iProgramLibraryRecentlyAddedItems, 1, INT_MAX); + XMLUtils::GetBoolean(pElement, "hiderecentlyaddeditems", m_bProgramLibraryHideRecentlyAddedItems); + XMLUtils::GetBoolean(pElement, "cleanonupdate", m_bProgramLibraryCleanOnUpdate); + XMLUtils::GetString(pElement, "itemseparator", m_programItemSeparator); + } + // Backward-compatibility of ExternalPlayer config pElement = pRootElement->FirstChildElement("externalplayer"); if (pElement) @@ -547,6 +590,11 @@ if (pExts) GetCustomExtensions(pExts,g_stSettings.m_videoExtensions); + // video extensions + pExts = pRootElement->FirstChildElement("programextensions"); + if (pExts) + GetCustomExtensions(pExts,g_stSettings.m_programExtensions); + const TiXmlNode *pTokens = pRootElement->FirstChild("sorttokens"); m_vecTokens.clear(); if (pTokens && !pTokens->NoChildren()) Index: xbmc/AdvancedSettings.h =================================================================== --- xbmc/AdvancedSettings.h (revision 24004) +++ xbmc/AdvancedSettings.h (working copy) @@ -122,13 +122,17 @@ bool m_displayRemoteCodes; CStdString m_videoCleanDateTimeRegExp; CStdStringArray m_videoCleanStringRegExps; + CStdStringArray m_programCleanStringRegExps; CStdStringArray m_videoExcludeFromListingRegExps; CStdStringArray m_moviesExcludeFromScanRegExps; + CStdStringArray m_programExcludeFromListingRegExps; + CStdStringArray m_gamesExcludeFromScanRegExps; CStdStringArray m_tvshowExcludeFromScanRegExps; CStdStringArray m_audioExcludeFromListingRegExps; CStdStringArray m_audioExcludeFromScanRegExps; CStdStringArray m_pictureExcludeFromListingRegExps; CStdStringArray m_videoStackRegExps; + CStdStringArray m_programStackRegExps; SETTINGS_TVSHOWLIST m_tvshowStackRegExps; CStdString m_tvshowMultiPartStackRegExp; CStdStringArray m_pathSubstitutions; @@ -158,6 +162,7 @@ bool m_prioritiseAPEv2tags; CStdString m_musicItemSeparator; CStdString m_videoItemSeparator; + CStdString m_programItemSeparator; std::vector m_musicTagsFromFileFilters; bool m_bVideoLibraryHideAllItems; @@ -169,6 +174,11 @@ bool m_bVideoLibraryExportAutoThumbs; bool m_bVideoLibraryMyMoviesCategoriesToGenres; + bool m_bProgramLibraryHideAllItems; + bool m_bProgramLibraryAllItemsOnBottom; + int m_iProgramLibraryRecentlyAddedItems; + bool m_bProgramLibraryHideRecentlyAddedItems; + bool m_bProgramLibraryCleanOnUpdate; bool m_bUseEvilB; std::vector m_vecTokens; // cleaning strings tied to language //TuxBox Index: xbmc/Application.cpp =================================================================== --- xbmc/Application.cpp (revision 24004) +++ xbmc/Application.cpp (working copy) @@ -149,6 +149,9 @@ #include "GUIWindowVideoInfo.h" #include "GUIWindowVideoFiles.h" #include "GUIWindowVideoNav.h" +#include "GUIWindowProgramInfo.h" +#include "GUIWindowProgramFiles.h" +#include "GUIWindowProgramNav.h" #include "GUIWindowSettingsProfile.h" #ifdef HAS_GL #include "GUIWindowTestPatternGL.h" @@ -157,7 +160,7 @@ #include "GUIWindowTestPatternDX.h" #endif #include "GUIWindowSettingsScreenCalibration.h" -#include "GUIWindowPrograms.h" +//#include "GUIWindowPrograms.h" #include "GUIWindowPictures.h" #include "GUIWindowScripts.h" #include "GUIWindowWeather.h" @@ -171,7 +174,7 @@ #include "GUIWindowOSD.h" #include "GUIWindowMusicOverlay.h" #include "GUIWindowVideoOverlay.h" -#include "GUIWindowProgramNav.h" +//#include "GUIWindowProgramNav.h" // Dialog includes #include "GUIDialogMusicOSD.h" @@ -186,7 +189,9 @@ #include "GUIDialogProfileSettings.h" #include "GUIDialogLockSettings.h" #include "GUIDialogContentSettings.h" +#include "GUIDialogProgramContentSettings.h" #include "GUIDialogVideoScan.h" +#include "GUIDialogProgramScan.h" #include "GUIDialogBusy.h" #include "GUIDialogKeyboard.h" @@ -273,6 +278,7 @@ #endif using namespace PLAYLIST; using namespace VIDEO; +using namespace PROGRAM; using namespace MUSIC_INFO; #ifdef HAS_EVENT_SERVER using namespace EVENTSERVER; @@ -1143,7 +1149,7 @@ CLog::Log(LOGNOTICE, "load default skin:[%s]", g_guiSettings.GetString("lookandfeel.skin").c_str()); LoadSkin(g_guiSettings.GetString("lookandfeel.skin")); - m_gWindowManager.Add(new CGUIWindowPrograms); // window id = 1 + m_gWindowManager.Add(new CGUIWindowProgramFiles); // window id = 1 m_gWindowManager.Add(new CGUIWindowPictures); // window id = 2 m_gWindowManager.Add(new CGUIWindowFileManager); // window id = 3 m_gWindowManager.Add(new CGUIWindowVideoFiles); // window id = 6 @@ -1191,6 +1197,7 @@ m_gWindowManager.Add(new CGUIDialogMediaSource); // window id = 129 m_gWindowManager.Add(new CGUIDialogProfileSettings); // window id = 130 m_gWindowManager.Add(new CGUIDialogVideoScan); // window id = 133 + m_gWindowManager.Add(new CGUIDialogProgramScan); m_gWindowManager.Add(new CGUIDialogFavourites); // window id = 134 m_gWindowManager.Add(new CGUIDialogSongInfo); // window id = 135 m_gWindowManager.Add(new CGUIDialogSmartPlaylistEditor); // window id = 136 @@ -1204,7 +1211,9 @@ m_gWindowManager.Add(new CGUIDialogLockSettings); // window id = 131 + m_gWindowManager.Add(new CGUIDialogContentSettings); // window id = 132 + //m_gWindowManager.Add(new CGUIDialogProgramContentSettings); // window id = 147 m_gWindowManager.Add(new CGUIWindowMusicPlayList); // window id = 500 m_gWindowManager.Add(new CGUIWindowMusicSongs); // window id = 501 @@ -1216,6 +1225,7 @@ m_gWindowManager.Add(new CGUIWindowMusicInfo); // window id = 2001 m_gWindowManager.Add(new CGUIDialogOK); // window id = 2002 m_gWindowManager.Add(new CGUIWindowVideoInfo); // window id = 2003 + m_gWindowManager.Add(new CGUIWindowProgramInfo); m_gWindowManager.Add(new CGUIWindowScriptsInfo); // window id = 2004 m_gWindowManager.Add(new CGUIWindowFullScreen); // window id = 2005 m_gWindowManager.Add(new CGUIWindowVisualisation); // window id = 2006 @@ -1314,6 +1324,16 @@ scanner->StartScanning("",info,settings,false); } + if (g_guiSettings.GetBool("programlibrary.updateonstartup")) + { + CLog::Log(LOGNOTICE, "Updating program library on startup"); + CGUIDialogProgramScan *scanner = (CGUIDialogProgramScan *)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRAM_SCAN); + SScraperInfo info; + PROGRAM::SScanSettings settings; + if (scanner && !scanner->IsScanning()) + scanner->StartScanning("",info,settings,false); + } + #ifdef HAS_HAL g_HalManager.Initialize(); #endif @@ -3292,14 +3312,13 @@ m_gWindowManager.Delete(WINDOW_MUSIC_FILES); m_gWindowManager.Delete(WINDOW_MUSIC_NAV); m_gWindowManager.Delete(WINDOW_PROGRAM_NAV); + m_gWindowManager.Delete(WINDOW_PROGRAM_INFO); m_gWindowManager.Delete(WINDOW_MUSIC_INFO); m_gWindowManager.Delete(WINDOW_VIDEO_INFO); m_gWindowManager.Delete(WINDOW_VIDEO_FILES); m_gWindowManager.Delete(WINDOW_VIDEO_PLAYLIST); m_gWindowManager.Delete(WINDOW_VIDEO_NAV); m_gWindowManager.Delete(WINDOW_FILES); - m_gWindowManager.Delete(WINDOW_MUSIC_INFO); - m_gWindowManager.Delete(WINDOW_VIDEO_INFO); m_gWindowManager.Delete(WINDOW_DIALOG_YES_NO); m_gWindowManager.Delete(WINDOW_DIALOG_PROGRESS); m_gWindowManager.Delete(WINDOW_DIALOG_NUMERIC); @@ -3328,6 +3347,7 @@ m_gWindowManager.Delete(WINDOW_DIALOG_VIDEO_BOOKMARKS); m_gWindowManager.Delete(WINDOW_DIALOG_VIDEO_SCAN); m_gWindowManager.Delete(WINDOW_DIALOG_CONTENT_SETTINGS); + m_gWindowManager.Delete(WINDOW_DIALOG_PROGRAM_CONTENT_SETTINGS); m_gWindowManager.Delete(WINDOW_DIALOG_FAVOURITES); m_gWindowManager.Delete(WINDOW_DIALOG_SONG_INFO); m_gWindowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_EDITOR); @@ -3468,6 +3488,10 @@ if (videoScan) videoScan->StopScanning(); + CGUIDialogProgramScan *programScan = (CGUIDialogProgramScan *)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRAM_SCAN); + if (programScan) + programScan->StopScanning(); + StopServices(); //Sleep(5000); @@ -4075,6 +4099,12 @@ return false; } +bool CApplication::IsPlayingProgram() const +{ + return true; +} + + bool CApplication::IsPlayingVideo() const { if (!m_pPlayer) @@ -4463,7 +4493,7 @@ { CGUIDialogMusicScan *pMusicScan = (CGUIDialogMusicScan *)m_gWindowManager.GetWindow(WINDOW_DIALOG_MUSIC_SCAN); CGUIDialogVideoScan *pVideoScan = (CGUIDialogVideoScan *)m_gWindowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN); - + CGUIDialogProgramScan *pProgramScan = (CGUIDialogProgramScan *)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRAM_SCAN); // first check if we should reset the timer bool resetTimer = false; if (IsPlaying()) // is something playing? @@ -4480,6 +4510,9 @@ if (pVideoScan && pVideoScan->IsScanning()) // video scanning? resetTimer = true; + if (pProgramScan && pProgramScan->IsScanning()) // video scanning? + resetTimer = true; + if (m_gWindowManager.IsWindowActive(WINDOW_DIALOG_PROGRESS)) // progress dialog is onscreen resetTimer = true; Index: xbmc/Application.h =================================================================== --- xbmc/Application.h (revision 24004) +++ xbmc/Application.h (working copy) @@ -152,6 +152,7 @@ bool IsPaused() const; bool IsPlayingAudio() const; bool IsPlayingVideo() const; + bool IsPlayingProgram() const; bool IsPlayingFullScreenVideo() const; bool IsStartingPlayback() const { return m_bPlaybackStarting; } bool OnKey(CKey& key); Index: xbmc/ButtonTranslator.cpp =================================================================== --- xbmc/ButtonTranslator.cpp (revision 24004) +++ xbmc/ButtonTranslator.cpp (working copy) @@ -872,6 +872,8 @@ else if (strWindow.Equals("musicinformation")) wWindowID = WINDOW_MUSIC_INFO; else if (strWindow.Equals("video") || strWindow.Equals("videos")) wWindowID = WINDOW_VIDEOS; else if (strWindow.Equals("videofiles")) wWindowID = WINDOW_VIDEO_FILES; + else if (strWindow.Equals("programfiles")) wWindowID = WINDOW_PROGRAM_FILES; + else if (strWindow.Equals("programlibrary")) wWindowID = WINDOW_PROGRAM_NAV; else if (strWindow.Equals("videolibrary")) wWindowID = WINDOW_VIDEO_NAV; else if (strWindow.Equals("videoplaylist")) wWindowID = WINDOW_VIDEO_PLAYLIST; else if (strWindow.Equals("systeminfo")) wWindowID = WINDOW_SYSTEM_INFORMATION; @@ -912,6 +914,7 @@ else if (strWindow.Equals("profilesettings")) wWindowID = WINDOW_DIALOG_PROFILE_SETTINGS; else if (strWindow.Equals("locksettings")) wWindowID = WINDOW_DIALOG_LOCK_SETTINGS; else if (strWindow.Equals("contentsettings")) wWindowID = WINDOW_DIALOG_CONTENT_SETTINGS; + else if (strWindow.Equals("programcontentsettings")) wWindowID = WINDOW_DIALOG_PROGRAM_CONTENT_SETTINGS; else if (strWindow.Equals("networksetup")) wWindowID = WINDOW_DIALOG_NETWORK_SETUP; else if (strWindow.Equals("mediasource")) wWindowID = WINDOW_DIALOG_MEDIA_SOURCE; else if (strWindow.Equals("smartplaylisteditor")) wWindowID = WINDOW_DIALOG_SMART_PLAYLIST_EDITOR; @@ -919,6 +922,7 @@ else if (strWindow.Equals("selectdialog")) wWindowID = WINDOW_DIALOG_SELECT; else if (strWindow.Equals("okdialog")) wWindowID = WINDOW_DIALOG_OK; else if (strWindow.Equals("movieinformation")) wWindowID = WINDOW_VIDEO_INFO; + else if (strWindow.Equals("gameinformation")) wWindowID = WINDOW_PROGRAM_INFO; else if (strWindow.Equals("scriptsdebuginfo")) wWindowID = WINDOW_SCRIPTS_INFO; else if (strWindow.Equals("fullscreenvideo")) wWindowID = WINDOW_FULLSCREEN_VIDEO; else if (strWindow.Equals("visualisation")) wWindowID = WINDOW_VISUALISATION; Index: xbmc/FileItem.cpp =================================================================== --- xbmc/FileItem.cpp (revision 24004) +++ xbmc/FileItem.cpp (working copy) @@ -34,6 +34,7 @@ #include "FileSystem/MultiPathDirectory.h" #include "FileSystem/MusicDatabaseDirectory.h" #include "FileSystem/VideoDatabaseDirectory.h" +#include "FileSystem/ProgramDatabaseDirectory.h" #include "FileSystem/IDirectory.h" #include "FileSystem/FactoryDirectory.h" #include "MusicInfoTagLoaderFactory.h" @@ -41,12 +42,14 @@ #include "utils/fstrcmp.h" #include "VideoDatabase.h" #include "MusicDatabase.h" +#include "ProgramDatabase.h" #include "SortFileItem.h" #include "utils/TuxBoxUtil.h" #include "VideoInfoTag.h" #include "utils/SingleLock.h" #include "MusicInfoTag.h" #include "PictureInfoTag.h" +#include "ProgramInfoTag.h" #include "Artist.h" #include "Album.h" #include "Song.h" @@ -63,61 +66,65 @@ CFileItem::CFileItem(const CSong& song) { - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; Reset(); SetLabel(song.strTitle); - m_strPath = song.strFileName; + m_strPath = song.strFileName; GetMusicInfoTag()->SetSong(song); m_lStartOffset = song.iStartOffset; - m_lEndOffset = song.iEndOffset; + m_lEndOffset = song.iEndOffset; m_strThumbnailImage = song.strThumb; } CFileItem::CFileItem(const CStdString &path, const CAlbum& album) { - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; Reset(); SetLabel(album.strAlbum); - m_strPath = path; + m_strPath = path; m_bIsFolder = true; m_strLabel2 = album.strArtist; CUtil::AddSlashAtEnd(m_strPath); GetMusicInfoTag()->SetAlbum(album); + if (album.thumbURL.m_url.size() > 0) m_strThumbnailImage = album.thumbURL.m_url[0].m_url; else m_strThumbnailImage.clear(); SetProperty("description", album.strReview); - SetProperty("theme", album.strThemes); - SetProperty("mood", album.strMoods); - SetProperty("style", album.strStyles); - SetProperty("type", album.strType); - SetProperty("label", album.strLabel); + SetProperty("theme", album.strThemes); + SetProperty("mood", album.strMoods); + SetProperty("style", album.strStyles); + SetProperty("type", album.strType); + SetProperty("label", album.strLabel); if (album.iRating > 0) - SetProperty("rating", album.iRating); + SetProperty("rating", album.iRating); } CFileItem::CFileItem(const CVideoInfoTag& movie) { - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; Reset(); SetLabel(movie.m_strTitle); if (movie.m_strFileNameAndPath.IsEmpty()) { - m_strPath = movie.m_strPath; + m_strPath = movie.m_strPath; CUtil::AddSlashAtEnd(m_strPath); m_bIsFolder = true; } else { - m_strPath = movie.m_strFileNameAndPath; + m_strPath = movie.m_strFileNameAndPath; m_bIsFolder = false; } *GetVideoInfoTag() = movie; @@ -125,14 +132,41 @@ SetCachedVideoThumb(); } + +CFileItem::CFileItem(const CProgramInfoTag& game) +{ + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; + m_pictureInfoTag = NULL; + m_programInfoTag = NULL; + Reset(); + SetLabel(game.m_strTitle); + if (game.m_strFileNameAndPath.IsEmpty()) + { + m_strPath = game.m_strPath; + CUtil::AddSlashAtEnd(m_strPath); + m_bIsFolder = true; + } + else + { + m_strPath = game.m_strFileNameAndPath; + m_bIsFolder = false; + } + *GetProgramInfoTag() = game; + FillInDefaultIcon(); + SetCachedProgramThumb(); +} + + CFileItem::CFileItem(const CArtist& artist) { - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; Reset(); SetLabel(artist.strArtist); - m_strPath = artist.strArtist; + m_strPath = artist.strArtist; m_bIsFolder = true; CUtil::AddSlashAtEnd(m_strPath); GetMusicInfoTag()->SetArtist(artist.strArtist); @@ -140,12 +174,13 @@ CFileItem::CFileItem(const CGenre& genre) { - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; Reset(); SetLabel(genre.strGenre); - m_strPath = genre.strGenre; + m_strPath = genre.strGenre; m_bIsFolder = true; CUtil::AddSlashAtEnd(m_strPath); GetMusicInfoTag()->SetGenre(genre.strGenre); @@ -153,17 +188,19 @@ CFileItem::CFileItem(const CFileItem& item): CGUIListItem() { - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; *this = item; } CFileItem::CFileItem(const CGUIListItem& item) { - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; Reset(); // not particularly pretty, but it gets around the issue of Reset() defaulting // parameters in the CGUIListItem base class. @@ -172,29 +209,32 @@ CFileItem::CFileItem(void) { - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; Reset(); } CFileItem::CFileItem(const CStdString& strLabel) : CGUIListItem() { - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; Reset(); SetLabel(strLabel); } CFileItem::CFileItem(const CStdString& strPath, bool bIsFolder) { - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; Reset(); - m_strPath = strPath; + m_strPath = strPath; m_bIsFolder = bIsFolder; // tuxbox urls cannot have a / at end if (m_bIsFolder && !m_strPath.IsEmpty() && !IsFileFolder() && !CUtil::IsTuxBox(m_strPath)) @@ -208,23 +248,24 @@ CFileItem::CFileItem(const CMediaSource& share) { - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; Reset(); - m_bIsFolder = true; - m_bIsShareOrDrive = true; - m_strPath = share.strPath; + m_bIsFolder = true; + m_bIsShareOrDrive = true; + m_strPath = share.strPath; CUtil::AddSlashAtEnd(m_strPath); - CStdString label = share.strName; + CStdString label = share.strName; if (!share.strStatus.IsEmpty()) label.Format("%s (%s)", share.strName.c_str(), share.strStatus.c_str()); SetLabel(label); - m_iLockMode = share.m_iLockMode; - m_strLockCode = share.m_strLockCode; - m_iHasLock = share.m_iHasLock; - m_iBadPwdCount = share.m_iBadPwdCount; - m_iDriveType = share.m_iDriveType; + m_iLockMode = share.m_iLockMode; + m_strLockCode = share.m_strLockCode; + m_iHasLock = share.m_iHasLock; + m_iBadPwdCount = share.m_iBadPwdCount; + m_iDriveType = share.m_iDriveType; m_strThumbnailImage = share.m_strThumbnailImage; SetLabelPreformated(true); } @@ -234,10 +275,12 @@ delete m_musicInfoTag; delete m_videoInfoTag; delete m_pictureInfoTag; + delete m_programInfoTag; - m_musicInfoTag = NULL; - m_videoInfoTag = NULL; + m_musicInfoTag = NULL; + m_videoInfoTag = NULL; m_pictureInfoTag = NULL; + m_programInfoTag = NULL; } const CFileItem& CFileItem::operator=(const CFileItem& item) @@ -246,12 +289,12 @@ CGUIListItem::operator=(item); m_bLabelPreformated=item.m_bLabelPreformated; FreeMemory(); - m_strPath = item.m_strPath; + m_strPath = item.m_strPath; m_bIsParentFolder = item.m_bIsParentFolder; - m_iDriveType = item.m_iDriveType; + m_iDriveType = item.m_iDriveType; m_bIsShareOrDrive = item.m_bIsShareOrDrive; - m_dateTime = item.m_dateTime; - m_dwSize = item.m_dwSize; + m_dateTime = item.m_dateTime; + m_dwSize = item.m_dwSize; if (item.HasMusicInfoTag()) { m_musicInfoTag = GetMusicInfoTag(); @@ -287,56 +330,71 @@ delete m_pictureInfoTag; m_pictureInfoTag = NULL; } + + if (item.HasProgramInfoTag()) + { + m_programInfoTag = GetProgramInfoTag(); + if (m_programInfoTag) + *m_programInfoTag = *item.m_programInfoTag; + } + else + { + delete m_programInfoTag; + m_programInfoTag = NULL; + } - m_lStartOffset = item.m_lStartOffset; - m_lEndOffset = item.m_lEndOffset; - m_strDVDLabel = item.m_strDVDLabel; - m_strTitle = item.m_strTitle; + m_lStartOffset = item.m_lStartOffset; + m_lEndOffset = item.m_lEndOffset; + m_strDVDLabel = item.m_strDVDLabel; + m_strTitle = item.m_strTitle; m_iprogramCount = item.m_iprogramCount; - m_idepth = item.m_idepth; - m_iLockMode = item.m_iLockMode; - m_strLockCode = item.m_strLockCode; - m_iHasLock = item.m_iHasLock; - m_iBadPwdCount = item.m_iBadPwdCount; - m_bCanQueue=item.m_bCanQueue; - m_contenttype = item.m_contenttype; - m_extrainfo = item.m_extrainfo; + m_idepth = item.m_idepth; + m_iLockMode = item.m_iLockMode; + m_strLockCode = item.m_strLockCode; + m_iHasLock = item.m_iHasLock; + m_iBadPwdCount = item.m_iBadPwdCount; + m_bCanQueue = item.m_bCanQueue; + m_contenttype = item.m_contenttype; + m_extrainfo = item.m_extrainfo; return *this; } +//Misc type tests void CFileItem::Reset() { m_strLabel2.Empty(); SetLabel(""); - m_bLabelPreformated=false; + m_bLabelPreformated = false; FreeIcons(); m_overlayIcon = ICON_OVERLAY_NONE; - m_bSelected = false; + m_bSelected = false; m_strDVDLabel.Empty(); m_strTitle.Empty(); m_strPath.Empty(); - m_dwSize = 0; - m_bIsFolder = false; - m_bIsParentFolder=false; + m_dwSize = 0; + m_bIsFolder = false; + m_bIsParentFolder = false; m_bIsShareOrDrive = false; m_dateTime.Reset(); - m_iDriveType = CMediaSource::SOURCE_TYPE_UNKNOWN; - m_lStartOffset = 0; - m_lEndOffset = 0; + m_iDriveType = CMediaSource::SOURCE_TYPE_UNKNOWN; + m_lStartOffset = 0; + m_lEndOffset = 0; m_iprogramCount = 0; - m_idepth = 1; - m_iLockMode = LOCK_MODE_EVERYONE; - m_strLockCode = ""; - m_iBadPwdCount = 0; - m_iHasLock = 0; - m_bCanQueue=true; - m_contenttype = ""; + m_idepth = 1; + m_iLockMode = LOCK_MODE_EVERYONE; + m_strLockCode = ""; + m_iBadPwdCount = 0; + m_iHasLock = 0; + m_bCanQueue = true; + m_contenttype = ""; delete m_musicInfoTag; - m_musicInfoTag=NULL; + m_musicInfoTag = NULL; delete m_videoInfoTag; - m_videoInfoTag=NULL; + m_videoInfoTag = NULL; delete m_pictureInfoTag; - m_pictureInfoTag=NULL; + m_pictureInfoTag = NULL; + delete m_programInfoTag; + m_programInfoTag = NULL; m_extrainfo.Empty(); SetInvalid(); } @@ -363,7 +421,6 @@ ar << m_iLockMode; ar << m_strLockCode; ar << m_iBadPwdCount; - ar << m_bCanQueue; ar << m_contenttype; ar << m_extrainfo; @@ -389,6 +446,13 @@ } else ar << 0; + if (m_programInfoTag) + { + ar << 1; + ar << *m_programInfoTag; + } + else + ar << 0; } else { @@ -425,6 +489,9 @@ ar >> iType; if (iType == 1) ar >> *GetPictureInfoTag(); + ar >> iType; + if (iType == 1) + ar >> *GetProgramInfoTag(); SetInvalid(); } @@ -440,6 +507,12 @@ return dbItem.Exists(); } + if (IsProgramDb() && HasProgramInfoTag()) + { + CFileItem dbItem(m_bIsFolder ? GetProgramInfoTag()->m_strPath : GetProgramInfoTag()->m_strFileNameAndPath, m_bIsFolder); + return dbItem.Exists(); + } + CStdString strPath = m_strPath; if (CUtil::IsMultiPath(strPath)) @@ -458,9 +531,10 @@ bool CFileItem::IsVideo() const { - if (HasVideoInfoTag()) return true; - if (HasMusicInfoTag()) return false; + if (HasVideoInfoTag()) return true; + if (HasMusicInfoTag()) return false; if (HasPictureInfoTag()) return false; + if (HasProgramInfoTag()) return false; /* check preset content type */ if( m_contenttype.Left(6).Equals("video/") ) @@ -500,12 +574,13 @@ bool CFileItem::IsAudio() const { - if (HasMusicInfoTag()) return true; - if (HasVideoInfoTag()) return false; + if (HasMusicInfoTag()) return true; + if (HasVideoInfoTag()) return false; if (HasPictureInfoTag()) return false; - if (IsCDDA()) return true; + if (HasProgramInfoTag()) return false; + if (IsCDDA()) return true; if (IsShoutCast() && !m_bIsFolder) return true; - if (IsLastFM() && !m_bIsFolder) return true; + if (IsLastFM() && !m_bIsFolder) return true; /* check preset content type */ if( m_contenttype.Left(6).Equals("audio/") ) @@ -536,8 +611,9 @@ bool CFileItem::IsPicture() const { if (HasPictureInfoTag()) return true; - if (HasMusicInfoTag()) return false; - if (HasVideoInfoTag()) return false; + if (HasMusicInfoTag()) return false; + if (HasVideoInfoTag()) return false; + if (HasProgramInfoTag()) return false; if( m_contenttype.Left(6).Equals("image/") ) return true; @@ -558,6 +634,26 @@ return false; } +bool CFileItem::IsProgram() const +{ + if (HasPictureInfoTag()) return false; + if (HasMusicInfoTag()) return false; + if (HasVideoInfoTag()) return false; + if (HasProgramInfoTag()) return true; + + CStdString extension; + CUtil::GetExtension(m_strPath, extension); + + if (extension.IsEmpty()) + return false; + + extension.ToLower(); + if (g_stSettings.m_programExtensions.Find(extension) != -1) + return true; + + return false; +} + bool CFileItem::IsLyrics() const { CStdString strExtension; @@ -613,18 +709,17 @@ { return ( m_bIsFolder && ( - IsPlugin() || - IsSmartPlayList() || - IsPlayList() || - IsZIP() || - IsRAR() || - IsType(".ogg") || - IsType(".nsf") || - IsType(".sid") || - IsType(".sap") || - IsShoutCast() - ) - ); + IsPlugin() || + IsSmartPlayList() || + IsPlayList() || + IsZIP() || + IsRAR() || + IsType(".ogg") || + IsType(".nsf") || + IsType(".sid") || + IsType(".sap") || + IsShoutCast() + )); } @@ -825,6 +920,12 @@ return false; } +bool CFileItem::IsProgramDb() const +{ + if (strstr(m_strPath.c_str(), "programdb:") ) return true; + return false; +} + bool CFileItem::IsVirtualDirectoryRoot() const { return (m_bIsFolder && m_strPath.IsEmpty()); @@ -897,6 +998,11 @@ // xbe SetIconImage("DefaultProgram.png"); } + else if ( IsProgram() ) + { + // xbe + SetIconImage("DefaultProgram.png"); + } else if ( IsShortCut() && !IsLabelPreformated() ) { // shortcut @@ -942,16 +1048,126 @@ } } -CStdString CFileItem::GetCachedArtistThumb() const +CStdString CFileItem::GetTBNFile() const { - return GetCachedThumb("artist"+GetLabel(),g_settings.GetMusicArtistThumbFolder()); + CStdString thumbFile; + CStdString strFile = m_strPath; + + if (IsStack()) + { + CStdString strPath, strReturn; + CUtil::GetParentPath(m_strPath,strPath); + CFileItem item(CStackDirectory::GetFirstStackedFile(strFile),false); + CStdString strTBNFile = item.GetTBNFile(); + CUtil::AddFileToFolder(strPath,CUtil::GetFileName(strTBNFile),strReturn); + if (CFile::Exists(strReturn)) + return strReturn; + + CUtil::AddFileToFolder(strPath,CUtil::GetFileName(CStackDirectory::GetStackedTitlePath(strFile)),strFile); + } + + if (CUtil::IsInRAR(strFile) || CUtil::IsInZIP(strFile)) + { + CStdString strPath, strParent; + CUtil::GetDirectory(strFile,strPath); + CUtil::GetParentPath(strPath,strParent); + CUtil::AddFileToFolder(strParent,CUtil::GetFileName(m_strPath),strFile); + } + + CURL url(strFile); + strFile = url.GetFileName(); + + if (m_bIsFolder && !IsFileFolder()) + CUtil::RemoveSlashAtEnd(strFile); + + if (!strFile.IsEmpty()) + { + if (m_bIsFolder && !IsFileFolder()) + thumbFile = strFile + ".tbn"; // folder, so just add ".tbn" + else + CUtil::ReplaceExtension(strFile, ".tbn", thumbFile); + url.SetFileName(thumbFile); + url.GetURL(thumbFile); + } + return thumbFile; } +CStdString CFileItem::GetFolderThumb(const CStdString &folderJPG /* = "folder.jpg" */) const +{ + CStdString folderThumb; + CStdString strFolder = m_strPath; + + if (IsStack()) + { + CStdString strPath; + CUtil::GetParentPath(m_strPath,strPath); + CStdString strFolder = CStackDirectory::GetStackedTitlePath(m_strPath); + } + + if (CUtil::IsInRAR(strFolder) || CUtil::IsInZIP(strFolder)) + { + CStdString strPath, strParent; + CUtil::GetDirectory(strFolder,strPath); + CUtil::GetParentPath(strPath,strParent); + } + + if (IsMultiPath()) + strFolder = CMultiPathDirectory::GetFirstPath(m_strPath); + + CUtil::AddFileToFolder(strFolder, folderJPG, folderThumb); + return folderThumb; +} + +CStdString CFileItem::GetCachedThumb(const CStdString &path, const CStdString &path2, bool split) +{ + // get the locally cached thumb + Crc32 crc; + crc.ComputeFromLowerCase(path); + + CStdString thumb; + if (split) + { + CStdString hex; + hex.Format("%08x", (__int32)crc); + thumb.Format("%c\\%08x.tbn", hex[0], (unsigned __int32)crc); + } + else + thumb.Format("%08x.tbn", (unsigned __int32)crc); + + return CUtil::AddFileToFolder(path2, thumb); +} + + CStdString CFileItem::GetCachedProfileThumb() const { return GetCachedThumb("profile"+m_strPath,CUtil::AddFileToFolder(g_settings.GetUserDataFolder(),"Thumbnails\\Profiles")); } +CStdString CFileItem::GetCachedPictureThumb() const +{ + return GetCachedThumb(m_strPath,g_settings.GetPicturesThumbFolder(),true); +} + +CStdString CFileItem::GetCachedVideoThumb() const +{ + if (IsStack()) + return GetCachedThumb(CStackDirectory::GetFirstStackedFile(m_strPath),g_settings.GetVideoThumbFolder(),true); + else + return GetCachedThumb(m_strPath,g_settings.GetVideoThumbFolder(),true); +} + +CStdString CFileItem::GetCachedProgramThumb() const +{ + return GetCachedThumb(m_strPath, g_settings.GetProgramThumbFolder()); +} + +CStdString CFileItem::GetCachedEpisodeThumb() const +{ + // get the locally cached thumb + CStdString strCRC; + strCRC.Format("%sepisode%i",GetVideoInfoTag()->m_strFileNameAndPath.c_str(),GetVideoInfoTag()->m_iEpisode); + return GetCachedThumb(strCRC,g_settings.GetVideoThumbFolder(),true); +} CStdString CFileItem::GetCachedSeasonThumb() const { CStdString seasonPath; @@ -966,6 +1182,391 @@ return GetCachedThumb("actor"+GetLabel(),g_settings.GetVideoThumbFolder(),true); } +CStdString CFileItem::GetCachedArtistThumb() const +{ + return GetCachedThumb("artist"+GetLabel(),g_settings.GetMusicArtistThumbFolder()); +} + +CStdString CFileItem::GetCachedFanart() const +{ + // get the locally cached thumb + if (IsVideoDb()) + { + if (!HasVideoInfoTag()) + return ""; + if (!GetVideoInfoTag()->m_strArtist.IsEmpty()) + return GetCachedThumb(GetVideoInfoTag()->m_strArtist,g_settings.GetMusicFanartFolder()); + if (!m_bIsFolder && !GetVideoInfoTag()->m_strShowTitle.IsEmpty()) + { + CVideoDatabase database; + database.Open(); + int iShowId = database.GetTvShowId(GetVideoInfoTag()->m_strPath); + CStdString showPath; + database.GetFilePathById(iShowId,showPath,VIDEODB_CONTENT_TVSHOWS); + return GetCachedThumb(showPath,g_settings.GetVideoFanartFolder()); + } + return GetCachedThumb(m_bIsFolder ? GetVideoInfoTag()->m_strPath : GetVideoInfoTag()->m_strFileNameAndPath,g_settings.GetVideoFanartFolder()); + } + if (HasMusicInfoTag()) + return GetCachedThumb(GetMusicInfoTag()->GetArtist(),g_settings.GetMusicFanartFolder()); + + return GetCachedThumb(m_strPath,g_settings.GetVideoFanartFolder()); +} + + +CStdString CFileItem::GetCachedGameSaveThumb() const +{ + return ""; +} + + +CStdString CFileItem::GetPreviouslyCachedMusicThumb() const +{ + // look if an album thumb is available, + // could be any file with tags loaded or + // a directory in album window + CStdString strAlbum, strArtist; + if (HasMusicInfoTag() && m_musicInfoTag->Loaded()) + { + strAlbum = m_musicInfoTag->GetAlbum(); + if (!m_musicInfoTag->GetAlbumArtist().IsEmpty()) + strArtist = m_musicInfoTag->GetAlbumArtist(); + else + strArtist = m_musicInfoTag->GetArtist(); + } + if (!strAlbum.IsEmpty() && !strArtist.IsEmpty()) + { + // try permanent album thumb using "album name + artist name" + CStdString thumb(CUtil::GetCachedAlbumThumb(strAlbum, strArtist)); + if (CFile::Exists(thumb)) + return thumb; + } + + // if a file, try to find a cached filename.tbn + if (!m_bIsFolder) + { + // look for locally cached tbn + CStdString thumb(CUtil::GetCachedMusicThumb(m_strPath)); + if (CFile::Exists(thumb)) + return thumb; + } + + // try and find a cached folder thumb (folder.jpg or folder.tbn) + CStdString strPath; + if (!m_bIsFolder) + CUtil::GetDirectory(m_strPath, strPath); + else + strPath = m_strPath; + // music thumbs are cached without slash at end + CUtil::RemoveSlashAtEnd(strPath); + + CStdString thumb(CUtil::GetCachedMusicThumb(strPath)); + if (CFile::Exists(thumb)) + return thumb; + + return ""; +} + +CStdString CFileItem::GetUserMusicThumb(bool alwaysCheckRemote /* = false */) const +{ + if (m_strPath.IsEmpty() || m_bIsShareOrDrive || IsInternetStream() || CUtil::IsUPnP(m_strPath) || IsParentFolder() || IsMusicDb()) + return ""; + + // we first check for .tbn or .tbn + CStdString fileThumb(GetTBNFile()); + if (CFile::Exists(fileThumb)) + return fileThumb; + // if a folder, check for folder.jpg + if (m_bIsFolder && (!IsRemote() || alwaysCheckRemote || g_guiSettings.GetBool("musicfiles.findremotethumbs"))) + { + CStdStringArray thumbs; + StringUtils::SplitString(g_advancedSettings.m_musicThumbs, "|", thumbs); + for (unsigned int i = 0; i < thumbs.size(); ++i) + { + CStdString folderThumb(GetFolderThumb(thumbs[i])); + if (CFile::Exists(folderThumb)) + { + return folderThumb; + } + } + } + // this adds support for files which inherit a folder.jpg icon which has not been cached yet. + // this occurs when queueing a top-level folder which has not been traversed yet. + else if (!IsRemote() || alwaysCheckRemote || g_guiSettings.GetBool("musicfiles.findremotethumbs")) + { + CStdString strFolder, strFile; + CUtil::Split(m_strPath, strFolder, strFile); + CFileItem folderItem(strFolder, true); + folderItem.SetMusicThumb(alwaysCheckRemote); + if (folderItem.HasThumbnail()) + return folderItem.GetThumbnailImage(); + } + // No thumb found + return ""; +} + +CStdString CFileItem::GetUserVideoThumb() const +{ + if (IsTuxBox()) + { + if (!m_bIsFolder) + return g_tuxbox.GetPicon(GetLabel()); + else return ""; + } + + if (m_strPath.IsEmpty() + || m_bIsShareOrDrive + || IsInternetStream() + || CUtil::IsUPnP(m_strPath) + || IsParentFolder() + || IsLiveTV()) + return ""; + + + // 1. check .tbn or .tbn + CStdString fileThumb(GetTBNFile()); + if (CFile::Exists(fileThumb)) + return fileThumb; + + // 2. - check movie.tbn, as long as it's not a folder + if (!m_bIsFolder) + { + CStdString strPath, movietbnFile; + CUtil::GetParentPath(m_strPath, strPath); + CUtil::AddFileToFolder(strPath, "movie.tbn", movietbnFile); + if (CFile::Exists(movietbnFile)) + return movietbnFile; + } + + // 3. check folder image in_m_dvdThumbs (folder.jpg) + if (m_bIsFolder) + { + CStdStringArray thumbs; + StringUtils::SplitString(g_advancedSettings.m_dvdThumbs, "|", thumbs); + for (unsigned int i = 0; i < thumbs.size(); ++i) + { + CStdString folderThumb(GetFolderThumb(thumbs[i])); + if (CFile::Exists(folderThumb)) + { + return folderThumb; + } + } + } + // No thumb found + return ""; +} + + +CStdString CFileItem::GetUserProgramThumb() const +{ + if (m_strPath.IsEmpty() || IsParentFolder()) + return ""; + + // 1. check .tbn or .tbn + CStdString fileThumb(GetTBNFile()); + if (CFile::Exists(fileThumb)) + return fileThumb; + + // 2. - check game.tbn, as long as it's not a folder + if (!m_bIsFolder) + { + CStdString strPath, gametbnFile; + CUtil::GetParentPath(m_strPath, strPath); + CUtil::AddFileToFolder(strPath, "game.tbn", gametbnFile); + if (CFile::Exists(gametbnFile)) + return gametbnFile; + } + // No thumb found + return ""; +} + + +CStdString CFileItem::GetMovieName(bool bUseFolderNames /* = false */) const +{ + if (IsLabelPreformated()) + return GetLabel(); + + CStdString strMovieName = m_strPath; + + if (IsMultiPath()) + strMovieName = CMultiPathDirectory::GetFirstPath(m_strPath); + + if (CUtil::IsStack(strMovieName)) + strMovieName = CStackDirectory::GetStackedTitlePath(strMovieName); + + if ((!m_bIsFolder || IsDVDFile(false, true) || CUtil::IsInArchive(m_strPath)) && bUseFolderNames) + { + CUtil::GetParentPath(m_strPath, strMovieName); + if (CUtil::IsInArchive(m_strPath) || strMovieName.Find( "VIDEO_TS" ) != -1) + { + CStdString strArchivePath; + CUtil::GetParentPath(strMovieName, strArchivePath); + strMovieName = strArchivePath; + } + } + + CUtil::RemoveSlashAtEnd(strMovieName); + strMovieName = CUtil::GetFileName(strMovieName); + + return strMovieName; +} + +CStdString CFileItem::GetGameName(bool bUseFolderNames /* = false */) const +{ + if (IsLabelPreformated()) return GetLabel(); + + CStdString strGameName = m_strPath; + + if (IsMultiPath()) + strGameName = CMultiPathDirectory::GetFirstPath(m_strPath); + + if (CUtil::IsStack(strGameName)) + strGameName = CStackDirectory::GetStackedTitlePath(strGameName); + + if ((!m_bIsFolder || CUtil::IsInArchive(m_strPath)) && bUseFolderNames) + { + CUtil::GetParentPath(m_strPath, strGameName); + if (CUtil::IsInArchive(m_strPath)) + { + CStdString strArchivePath; + CUtil::GetParentPath(strGameName, strArchivePath); + strGameName = strArchivePath; + } + } + + CUtil::RemoveSlashAtEnd(strGameName); + strGameName = CUtil::GetFileName(strGameName); + + return strGameName; +} + +void CFileItem::SetUserMusicThumb(bool alwaysCheckRemote /* = false */) +{ + // caches as the local thumb + CStdString thumb(GetUserMusicThumb(alwaysCheckRemote)); + if (!thumb.IsEmpty()) + { + CStdString cachedThumb(CUtil::GetCachedMusicThumb(m_strPath)); + CPicture pic; + pic.DoCreateThumbnail(thumb, cachedThumb); + } + + SetCachedMusicThumb(); +} + +void CFileItem::SetUserProgramThumb() +{ + if (m_bIsShareOrDrive) return; + if (IsParentFolder()) return; + + if (IsShortCut()) + { + CShortcut shortcut; + if ( shortcut.Create( m_strPath ) ) + { + // use the shortcut's thumb + if (!shortcut.m_strThumb.IsEmpty()) + m_strThumbnailImage = shortcut.m_strThumb; + else + { + CFileItem item(shortcut.m_strPath,false); + item.SetUserProgramThumb(); + m_strThumbnailImage = item.m_strThumbnailImage; + } + return; + } + } + // 1. Try .tbn + CStdString fileThumb(GetTBNFile()); + CStdString thumb(GetCachedProgramThumb()); + if (CFile::Exists(fileThumb)) + { // cache + CPicture pic; + if (pic.DoCreateThumbnail(fileThumb, thumb)) + SetThumbnailImage(thumb); + } + else if (m_bIsFolder) + { + // 3. cache the folder image + CStdString folderThumb(GetFolderThumb()); + if (CFile::Exists(folderThumb)) + { + CPicture pic; + if (pic.DoCreateThumbnail(folderThumb, thumb)) + SetThumbnailImage(thumb); + } + } +} +void CFileItem::SetUserVideoThumb() +{ + if (m_bIsShareOrDrive) return; + if (IsParentFolder()) return; + + // caches as the local thumb + CStdString thumb(GetUserVideoThumb()); + if (!thumb.IsEmpty()) + { + CStdString cachedThumb(GetCachedVideoThumb()); + CPicture pic; + pic.DoCreateThumbnail(thumb, cachedThumb); + } + SetCachedVideoThumb(); +} + +void CFileItem::SetCachedPictureThumb() +{ + if (IsParentFolder()) return; + CStdString cachedThumb(GetCachedPictureThumb()); + if (CFile::Exists(cachedThumb)) + SetThumbnailImage(cachedThumb); +} + +void CFileItem::SetCachedVideoThumb() +{ + if (IsParentFolder()) return; + CStdString cachedThumb(GetCachedVideoThumb()); + if (CFile::Exists(cachedThumb)) + SetThumbnailImage(cachedThumb); +} + +void CFileItem::SetCachedMusicThumb() +{ + // if it already has a thumbnail, then return + if (HasThumbnail() || m_bIsShareOrDrive) return ; + + // streams do not have thumbnails + if (IsInternetStream()) return ; + + // music db items already have thumbs or there is no thumb available + if (IsMusicDb()) return; + + // ignore the parent dir items + if (IsParentFolder()) return; + + CStdString cachedThumb(GetPreviouslyCachedMusicThumb()); + if (!cachedThumb.IsEmpty()) + SetThumbnailImage(cachedThumb); + // SetIconImage(cachedThumb); +} + +void CFileItem::SetCachedProgramThumb() +{ + // don't set any thumb for programs on DVD, as they're bound to be named the + // same (D:\default.xbe). + if (IsParentFolder()) return; + CStdString thumb(GetCachedProgramThumb()); + if (CFile::Exists(thumb)) + SetThumbnailImage(thumb); +} + +void CFileItem::SetCachedGameSavesThumb() +{ + if (IsParentFolder()) return; + CStdString thumb(GetCachedGameSaveThumb()); + if (CFile::Exists(thumb)) + SetThumbnailImage(thumb); +} + void CFileItem::SetCachedArtistThumb() { CStdString thumb(GetCachedArtistThumb()); @@ -976,7 +1577,16 @@ } } -// set the album thumb for a file or folder +void CFileItem::SetCachedSeasonThumb() +{ + CStdString thumb(GetCachedSeasonThumb()); + if (CFile::Exists(thumb)) + { + // found it, we are finished. + SetThumbnailImage(thumb); + } +} + void CFileItem::SetMusicThumb(bool alwaysCheckRemote /* = true */) { if (HasThumbnail()) return; @@ -986,20 +1596,210 @@ SetUserMusicThumb(alwaysCheckRemote); } -void CFileItem::SetCachedSeasonThumb() + +void CFileItem::SetVideoThumb() { - CStdString thumb(GetCachedSeasonThumb()); - if (CFile::Exists(thumb)) + if (HasThumbnail()) return; + SetCachedVideoThumb(); + if (!HasThumbnail()) + SetUserVideoThumb(); +} + + +void CFileItem::SetProgramThumb() +{ + if (HasThumbnail()) return; + SetCachedProgramThumb(); + if (!HasThumbnail()) + SetUserProgramThumb(); +} + + +/// +/// If a cached fanart image already exists, then we're fine. Otherwise, we look for a local fanart.jpg +/// and cache that image as our fanart. +CStdString CFileItem::CacheFanart(bool probe) const +{ + if (IsVideoDb() || IsProgramDb()) { - // found it, we are finished. - SetThumbnailImage(thumb); + if (HasVideoInfoTag()) + { + CFileItem dbItem(m_bIsFolder ? GetVideoInfoTag()->m_strPath : GetVideoInfoTag()->m_strFileNameAndPath, m_bIsFolder); + return dbItem.CacheFanart(); + } + else if (HasProgramInfoTag()) + { + CFileItem dbItem(m_bIsFolder ? GetProgramInfoTag()->m_strPath : GetProgramInfoTag()->m_strFileNameAndPath, m_bIsFolder); + return dbItem.CacheFanart(); + } + return ""; } + + CStdString cachedFanart(GetCachedFanart()); + if (!probe) + { + // first check for an already cached fanart image + if (CFile::Exists(cachedFanart)) + return ""; + } + + CStdString strFile2; + CStdString strFile = m_strPath; + if (IsStack()) + { + CStdString strPath; + CUtil::GetParentPath(m_strPath,strPath); + CStackDirectory dir; + CStdString strPath2; + strPath2 = dir.GetStackedTitlePath(strFile); + CUtil::AddFileToFolder(strPath,CUtil::GetFileName(strPath2),strFile); + CFileItem item(dir.GetFirstStackedFile(m_strPath),false); + CStdString strTBNFile = item.GetTBNFile(); + CUtil::ReplaceExtension(strTBNFile, "-fanart",strTBNFile); + CUtil::AddFileToFolder(strPath,CUtil::GetFileName(strTBNFile),strFile2); + } + if (CUtil::IsInRAR(strFile) || CUtil::IsInZIP(strFile)) + { + CStdString strPath, strParent; + CUtil::GetDirectory(strFile,strPath); + CUtil::GetParentPath(strPath,strParent); + CUtil::AddFileToFolder(strParent,CUtil::GetFileName(m_strPath),strFile); + } + + // no local fanart available for these + if (IsInternetStream() + || CUtil::IsUPnP(strFile) + || IsLiveTV() + || IsPlugin() + || CUtil::IsFTP(strFile)) + return ""; + + CStdString localFanart; + + // special checks for subfolders + if(m_bIsFolder) + { + CStdString strArt; + CUtil::AddFileToFolder(strFile, "fanart.jpg", strArt); + if(CFile::Exists(strArt)) + localFanart = strArt; + + CUtil::AddFileToFolder(strFile, "fanart.png", strArt); + if(localFanart.IsEmpty() && CFile::Exists(strArt)) + localFanart = strArt; + } + + // we don't have a cached image, so let's see if the user has a local image .. + if (localFanart.IsEmpty()) + { + CStdString strDir; + CUtil::GetDirectory(strFile, strDir); + if (strDir.IsEmpty()) return ""; + + CFileItemList items; + CDirectory::GetDirectory(strDir, items, g_stSettings.m_pictureExtensions, false, false, DIR_CACHE_ALWAYS, false); + CUtil::RemoveExtension(strFile); + strFile += "-fanart"; + CStdString strFile3 = CUtil::AddFileToFolder(strDir, "fanart"); + + for (int i = 0; i < items.Size(); i++) + { + CStdString strCandidate = items[i]->m_strPath; + CUtil::RemoveExtension(strCandidate); + if (strCandidate.CompareNoCase(strFile) == 0 || + strCandidate.CompareNoCase(strFile2) == 0 || + strCandidate.CompareNoCase(strFile3) == 0) + { + localFanart = items[i]->m_strPath; + break; + } + } + } + + // no local fanart found + if(localFanart.IsEmpty()) + return ""; + + if (!probe) + { + CPicture pic; + pic.CacheImage(localFanart, cachedFanart); + } + + return localFanart; } + + + +bool CFileItem::LoadMusicTag() +{ + // not audio + if (!IsAudio()) + return false; + // already loaded? + if (HasMusicInfoTag() && m_musicInfoTag->Loaded()) + return true; + // check db + CMusicDatabase musicDatabase; + if (musicDatabase.Open()) + { + CSong song; + if (musicDatabase.GetSongByFileName(m_strPath, song)) + { + GetMusicInfoTag()->SetSong(song); + SetThumbnailImage(song.strThumb); + return true; + } + musicDatabase.Close(); + } + // load tag from file + CLog::Log(LOGDEBUG, "%s: loading tag information for file: %s", __FUNCTION__, m_strPath.c_str()); + CMusicInfoTagLoaderFactory factory; + auto_ptr pLoader (factory.CreateLoader(m_strPath)); + if (NULL != pLoader.get()) + { + if (pLoader->Load(m_strPath, *GetMusicInfoTag())) + return true; + } + // no tag - try some other things + if (IsCDDA()) + { + // we have the tracknumber... + int iTrack = GetMusicInfoTag()->GetTrackNumber(); + if (iTrack >= 1) + { + CStdString strText = g_localizeStrings.Get(554); // "Track" + if (strText.GetAt(strText.size() - 1) != ' ') + strText += " "; + CStdString strTrack; + strTrack.Format(strText + "%i", iTrack); + GetMusicInfoTag()->SetTitle(strTrack); + GetMusicInfoTag()->SetLoaded(true); + return true; + } + } + else + { + CStdString fileName = CUtil::GetFileName(m_strPath); + CUtil::RemoveExtension(fileName); + for (unsigned int i = 0; i < g_advancedSettings.m_musicTagsFromFileFilters.size(); i++) + { + CLabelFormatter formatter(g_advancedSettings.m_musicTagsFromFileFilters[i], ""); + if (formatter.FillMusicTag(fileName, GetMusicInfoTag())) + { + GetMusicInfoTag()->SetLoaded(true); + return true; + } + } + } + return false; +} + + void CFileItem::RemoveExtension() { - if (m_bIsFolder) - return; + if (m_bIsFolder) return; CStdString strLabel = GetLabel(); CUtil::RemoveExtension(strLabel); SetLabel(strLabel); @@ -1026,8 +1826,8 @@ { if (strLabel=="..") { - m_bIsParentFolder=true; - m_bIsFolder=true; + m_bIsParentFolder = true; + m_bIsFolder = true; SetLabelPreformated(true); } CGUIListItem::SetLabel(strLabel); @@ -1053,7 +1853,7 @@ void CFileItem::SetCanQueue(bool bYesNo) { - m_bCanQueue=bYesNo; + m_bCanQueue = bYesNo; } bool CFileItem::IsParentFolder() const @@ -1130,9 +1930,9 @@ dbItem.m_lStartOffset = item->m_lStartOffset; return IsSamePath(&dbItem); } - if (item->IsVideoDb() && item->HasVideoInfoTag()) + if (item->IsProgramDb() && item->HasProgramInfoTag()) { - CFileItem dbItem(item->m_videoInfoTag->m_strFileNameAndPath, false); + CFileItem dbItem(item->m_programInfoTag->m_strFileNameAndPath, false); dbItem.m_lStartOffset = item->m_lStartOffset; return IsSamePath(&dbItem); } @@ -1147,22 +1947,22 @@ CFileItemList::CFileItemList() { - m_fastLookup = false; - m_bIsFolder=true; - m_cacheToDisc=CACHE_IF_SLOW; - m_sortMethod=SORT_METHOD_NONE; - m_sortOrder=SORT_ORDER_NONE; + m_fastLookup = false; + m_bIsFolder = true; + m_cacheToDisc = CACHE_IF_SLOW; + m_sortMethod = SORT_METHOD_NONE; + m_sortOrder = SORT_ORDER_NONE; m_replaceListing = false; } CFileItemList::CFileItemList(const CStdString& strPath) { - m_strPath=strPath; - m_fastLookup = false; - m_bIsFolder=true; - m_cacheToDisc=CACHE_IF_SLOW; - m_sortMethod=SORT_METHOD_NONE; - m_sortOrder=SORT_ORDER_NONE; + m_strPath = strPath; + m_fastLookup = false; + m_bIsFolder = true; + m_cacheToDisc = CACHE_IF_SLOW; + m_sortMethod = SORT_METHOD_NONE; + m_sortOrder = SORT_ORDER_NONE; m_replaceListing = false; } @@ -1233,9 +2033,9 @@ CSingleLock lock(m_lock); ClearItems(); - m_sortMethod=SORT_METHOD_NONE; - m_sortOrder=SORT_ORDER_NONE; - m_cacheToDisc=CACHE_IF_SLOW; + m_sortMethod = SORT_METHOD_NONE; + m_sortOrder = SORT_ORDER_NONE; + m_cacheToDisc = CACHE_IF_SLOW; m_sortDetails.clear(); m_replaceListing = false; m_content.Empty(); @@ -1335,12 +2135,12 @@ if (!append) Clear(); Append(itemlist); - m_strPath = itemlist.m_strPath; - m_sortDetails = itemlist.m_sortDetails; + m_strPath = itemlist.m_strPath; + m_sortDetails = itemlist.m_sortDetails; m_replaceListing = itemlist.m_replaceListing; - m_content = itemlist.m_content; - m_mapProperties = itemlist.m_mapProperties; - m_cacheToDisc = itemlist.m_cacheToDisc; + m_content = itemlist.m_content; + m_mapProperties = itemlist.m_mapProperties; + m_cacheToDisc = itemlist.m_cacheToDisc; } bool CFileItemList::Copy(const CFileItemList& items) @@ -1456,7 +2256,7 @@ void CFileItemList::Sort(FILEITEMLISTCOMPARISONFUNC func) { CSingleLock lock(m_lock); - DWORD dwStart = GetTickCount(); + DWORD dwStart = GetTickCount(); std::sort(m_items.begin(), m_items.end(), func); DWORD dwElapsed = GetTickCount() - dwStart; CLog::Log(LOGDEBUG,"%s, sorting took %u millis", __FUNCTION__, dwElapsed); @@ -1536,6 +2336,15 @@ case SORT_METHOD_VIDEO_SORT_TITLE_IGNORE_THE: FillSortFields(SSortFileItem::ByMovieSortTitleNoThe); break; + case SORT_METHOD_PROGRAM_TITLE: + FillSortFields(SSortFileItem::ByMovieTitle); + break; + case SORT_METHOD_PROGRAM_SORT_TITLE: + FillSortFields(SSortFileItem::ByMovieSortTitle); + break; + case SORT_METHOD_PROGRAM_SORT_TITLE_IGNORE_THE: + FillSortFields(SSortFileItem::ByMovieSortTitleNoThe); + break; case SORT_METHOD_YEAR: FillSortFields(SSortFileItem::ByYear); break; @@ -1656,9 +2465,9 @@ int tempint; ar >> (int&)tempint; - m_sortMethod = SORT_METHOD(tempint); + m_sortMethod = SORT_METHOD(tempint); ar >> (int&)tempint; - m_sortOrder = SORT_ORDER(tempint); + m_sortOrder = SORT_ORDER(tempint); ar >> (int&)tempint; m_cacheToDisc = CACHE_TYPE(tempint); @@ -2172,7 +2981,7 @@ CStdString CFileItemList::GetDiscCacheFile() const { - CStdString strPath=m_strPath; + CStdString strPath = m_strPath; CUtil::RemoveSlashAtEnd(strPath); Crc32 crc; @@ -2185,6 +2994,8 @@ cacheFile.Format("special://temp/mdb-%08x.fi", (unsigned __int32)crc); else if (IsVideoDb()) cacheFile.Format("special://temp/vdb-%08x.fi", (unsigned __int32)crc); + else if (IsProgramDb()) + cacheFile.Format("special://temp/vdb-%08x.fi", (unsigned __int32)crc); else cacheFile.Format("special://temp/%08x.fi", (unsigned __int32)crc); return cacheFile; @@ -2197,6 +3008,8 @@ return CMusicDatabaseDirectory::CanCache(m_strPath); if (IsVideoDb()) return CVideoDatabaseDirectory::CanCache(m_strPath); + if (IsProgramDb()) + return CProgramDatabaseDirectory::CanCache(m_strPath); return false; } @@ -2233,556 +3046,6 @@ } } -CStdString CFileItem::GetCachedPictureThumb() const -{ - return GetCachedThumb(m_strPath,g_settings.GetPicturesThumbFolder(),true); -} - -void CFileItem::SetCachedMusicThumb() -{ - // if it already has a thumbnail, then return - if (HasThumbnail() || m_bIsShareOrDrive) return ; - - // streams do not have thumbnails - if (IsInternetStream()) return ; - - // music db items already have thumbs or there is no thumb available - if (IsMusicDb()) return; - - // ignore the parent dir items - if (IsParentFolder()) return; - - CStdString cachedThumb(GetPreviouslyCachedMusicThumb()); - if (!cachedThumb.IsEmpty()) - SetThumbnailImage(cachedThumb); - // SetIconImage(cachedThumb); -} - -CStdString CFileItem::GetPreviouslyCachedMusicThumb() const -{ - // look if an album thumb is available, - // could be any file with tags loaded or - // a directory in album window - CStdString strAlbum, strArtist; - if (HasMusicInfoTag() && m_musicInfoTag->Loaded()) - { - strAlbum = m_musicInfoTag->GetAlbum(); - if (!m_musicInfoTag->GetAlbumArtist().IsEmpty()) - strArtist = m_musicInfoTag->GetAlbumArtist(); - else - strArtist = m_musicInfoTag->GetArtist(); - } - if (!strAlbum.IsEmpty() && !strArtist.IsEmpty()) - { - // try permanent album thumb using "album name + artist name" - CStdString thumb(CUtil::GetCachedAlbumThumb(strAlbum, strArtist)); - if (CFile::Exists(thumb)) - return thumb; - } - - // if a file, try to find a cached filename.tbn - if (!m_bIsFolder) - { - // look for locally cached tbn - CStdString thumb(CUtil::GetCachedMusicThumb(m_strPath)); - if (CFile::Exists(thumb)) - return thumb; - } - - // try and find a cached folder thumb (folder.jpg or folder.tbn) - CStdString strPath; - if (!m_bIsFolder) - CUtil::GetDirectory(m_strPath, strPath); - else - strPath = m_strPath; - // music thumbs are cached without slash at end - CUtil::RemoveSlashAtEnd(strPath); - - CStdString thumb(CUtil::GetCachedMusicThumb(strPath)); - if (CFile::Exists(thumb)) - return thumb; - - return ""; -} - -CStdString CFileItem::GetUserMusicThumb(bool alwaysCheckRemote /* = false */) const -{ - if (m_strPath.IsEmpty() || m_bIsShareOrDrive || IsInternetStream() || CUtil::IsUPnP(m_strPath) || IsParentFolder() || IsMusicDb()) - return ""; - - // we first check for .tbn or .tbn - CStdString fileThumb(GetTBNFile()); - if (CFile::Exists(fileThumb)) - return fileThumb; - // if a folder, check for folder.jpg - if (m_bIsFolder && (!IsRemote() || alwaysCheckRemote || g_guiSettings.GetBool("musicfiles.findremotethumbs"))) - { - CStdStringArray thumbs; - StringUtils::SplitString(g_advancedSettings.m_musicThumbs, "|", thumbs); - for (unsigned int i = 0; i < thumbs.size(); ++i) - { - CStdString folderThumb(GetFolderThumb(thumbs[i])); - if (CFile::Exists(folderThumb)) - { - return folderThumb; - } - } - } - // this adds support for files which inherit a folder.jpg icon which has not been cached yet. - // this occurs when queueing a top-level folder which has not been traversed yet. - else if (!IsRemote() || alwaysCheckRemote || g_guiSettings.GetBool("musicfiles.findremotethumbs")) - { - CStdString strFolder, strFile; - CUtil::Split(m_strPath, strFolder, strFile); - CFileItem folderItem(strFolder, true); - folderItem.SetMusicThumb(alwaysCheckRemote); - if (folderItem.HasThumbnail()) - return folderItem.GetThumbnailImage(); - } - // No thumb found - return ""; -} - -void CFileItem::SetUserMusicThumb(bool alwaysCheckRemote /* = false */) -{ - // caches as the local thumb - CStdString thumb(GetUserMusicThumb(alwaysCheckRemote)); - if (!thumb.IsEmpty()) - { - CStdString cachedThumb(CUtil::GetCachedMusicThumb(m_strPath)); - CPicture pic; - pic.DoCreateThumbnail(thumb, cachedThumb); - } - - SetCachedMusicThumb(); -} - -void CFileItem::SetCachedPictureThumb() -{ - if (IsParentFolder()) return; - CStdString cachedThumb(GetCachedPictureThumb()); - if (CFile::Exists(cachedThumb)) - SetThumbnailImage(cachedThumb); -} - -CStdString CFileItem::GetCachedVideoThumb() const -{ - if (IsStack()) - return GetCachedThumb(CStackDirectory::GetFirstStackedFile(m_strPath),g_settings.GetVideoThumbFolder(),true); - else - return GetCachedThumb(m_strPath,g_settings.GetVideoThumbFolder(),true); -} - -CStdString CFileItem::GetCachedEpisodeThumb() const -{ - // get the locally cached thumb - CStdString strCRC; - strCRC.Format("%sepisode%i",GetVideoInfoTag()->m_strFileNameAndPath.c_str(),GetVideoInfoTag()->m_iEpisode); - return GetCachedThumb(strCRC,g_settings.GetVideoThumbFolder(),true); -} - -void CFileItem::SetCachedVideoThumb() -{ - if (IsParentFolder()) return; - CStdString cachedThumb(GetCachedVideoThumb()); - if (CFile::Exists(cachedThumb)) - SetThumbnailImage(cachedThumb); -} - -// Gets the .tbn filename from a file or folder name. -// .ext -> .tbn -// / -> .tbn -CStdString CFileItem::GetTBNFile() const -{ - CStdString thumbFile; - CStdString strFile = m_strPath; - - if (IsStack()) - { - CStdString strPath, strReturn; - CUtil::GetParentPath(m_strPath,strPath); - CFileItem item(CStackDirectory::GetFirstStackedFile(strFile),false); - CStdString strTBNFile = item.GetTBNFile(); - CUtil::AddFileToFolder(strPath,CUtil::GetFileName(strTBNFile),strReturn); - if (CFile::Exists(strReturn)) - return strReturn; - - CUtil::AddFileToFolder(strPath,CUtil::GetFileName(CStackDirectory::GetStackedTitlePath(strFile)),strFile); - } - - if (CUtil::IsInRAR(strFile) || CUtil::IsInZIP(strFile)) - { - CStdString strPath, strParent; - CUtil::GetDirectory(strFile,strPath); - CUtil::GetParentPath(strPath,strParent); - CUtil::AddFileToFolder(strParent,CUtil::GetFileName(m_strPath),strFile); - } - - CURL url(strFile); - strFile = url.GetFileName(); - - if (m_bIsFolder && !IsFileFolder()) - CUtil::RemoveSlashAtEnd(strFile); - - if (!strFile.IsEmpty()) - { - if (m_bIsFolder && !IsFileFolder()) - thumbFile = strFile + ".tbn"; // folder, so just add ".tbn" - else - CUtil::ReplaceExtension(strFile, ".tbn", thumbFile); - url.SetFileName(thumbFile); - url.GetURL(thumbFile); - } - return thumbFile; -} - -CStdString CFileItem::GetUserVideoThumb() const -{ - if (IsTuxBox()) - { - if (!m_bIsFolder) - return g_tuxbox.GetPicon(GetLabel()); - else return ""; - } - - if (m_strPath.IsEmpty() - || m_bIsShareOrDrive - || IsInternetStream() - || CUtil::IsUPnP(m_strPath) - || IsParentFolder() - || IsLiveTV()) - return ""; - - - // 1. check .tbn or .tbn - CStdString fileThumb(GetTBNFile()); - if (CFile::Exists(fileThumb)) - return fileThumb; - - // 2. - check movie.tbn, as long as it's not a folder - if (!m_bIsFolder) - { - CStdString strPath, movietbnFile; - CUtil::GetParentPath(m_strPath, strPath); - CUtil::AddFileToFolder(strPath, "movie.tbn", movietbnFile); - if (CFile::Exists(movietbnFile)) - return movietbnFile; - } - - // 3. check folder image in_m_dvdThumbs (folder.jpg) - if (m_bIsFolder) - { - CStdStringArray thumbs; - StringUtils::SplitString(g_advancedSettings.m_dvdThumbs, "|", thumbs); - for (unsigned int i = 0; i < thumbs.size(); ++i) - { - CStdString folderThumb(GetFolderThumb(thumbs[i])); - if (CFile::Exists(folderThumb)) - { - return folderThumb; - } - } - } - // No thumb found - return ""; -} - -CStdString CFileItem::GetFolderThumb(const CStdString &folderJPG /* = "folder.jpg" */) const -{ - CStdString folderThumb; - CStdString strFolder = m_strPath; - - if (IsStack()) - { - CStdString strPath; - CUtil::GetParentPath(m_strPath,strPath); - CStdString strFolder = CStackDirectory::GetStackedTitlePath(m_strPath); - } - - if (CUtil::IsInRAR(strFolder) || CUtil::IsInZIP(strFolder)) - { - CStdString strPath, strParent; - CUtil::GetDirectory(strFolder,strPath); - CUtil::GetParentPath(strPath,strParent); - } - - if (IsMultiPath()) - strFolder = CMultiPathDirectory::GetFirstPath(m_strPath); - - CUtil::AddFileToFolder(strFolder, folderJPG, folderThumb); - return folderThumb; -} - -CStdString CFileItem::GetMovieName(bool bUseFolderNames /* = false */) const -{ - if (IsLabelPreformated()) - return GetLabel(); - - CStdString strMovieName = m_strPath; - - if (IsMultiPath()) - strMovieName = CMultiPathDirectory::GetFirstPath(m_strPath); - - if (CUtil::IsStack(strMovieName)) - strMovieName = CStackDirectory::GetStackedTitlePath(strMovieName); - - if ((!m_bIsFolder || IsDVDFile(false, true) || CUtil::IsInArchive(m_strPath)) && bUseFolderNames) - { - CUtil::GetParentPath(m_strPath, strMovieName); - if (CUtil::IsInArchive(m_strPath) || strMovieName.Find( "VIDEO_TS" ) != -1) - { - CStdString strArchivePath; - CUtil::GetParentPath(strMovieName, strArchivePath); - strMovieName = strArchivePath; - } - } - - CUtil::RemoveSlashAtEnd(strMovieName); - strMovieName = CUtil::GetFileName(strMovieName); - - return strMovieName; -} - -void CFileItem::SetVideoThumb() -{ - if (HasThumbnail()) return; - SetCachedVideoThumb(); - if (!HasThumbnail()) - SetUserVideoThumb(); -} - -void CFileItem::SetUserVideoThumb() -{ - if (m_bIsShareOrDrive) return; - if (IsParentFolder()) return; - - // caches as the local thumb - CStdString thumb(GetUserVideoThumb()); - if (!thumb.IsEmpty()) - { - CStdString cachedThumb(GetCachedVideoThumb()); - CPicture pic; - pic.DoCreateThumbnail(thumb, cachedThumb); - } - SetCachedVideoThumb(); -} - -/// -/// If a cached fanart image already exists, then we're fine. Otherwise, we look for a local fanart.jpg -/// and cache that image as our fanart. -CStdString CFileItem::CacheFanart(bool probe) const -{ - if (IsVideoDb()) - { - if (!HasVideoInfoTag()) - return ""; // nothing can be done - CFileItem dbItem(m_bIsFolder ? GetVideoInfoTag()->m_strPath : GetVideoInfoTag()->m_strFileNameAndPath, m_bIsFolder); - return dbItem.CacheFanart(); - } - - CStdString cachedFanart(GetCachedFanart()); - if (!probe) - { - // first check for an already cached fanart image - if (CFile::Exists(cachedFanart)) - return ""; - } - - CStdString strFile2; - CStdString strFile = m_strPath; - if (IsStack()) - { - CStdString strPath; - CUtil::GetParentPath(m_strPath,strPath); - CStackDirectory dir; - CStdString strPath2; - strPath2 = dir.GetStackedTitlePath(strFile); - CUtil::AddFileToFolder(strPath,CUtil::GetFileName(strPath2),strFile); - CFileItem item(dir.GetFirstStackedFile(m_strPath),false); - CStdString strTBNFile = item.GetTBNFile(); - CUtil::ReplaceExtension(strTBNFile, "-fanart",strTBNFile); - CUtil::AddFileToFolder(strPath,CUtil::GetFileName(strTBNFile),strFile2); - } - if (CUtil::IsInRAR(strFile) || CUtil::IsInZIP(strFile)) - { - CStdString strPath, strParent; - CUtil::GetDirectory(strFile,strPath); - CUtil::GetParentPath(strPath,strParent); - CUtil::AddFileToFolder(strParent,CUtil::GetFileName(m_strPath),strFile); - } - - // no local fanart available for these - if (IsInternetStream() - || CUtil::IsUPnP(strFile) - || IsLiveTV() - || IsPlugin() - || CUtil::IsFTP(strFile)) - return ""; - - CStdString localFanart; - - // special checks for subfolders - if(m_bIsFolder) - { - CStdString strArt; - CUtil::AddFileToFolder(strFile, "fanart.jpg", strArt); - if(CFile::Exists(strArt)) - localFanart = strArt; - - CUtil::AddFileToFolder(strFile, "fanart.png", strArt); - if(localFanart.IsEmpty() && CFile::Exists(strArt)) - localFanart = strArt; - } - - // we don't have a cached image, so let's see if the user has a local image .. - if (localFanart.IsEmpty()) - { - CStdString strDir; - CUtil::GetDirectory(strFile, strDir); - if (strDir.IsEmpty()) return ""; - - CFileItemList items; - CDirectory::GetDirectory(strDir, items, g_stSettings.m_pictureExtensions, false, false, DIR_CACHE_ALWAYS, false); - CUtil::RemoveExtension(strFile); - strFile += "-fanart"; - CStdString strFile3 = CUtil::AddFileToFolder(strDir, "fanart"); - - for (int i = 0; i < items.Size(); i++) - { - CStdString strCandidate = items[i]->m_strPath; - CUtil::RemoveExtension(strCandidate); - if (strCandidate.CompareNoCase(strFile) == 0 || - strCandidate.CompareNoCase(strFile2) == 0 || - strCandidate.CompareNoCase(strFile3) == 0) - { - localFanart = items[i]->m_strPath; - break; - } - } - } - - // no local fanart found - if(localFanart.IsEmpty()) - return ""; - - if (!probe) - { - CPicture pic; - pic.CacheImage(localFanart, cachedFanart); - } - - return localFanart; -} - -CStdString CFileItem::GetCachedFanart() const -{ - // get the locally cached thumb - if (IsVideoDb()) - { - if (!HasVideoInfoTag()) - return ""; - if (!GetVideoInfoTag()->m_strArtist.IsEmpty()) - return GetCachedThumb(GetVideoInfoTag()->m_strArtist,g_settings.GetMusicFanartFolder()); - if (!m_bIsFolder && !GetVideoInfoTag()->m_strShowTitle.IsEmpty()) - { - CVideoDatabase database; - database.Open(); - int iShowId = database.GetTvShowId(GetVideoInfoTag()->m_strPath); - CStdString showPath; - database.GetFilePathById(iShowId,showPath,VIDEODB_CONTENT_TVSHOWS); - return GetCachedThumb(showPath,g_settings.GetVideoFanartFolder()); - } - return GetCachedThumb(m_bIsFolder ? GetVideoInfoTag()->m_strPath : GetVideoInfoTag()->m_strFileNameAndPath,g_settings.GetVideoFanartFolder()); - } - if (HasMusicInfoTag()) - return GetCachedThumb(GetMusicInfoTag()->GetArtist(),g_settings.GetMusicFanartFolder()); - - return GetCachedThumb(m_strPath,g_settings.GetVideoFanartFolder()); -} - -CStdString CFileItem::GetCachedThumb(const CStdString &path, const CStdString &path2, bool split) -{ - // get the locally cached thumb - Crc32 crc; - crc.ComputeFromLowerCase(path); - - CStdString thumb; - if (split) - { - CStdString hex; - hex.Format("%08x", (__int32)crc); - thumb.Format("%c\\%08x.tbn", hex[0], (unsigned __int32)crc); - } - else - thumb.Format("%08x.tbn", (unsigned __int32)crc); - - return CUtil::AddFileToFolder(path2, thumb); -} - -CStdString CFileItem::GetCachedProgramThumb() const -{ - return GetCachedThumb(m_strPath,g_settings.GetProgramsThumbFolder()); -} - -CStdString CFileItem::GetCachedGameSaveThumb() const -{ - return ""; -} - -void CFileItem::SetCachedProgramThumb() -{ - // don't set any thumb for programs on DVD, as they're bound to be named the - // same (D:\default.xbe). - if (IsParentFolder()) return; - CStdString thumb(GetCachedProgramThumb()); - if (CFile::Exists(thumb)) - SetThumbnailImage(thumb); -} - -void CFileItem::SetUserProgramThumb() -{ - if (m_bIsShareOrDrive) return; - if (IsParentFolder()) return; - - if (IsShortCut()) - { - CShortcut shortcut; - if ( shortcut.Create( m_strPath ) ) - { - // use the shortcut's thumb - if (!shortcut.m_strThumb.IsEmpty()) - m_strThumbnailImage = shortcut.m_strThumb; - else - { - CFileItem item(shortcut.m_strPath,false); - item.SetUserProgramThumb(); - m_strThumbnailImage = item.m_strThumbnailImage; - } - return; - } - } - // 1. Try .tbn - CStdString fileThumb(GetTBNFile()); - CStdString thumb(GetCachedProgramThumb()); - if (CFile::Exists(fileThumb)) - { // cache - CPicture pic; - if (pic.DoCreateThumbnail(fileThumb, thumb)) - SetThumbnailImage(thumb); - } - else if (m_bIsFolder) - { - // 3. cache the folder image - CStdString folderThumb(GetFolderThumb()); - if (CFile::Exists(folderThumb)) - { - CPicture pic; - if (pic.DoCreateThumbnail(folderThumb, thumb)) - SetThumbnailImage(thumb); - } - } -} - /*void CFileItem::SetThumb() { // we need to know the type of file at this point @@ -2810,92 +3073,6 @@ }*/ -void CFileItemList::SetProgramThumbs() -{ - // TODO: Is there a speed up if we cache the program thumbs first? - for (unsigned int i = 0; i < m_items.size(); i++) - { - CFileItemPtr pItem = m_items[i]; - if (pItem->IsParentFolder()) - continue; - pItem->SetCachedProgramThumb(); - if (!pItem->HasThumbnail()) - pItem->SetUserProgramThumb(); - } -} - -bool CFileItem::LoadMusicTag() -{ - // not audio - if (!IsAudio()) - return false; - // already loaded? - if (HasMusicInfoTag() && m_musicInfoTag->Loaded()) - return true; - // check db - CMusicDatabase musicDatabase; - if (musicDatabase.Open()) - { - CSong song; - if (musicDatabase.GetSongByFileName(m_strPath, song)) - { - GetMusicInfoTag()->SetSong(song); - SetThumbnailImage(song.strThumb); - return true; - } - musicDatabase.Close(); - } - // load tag from file - CLog::Log(LOGDEBUG, "%s: loading tag information for file: %s", __FUNCTION__, m_strPath.c_str()); - CMusicInfoTagLoaderFactory factory; - auto_ptr pLoader (factory.CreateLoader(m_strPath)); - if (NULL != pLoader.get()) - { - if (pLoader->Load(m_strPath, *GetMusicInfoTag())) - return true; - } - // no tag - try some other things - if (IsCDDA()) - { - // we have the tracknumber... - int iTrack = GetMusicInfoTag()->GetTrackNumber(); - if (iTrack >= 1) - { - CStdString strText = g_localizeStrings.Get(554); // "Track" - if (strText.GetAt(strText.size() - 1) != ' ') - strText += " "; - CStdString strTrack; - strTrack.Format(strText + "%i", iTrack); - GetMusicInfoTag()->SetTitle(strTrack); - GetMusicInfoTag()->SetLoaded(true); - return true; - } - } - else - { - CStdString fileName = CUtil::GetFileName(m_strPath); - CUtil::RemoveExtension(fileName); - for (unsigned int i = 0; i < g_advancedSettings.m_musicTagsFromFileFilters.size(); i++) - { - CLabelFormatter formatter(g_advancedSettings.m_musicTagsFromFileFilters[i], ""); - if (formatter.FillMusicTag(fileName, GetMusicInfoTag())) - { - GetMusicInfoTag()->SetLoaded(true); - return true; - } - } - } - return false; -} - -void CFileItem::SetCachedGameSavesThumb() -{ - if (IsParentFolder()) return; - CStdString thumb(GetCachedGameSaveThumb()); - if (CFile::Exists(thumb)) - SetThumbnailImage(thumb); -} - void CFileItemList::SetCachedGameSavesThumbs() { // TODO: Investigate caching time to see if it speeds things up @@ -2935,10 +3112,10 @@ void CFileItemList::AddSortMethod(SORT_METHOD sortMethod, int buttonLabel, const LABEL_MASKS &labelMasks) { - SORT_METHOD_DETAILS sort; - sort.m_sortMethod=sortMethod; - sort.m_buttonLabel=buttonLabel; - sort.m_labelMasks=labelMasks; + SORT_METHOD_DETAILS sort; + sort.m_sortMethod = sortMethod; + sort.m_buttonLabel = buttonLabel; + sort.m_labelMasks = labelMasks; m_sortDetails.push_back(sort); } @@ -2950,10 +3127,11 @@ void CFileItemList::ClearSortState() { - m_sortMethod=SORT_METHOD_NONE; - m_sortOrder=SORT_ORDER_NONE; + m_sortMethod = SORT_METHOD_NONE; + m_sortOrder = SORT_ORDER_NONE; } + CVideoInfoTag* CFileItem::GetVideoInfoTag() { if (!m_videoInfoTag) @@ -2970,6 +3148,14 @@ return m_pictureInfoTag; } +CProgramInfoTag* CFileItem::GetProgramInfoTag() +{ + if (!m_programInfoTag) + m_programInfoTag = new CProgramInfoTag; + + return m_programInfoTag; +} + MUSIC_INFO::CMusicInfoTag* CFileItem::GetMusicInfoTag() { if (!m_musicInfoTag) @@ -2978,42 +3164,49 @@ return m_musicInfoTag; } + + CStdString CFileItem::FindTrailer() const { - CStdString strFile2, strTrailer; - CStdString strFile = m_strPath; + CStdString strDir, strFile2, strFile3, strTrailer; + CStdString strFile = m_strPath; + CFileItemList items; + if (IsStack()) { - CStdString strPath; - CUtil::GetParentPath(m_strPath,strPath); - CStackDirectory dir; - CStdString strPath2; - strPath2 = dir.GetStackedTitlePath(strFile); + CStdString strPath, strPath2, strTBNFile; + CStackDirectory dir; + + CUtil::GetParentPath(m_strPath, strPath); + + strPath2 = dir.GetStackedTitlePath(strFile); CUtil::AddFileToFolder(strPath,CUtil::GetFileName(strPath2),strFile); CFileItem item(dir.GetFirstStackedFile(m_strPath),false); - CStdString strTBNFile = item.GetTBNFile(); - CUtil::ReplaceExtension(strTBNFile, "-trailer",strTBNFile); + + strTBNFile = item.GetTBNFile(); + CUtil::ReplaceExtension(strTBNFile, "-trailer", strTBNFile); CUtil::AddFileToFolder(strPath,CUtil::GetFileName(strTBNFile),strFile2); } + if (CUtil::IsInRAR(strFile) || CUtil::IsInZIP(strFile)) { CStdString strPath, strParent; - CUtil::GetDirectory(strFile,strPath); - CUtil::GetParentPath(strPath,strParent); - CUtil::AddFileToFolder(strParent,CUtil::GetFileName(m_strPath),strFile); + + CUtil::GetDirectory(strFile, strPath); + CUtil::GetParentPath(strPath, strParent); + CUtil::AddFileToFolder(strParent, CUtil::GetFileName(m_strPath), strFile); } // no local trailer available for these if (IsInternetStream() || CUtil::IsUPnP(strFile) || IsLiveTV() || IsPlugin()) return strTrailer; - CStdString strDir; CUtil::GetDirectory(strFile, strDir); - CFileItemList items; + CDirectory::GetDirectory(strDir, items, g_stSettings.m_videoExtensions, true, false, DIR_CACHE_ALWAYS, false); CUtil::RemoveExtension(strFile); strFile += "-trailer"; - CStdString strFile3 = CUtil::AddFileToFolder(strDir, "movie-trailer"); + strFile3 = CUtil::AddFileToFolder(strDir, "movie-trailer"); for (int i = 0; i < items.Size(); i++) { @@ -3031,3 +3224,60 @@ return strTrailer; } +CStdString CFileItem::FindPreview() const +{ + CStdString strDir, strFile2, strFile3, strPreview; + CStdString strFile = m_strPath; + CFileItemList items; + + if (IsStack()) + { + CStdString strPath, strPath2, strTBNFile; + CStackDirectory dir; + + CUtil::GetParentPath(m_strPath, strPath); + + strPath2 = dir.GetStackedTitlePath(strFile); + CUtil::AddFileToFolder(strPath,CUtil::GetFileName(strPath2),strFile); + CFileItem item(dir.GetFirstStackedFile(m_strPath),false); + + strTBNFile = item.GetTBNFile(); + CUtil::ReplaceExtension(strTBNFile, "-preview", strTBNFile); + CUtil::AddFileToFolder(strPath,CUtil::GetFileName(strTBNFile),strFile2); + } + + if (CUtil::IsInRAR(strFile) || CUtil::IsInZIP(strFile)) + { + CStdString strPath, strParent; + + CUtil::GetDirectory(strFile, strPath); + CUtil::GetParentPath(strPath, strParent); + CUtil::AddFileToFolder(strParent, CUtil::GetFileName(m_strPath), strFile); + } + + // no local trailer available for these + if (IsInternetStream() || CUtil::IsUPnP(strFile) || IsLiveTV() || IsPlugin()) + return strPreview; + + CUtil::GetDirectory(strFile, strDir); + + CDirectory::GetDirectory(strDir, items, g_stSettings.m_programExtensions, true, false, DIR_CACHE_ALWAYS, false); + CUtil::RemoveExtension(strFile); + strFile += "-preview"; + strFile3 = CUtil::AddFileToFolder(strDir, "game-preview"); + + for (int i = 0; i < items.Size(); i++) + { + CStdString strCandidate = items[i]->m_strPath; + CUtil::RemoveExtension(strCandidate); + if (strCandidate.CompareNoCase(strFile) == 0 || + strCandidate.CompareNoCase(strFile2) == 0 || + strCandidate.CompareNoCase(strFile3) == 0) + { + strPreview = items[i]->m_strPath; + break; + } + } + + return strPreview; +} Index: xbmc/FileItem.h =================================================================== --- xbmc/FileItem.h (revision 24004) +++ xbmc/FileItem.h (working copy) @@ -74,17 +74,19 @@ CFileItem(const CArtist& artist); CFileItem(const CGenre& genre); CFileItem(const CVideoInfoTag& movie); + CFileItem(const CProgramInfoTag& game); CFileItem(const CMediaSource& share); virtual ~CFileItem(void); void Reset(); - const CFileItem& operator=(const CFileItem& item); + const CFileItem& operator = (const CFileItem& item); virtual void Serialize(CArchive& ar); virtual bool IsFileItem() const { return true; }; bool Exists() const; bool IsVideo() const; bool IsPicture() const; + bool IsProgram() const; bool IsLyrics() const; bool IsAudio() const; bool IsCUESheet() const; @@ -119,6 +121,7 @@ bool IsMultiPath() const; bool IsMusicDb() const; bool IsVideoDb() const; + bool IsProgramDb() const; bool IsType(const char *ext) const; bool IsVirtualDirectoryRoot() const; bool IsReadOnly() const; @@ -156,6 +159,8 @@ return m_musicInfoTag; } + + inline bool HasVideoInfoTag() const { return m_videoInfoTag != NULL; @@ -168,6 +173,8 @@ return m_videoInfoTag; } + + inline bool HasPictureInfoTag() const { return m_pictureInfoTag != NULL; @@ -180,33 +187,37 @@ CPictureInfoTag* GetPictureInfoTag(); + + bool HasProgramInfoTag() const { return m_programInfoTag != NULL; } + CProgramInfoTag* GetProgramInfoTag(); + inline const CProgramInfoTag* GetProgramInfoTag() const { return m_programInfoTag; } - CProgramInfoTag* GetProgramInfoTag(); // Gets the cached thumb filename (no existence checks) - CStdString GetCachedVideoThumb() const; - CStdString GetCachedEpisodeThumb() const; - CStdString GetCachedPictureThumb() const; - CStdString GetCachedArtistThumb() const; - CStdString GetCachedProgramThumb() const; - CStdString GetCachedGameSaveThumb() const; - CStdString GetCachedProfileThumb() const; - CStdString GetCachedSeasonThumb() const; - CStdString GetCachedActorThumb() const; - CStdString GetCachedFanart() const; + CStdString GetCachedVideoThumb() const; + CStdString GetCachedEpisodeThumb() const; + CStdString GetCachedPictureThumb() const; + CStdString GetCachedArtistThumb() const; + CStdString GetCachedProgramThumb() const; + CStdString GetCachedGameSaveThumb() const; + CStdString GetCachedProfileThumb() const; + CStdString GetCachedSeasonThumb() const; + CStdString GetCachedActorThumb() const; + CStdString GetCachedFanart() const; static CStdString GetCachedThumb(const CStdString &path, const CStdString& strPath2, bool split=false); // Sets the video thumb (cached first, else caches user thumb) void SetVideoThumb(); + void SetProgramThumb(); CStdString CacheFanart(bool probe=false) const; // Sets the cached thumb for the item if it exists @@ -220,13 +231,19 @@ // Gets the .tbn file associated with this item CStdString GetTBNFile() const; + // Gets the folder image associated with this item (defaults to folder.jpg) CStdString GetFolderThumb(const CStdString &folderJPG = "folder.jpg") const; + // Gets the correct movie title CStdString GetMovieName(bool bUseFolderNames = false) const; + // Gets the correct game title + CStdString GetGameName(bool bUseFolderNames = false) const; + // Gets the user thumb, if it exists CStdString GetUserVideoThumb() const; + CStdString GetUserProgramThumb() const; CStdString GetUserMusicThumb(bool alwaysCheckRemote = false) const; // Caches the user thumb and assigns it to the item @@ -237,13 +254,16 @@ // finds a matching local trailer file CStdString FindTrailer() const; + // finds a matching local preview file + CStdString FindPreview() const; + virtual bool LoadMusicTag(); /* returns the content type of this item if known. will lookup for http streams */ const CStdString& GetContentType() const; /* sets the contenttype if known beforehand */ - void SetContentType(const CStdString& content) { m_contenttype = content; } ; + void SetContentType(const CStdString& content) { m_contenttype = content; } ; /* general extra info about the contents of the item, not for display */ void SetExtraInfo(const CStdString& info) { m_extrainfo = info; }; @@ -255,11 +275,11 @@ CStdString GetPreviouslyCachedMusicThumb() const; public: - CStdString m_strPath; ///< complete path to item - bool m_bIsShareOrDrive; ///< is this a root share/drive - int m_iDriveType; ///< If \e m_bIsShareOrDrive is \e true, use to get the share type. Types see: CMediaSource::m_iDriveType - CDateTime m_dateTime; ///< file creation date & time - __int64 m_dwSize; ///< file size (0 for folders) + CStdString m_strPath; ///< complete path to item + bool m_bIsShareOrDrive; ///< is this a root share/drive + int m_iDriveType; ///< If \e m_bIsShareOrDrive is \e true, use to get the share type. Types see: CMediaSource::m_iDriveType + CDateTime m_dateTime; ///< file creation date & time + __int64 m_dwSize; ///< file size (0 for folders) CStdString m_strDVDLabel; CStdString m_strTitle; int m_iprogramCount; @@ -277,10 +297,11 @@ bool m_bLabelPreformated; CStdString m_contenttype; CStdString m_extrainfo; - MUSIC_INFO::CMusicInfoTag* m_musicInfoTag; - CVideoInfoTag* m_videoInfoTag; - CPictureInfoTag* m_pictureInfoTag; - CProgramInfoTag* m_programInfoTag; + + MUSIC_INFO::CMusicInfoTag* m_musicInfoTag; + CVideoInfoTag* m_videoInfoTag; + CPictureInfoTag* m_pictureInfoTag; + CProgramInfoTag* m_programInfoTag; }; /*! @@ -293,13 +314,13 @@ \brief A vector of pointer to CFileItem \sa CFileItem */ -typedef std::vector< CFileItemPtr > VECFILEITEMS; +typedef std::vectorVECFILEITEMS; /*! \brief Iterator for VECFILEITEMS \sa CFileItemList */ -typedef std::vector< CFileItemPtr >::iterator IVECFILEITEMS; +typedef std::vector::iterator IVECFILEITEMS; /*! \brief A map of pointers to CFileItem @@ -336,80 +357,80 @@ virtual ~CFileItemList(); virtual void Serialize(CArchive& ar); CFileItemPtr operator[] (int iItem); + CFileItemPtr operator[] (const CStdString& strPath); + CFileItemPtr Get(int iItem); + CFileItemPtr Get(const CStdString& strPath); const CFileItemPtr operator[] (int iItem) const; - CFileItemPtr operator[] (const CStdString& strPath); const CFileItemPtr operator[] (const CStdString& strPath) const; - void Clear(); - void ClearItems(); - void Add(const CFileItemPtr &pItem); - void AddFront(const CFileItemPtr &pItem, int itemPosition); - void Remove(CFileItem* pItem); - void Remove(int iItem); - CFileItemPtr Get(int iItem); const CFileItemPtr Get(int iItem) const; - CFileItemPtr Get(const CStdString& strPath); const CFileItemPtr Get(const CStdString& strPath) const; - int Size() const; - bool IsEmpty() const; - void Append(const CFileItemList& itemlist); - void Assign(const CFileItemList& itemlist, bool append = false); - bool Copy (const CFileItemList& item); - void Reserve(int iCount); - void Sort(SORT_METHOD sortMethod, SORT_ORDER sortOrder); - void Randomize(); - void SetMusicThumbs(); - void FillInDefaultIcons(); - int GetFolderCount() const; - int GetFileCount() const; - int GetSelectedCount() const; - int GetObjectCount() const; - void FilterCueItems(); - void RemoveExtensions(); - void SetFastLookup(bool fastLookup); - bool Contains(const CStdString& fileName) const; - bool GetFastLookup() const { return m_fastLookup; }; - void Stack(); - SORT_ORDER GetSortOrder() const { return m_sortOrder; } - SORT_METHOD GetSortMethod() const { return m_sortMethod; } - bool Load(); - bool Save(); - void SetCacheToDisc(CACHE_TYPE cacheToDisc) { m_cacheToDisc = cacheToDisc; } - bool CacheToDiscAlways() const { return m_cacheToDisc == CACHE_ALWAYS; } - bool CacheToDiscIfSlow() const { return m_cacheToDisc == CACHE_IF_SLOW; } - void RemoveDiscCache() const; - bool AlwaysCache() const; + void Clear(); + void ClearItems(); + void Add(const CFileItemPtr &pItem); + void AddFront(const CFileItemPtr &pItem, int itemPosition); + void Remove(CFileItem* pItem); + void Remove(int iItem); + int Size() const; + bool IsEmpty() const; + void Append(const CFileItemList& itemlist); + void Assign(const CFileItemList& itemlist, bool append = false); + bool Copy (const CFileItemList& item); + void Reserve(int iCount); + void Sort(SORT_METHOD sortMethod, SORT_ORDER sortOrder); + void Randomize(); + void FillInDefaultIcons(); + int GetFolderCount() const; + int GetFileCount() const; + int GetSelectedCount() const; + int GetObjectCount() const; + void FilterCueItems(); + void RemoveExtensions(); + void SetFastLookup(bool fastLookup); + bool Contains(const CStdString& fileName) const; + bool GetFastLookup() const { return m_fastLookup; }; + void Stack(); + bool Load(); + bool Save(); + void SetCacheToDisc(CACHE_TYPE cacheToDisc) { m_cacheToDisc = cacheToDisc; } + bool CacheToDiscAlways() const { return m_cacheToDisc == CACHE_ALWAYS; } + bool CacheToDiscIfSlow() const { return m_cacheToDisc == CACHE_IF_SLOW; } + void RemoveDiscCache() const; + bool AlwaysCache() const; - void SetCachedVideoThumbs(); - void SetCachedProgramThumbs(); - void SetCachedGameSavesThumbs(); - void SetCachedMusicThumbs(); - void SetProgramThumbs(); - void SetGameSavesThumbs(); + void SetCachedVideoThumbs(); + void SetCachedProgramThumbs(); + void SetCachedGameSavesThumbs(); + void SetCachedMusicThumbs(); - void Swap(unsigned int item1, unsigned int item2); + void SetProgramThumbs(); + void SetGameSavesThumbs(); + void SetMusicThumbs(); - void UpdateItem(const CFileItem *item); - - void AddSortMethod(SORT_METHOD method, int buttonLabel, const LABEL_MASKS &labelMasks); - bool HasSortDetails() const { return m_sortDetails.size() != 0; }; + void Swap(unsigned int item1, unsigned int item2); + void UpdateItem(const CFileItem *item); + void AddSortMethod(SORT_METHOD method, int buttonLabel, const LABEL_MASKS &labelMasks); + bool HasSortDetails() const { return m_sortDetails.size() != 0; }; const std::vector &GetSortDetails() const { return m_sortDetails; }; - bool GetReplaceListing() const { return m_replaceListing; }; - void SetReplaceListing(bool replace); - void SetContent(const CStdString &content) { m_content = content; }; + bool GetReplaceListing() const { return m_replaceListing; }; + void SetReplaceListing(bool replace); + void SetContent(const CStdString &content) { m_content = content; }; const CStdString &GetContent() const { return m_content; }; + void ClearSortState(); - void ClearSortState(); + SORT_ORDER GetSortOrder() const { return m_sortOrder; } + SORT_METHOD GetSortMethod() const { return m_sortMethod; } + private: void Sort(FILEITEMLISTCOMPARISONFUNC func); void FillSortFields(FILEITEMFILLFUNC func); CStdString GetDiscCacheFile() const; - VECFILEITEMS m_items; - MAPFILEITEMS m_map; - bool m_fastLookup; - SORT_METHOD m_sortMethod; - SORT_ORDER m_sortOrder; - CACHE_TYPE m_cacheToDisc; + VECFILEITEMS m_items; + MAPFILEITEMS m_map; + SORT_METHOD m_sortMethod; + SORT_ORDER m_sortOrder; + CACHE_TYPE m_cacheToDisc; + bool m_fastLookup; bool m_replaceListing; CStdString m_content; Index: xbmc/FileSystem/FactoryDirectory.cpp =================================================================== --- xbmc/FileSystem/FactoryDirectory.cpp (revision 24004) +++ xbmc/FileSystem/FactoryDirectory.cpp (working copy) @@ -31,6 +31,7 @@ #include "MusicDatabaseDirectory.h" #include "MusicSearchDirectory.h" #include "VideoDatabaseDirectory.h" +#include "ProgramDatabaseDirectory.h" #include "ShoutcastDirectory.h" #include "LastFMDirectory.h" #include "FTPDirectory.h" @@ -124,6 +125,7 @@ if (strProtocol == "musicdb") return new CMusicDatabaseDirectory(); if (strProtocol == "musicsearch") return new CMusicSearchDirectory(); if (strProtocol == "videodb") return new CVideoDatabaseDirectory(); + if (strProtocol == "programdb") return new CProgramDatabaseDirectory(); if (strProtocol == "filereader") return CFactoryDirectory::Create(url.GetFileName()); Index: xbmc/FileSystem/ProgramDatabaseDirectory.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory.cpp (revision 0) @@ -0,0 +1,279 @@ +/////////////////////////////////////////////////////////// +/// \file ProgramDatabaseDirectory.cpp +/////////////////////////////////////////////////////////// + + +#include "stdafx.h" +#include "ProgramDatabaseDirectory.h" +#include "Util.h" +#include "ProgramDatabaseDirectory/QueryParams.h" +#include "ProgramDatabase.h" +#include "TextureManager.h" +#include "FileSystem/File.h" +#include "FileItem.h" +#include "Settings.h" +#include "Crc32.h" +#include "LocalizeStrings.h" +#include "utils/log.h" + +using namespace std; +using namespace XFILE; +using namespace DIRECTORY; +using namespace PROGRAMDATABASEDIRECTORY; + + +CProgramDatabaseDirectory::CProgramDatabaseDirectory(void){} + + +CProgramDatabaseDirectory::~CProgramDatabaseDirectory(void){} + + +bool CProgramDatabaseDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items) +{ + auto_ptr pNode(CDirectoryNode::ParseURL(strPath)); + + if (!pNode.get()) + return false; + + bool bResult = pNode->GetChilds(items); + + for (int i = 0; i < items.Size();++i) { + CFileItemPtr item = items[i]; + + if (item->m_bIsFolder && !item->HasIcon() && !item->HasThumbnail()) { + CStdString strImage = GetIcon(item->m_strPath); + + if (!strImage.IsEmpty() && g_TextureManager.HasTexture(strImage)) + item->SetThumbnailImage(strImage); + } + } + + return bResult; +} + + +NODE_TYPE CProgramDatabaseDirectory::GetDirectoryChildType(const CStdString& strPath) +{ + auto_ptr pNode(CDirectoryNode::ParseURL(strPath)); + + if (!pNode.get()) + return NODE_TYPE_NONE; + + return pNode->GetChildType(); +} + + +NODE_TYPE CProgramDatabaseDirectory::GetDirectoryType(const CStdString& strPath) +{ + auto_ptr pNode(CDirectoryNode::ParseURL(strPath)); + + if (!pNode.get()) + return NODE_TYPE_NONE; + + return pNode->GetType(); +} + + +NODE_TYPE CProgramDatabaseDirectory::GetDirectoryParentType(const CStdString& strPath) +{ + auto_ptr pNode(CDirectoryNode::ParseURL(strPath)); + + if (!pNode.get()) + return NODE_TYPE_NONE; + + CDirectoryNode* pParentNode = pNode->GetParent(); + + if (!pParentNode) + return NODE_TYPE_NONE; + + return pParentNode->GetChildType(); +} + + +bool CProgramDatabaseDirectory::GetQueryParams(const CStdString& strPath, CQueryParams& params) +{ + auto_ptr pNode(CDirectoryNode::ParseURL(strPath)); + + if (!pNode.get()) + return false; + + CDirectoryNode::GetDatabaseInfo(strPath,params); + + return true; +} + + +void CProgramDatabaseDirectory::ClearDirectoryCache(const CStdString& strDirectory) +{ + CFileItem directory(strDirectory, true); + CUtil::RemoveSlashAtEnd(directory.m_strPath); + + Crc32 crc; + crc.ComputeFromLowerCase(directory.m_strPath); + + CStdString strFileName; + strFileName.Format("special://temp/%08x.fi", (unsigned __int32) crc); + CFile::Delete(strFileName); +} + + +bool CProgramDatabaseDirectory::IsAllItem(const CStdString& strDirectory) +{ + if (strDirectory.Right(4).Equals("/-1/")) + return true; + + return false; +} + + +bool CProgramDatabaseDirectory::GetLabel(const CStdString& strDirectory, CStdString& strLabel) +{ + strLabel = ""; + + auto_ptr pNode(CDirectoryNode::ParseURL(strDirectory)); + if (!pNode.get() || strDirectory.IsEmpty()) + return false; + + // first see if there's any filter criteria + CQueryParams params; + CDirectoryNode::GetDatabaseInfo(strDirectory, params); + + CProgramDatabase programdatabase; + if (!programdatabase.Open()) + return false; + + // get genre + CStdString strTemp; + if (params.GetGenreId() != -1) { + programdatabase.GetGenreById(params.GetGenreId(), strTemp); + strLabel += strTemp; + } + + // get year + if (params.GetYear() != -1) { + strTemp.Format("%i", params.GetYear()); + + if (!strLabel.IsEmpty()) + strLabel += " / "; + + strLabel += strTemp; + } + + if (strLabel.IsEmpty()) { + switch (pNode->GetChildType()) { + + case NODE_TYPE_TITLE_GAMES: // Games + strLabel = g_localizeStrings.Get(369); break; + + case NODE_TYPE_GENRE: // Genres + strLabel = g_localizeStrings.Get(135); break; + + case NODE_TYPE_PERSPECTIVE: // Perspectives + strLabel = g_localizeStrings.Get(14602); break; + + case NODE_TYPE_YEAR: // Year + strLabel = g_localizeStrings.Get(562); break; + + case NODE_TYPE_DEVELOPER: // Developer + strLabel = g_localizeStrings.Get(14602); break; + + case NODE_TYPE_GAMES_OVERVIEW: // Games + strLabel = g_localizeStrings.Get(14502); break; + + case NODE_TYPE_RECENTLY_ADDED_GAMES: // Recently Added Games + strLabel = g_localizeStrings.Get(14610); break; + + case NODE_TYPE_PUBLISHER: // Publishers + strLabel = g_localizeStrings.Get(14603); break; + + case NODE_TYPE_PLATFORM: // Platform + strLabel = g_localizeStrings.Get(14601); break; + + default: + CLog::Log(LOGWARNING, "%s - Unknown nodetype requested(%d) - %s", + __FUNCTION__, pNode->GetChildType(), strDirectory.c_str()); + + return false; + } + } + + return true; +} + + +CStdString CProgramDatabaseDirectory::GetIcon(const CStdString &strDirectory) +{ + switch (GetDirectoryChildType(strDirectory)) { + + case NODE_TYPE_TITLE_GAMES: + if (strDirectory.Equals("programdb://1/2/")) { + if (g_stSettings.m_bMyProgramNavFlatten) + return "DefaultGames.png"; + //else + return "DefaultGameTitle.png"; + } + return ""; + + case NODE_TYPE_GENRE: // Genres + return "DefaultGenre.png"; + + case NODE_TYPE_YEAR: // Year + return "DefaultYear.png"; + + case NODE_TYPE_PLATFORM: // Platform + return "DefaultPlatform.png"; + + case NODE_TYPE_DEVELOPER: // Developer + return "DefaultDeveloper.png"; + + case NODE_TYPE_GAMES_OVERVIEW: // Games + return "DefaultGames.png"; + + case NODE_TYPE_RECENTLY_ADDED_GAMES: // Recently Added Games + return "DefaultRecentlyAddedGames.png"; + + case NODE_TYPE_PUBLISHER: // Publishers + return "DefaultPublishers.png"; + + default: + CLog::Log(LOGWARNING, "%s - Unknown nodetype requested %s", + __FUNCTION__, strDirectory.c_str()); + break; + } + + return ""; +} + + +bool CProgramDatabaseDirectory::ContainsGames(const CStdString &path) +{ + PROGRAMDATABASEDIRECTORY::NODE_TYPE type = GetDirectoryChildType(path); + if (type == PROGRAMDATABASEDIRECTORY::NODE_TYPE_TITLE_GAMES) + return true; + + return false; +} + + +bool CProgramDatabaseDirectory::Exists(const char* strPath) +{ + auto_ptr pNode(CDirectoryNode::ParseURL(strPath)); + + if (!pNode.get()) + return false; + + if (pNode->GetChildType() == PROGRAMDATABASEDIRECTORY::NODE_TYPE_NONE) + return false; + + return true; +} + + +bool CProgramDatabaseDirectory::CanCache(const CStdString& strPath) +{ + auto_ptr pNode(CDirectoryNode::ParseURL(strPath)); + if (!pNode.get()) + return false; + + return pNode->CanCache(); +} Index: xbmc/FileSystem/ProgramDatabaseDirectory.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory.h (revision 0) @@ -0,0 +1,48 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "IDirectory.h" +#include "ProgramDatabaseDirectory/DirectoryNode.h" +#include "ProgramDatabaseDirectory/QueryParams.h" + +namespace DIRECTORY +{ + class CProgramDatabaseDirectory : public IDirectory + { + public: + CProgramDatabaseDirectory(void); + virtual ~CProgramDatabaseDirectory(void); + virtual bool GetDirectory(const CStdString& strPath, CFileItemList &items); + virtual bool Exists(const char* strPath); + virtual bool IsAllowed(const CStdString& strFile) const { return true; }; + static PROGRAMDATABASEDIRECTORY::NODE_TYPE GetDirectoryChildType(const CStdString& strPath); + static PROGRAMDATABASEDIRECTORY::NODE_TYPE GetDirectoryType(const CStdString& strPath); + static PROGRAMDATABASEDIRECTORY::NODE_TYPE GetDirectoryParentType(const CStdString& strPath); + static bool GetQueryParams(const CStdString& strPath, PROGRAMDATABASEDIRECTORY::CQueryParams& params); + void ClearDirectoryCache(const CStdString& strDirectory); + static bool IsAllItem(const CStdString& strDirectory); + static bool GetLabel(const CStdString& strDirectory, CStdString& strLabel); + static CStdString GetIcon(const CStdString& strDirectory); + bool ContainsGames(const CStdString &path); + static bool CanCache(const CStdString &path); + }; +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNode.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNode.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNode.cpp (revision 0) @@ -0,0 +1,266 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "DirectoryNode.h" +#include "Util.h" +#include "QueryParams.h" +#include "DirectoryNodeRoot.h" +#include "DirectoryNodeOverview.h" +#include "DirectoryNodeGenre.h" +#include "DirectoryNodeTitleGames.h" +#include "DirectoryNodeYear.h" +#include "DirectoryNodeDeveloper.h" +#include "DirectoryNodeGamesOverview.h" +#include "DirectoryNodeRecentlyAddedGames.h" +#include "DirectoryNodePublisher.h" +#include "DirectoryNodePlatform.h" +#include "ProgramInfoTag.h" +#include "URL.h" +#include "AdvancedSettings.h" +#include "FileItem.h" +#include "FileSystem/File.h" +#include "StringUtils.h" +#include "LocalizeStrings.h" + +using namespace std; +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + +// Constructor is protected use ParseURL() +CDirectoryNode::CDirectoryNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent) +{ + m_Type = Type; + m_strName = strName; + m_pParent = pParent; +} + +CDirectoryNode::~CDirectoryNode() +{ + delete m_pParent; +} + +// Parses a given path and returns the current node of the path +CDirectoryNode* CDirectoryNode::ParseURL(const CStdString& strPath) +{ + CURL url(strPath); + + CStdString strDirectory = url.GetFileName(); + CUtil::RemoveSlashAtEnd(strDirectory); + + CStdStringArray Path; + StringUtils::SplitString(strDirectory, "/", Path); + if (!strDirectory.IsEmpty()) + Path.insert(Path.begin(), ""); + + CDirectoryNode* pNode = NULL; + CDirectoryNode* pParent = NULL; + NODE_TYPE NodeType = NODE_TYPE_ROOT; + + for (int i=0; i<(int)Path.size(); ++i) + { + pNode = CDirectoryNode::CreateNode(NodeType, Path[i], pParent); + NodeType = pNode ? pNode->GetChildType() : NODE_TYPE_NONE; + pParent = pNode; + } + + return pNode; +} + +// returns the database ids of the path, +void CDirectoryNode::GetDatabaseInfo(const CStdString& strPath, CQueryParams& params) +{ + auto_ptr pNode(CDirectoryNode::ParseURL(strPath)); + + if (!pNode.get()) return; + + pNode->CollectQueryParams(params); +} + +// Create a node object +CDirectoryNode* CDirectoryNode::CreateNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent) +{ + switch (Type) + { + case NODE_TYPE_ROOT: + return new CDirectoryNodeRoot(strName, pParent); + case NODE_TYPE_OVERVIEW: + return new CDirectoryNodeOverview(strName, pParent); + case NODE_TYPE_GENRE: + return new CDirectoryNodeGenre(strName, pParent); + case NODE_TYPE_YEAR: + return new CDirectoryNodeYear(strName, pParent); + case NODE_TYPE_DEVELOPER: + return new CDirectoryNodeDeveloper(strName, pParent); + case NODE_TYPE_TITLE_GAMES: + return new CDirectoryNodeTitleGames(strName, pParent); + case NODE_TYPE_GAMES_OVERVIEW: + return new CDirectoryNodeGamesOverview(strName, pParent); + case NODE_TYPE_RECENTLY_ADDED_GAMES: + return new CDirectoryNodeRecentlyAddedGames(strName, pParent); + case NODE_TYPE_PUBLISHER: + return new CDirectoryNodePublisher(strName, pParent); + case NODE_TYPE_PLATFORM: + return new CDirectoryNodePlatform(strName, pParent); + default: + break; + } + + return NULL; +} + +// Current node name +const CStdString& CDirectoryNode::GetName() +{ + return m_strName; +} + +// Current node type +NODE_TYPE CDirectoryNode::GetType() +{ + return m_Type; +} + +// Return the parent directory node or NULL, if there is no +CDirectoryNode* CDirectoryNode::GetParent() +{ + return m_pParent; +} + +void CDirectoryNode::RemoveParent() +{ + m_pParent = NULL; +} + +// should be overloaded by a derived class +// to get the content of a node. Will be called +// by GetChilds() of a parent node +bool CDirectoryNode::GetContent(CFileItemList& items) +{ + return false; +} + +// Creates a programdb url +CStdString CDirectoryNode::BuildPath() +{ + CStdStringArray array; + + if (!m_strName.IsEmpty()) + array.insert(array.begin(), m_strName); + + CDirectoryNode* pParent = m_pParent; + while (pParent != NULL) + { + const CStdString& strNodeName = pParent->GetName(); + if (!strNodeName.IsEmpty()) + array.insert(array.begin(), strNodeName); + + pParent = pParent->GetParent(); + } + + CStdString strPath = "programdb://"; + for (int i = 0; i < (int)array.size(); ++i) + strPath += array[i] + "/"; + + return strPath; +} + +// Collects Query params from this and all parent nodes. If a NODE_TYPE can +// be used as a database parameter, it will be added to the +// params object. +void CDirectoryNode::CollectQueryParams(CQueryParams& params) +{ + params.SetQueryParam(m_Type, m_strName); + + CDirectoryNode* pParent = m_pParent; + while (pParent != NULL) + { + params.SetQueryParam(pParent->GetType(), pParent->GetName()); + pParent = pParent->GetParent(); + } +} + +// Should be overloaded by a derived class. +// Returns the NODE_TYPE of the child nodes. +NODE_TYPE CDirectoryNode::GetChildType() +{ + return NODE_TYPE_NONE; +} + +// Get the child fileitems of this node +bool CDirectoryNode::GetChilds(CFileItemList& items) +{ + if (CanCache() && items.Load()) + return true; + + auto_ptr pNode(CDirectoryNode::CreateNode(GetChildType(), "", this)); + + bool bSuccess=false; + if (pNode.get()) + { + bSuccess = pNode->GetContent(items); + if (bSuccess) + { + AddQueuingFolder(items); + if (CanCache()) + items.SetCacheToDisc(CFileItemList::CACHE_ALWAYS); + } + else + items.Clear(); + + pNode->RemoveParent(); + } + + return bSuccess; +} + + +// Add an "* All ..." folder to the CFileItemList +// depending on the child node +void CDirectoryNode::AddQueuingFolder(CFileItemList& items) +{ + CFileItemPtr pItem; + + // always hide "all" items + if (g_advancedSettings.m_bProgramLibraryHideAllItems) + return; + + // no need for "all" item when only one item + if (items.GetObjectCount() <= 1) + return; + + + if (pItem) + { + pItem->m_bIsFolder = true; + CStdString strFake; + // HACK: This item will stay on top of a list + strFake.Format("%c", 0x01); + if (g_advancedSettings.m_bProgramLibraryAllItemsOnBottom) + // HACK: This item will stay on bottom of a list + strFake.Format("%c", 0xff); + pItem->GetProgramInfoTag()->m_strTitle = strFake; + pItem->SetCanQueue(false); + pItem->SetLabelPreformated(true); + items.Add(pItem); + } +} + +bool CDirectoryNode::CanCache() { return true; } Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNode.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNode.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNode.h (revision 0) @@ -0,0 +1,88 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + + +#include "StdString.h" + +class CFileItemList; + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CQueryParams; + + typedef enum _NODE_TYPE { + NODE_TYPE_NONE = 0, + NODE_TYPE_GAMES_OVERVIEW, + NODE_TYPE_GENRE, + NODE_TYPE_ROOT, + NODE_TYPE_PERSPECTIVE, + NODE_TYPE_OVERVIEW, + NODE_TYPE_TITLE_GAMES, + NODE_TYPE_YEAR, + NODE_TYPE_DEVELOPER, + NODE_TYPE_RECENTLY_ADDED_GAMES, + NODE_TYPE_PUBLISHER, + NODE_TYPE_PLATFORM + } NODE_TYPE; + + class CDirectoryNode + { + public: + static CDirectoryNode* ParseURL(const CStdString& strPath); + static void GetDatabaseInfo(const CStdString& strPath, CQueryParams& params); + virtual ~CDirectoryNode(); + + NODE_TYPE GetType(); + + bool GetChilds(CFileItemList& items); + virtual NODE_TYPE GetChildType(); + + CDirectoryNode* GetParent(); + + bool CanCache(); + + protected: + CDirectoryNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent); + static CDirectoryNode* CreateNode(NODE_TYPE Type, const CStdString& strName, CDirectoryNode* pParent); + void CollectQueryParams(CQueryParams& params); + const CStdString& GetName(); + void RemoveParent(); + + virtual bool GetContent(CFileItemList& items); + + CStdString BuildPath(); + + private: + void AddQueuingFolder(CFileItemList& items); + + private: + NODE_TYPE m_Type; + CStdString m_strName; + CDirectoryNode *m_pParent; + }; + } +} + + + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeDeveloper.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeDeveloper.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeDeveloper.cpp (revision 0) @@ -0,0 +1,40 @@ +#include "stdafx.h" +#include "DirectoryNodeDeveloper.h" +#include "QueryParams.h" +#include "ProgramDatabase.h" + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + +CDirectoryNodeDeveloper::CDirectoryNodeDeveloper( + const CStdString& strName, + CDirectoryNode *pParent +) : CDirectoryNode(NODE_TYPE_DEVELOPER, strName, pParent){} + + +NODE_TYPE CDirectoryNodeDeveloper::GetChildType() +{ + CQueryParams params; + CollectQueryParams(params); + if (params.GetContentType() == PROGRAMDB_CONTENT_GAMES) + return NODE_TYPE_TITLE_GAMES; + + return NODE_TYPE_TITLE_GAMES; +} + + +bool CDirectoryNodeDeveloper::GetContent(CFileItemList& items) +{ + CProgramDatabase programdatabase; + if (!programdatabase.Open()) + return false; + + CQueryParams params; + CollectQueryParams(params); + bool bSuccess = programdatabase.GetDevelopersNav( + BuildPath(), items, params.GetContentType()); + + programdatabase.Close(); + + return bSuccess; +} + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeDeveloper.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeDeveloper.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeDeveloper.h (revision 0) @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CDirectoryNodeDeveloper : public CDirectoryNode + { + public: + CDirectoryNodeDeveloper(const CStdString& strName, CDirectoryNode* pParent); + protected: + virtual NODE_TYPE GetChildType(); + virtual bool GetContent(CFileItemList& items); + }; + } +} + + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGamesOverview.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGamesOverview.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGamesOverview.cpp (revision 0) @@ -0,0 +1,55 @@ +#include "stdafx.h" +#include "DirectoryNodeGamesOverview.h" +#include "FileItem.h" +#include "LocalizeStrings.h" + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + + +CDirectoryNodeGamesOverview::CDirectoryNodeGamesOverview(const CStdString& strName, CDirectoryNode* pParent) + : CDirectoryNode(NODE_TYPE_GAMES_OVERVIEW, strName, pParent){} + + +NODE_TYPE CDirectoryNodeGamesOverview::GetChildType() +{ + if (GetName()=="1") + return NODE_TYPE_GENRE; + else if (GetName()=="2") + return NODE_TYPE_TITLE_GAMES; + else if (GetName()=="3") + return NODE_TYPE_YEAR; + else if (GetName()=="4") + return NODE_TYPE_DEVELOPER; + else if (GetName()=="5") + return NODE_TYPE_PUBLISHER; + else if (GetName()=="6") + return NODE_TYPE_PERSPECTIVE; + + return NODE_TYPE_NONE; +} + + +bool CDirectoryNodeGamesOverview::GetContent(CFileItemList& items) +{ + CStdStringArray vecRoot; + + vecRoot.push_back(g_localizeStrings.Get(135)); // Genres + vecRoot.push_back(g_localizeStrings.Get(369)); // Title + vecRoot.push_back(g_localizeStrings.Get(562)); // Year + vecRoot.push_back(g_localizeStrings.Get(14602)); // Develpers + vecRoot.push_back(g_localizeStrings.Get(14603)); // Publishers + vecRoot.push_back(g_localizeStrings.Get(14609)); // Perspectives + + for (int i = 0; i < (int)vecRoot.size(); ++i) { + CFileItemPtr pItem(new CFileItem(vecRoot[i])); + CStdString strDir; + + strDir.Format("%i/", i+1); + pItem->m_strPath = BuildPath() + strDir; + pItem->m_bIsFolder = true; + pItem->SetCanQueue(false); + items.Add(pItem); + } + + return true; +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGamesOverview.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGamesOverview.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGamesOverview.h (revision 0) @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CDirectoryNodeGamesOverview : public CDirectoryNode + { + public: + CDirectoryNodeGamesOverview(const CStdString& strName, CDirectoryNode* pParent); + protected: + virtual NODE_TYPE GetChildType(); + virtual bool GetContent(CFileItemList& items); + }; + } +} + + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGenre.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGenre.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGenre.cpp (revision 0) @@ -0,0 +1,36 @@ +#include "stdafx.h" +#include "DirectoryNodeGenre.h" +#include "QueryParams.h" +#include "ProgramDatabase.h" + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + + +CDirectoryNodeGenre::CDirectoryNodeGenre(const CStdString& strName, CDirectoryNode* pParent) + : CDirectoryNode(NODE_TYPE_GENRE, strName, pParent){} + + +NODE_TYPE CDirectoryNodeGenre::GetChildType() +{ + CQueryParams params; + CollectQueryParams(params); + if (params.GetContentType() == PROGRAMDB_CONTENT_GAMES) + return NODE_TYPE_TITLE_GAMES; + + return NODE_TYPE_TITLE_GAMES; +} + + +bool CDirectoryNodeGenre::GetContent(CFileItemList& items) +{ + CProgramDatabase programdatabase; + if (!programdatabase.Open()) + return false; + + CQueryParams params; + CollectQueryParams(params); + bool bSuccess = programdatabase.GetGenresNav(BuildPath(), items, params.GetContentType()); + programdatabase.Close(); + + return bSuccess; +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGenre.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGenre.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeGenre.h (revision 0) @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CDirectoryNodeGenre : public CDirectoryNode + { + public: + CDirectoryNodeGenre(const CStdString& strName, CDirectoryNode* pParent); + protected: + virtual NODE_TYPE GetChildType(); + virtual bool GetContent(CFileItemList& items); + }; + } +} + + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeOverview.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeOverview.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeOverview.cpp (revision 0) @@ -0,0 +1,51 @@ +#include "stdafx.h" +#include "ProgramDatabase.h" +#include "DirectoryNodeOverview.h" +#include "AdvancedSettings.h" +#include "Settings.h" +#include "FileItem.h" +#include "LocalizeStrings.h" + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; +using namespace std; + + +CDirectoryNodeOverview::CDirectoryNodeOverview(const CStdString& strName, CDirectoryNode* pParent) + : CDirectoryNode(NODE_TYPE_OVERVIEW, strName, pParent){} + + +NODE_TYPE CDirectoryNodeOverview::GetChildType() +{ + if (GetName() == "1") + return NODE_TYPE_GAMES_OVERVIEW; + else if (GetName() == "2") + return NODE_TYPE_RECENTLY_ADDED_GAMES; + + return NODE_TYPE_NONE; +} + + +bool CDirectoryNodeOverview::GetContent(CFileItemList& items) +{ + CProgramDatabase database; + database.Open(); + bool hasGames = database.HasContent(PROGRAMDB_CONTENT_GAMES); + vector > vec; + + if (hasGames) { + if (g_stSettings.m_bMyProgramNavFlatten) + vec.push_back(make_pair("1/2", 14502)); + else vec.push_back(make_pair("1", 14502)); // Games + } + + CStdString path = BuildPath(); + for (unsigned int i = 0; i < vec.size(); ++i) { + CFileItemPtr pItem(new CFileItem(path + vec[i].first + "/", true)); + pItem->SetLabel(g_localizeStrings.Get(vec[i].second)); + pItem->SetLabelPreformated(true); + pItem->SetCanQueue(false); + items.Add(pItem); + } + + return true; +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeOverview.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeOverview.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeOverview.h (revision 0) @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CDirectoryNodeOverview : public CDirectoryNode + { + public: + CDirectoryNodeOverview(const CStdString& strName, CDirectoryNode* pParent); + protected: + virtual NODE_TYPE GetChildType(); + virtual bool GetContent(CFileItemList& items); + }; + } +} + + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePerspective.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePerspective.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePerspective.cpp (revision 0) @@ -0,0 +1,38 @@ +#include "stdafx.h" +#include "DirectoryNodePerspective.h" +#include "QueryParams.h" +#include "ProgramDatabase.h" + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + + +CDirectoryNodePerspective::CDirectoryNodePerspective(const CStdString& strName, CDirectoryNode* pParent) + : CDirectoryNode(NODE_TYPE_PERSPECTIVE, strName, pParent){} + + +NODE_TYPE CDirectoryNodePerspective::GetChildType() +{ + CQueryParams params; + CollectQueryParams(params); + if (params.GetContentType() == PROGRAMDB_CONTENT_GAMES) + return NODE_TYPE_TITLE_GAMES; + + return NODE_TYPE_TITLE_GAMES; +} + + +bool CDirectoryNodePerspective::GetContent(CFileItemList& items) +{ + CProgramDatabase programdatabase; + if (!programdatabase.Open()) + return false; + + CQueryParams params; + CollectQueryParams(params); + + bool bSuccess = programdatabase.GetPerspectivesNav(BuildPath(), items, params.GetContentType()); + + programdatabase.Close(); + + return bSuccess; +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePerspective.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePerspective.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePerspective.h (revision 0) @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CDirectoryNodePerspective : public CDirectoryNode + { + public: + CDirectoryNodePerspective(const CStdString& strName, CDirectoryNode* pParent); + protected: + virtual NODE_TYPE GetChildType(); + virtual bool GetContent(CFileItemList& items); + }; + } +} + + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePlatform.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePlatform.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePlatform.cpp (revision 0) @@ -0,0 +1,37 @@ +#include "stdafx.h" +#include "DirectoryNodePlatform.h" +#include "QueryParams.h" +#include "ProgramDatabase.h" + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + + +CDirectoryNodePlatform::CDirectoryNodePlatform(const CStdString& strName, CDirectoryNode* pParent) + : CDirectoryNode(NODE_TYPE_PLATFORM, strName, pParent){} + + +NODE_TYPE CDirectoryNodePlatform::GetChildType() +{ + CQueryParams params; + CollectQueryParams(params); + if (params.GetContentType() == PROGRAMDB_CONTENT_GAMES) + return NODE_TYPE_TITLE_GAMES; + + return NODE_TYPE_TITLE_GAMES; +} + + +bool CDirectoryNodePlatform::GetContent(CFileItemList& items) +{ + CProgramDatabase programdatabase; + if (!programdatabase.Open()) + return false; + + CQueryParams params; + CollectQueryParams(params); + CStdString strBaseDir = BuildPath(); + bool bSuccess = programdatabase.GetPlatformsNav(strBaseDir, items, params.GetContentType()); + programdatabase.Close(); + + return bSuccess; +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePlatform.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePlatform.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePlatform.h (revision 0) @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CDirectoryNodePlatform : public CDirectoryNode + { + public: + CDirectoryNodePlatform(const CStdString& strEntryName, CDirectoryNode* pParent); + protected: + virtual bool GetContent(CFileItemList& items); + virtual NODE_TYPE GetChildType(); + }; + } +} + + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePublisher.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePublisher.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePublisher.cpp (revision 0) @@ -0,0 +1,40 @@ +#include "stdafx.h" +#include "DirectoryNodePublisher.h" +#include "QueryParams.h" +#include "ProgramDatabase.h" + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + + +CDirectoryNodePublisher::CDirectoryNodePublisher( + const CStdString& strName, CDirectoryNode* pParent) : + CDirectoryNode(NODE_TYPE_PUBLISHER, strName, pParent) {} + + +NODE_TYPE CDirectoryNodePublisher::GetChildType() +{ + CQueryParams params; + CollectQueryParams(params); + if (params.GetContentType() == PROGRAMDB_CONTENT_GAMES) + return NODE_TYPE_TITLE_GAMES; + return NODE_TYPE_TITLE_GAMES; +} + + +bool CDirectoryNodePublisher::GetContent(CFileItemList& items) +{ + CProgramDatabase programdatabase; + if (!programdatabase.Open()) + return false; + + CQueryParams params; + CollectQueryParams(params); + + bool bSuccess = programdatabase.GetPublishersNav( + BuildPath(), items, params.GetContentType()); + + programdatabase.Close(); + + return bSuccess; +} + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePublisher.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePublisher.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodePublisher.h (revision 0) @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CDirectoryNodePublisher : public CDirectoryNode + { + public: + CDirectoryNodePublisher(const CStdString& strName, CDirectoryNode* pParent); + protected: + virtual NODE_TYPE GetChildType(); + virtual bool GetContent(CFileItemList& items); + }; + } +} + + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRecentlyAddedGames.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRecentlyAddedGames.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRecentlyAddedGames.cpp (revision 0) @@ -0,0 +1,31 @@ +#include "stdafx.h" +#include "DirectoryNodeRecentlyAddedGames.h" +#include "QueryParams.h" +#include "ProgramDatabase.h" + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + + +CDirectoryNodeRecentlyAddedGames::CDirectoryNodeRecentlyAddedGames(const CStdString& strName, CDirectoryNode* pParent) + : CDirectoryNode(NODE_TYPE_RECENTLY_ADDED_GAMES, strName, pParent){} + + +NODE_TYPE CDirectoryNodeRecentlyAddedGames::GetChildType() +{ + return NODE_TYPE_TITLE_GAMES; +} + + +bool CDirectoryNodeRecentlyAddedGames::GetContent(CFileItemList& items) +{ + CProgramDatabase programdatabase; + if (!programdatabase.Open()) + return false; + + CStdString strBaseDir = BuildPath(); + bool bSuccess = programdatabase.GetRecentlyAddedGamesNav(strBaseDir, items); + + programdatabase.Close(); + + return bSuccess; +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRecentlyAddedGames.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRecentlyAddedGames.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRecentlyAddedGames.h (revision 0) @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CDirectoryNodeRecentlyAddedGames : public CDirectoryNode + { + public: + CDirectoryNodeRecentlyAddedGames(const CStdString& strEntryName, CDirectoryNode* pParent); + protected: + virtual bool GetContent(CFileItemList& items); + virtual NODE_TYPE GetChildType(); + }; + } +} + + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRoot.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRoot.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRoot.cpp (revision 0) @@ -0,0 +1,14 @@ +#include "stdafx.h" +#include "DirectoryNodeRoot.h" + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + + +CDirectoryNodeRoot::CDirectoryNodeRoot(const CStdString& strName, CDirectoryNode* pParent) + : CDirectoryNode(NODE_TYPE_ROOT, strName, pParent){} + + +NODE_TYPE CDirectoryNodeRoot::GetChildType() +{ + return NODE_TYPE_OVERVIEW; +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRoot.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRoot.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeRoot.h (revision 0) @@ -0,0 +1,39 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CDirectoryNodeRoot : public CDirectoryNode + { + public: + CDirectoryNodeRoot(const CStdString& strName, CDirectoryNode* pParent); + protected: + virtual NODE_TYPE GetChildType(); + }; + } +} + + Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeTitleGames.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeTitleGames.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeTitleGames.cpp (revision 0) @@ -0,0 +1,30 @@ +#include "stdafx.h" +#include "DirectoryNodeTitleGames.h" +#include "QueryParams.h" +#include "ProgramDatabase.h" + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + + +CDirectoryNodeTitleGames::CDirectoryNodeTitleGames(const CStdString& strName, CDirectoryNode* pParent) + : CDirectoryNode(NODE_TYPE_TITLE_GAMES, strName, pParent){} + + +bool CDirectoryNodeTitleGames::GetContent(CFileItemList& items) +{ + CProgramDatabase programdatabase; + if (!programdatabase.Open()) + return false; + + CQueryParams params; + CollectQueryParams(params); + + CStdString strBaseDir = BuildPath(); + bool bSuccess = programdatabase.GetGamesNav( + strBaseDir, items, params.GetGenreId(), params.GetYear(), + params.GetDeveloperId(), params.GetPublisherId() ); + + programdatabase.Close(); + + return bSuccess; +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeTitleGames.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeTitleGames.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeTitleGames.h (revision 0) @@ -0,0 +1,37 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CDirectoryNodeTitleGames : public CDirectoryNode + { + public: + CDirectoryNodeTitleGames(const CStdString& strEntryName, CDirectoryNode* pParent); + protected: + virtual bool GetContent(CFileItemList& items); + }; + } +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeYear.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeYear.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeYear.cpp (revision 0) @@ -0,0 +1,37 @@ +#include "stdafx.h" +#include "DirectoryNodeYear.h" +#include "QueryParams.h" +#include "ProgramDatabase.h" + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + + +CDirectoryNodeYear::CDirectoryNodeYear(const CStdString& strName, CDirectoryNode* pParent) + : CDirectoryNode(NODE_TYPE_YEAR, strName, pParent){} + + +NODE_TYPE CDirectoryNodeYear::GetChildType() +{ + CQueryParams params; + CollectQueryParams(params); + if (params.GetContentType() == PROGRAMDB_CONTENT_GAMES) + return NODE_TYPE_TITLE_GAMES; + + return NODE_TYPE_TITLE_GAMES; +} + + +bool CDirectoryNodeYear::GetContent(CFileItemList& items) +{ + CProgramDatabase programdatabase; + if (!programdatabase.Open()) + return false; + + CQueryParams params; + CollectQueryParams(params); + CStdString strBaseDir = BuildPath(); + bool bSuccess = programdatabase.GetYearsNav(strBaseDir, items, params.GetContentType()); + programdatabase.Close(); + + return bSuccess; +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeYear.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeYear.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/DirectoryNodeYear.h (revision 0) @@ -0,0 +1,40 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CDirectoryNodeYear : public CDirectoryNode + { + public: + CDirectoryNodeYear(const CStdString& strEntryName, CDirectoryNode* pParent); + protected: + virtual bool GetContent(CFileItemList& items); + virtual NODE_TYPE GetChildType(); + }; + } +} + + Index: xbmc/FileSystem/ProgramDatabaseDirectory/QueryParams.cpp =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/QueryParams.cpp (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/QueryParams.cpp (revision 0) @@ -0,0 +1,50 @@ +#include "stdafx.h" +#include "QueryParams.h" + + +using namespace DIRECTORY::PROGRAMDATABASEDIRECTORY; + + +CQueryParams::CQueryParams() +{ + m_idGame = -1; + m_idGenre = -1; + m_idYear = -1; + m_idDeveloper = -1; + m_idContent = -1; + m_idPublisher = -1; + m_idPlatform = -1; +} + + +void CQueryParams::SetQueryParam(NODE_TYPE NodeType, const CStdString& strNodeName) +{ + long idDb = atol(strNodeName.c_str()); + + switch (NodeType) + { + case NODE_TYPE_OVERVIEW: + m_idContent = idDb; + break; + case NODE_TYPE_GENRE: + m_idGenre = idDb; + break; + case NODE_TYPE_YEAR: + m_idYear = idDb; + break; + case NODE_TYPE_DEVELOPER: + m_idDeveloper = idDb; + break; + case NODE_TYPE_TITLE_GAMES: + m_idGame = idDb; + break; + case NODE_TYPE_PUBLISHER: + m_idPublisher = idDb; + break; + case NODE_TYPE_PLATFORM: + m_idPlatform = idDb; + break; + default: + break; + } +} Index: xbmc/FileSystem/ProgramDatabaseDirectory/QueryParams.h =================================================================== --- xbmc/FileSystem/ProgramDatabaseDirectory/QueryParams.h (revision 0) +++ xbmc/FileSystem/ProgramDatabaseDirectory/QueryParams.h (revision 0) @@ -0,0 +1,54 @@ +#pragma once +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "DirectoryNode.h" + +namespace DIRECTORY +{ + namespace PROGRAMDATABASEDIRECTORY + { + class CQueryParams + { + public: + CQueryParams(); + long GetContentType() const { return m_idContent; } + long GetGameId() const { return m_idGame; } + long GetYear() const { return m_idYear; } + long GetGenreId() const { return m_idGenre; } + long GetDeveloperId() const { return m_idDeveloper; } + long GetPublisherId() const { return m_idPublisher; } + + protected: + void SetQueryParam(NODE_TYPE NodeType, const CStdString& strNodeName); + + friend class CDirectoryNode; + private: + long m_idContent; + long m_idGame; + long m_idGenre; + long m_idYear; + long m_idDeveloper; + long m_idPublisher; + long m_idPlatform; + }; + } +} Index: xbmc/GUIDialogContentSettings.cpp =================================================================== --- xbmc/GUIDialogContentSettings.cpp (revision 24004) +++ xbmc/GUIDialogContentSettings.cpp (working copy) @@ -26,6 +26,7 @@ #include "VideoDatabase.h" #include "ProgramDatabase.h" #include "VideoInfoScanner.h" +#include "ProgramInfoScanner.h" #include "FileSystem/Directory.h" #include "FileSystem/MultiPathDirectory.h" #include "GUIWindowManager.h" @@ -96,40 +97,47 @@ CStdString strLabel; switch (iSelected) { - case 0: m_info.strContent.Empty(); - m_info.strPath.Empty(); - m_info.strThumb.Empty(); - m_info.strTitle.Empty(); - OnSettingChanged(0); - SetupPage(); - break; - case 1: strLabel = g_localizeStrings.Get(20342); - m_info = FindDefault("movies", g_guiSettings.GetString("scrapers.moviedefault")); - CreateSettings(); - SetupPage(); - break; - case 2: strLabel = g_localizeStrings.Get(20343); - m_info = FindDefault("tvshows", g_guiSettings.GetString("scrapers.tvshowdefault")); - CreateSettings(); - SetupPage(); - break; - case 3: strLabel = g_localizeStrings.Get(20389); - m_info = FindDefault("musicvideos", g_guiSettings.GetString("scrapers.musicvideodefault")); - CreateSettings(); - SetupPage(); - break; - case 4: strLabel = g_localizeStrings.Get(132); - m_info = FindDefault("albums", g_guiSettings.GetString("musiclibrary.defaultscraper")); - CreateSettings(); - SetupPage(); - break; - case 5: strLabel = g_localizeStrings.Get(350); - m_info = FindDefault("programs", g_guiSettings.GetString("programfiles.defaultscraper")); - CreateSettings(); - SetupPage(); - break; + case 0: + m_info.strContent.Empty(); + m_info.strPath.Empty(); + m_info.strThumb.Empty(); + m_info.strTitle.Empty(); + OnSettingChanged(0); + SetupPage(); + break; + case 1: + strLabel = g_localizeStrings.Get(20342); + m_info = FindDefault("movies", g_guiSettings.GetString("scrapers.moviedefault")); + CreateSettings(); + SetupPage(); + break; + case 2: + strLabel = g_localizeStrings.Get(20343); + m_info = FindDefault("tvshows", g_guiSettings.GetString("scrapers.tvshowdefault")); + CreateSettings(); + SetupPage(); + break; + case 3: + strLabel = g_localizeStrings.Get(20389); + m_info = FindDefault("musicvideos", g_guiSettings.GetString("scrapers.musicvideodefault")); + CreateSettings(); + SetupPage(); + break; + case 4: + strLabel = g_localizeStrings.Get(132); + m_info = FindDefault("albums", g_guiSettings.GetString("musiclibrary.defaultscraper")); + CreateSettings(); + SetupPage(); + break; + case 5: + strLabel = g_localizeStrings.Get(350); + m_info = FindDefault("games", g_guiSettings.GetString("programscrapers.gamedefault")); + CreateSettings(); + SetupPage(); + break; } } + if (iControl == CONTROL_SCRAPER_LIST) { CGUIMessage msg(GUI_MSG_ITEM_SELECTED,GetID(),CONTROL_SCRAPER_LIST); @@ -140,20 +148,35 @@ FillListControl(); SET_CONTROL_FOCUS(30,0); } + if (iControl == CONTROL_SCRAPER_SETTINGS) { - if (m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/video/"+m_info.strPath)) + if (m_info.strContent.Equals("games")) { + if (m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/programs/" + m_info.strPath)) + { + CGUIDialogPluginSettings::ShowAndGetInput(m_info); + m_bNeedSave = true; + return true; + } + } + else if (m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/video/"+m_info.strPath)) + { CGUIDialogPluginSettings::ShowAndGetInput(m_info); m_bNeedSave = true; return true; } return false; } + CScraperParser parser; CStdString strPath; - if (!m_info.strContent.IsEmpty()) - strPath="special://xbmc/system/scrapers/video/"+m_info.strPath; + + if (!m_info.strContent.IsEmpty() && m_info.strContent.Equals("games")) + strPath = "special://xbmc/system/scrapers/programs/"+m_info.strPath; + else if (!m_info.strContent.IsEmpty()) + strPath = "special://xbmc/system/scrapers/video/"+m_info.strPath; + if (!strPath.IsEmpty() && parser.Load(strPath) && parser.HasFunction("GetSettings")) CONTROL_ENABLE(CONTROL_SCRAPER_SETTINGS); else @@ -170,10 +193,12 @@ CFileItemList items; if (m_info.strContent.Equals("albums")) CDirectory::GetDirectory("special://xbmc/system/scrapers/music/",items,".xml",false); - else if (m_info.strContent.Equals("programs")) + else + { CDirectory::GetDirectory("special://xbmc/system/scrapers/programs/",items,".xml",false); - else CDirectory::GetDirectory("special://xbmc/system/scrapers/video/",items,".xml",false); + } + for (int i=0;im_bIsFolder) @@ -183,9 +208,9 @@ if (doc.RootElement()) { bool IsDefaultScraper = false; - const char* content = doc.RootElement()->Attribute("content"); - const char* name = doc.RootElement()->Attribute("name"); - const char* thumb = doc.RootElement()->Attribute("thumb"); + const char* content = doc.RootElement()->Attribute("content"); + const char* name = doc.RootElement()->Attribute("name"); + const char* thumb = doc.RootElement()->Attribute("thumb"); if (content && name) { SScraperInfo info; @@ -196,7 +221,7 @@ info.strContent = content; info.settings = m_scraperSettings; - if ( info.strPath == g_guiSettings.GetString("programfiles.defaultscraper") + if ( info.strPath == g_guiSettings.GetString("programscrapers.gamedefault") || info.strPath == g_guiSettings.GetString("musiclibrary.defaultscraper") || info.strPath == g_guiSettings.GetString("scrapers.moviedefault") || info.strPath == g_guiSettings.GetString("scrapers.tvshowdefault") @@ -243,7 +268,9 @@ CScraperParser parser; CStdString strPath; - if (!m_info.strContent.IsEmpty()) + if (!m_info.strContent.IsEmpty() && m_info.strContent.Equals("games")) + strPath="special://xbmc/system/scrapers/programs/"+m_info.strPath; + else if (!m_info.strContent.IsEmpty()) strPath="special://xbmc/system/scrapers/video/"+m_info.strPath; if (!strPath.IsEmpty() && parser.Load(strPath) && parser.HasFunction("GetSettings")) CONTROL_ENABLE(CONTROL_SCRAPER_SETTINGS); @@ -310,15 +337,15 @@ CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 3); } } - if (m_scrapers.find("programs") != m_scrapers.end()) + if (m_scrapers.find("games") != m_scrapers.end()) { msg2.SetLabel(m_strContentType); msg2.SetParam1(5); g_graphicsContext.SendMessage(msg2); - if (m_info.strContent.Equals("programs")) + if (m_info.strContent.Equals("games")) { SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,m_strContentType); - CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 3); + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 4); } } @@ -372,9 +399,11 @@ { AddBool(1,20345,&m_bRunScan); } - if (m_info.strContent.Equals("programs")) + if (m_info.strContent.Equals("games")) { AddBool(1,20345,&m_bRunScan); + AddBool(3,20346,&m_bScanRecursive); + AddBool(5,20432,&m_bUpdate); } } @@ -427,7 +456,7 @@ item->m_strPath = iter->strPath; if (m_info.strContent.Equals("albums")) item->SetThumbnailImage("special://xbmc/system/scrapers/music/"+iter->strThumb); - else if (m_info.strContent.Equals("programs")) + else if (m_info.strContent.Equals("games")) item->SetThumbnailImage("special://xbmc/system/scrapers/programs/"+iter->strThumb); else item->SetThumbnailImage("special://xbmc/system/scrapers/video/"+iter->strThumb); @@ -469,26 +498,27 @@ database.Open(); int iFound; database.GetScraperForPath(strDirectory,scraper,settings, iFound); - bool bResult = Show(scraper,settings,bRunScan); + bool bResult = Show(scraper, settings, bRunScan); if (bResult) database.SetScraperForPath(strDirectory,scraper,settings); return bResult; } -bool CGUIDialogContentSettings::ShowForProgramsDirectory(const CStdString& strDirectory, SScraperInfo& scraper, bool& bRunScan) +bool CGUIDialogContentSettings::ShowForProgramDirectory(const CStdString& strDirectory, SScraperInfo& scraper, PROGRAM::SScanSettings& settings, bool& bRunScan) { CProgramDatabase database; database.Open(); - if (!database.GetScraperForPath(strDirectory,scraper)) - scraper.strContent = "programs"; - bool bResult = Show(scraper,bRunScan); + int iFound; + database.GetScraperForPath(strDirectory, scraper, settings, iFound); + bool bResult = Show(scraper, settings, bRunScan); if (bResult) - database.SetScraperForPath(strDirectory,scraper); + database.SetScraperForPath(strDirectory, scraper, settings); return bResult; } + bool CGUIDialogContentSettings::Show(SScraperInfo& scraper, bool& bRunScan, int iLabel) { VIDEO::SScanSettings dummy; @@ -509,7 +539,7 @@ dialog->m_strContentType = g_localizeStrings.Get(iLabel); dialog->m_scraperSettings = scraper.settings; - dialog->m_bRunScan = bRunScan; + dialog->m_bRunScan = bRunScan; dialog->m_bScanRecursive = (settings.recurse > 0 && !settings.parent_name) || (settings.recurse > 1 && settings.parent_name); dialog->m_bUseDirNames = settings.parent_name; dialog->m_bExclude = scraper.strContent.Equals("None"); @@ -565,10 +595,6 @@ { bRunScan = dialog->m_bRunScan; } - else if (scraper.strContent.Equals("programs")) - { - bRunScan = dialog->m_bRunScan; - } else if (scraper.strContent.IsEmpty() || scraper.strContent.Equals("None") ) { if (dialog->m_bExclude) @@ -590,6 +616,87 @@ return false; } + + + +bool CGUIDialogContentSettings::Show(SScraperInfo& scraper, PROGRAM::SScanSettings& settings, bool& bRunScan, int iLabel) +{ + CGUIDialogContentSettings *dialog = (CGUIDialogContentSettings *)m_gWindowManager.GetWindow(WINDOW_DIALOG_CONTENT_SETTINGS); + if (!dialog) + return false; + + dialog->m_info = scraper; + if (iLabel != -1) + dialog->m_strContentType = g_localizeStrings.Get(iLabel); + + dialog->m_scraperSettings = scraper.settings; + dialog->m_bRunScan = bRunScan; + dialog->m_bScanRecursive = (settings.recurse > 0 && !settings.parent_name) || (settings.recurse > 1 && settings.parent_name); + dialog->m_bUseDirNames = settings.parent_name; + dialog->m_bExclude = scraper.strContent.Equals("None"); + dialog->m_bSingleItem = settings.parent_name_root; + dialog->m_bNeedSave = false; + dialog->m_bUpdate = settings.noupdate; + dialog->DoModal(); + + if (dialog->m_bNeedSave) + { + scraper = dialog->m_info; + settings.noupdate = dialog->m_bUpdate; + + if (scraper.strContent.Equals("games")) + { + if (dialog->m_bUseDirNames) + { + settings.parent_name = true; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 1; + + if (dialog->m_bSingleItem) + { + settings.parent_name_root = true; + settings.recurse = 0; + } + } + else + { + settings.parent_name = false; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 0; + } + + bRunScan = dialog->m_bRunScan; + } + + else if (scraper.strContent.IsEmpty() || + scraper.strContent.Equals("None") ) + { + if (dialog->m_bExclude) + scraper.strContent = "None"; + else + scraper.strContent = ""; + bRunScan = false; + } + + if (!scraper.strContent.IsEmpty() + && !scraper.strContent.Equals("None") + && (!scraper.settings.GetPluginRoot() + || scraper.settings.GetSettings().IsEmpty())) + { + // load default scraper settings + scraper.settings.LoadSettingsXML( + "special://xbmc/system/scrapers/programs/" + scraper.strPath + ); + scraper.settings.SaveFromDefault(); + } + + return true; + } + return false; +} + + + SScraperInfo CGUIDialogContentSettings::FindDefault(const CStdString& strType, const CStdString& strDefault) { SScraperInfo result = m_scrapers[strType][0]; // default to first Index: xbmc/GUIDialogContentSettings.cppbck.cpp =================================================================== --- xbmc/GUIDialogContentSettings.cppbck.cpp (revision 0) +++ xbmc/GUIDialogContentSettings.cppbck.cpp (revision 0) @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "GUIDialogContentSettings.h" +#include "GUIDialogPluginSettings.h" +#include "Util.h" +#include "VideoDatabase.h" +#include "ProgramDatabase.h" +#include "VideoInfoScanner.h" +#include "ProgramInfoScanner.h" +#include "FileSystem/Directory.h" +#include "FileSystem/MultiPathDirectory.h" +#include "GUIWindowManager.h" +#include "utils/ScraperParser.h" +#include "FileItem.h" +#include "GUISettings.h" +#include "LocalizeStrings.h" + +#define CONTROL_CONTENT_TYPE 3 +#define CONTROL_SCRAPER_LIST 4 +#define CONTROL_SCRAPER_SETTINGS 6 +#define CONTROL_START 30 + +using namespace DIRECTORY; +using namespace std; + +CGUIDialogContentSettings::CGUIDialogContentSettings(void) + : CGUIDialogSettings(WINDOW_DIALOG_CONTENT_SETTINGS, "DialogContentSettings.xml") +{ + m_bNeedSave = false; + m_vecItems = new CFileItemList; +} + +CGUIDialogContentSettings::~CGUIDialogContentSettings(void) +{ + delete m_vecItems; +} + +bool CGUIDialogContentSettings::OnMessage(CGUIMessage &message) +{ + switch (message.GetMessage()) + { + case GUI_MSG_WINDOW_DEINIT: + { + m_scrapers.clear(); + m_vecItems->Clear(); + CGUIDialogSettings::OnMessage(message); + } + break; + + case GUI_MSG_ITEM_SELECT: + { + if (message.GetControlId() == CONTROL_SCRAPER_LIST) + { + if (!m_info.strContent.IsEmpty()) + m_info = m_scrapers[m_info.strContent][message.GetParam1()]; + } + } + break; + + case GUI_MSG_CLICKED: + int iControl = message.GetSenderId(); + if (iControl == 500) + Close(); + if (iControl == 501) + { + m_bNeedSave = false; + Close(); + } + + if (iControl == CONTROL_CONTENT_TYPE) + { + CGUIMessage msg(GUI_MSG_ITEM_SELECTED,GetID(),CONTROL_CONTENT_TYPE); + m_gWindowManager.SendMessage(msg); + int iSelected = msg.GetParam1(); + + m_bNeedSave = true; + CStdString strLabel; + switch (iSelected) + { + case 0: m_info.strContent.Empty(); + m_info.strPath.Empty(); + m_info.strThumb.Empty(); + m_info.strTitle.Empty(); + OnSettingChanged(0); + SetupPage(); + break; + case 1: strLabel = g_localizeStrings.Get(20342); + m_info = FindDefault("movies", g_guiSettings.GetString("scrapers.moviedefault")); + CreateSettings(); + SetupPage(); + break; + case 2: strLabel = g_localizeStrings.Get(20343); + m_info = FindDefault("tvshows", g_guiSettings.GetString("scrapers.tvshowdefault")); + CreateSettings(); + SetupPage(); + break; + case 3: strLabel = g_localizeStrings.Get(20389); + m_info = FindDefault("musicvideos", g_guiSettings.GetString("scrapers.musicvideodefault")); + CreateSettings(); + SetupPage(); + break; + case 4: strLabel = g_localizeStrings.Get(132); + m_info = FindDefault("albums", g_guiSettings.GetString("musiclibrary.defaultscraper")); + CreateSettings(); + SetupPage(); + break; + case 5: strLabel = g_localizeStrings.Get(350); + m_info = FindDefault("games", g_guiSettings.GetString("programscrapers.gamedefault")); + CreateSettings(); + SetupPage(); + break; + } + } + if (iControl == CONTROL_SCRAPER_LIST) + { + CGUIMessage msg(GUI_MSG_ITEM_SELECTED,GetID(),CONTROL_SCRAPER_LIST); + m_gWindowManager.SendMessage(msg); + int iSelected = msg.GetParam1(); + + m_info = m_scrapers[m_info.strContent][iSelected]; + FillListControl(); + SET_CONTROL_FOCUS(30,0); + } + if (iControl == CONTROL_SCRAPER_SETTINGS) + { + if (m_info.strContent.Equals("games")) + { + if (m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/programs/"+m_info.strPath)) + { + CGUIDialogPluginSettings::ShowAndGetInput(m_info); + m_bNeedSave = true; + return true; + } + } + else if (m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/video/"+m_info.strPath)) + { + CGUIDialogPluginSettings::ShowAndGetInput(m_info); + m_bNeedSave = true; + return true; + } + return false; + } + CScraperParser parser; + CStdString strPath; + if (!m_info.strContent.IsEmpty() && m_info.strContent.Equals("games")) + strPath = "special://xbmc/system/scrapers/programs/"+m_info.strPath; + else if (!m_info.strContent.IsEmpty()) + strPath = "special://xbmc/system/scrapers/video/"+m_info.strPath; + if (!strPath.IsEmpty() && parser.Load(strPath) && parser.HasFunction("GetSettings")) + CONTROL_ENABLE(CONTROL_SCRAPER_SETTINGS); + else + CONTROL_DISABLE(CONTROL_SCRAPER_SETTINGS); + break; + } + return CGUIDialogSettings::OnMessage(message); +} + +void CGUIDialogContentSettings::OnWindowLoaded() +{ + CGUIDialogSettings::OnWindowLoaded(); + + CFileItemList items; + if (m_info.strContent.Equals("albums")) + CDirectory::GetDirectory("special://xbmc/system/scrapers/music/",items,".xml",false); + else if (m_info.strContent.Equals("games")) + CDirectory::GetDirectory("special://xbmc/system/scrapers/programs/",items,".xml",false); + else{ + CDirectory::GetDirectory("special://xbmc/system/scrapers/video/",items,".xml",false); + CDirectory::GetDirectory("special://xbmc/system/scrapers/programs/",items,".xml",false); + } + for (int i=0;im_bIsFolder) + { + TiXmlDocument doc; + doc.LoadFile(items[i]->m_strPath); + if (doc.RootElement()) + { + bool IsDefaultScraper = false; + const char* content = doc.RootElement()->Attribute("content"); + const char* name = doc.RootElement()->Attribute("name"); + const char* thumb = doc.RootElement()->Attribute("thumb"); + if (content && name) + { + SScraperInfo info; + info.strTitle = name; + info.strPath = CUtil::GetFileName(items[i]->m_strPath); + if (thumb) + info.strThumb = thumb; + info.strContent = content; + info.settings = m_scraperSettings; + + if ( info.strPath == g_guiSettings.GetString("programscrapers.gamedefault") + || info.strPath == g_guiSettings.GetString("musiclibrary.defaultscraper") + || info.strPath == g_guiSettings.GetString("scrapers.moviedefault") + || info.strPath == g_guiSettings.GetString("scrapers.tvshowdefault") + || info.strPath == g_guiSettings.GetString("scrapers.musicvideodefault")) + { + IsDefaultScraper = true; + } + + map >::iterator iter=m_scrapers.find(content); + if (iter != m_scrapers.end()) + { + if (IsDefaultScraper) + iter->second.insert(iter->second.begin(),info); + else + iter->second.push_back(info); + } + else + { + vector vec; + vec.push_back(info); + m_scrapers.insert(make_pair(content,vec)); + } + } + } + } + } + + // now select the correct scraper + if (!m_info.strContent.IsEmpty()) + { + map >::iterator iter = m_scrapers.find(m_info.strContent); + if (iter != m_scrapers.end()) + { + for (vector::iterator iter2 = iter->second.begin();iter2 != iter->second.end();++iter2) + { + if (iter2->strPath == m_info.strPath) + { + m_info = *iter2; + break; + } + } + } + } + + CScraperParser parser; + CStdString strPath; + if (!m_info.strContent.IsEmpty() && m_info.strContent.Equals("games")) + strPath="special://xbmc/system/scrapers/programs/"+m_info.strPath; + else if (!m_info.strContent.IsEmpty()) + strPath="special://xbmc/system/scrapers/video/"+m_info.strPath; + if (!strPath.IsEmpty() && parser.Load(strPath) && parser.HasFunction("GetSettings")) + CONTROL_ENABLE(CONTROL_SCRAPER_SETTINGS); + else + CONTROL_DISABLE(CONTROL_SCRAPER_SETTINGS); +} + +void CGUIDialogContentSettings::SetupPage() +{ + CGUIDialogSettings::SetupPage(); + + CGUIMessage msg(GUI_MSG_LABEL_RESET,GetID(),CONTROL_CONTENT_TYPE); + g_graphicsContext.SendMessage(msg); + CGUIMessage msg2(GUI_MSG_LABEL_ADD,GetID(),CONTROL_CONTENT_TYPE); + + if (!m_info.strContent.Equals("albums")) // none does not apply to music + { + msg2.SetLabel("<"+g_localizeStrings.Get(231)+">"); + msg2.SetParam1(0); + g_graphicsContext.SendMessage(msg2); + } + + if (m_scrapers.find("movies") != m_scrapers.end()) + { + msg2.SetLabel(g_localizeStrings.Get(20342)); + msg2.SetParam1(1); + g_graphicsContext.SendMessage(msg2); + if (m_info.strContent.Equals("movies")) + { + SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,g_localizeStrings.Get(20342)); + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 1); + } + } + + if (m_scrapers.find("tvshows") != m_scrapers.end()) + { + msg2.SetLabel(g_localizeStrings.Get(20343)); + msg2.SetParam1(2); + g_graphicsContext.SendMessage(msg2); + if (m_info.strContent.Equals("tvshows")) + { + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 2); + } + } + if (m_scrapers.find("musicvideos") != m_scrapers.end()) + { + msg2.SetLabel(g_localizeStrings.Get(20389)); + msg2.SetParam1(3); + g_graphicsContext.SendMessage(msg2); + if (m_info.strContent.Equals("musicvideos")) + { + SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,g_localizeStrings.Get(20389)); + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 3); + } + } + if (m_scrapers.find("albums") != m_scrapers.end()) + { + msg2.SetLabel(m_strContentType); + msg2.SetParam1(4); + g_graphicsContext.SendMessage(msg2); + if (m_info.strContent.Equals("albums")) + { + SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,m_strContentType); + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 3); + } + } + if (m_scrapers.find("games") != m_scrapers.end()) + { + msg2.SetLabel(m_strContentType); + msg2.SetParam1(5); + g_graphicsContext.SendMessage(msg2); + if (m_info.strContent.Equals("games")) + { + SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,m_strContentType); + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 3); + } + } + + SET_CONTROL_VISIBLE(CONTROL_CONTENT_TYPE); + // now add them scrapers to the list control + if (m_info.strContent.IsEmpty() || m_info.strContent.Equals("None")) + { + CGUIMessage msgReset(GUI_MSG_LABEL_RESET, GetID(), CONTROL_SCRAPER_LIST); + OnMessage(msgReset); + CONTROL_DISABLE(CONTROL_SCRAPER_LIST); + } + else + { + CONTROL_ENABLE(CONTROL_SCRAPER_LIST); + FillListControl(); + } + + OnSettingChanged(0); +} + +void CGUIDialogContentSettings::CreateSettings() +{ + // clear out any old settings + m_settings.clear(); + + if (m_info.strContent.IsEmpty() || m_info.strContent.Equals("None")) + { + AddBool(1,20380,&m_bExclude); + } + if (m_info.strContent.Equals("movies")) + { + AddBool(1,20345,&m_bRunScan); + AddBool(2,20330,&m_bUseDirNames); + AddBool(3,20346,&m_bScanRecursive); + AddBool(4,20383,&m_bSingleItem, m_bUseDirNames); + AddBool(5,20432,&m_bUpdate); + } + if (m_info.strContent.Equals("tvshows")) + { + AddBool(1,20345,&m_bRunScan); + AddBool(2,20379,&m_bSingleItem); + AddBool(3,20432,&m_bUpdate); + } + if (m_info.strContent.Equals("musicvideos")) + { + AddBool(1,20345,&m_bRunScan); + AddBool(2,20346,&m_bScanRecursive); + AddBool(3,20432,&m_bUpdate); + } + if (m_info.strContent.Equals("albums")) + { + AddBool(1,20345,&m_bRunScan); + } + if (m_info.strContent.Equals("games")) + { + AddBool(1,20345,&m_bRunScan); + AddBool(3,20346,&m_bScanRecursive); + AddBool(5,20432,&m_bUpdate); + } +} + +void CGUIDialogContentSettings::OnSettingChanged(unsigned int num) +{ + // setting has changed - update anything that needs it + if (num >= m_settings.size()) return; + SettingInfo &setting = m_settings.at(num); + OnSettingChanged(setting); +} + +void CGUIDialogContentSettings::OnSettingChanged(SettingInfo &setting) +{ + // check and update anything that needs it + if (setting.id == 1 || setting.id == 2) + { + CreateSettings(); + UpdateSetting(1); + UpdateSetting(2); + UpdateSetting(3); + UpdateSetting(4); + UpdateSetting(5); + } + + m_bNeedSave = true; +} + +void CGUIDialogContentSettings::OnCancel() +{ + m_bNeedSave = false; +} + +void CGUIDialogContentSettings::OnInitWindow() +{ + m_bNeedSave = false; + + CGUIDialogSettings::OnInitWindow(); + SET_CONTROL_FOCUS(CONTROL_CONTENT_TYPE,0); +} + +void CGUIDialogContentSettings::FillListControl() +{ + CGUIMessage msgReset(GUI_MSG_LABEL_RESET, GetID(), CONTROL_SCRAPER_LIST); + OnMessage(msgReset); + int iIndex=0; + m_vecItems->Clear(); + for (vector::iterator iter=m_scrapers.find(m_info.strContent)->second.begin();iter!=m_scrapers.find(m_info.strContent)->second.end();++iter) + { + CFileItemPtr item(new CFileItem(iter->strTitle)); + item->m_strPath = iter->strPath; + if (m_info.strContent.Equals("albums")) + item->SetThumbnailImage("special://xbmc/system/scrapers/music/"+iter->strThumb); + else if (m_info.strContent.Equals("games")) + item->SetThumbnailImage("special://xbmc/system/scrapers/programs/"+iter->strThumb); + else + item->SetThumbnailImage("special://xbmc/system/scrapers/video/"+iter->strThumb); + if (iter->strPath.Equals(m_info.strPath)) + { + CGUIMessage msg2(GUI_MSG_ITEM_SELECT, GetID(), CONTROL_SCRAPER_LIST, iIndex); + OnMessage(msg2); + item->Select(true); + } + m_vecItems->Add(item); + CGUIMessage msg(GUI_MSG_LABEL_ADD, GetID(), CONTROL_SCRAPER_LIST, 0, 0, item); + OnMessage(msg); + iIndex++; + } +} + +CFileItemPtr CGUIDialogContentSettings::GetCurrentListItem(int offset) +{ + int currentItem = -1; + if( m_info.strContent.IsEmpty()) + return CFileItemPtr(); + for (int i=0;iSize();++i ) + { + if (m_vecItems->Get(i)->IsSelected()) + { + currentItem = i; + break; + } + } + if (currentItem == -1) return CFileItemPtr(); + int item = (currentItem + offset) % m_vecItems->Size(); + if (item < 0) item += m_vecItems->Size(); + return m_vecItems->Get(item); +} + +bool CGUIDialogContentSettings::ShowForVideoDirectory(const CStdString& strDirectory, SScraperInfo& scraper, VIDEO::SScanSettings& settings, bool& bRunScan) +{ + CVideoDatabase database; + database.Open(); + int iFound; + database.GetScraperForPath(strDirectory,scraper,settings, iFound); + bool bResult = Show(scraper, settings, bRunScan); + if (bResult) + database.SetScraperForPath(strDirectory,scraper,settings); + + return bResult; +} + +bool CGUIDialogContentSettings::ShowForProgramDirectory(const CStdString& strDirectory, SScraperInfo& scraper, PROGRAM::SScanSettings& settings, bool& bRunScan) +{ + CProgramDatabase database; + database.Open(); + int iFound; + database.GetScraperForPath(strDirectory,scraper,settings, iFound); + bool bResult = Show(scraper,settings,bRunScan); + if (bResult) + database.SetScraperForPath(strDirectory,scraper,settings); + + return bResult; +} + + +bool CGUIDialogContentSettings::Show(SScraperInfo& scraper, bool& bRunScan, int iLabel) +{ + VIDEO::SScanSettings dummy; + dummy.recurse = -1; + dummy.parent_name = false; + dummy.parent_name_root = false; + dummy.noupdate = false; + return Show(scraper,dummy,bRunScan,iLabel); +} + +bool CGUIDialogContentSettings::Show(SScraperInfo& scraper, VIDEO::SScanSettings& settings, bool& bRunScan, int iLabel) +{ + CGUIDialogContentSettings *dialog = (CGUIDialogContentSettings *)m_gWindowManager.GetWindow(WINDOW_DIALOG_CONTENT_SETTINGS); + if (!dialog) return false; + + dialog->m_info = scraper; + if (iLabel != -1) // to switch between albums and artists + dialog->m_strContentType = g_localizeStrings.Get(iLabel); + + dialog->m_scraperSettings = scraper.settings; + dialog->m_bRunScan = bRunScan; + dialog->m_bScanRecursive = (settings.recurse > 0 && !settings.parent_name) || (settings.recurse > 1 && settings.parent_name); + dialog->m_bUseDirNames = settings.parent_name; + dialog->m_bExclude = scraper.strContent.Equals("None"); + dialog->m_bSingleItem = settings.parent_name_root; + dialog->m_bNeedSave = false; + dialog->m_bUpdate = settings.noupdate; + dialog->DoModal(); + if (dialog->m_bNeedSave) + { + scraper = dialog->m_info; + settings.noupdate = dialog->m_bUpdate; + + if (scraper.strContent.Equals("tvshows")) + { + settings.parent_name = dialog->m_bSingleItem; + settings.parent_name_root = dialog->m_bSingleItem; + settings.recurse = 0; + + bRunScan = dialog->m_bRunScan; + } + else if (scraper.strContent.Equals("movies")) + { + if (dialog->m_bUseDirNames) + { + settings.parent_name = true; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 1; + + if (dialog->m_bSingleItem) + { + settings.parent_name_root = true; + settings.recurse = 0; + } + } + else + { + settings.parent_name = false; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 0; + } + + bRunScan = dialog->m_bRunScan; + } + else if (scraper.strContent.Equals("musicvideos")) + { + settings.parent_name = false; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 0; + + bRunScan = dialog->m_bRunScan; + } + else if (scraper.strContent.Equals("albums")) + { + bRunScan = dialog->m_bRunScan; + } + else if (scraper.strContent.Equals("programs")) + { + bRunScan = dialog->m_bRunScan; + } + else if (scraper.strContent.IsEmpty() || scraper.strContent.Equals("None") ) + { + if (dialog->m_bExclude) + scraper.strContent = "None"; + else + scraper.strContent = ""; + + bRunScan = false; + } + + if (!scraper.strContent.IsEmpty() && !scraper.strContent.Equals("None") && (!scraper.settings.GetPluginRoot() || scraper.settings.GetSettings().IsEmpty())) + { // load default scraper settings + scraper.settings.LoadSettingsXML("special://xbmc/system/scrapers/video/"+scraper.strPath); + scraper.settings.SaveFromDefault(); + } + + return true; + } + return false; +} + + + + +bool CGUIDialogContentSettings::Show(SScraperInfo& scraper, PROGRAM::SScanSettings& settings, bool& bRunScan, int iLabel) +{ + CGUIDialogContentSettings *dialog = (CGUIDialogContentSettings *)m_gWindowManager.GetWindow(WINDOW_DIALOG_CONTENT_SETTINGS); + if (!dialog) return false; + + dialog->m_info = scraper; + if (iLabel != -1) dialog->m_strContentType = g_localizeStrings.Get(iLabel); + + dialog->m_scraperSettings = scraper.settings; + dialog->m_bRunScan = bRunScan; + dialog->m_bScanRecursive = (settings.recurse > 0 && !settings.parent_name) || (settings.recurse > 1 && settings.parent_name); + dialog->m_bUseDirNames = settings.parent_name; + dialog->m_bExclude = scraper.strContent.Equals("None"); + dialog->m_bSingleItem = settings.parent_name_root; + dialog->m_bNeedSave = false; + dialog->m_bUpdate = settings.noupdate; + dialog->DoModal(); + + if (dialog->m_bNeedSave) { + scraper = dialog->m_info; + settings.noupdate = dialog->m_bUpdate; + + if (scraper.strContent.Equals("games")) { + if (dialog->m_bUseDirNames) { + settings.parent_name = true; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 1; + + if (dialog->m_bSingleItem) { + settings.parent_name_root = true; + settings.recurse = 0; + } + } + else { + settings.parent_name = false; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 0; + } + + bRunScan = dialog->m_bRunScan; + } + + else if (scraper.strContent.IsEmpty() || scraper.strContent.Equals("None") ) { + if (dialog->m_bExclude) scraper.strContent = "None"; + else scraper.strContent = ""; + bRunScan = false; + } + + if (!scraper.strContent.IsEmpty() + && !scraper.strContent.Equals("None") + && (!scraper.settings.GetPluginRoot() + || scraper.settings.GetSettings().IsEmpty())) { + + // load default scraper settings + scraper.settings.LoadSettingsXML("special://xbmc/system/scrapers/program/"+scraper.strPath); + scraper.settings.SaveFromDefault(); + } + + return true; + } + return false; +} + + + +SScraperInfo CGUIDialogContentSettings::FindDefault(const CStdString& strType, const CStdString& strDefault) +{ + SScraperInfo result = m_scrapers[strType][0]; // default to first + for (unsigned int i=0;iInitialize(); dialog->SetShare(CMediaSource()); dialog->SetTypeOfMedia(type); dialog->DoModal(); + bool confirmed(dialog->IsConfirmed()); if (confirmed) - { // yay, add this share - CMediaSource share; - unsigned int i,j=2; - bool bConfirmed=false; - VECSOURCES* pShares = g_settings.GetSourcesFromType(type); - CStdString strName = dialog->m_name; + { + // yay, add this share + CMediaSource share; + unsigned int i, j = 2; + bool bConfirmed = false; + VECSOURCES* pShares = g_settings.GetSourcesFromType(type); + CStdString strName = dialog->m_name; + while (!bConfirmed) { for (i=0;isize();++i) @@ -161,23 +170,31 @@ if ((*pShares)[i].strName.Equals(strName)) break; } + if (i < pShares->size()) // found a match - try next strName.Format("%s (%i)",dialog->m_name,j++); else bConfirmed = true; } + share.FromNameAndPaths(type, strName, dialog->GetPaths()); + if (dialog->m_paths->Size() > 0) { share.m_strThumbnailImage = dialog->m_paths->Get(0)->GetThumbnailImage(); } + g_settings.AddShare(type, share); if (type == "video") { if (dialog->m_bRunScan) - CGUIWindowVideoBase::OnScan(share.strPath,dialog->m_info,dialog->m_settings); - + CGUIWindowVideoBase::OnScan(share.strPath, dialog->m_info, dialog->m_settings); } + else if (type == "programs") + { + if (dialog->m_bRunScan) + CGUIWindowProgramBase::OnScan(share.strPath, dialog->m_info, dialog->m_psettings); + } } dialog->m_paths->Clear(); return confirmed; @@ -185,7 +202,7 @@ bool CGUIDialogMediaSource::ShowAndEditMediaSource(const CStdString &type, const CStdString&share) { - VECSOURCES* pShares=NULL; + VECSOURCES* pShares = NULL; if (type.Equals("upnpmusic")) pShares = &g_settings.m_UPnPMusicSources; @@ -208,20 +225,26 @@ bool CGUIDialogMediaSource::ShowAndEditMediaSource(const CStdString &type, const CMediaSource &share) { - CStdString strOldName = share.strName; - CGUIDialogMediaSource *dialog = (CGUIDialogMediaSource *)m_gWindowManager.GetWindow(WINDOW_DIALOG_MEDIA_SOURCE); - if (!dialog) return false; + CStdString strOldName = share.strName; + CGUIDialogMediaSource *dialog = \ + (CGUIDialogMediaSource *)m_gWindowManager.GetWindow(WINDOW_DIALOG_MEDIA_SOURCE); + + if (!dialog) + return false; + dialog->Initialize(); dialog->SetShare(share); dialog->SetTypeOfMedia(type, true); dialog->DoModal(); + bool confirmed(dialog->IsConfirmed()); if (confirmed) { // yay, add this share - unsigned int i,j=2; - bool bConfirmed=false; - VECSOURCES* pShares = g_settings.GetSourcesFromType(type); - CStdString strName = dialog->m_name; + unsigned int i, j = 2; + bool bConfirmed = false; + VECSOURCES *pShares = g_settings.GetSourcesFromType(type); + CStdString strName = dialog->m_name; + while (!bConfirmed) { for (i=0;isize();++i) @@ -249,7 +272,7 @@ // Browse is called. Open the filebrowser dialog. // Ignore current path is best at this stage?? CStdString path; - bool allowNetworkShares(m_type != "programs" && m_type.Left(4) != "upnp"); + bool allowNetworkShares(m_type.Left(4) != "upnp"); VECSOURCES extraShares; if (m_name != CUtil::GetTitleFromPath(m_paths->Get(item)->m_strPath)) @@ -409,6 +432,7 @@ } } + void CGUIDialogMediaSource::OnPath(int item) { if (item < 0 || item > m_paths->Size()) return; @@ -426,9 +450,11 @@ CUtil::RemoveSlashAtEnd(m_name); m_name = CUtil::GetTitleFromPath(m_name); } + UpdateButtons(); } + void CGUIDialogMediaSource::OnOK() { // verify the path by doing a GetDirectory. @@ -448,8 +474,10 @@ strPath.Replace("plugin://","special://home/plugins/"); CFileItem item(strPath,true); item.SetCachedProgramThumb(); + if (!item.HasThumbnail()) item.SetUserProgramThumb(); + if (!item.HasThumbnail()) { CUtil::AddFileToFolder(strPath,"default.py",item.m_strPath); @@ -458,6 +486,7 @@ if (!item.HasThumbnail()) item.SetUserProgramThumb(); } + if (item.HasThumbnail() && m_paths->Size()) { CFileItem item2(share.strPath,true); @@ -513,6 +542,7 @@ else if (m_type.Equals("programs")) { SET_CONTROL_VISIBLE(CONTROL_CONTENT); + CONTROL_ENABLE_ON_CONDITION(CONTROL_CONTENT, !m_paths->Get(0)->m_strPath.IsEmpty() && !m_name.IsEmpty()); } else { @@ -541,12 +571,13 @@ { m_type = type; int typeStringID = -1; + if (type == "music") - typeStringID = 249; // "Music" + typeStringID = 249; // "Music" else if (type == "video") - typeStringID = 291; // "Video" + typeStringID = 291; // "Video" else if (type == "programs") - typeStringID = 350; // "Programs" + typeStringID = 350; // "Programs" else if (type == "pictures") typeStringID = 1213; // "Pictures" else if (type == "upnpmusic") @@ -556,7 +587,8 @@ else if (type == "upnppictures") typeStringID = 21358; else // if (type == "files"); - typeStringID = 744; // "Files" + typeStringID = 744; // "Files" + CStdString format; format.Format(g_localizeStrings.Get(editNotAdd ? 1028 : 1020).c_str(), g_localizeStrings.Get(typeStringID).c_str()); SET_CONTROL_LABEL(CONTROL_HEADING, format); @@ -572,8 +604,11 @@ { CGUIMessage message(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_PATH); OnMessage(message); - int value = message.GetParam1(); - if (value < 0 || value > m_paths->Size()) return 0; + + int value = message.GetParam1(); + if (value < 0 || value > m_paths->Size()) + return 0; + return value; } @@ -581,8 +616,10 @@ { for (int i = 0; i < m_paths->Size(); i++) m_paths->Get(i)->Select(false); + if (item >= 0 && item < m_paths->Size()) m_paths->Get(item)->Select(true); + CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), CONTROL_PATH, item); OnMessage(msg); } @@ -591,14 +628,15 @@ { m_paths->Remove(item); UpdateButtons(); + if (item >= m_paths->Size()) HighlightItem(m_paths->Size() - 1); else HighlightItem(item); + if (m_paths->Size() <= 1) - { SET_CONTROL_FOCUS(CONTROL_PATH_ADD, 0); - } + } void CGUIDialogMediaSource::OnPathAdd() @@ -613,9 +651,11 @@ vector CGUIDialogMediaSource::GetPaths() { vector paths; + for (int i = 0; i < m_paths->Size(); i++) if (!m_paths->Get(i)->m_strPath.IsEmpty()) paths.push_back(m_paths->Get(i)->m_strPath); + return paths; } Index: xbmc/GUIDialogMediaSource.h =================================================================== --- xbmc/GUIDialogMediaSource.h (revision 24004) +++ xbmc/GUIDialogMediaSource.h (working copy) @@ -23,6 +23,7 @@ #include "GUIDialog.h" #include "VideoInfoScanner.h" +#include "ProgramInfoScanner.h" class CFileItemList; class CMediaSource; @@ -66,4 +67,5 @@ bool m_bNameChanged; VIDEO::SScanSettings m_settings; + PROGRAM::SScanSettings m_psettings; }; Index: xbmc/GUIDialogProgramContentSettings.cpp =================================================================== --- xbmc/GUIDialogProgramContentSettings.cpp (revision 0) +++ xbmc/GUIDialogProgramContentSettings.cpp (revision 0) @@ -0,0 +1,457 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "GUIDialogProgramContentSettings.h" +#include "GUIDialogPluginSettings.h" +#include "Util.h" +#include "ProgramDatabase.h" +#include "ProgramInfoScanner.h" +#include "FileSystem/Directory.h" +#include "FileSystem/MultiPathDirectory.h" +#include "GUIWindowManager.h" +#include "utils/ScraperParser.h" +#include "FileItem.h" +#include "GUISettings.h" +#include "LocalizeStrings.h" + +#define CONTROL_CONTENT_TYPE 3 +#define CONTROL_SCRAPER_LIST 4 +#define CONTROL_SCRAPER_SETTINGS 6 +#define CONTROL_START 30 + +using namespace DIRECTORY; +using namespace std; + +CGUIDialogProgramContentSettings::CGUIDialogProgramContentSettings(void) + : CGUIDialogSettings(WINDOW_DIALOG_PROGRAM_CONTENT_SETTINGS, "DialogProgramContentSettings.xml") +{ + m_bNeedSave = false; + m_vecItems = new CFileItemList; +} + +CGUIDialogProgramContentSettings::~CGUIDialogProgramContentSettings(void) +{ + delete m_vecItems; +} + +bool CGUIDialogProgramContentSettings::OnMessage(CGUIMessage &message) +{ + switch (message.GetMessage()) + { + case GUI_MSG_WINDOW_DEINIT: + { + m_scrapers.clear(); + m_vecItems->Clear(); + CGUIDialogSettings::OnMessage(message); + } + break; + + case GUI_MSG_ITEM_SELECT: + { + if (message.GetControlId() == CONTROL_SCRAPER_LIST) + { + if (!m_info.strContent.IsEmpty()) + m_info = m_scrapers[m_info.strContent][message.GetParam1()]; + } + } + break; + + case GUI_MSG_CLICKED: + int iControl = message.GetSenderId(); + if (iControl == 500) + Close(); + if (iControl == 501) + { + m_bNeedSave = false; + Close(); + } + + if (iControl == CONTROL_CONTENT_TYPE) + { + CGUIMessage msg(GUI_MSG_ITEM_SELECTED,GetID(),CONTROL_CONTENT_TYPE); + m_gWindowManager.SendMessage(msg); + int iSelected = msg.GetParam1(); + + m_bNeedSave = true; + CStdString strLabel; + switch (iSelected) + { + case 0: m_info.strContent.Empty(); + m_info.strPath.Empty(); + m_info.strThumb.Empty(); + m_info.strTitle.Empty(); + OnSettingChanged(0); + SetupPage(); + break; + case 1: strLabel = g_localizeStrings.Get(350); + m_info = FindDefault("games", g_guiSettings.GetString("programscrapers.gamedefault")); + CreateSettings(); + SetupPage(); + break; + } + } + if (iControl == CONTROL_SCRAPER_LIST) + { + CGUIMessage msg(GUI_MSG_ITEM_SELECTED,GetID(),CONTROL_SCRAPER_LIST); + m_gWindowManager.SendMessage(msg); + int iSelected = msg.GetParam1(); + + m_info = m_scrapers[m_info.strContent][iSelected]; + FillListControl(); + SET_CONTROL_FOCUS(30,0); + } + if (iControl == CONTROL_SCRAPER_SETTINGS) + { + if (m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/programs/" + m_info.strPath)) + { + CGUIDialogPluginSettings::ShowAndGetInput(m_info); + m_bNeedSave = true; + return true; + } + return false; + } + CScraperParser parser; + CStdString strPath; + if (!m_info.strContent.IsEmpty()) + strPath = "special://xbmc/system/scrapers/programs/"+m_info.strPath; + if (!strPath.IsEmpty() && parser.Load(strPath) && parser.HasFunction("GetSettings")) + CONTROL_ENABLE(CONTROL_SCRAPER_SETTINGS); + else + CONTROL_DISABLE(CONTROL_SCRAPER_SETTINGS); + break; + } + return CGUIDialogSettings::OnMessage(message); +} + +void CGUIDialogProgramContentSettings::OnWindowLoaded() +{ + CGUIDialogSettings::OnWindowLoaded(); + + CFileItemList items; + CDirectory::GetDirectory("special://xbmc/system/scrapers/programs/",items,".xml",false); + + for (int i=0;im_bIsFolder) + { + TiXmlDocument doc; + doc.LoadFile(items[i]->m_strPath); + if (doc.RootElement()) + { + bool IsDefaultScraper = false; + const char* content = doc.RootElement()->Attribute("content"); + const char* name = doc.RootElement()->Attribute("name"); + const char* thumb = doc.RootElement()->Attribute("thumb"); + if (content && name) + { + SScraperInfo info; + info.strTitle = name; + info.strPath = CUtil::GetFileName(items[i]->m_strPath); + if (thumb) + info.strThumb = thumb; + info.strContent = content; + info.settings = m_scraperSettings; + + if ( info.strPath == g_guiSettings.GetString("programscrapers.gamedefault")) + { + IsDefaultScraper = true; + } + + map >::iterator iter=m_scrapers.find(content); + if (iter != m_scrapers.end()) + { + if (IsDefaultScraper) + iter->second.insert(iter->second.begin(),info); + else + iter->second.push_back(info); + } + else + { + vector vec; + vec.push_back(info); + m_scrapers.insert(make_pair(content,vec)); + } + } + } + } + } + + // now select the correct scraper + if (!m_info.strContent.IsEmpty()) + { + map >::iterator iter = m_scrapers.find(m_info.strContent); + if (iter != m_scrapers.end()) + { + for (vector::iterator iter2 = iter->second.begin();iter2 != iter->second.end();++iter2) + { + if (iter2->strPath == m_info.strPath) + { + m_info = *iter2; + break; + } + } + } + } + + CScraperParser parser; + CStdString strPath; + if (!m_info.strContent.IsEmpty()) + strPath="special://xbmc/system/scrapers/programs/"+m_info.strPath; + + if (!strPath.IsEmpty() && parser.Load(strPath) && parser.HasFunction("GetSettings")) + CONTROL_ENABLE(CONTROL_SCRAPER_SETTINGS); + else + CONTROL_DISABLE(CONTROL_SCRAPER_SETTINGS); +} + +void CGUIDialogProgramContentSettings::SetupPage() +{ + CGUIDialogSettings::SetupPage(); + + CGUIMessage msg(GUI_MSG_LABEL_RESET,GetID(),CONTROL_CONTENT_TYPE); + g_graphicsContext.SendMessage(msg); + CGUIMessage msg2(GUI_MSG_LABEL_ADD,GetID(),CONTROL_CONTENT_TYPE); + + if (m_scrapers.find("games") != m_scrapers.end()) + { + msg2.SetLabel(m_strContentType); + msg2.SetParam1(5); + g_graphicsContext.SendMessage(msg2); + if (m_info.strContent.Equals("games")) + { + SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,m_strContentType); + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 3); + } + } + + SET_CONTROL_VISIBLE(CONTROL_CONTENT_TYPE); + // now add them scrapers to the list control + if (m_info.strContent.IsEmpty() || m_info.strContent.Equals("None")) + { + CGUIMessage msgReset(GUI_MSG_LABEL_RESET, GetID(), CONTROL_SCRAPER_LIST); + OnMessage(msgReset); + CONTROL_DISABLE(CONTROL_SCRAPER_LIST); + } + else + { + CONTROL_ENABLE(CONTROL_SCRAPER_LIST); + FillListControl(); + } + + OnSettingChanged(0); +} + +void CGUIDialogProgramContentSettings::CreateSettings() +{ + // clear out any old settings + m_settings.clear(); + + if (m_info.strContent.IsEmpty() || m_info.strContent.Equals("None")) + { + AddBool(1,20380,&m_bExclude); + } + if (m_info.strContent.Equals("games")) + { + AddBool(1,20345,&m_bRunScan); + AddBool(3,20346,&m_bScanRecursive); + AddBool(5,20432,&m_bUpdate); + } +} + +void CGUIDialogProgramContentSettings::OnSettingChanged(unsigned int num) +{ + // setting has changed - update anything that needs it + if (num >= m_settings.size()) return; + SettingInfo &setting = m_settings.at(num); + OnSettingChanged(setting); +} + +void CGUIDialogProgramContentSettings::OnSettingChanged(SettingInfo &setting) +{ + // check and update anything that needs it + if (setting.id == 1 || setting.id == 2) + { + CreateSettings(); + UpdateSetting(1); + UpdateSetting(2); + UpdateSetting(3); + UpdateSetting(4); + UpdateSetting(5); + } + + m_bNeedSave = true; +} + +void CGUIDialogProgramContentSettings::OnCancel() +{ + m_bNeedSave = false; +} + +void CGUIDialogProgramContentSettings::OnInitWindow() +{ + m_bNeedSave = false; + + CGUIDialogSettings::OnInitWindow(); + SET_CONTROL_FOCUS(CONTROL_CONTENT_TYPE,0); +} + +void CGUIDialogProgramContentSettings::FillListControl() +{ + CGUIMessage msgReset(GUI_MSG_LABEL_RESET, GetID(), CONTROL_SCRAPER_LIST); + OnMessage(msgReset); + int iIndex=0; + m_vecItems->Clear(); + for (vector::iterator iter=m_scrapers.find(m_info.strContent)->second.begin();iter!=m_scrapers.find(m_info.strContent)->second.end();++iter) + { + CFileItemPtr item(new CFileItem(iter->strTitle)); + item->m_strPath = iter->strPath; + item->SetThumbnailImage("special://xbmc/system/scrapers/programs/"+iter->strThumb); + + if (iter->strPath.Equals(m_info.strPath)) + { + CGUIMessage msg2(GUI_MSG_ITEM_SELECT, GetID(), CONTROL_SCRAPER_LIST, iIndex); + OnMessage(msg2); + item->Select(true); + } + m_vecItems->Add(item); + CGUIMessage msg(GUI_MSG_LABEL_ADD, GetID(), CONTROL_SCRAPER_LIST, 0, 0, item); + OnMessage(msg); + iIndex++; + } +} + +CFileItemPtr CGUIDialogProgramContentSettings::GetCurrentListItem(int offset) +{ + int currentItem = -1; + if( m_info.strContent.IsEmpty()) + return CFileItemPtr(); + for (int i=0;iSize();++i ) + { + if (m_vecItems->Get(i)->IsSelected()) + { + currentItem = i; + break; + } + } + if (currentItem == -1) return CFileItemPtr(); + int item = (currentItem + offset) % m_vecItems->Size(); + if (item < 0) item += m_vecItems->Size(); + return m_vecItems->Get(item); +} + +bool CGUIDialogProgramContentSettings::ShowDirectory(const CStdString& strDirectory, SScraperInfo& scraper, PROGRAM::SScanSettings& settings, bool& bRunScan) +{ + CProgramDatabase database; + database.Open(); + int iFound; + database.GetScraperForPath(strDirectory,scraper,settings, iFound); + bool bResult = Show(scraper,settings,bRunScan); + if (bResult) + database.SetScraperForPath(strDirectory,scraper,settings); + + return bResult; +} + + + + + +bool CGUIDialogProgramContentSettings::Show(SScraperInfo& scraper, PROGRAM::SScanSettings& settings, bool& bRunScan, int iLabel) +{ + CGUIDialogProgramContentSettings *dialog = (CGUIDialogProgramContentSettings *)m_gWindowManager.GetWindow(WINDOW_DIALOG_CONTENT_SETTINGS); + if (!dialog) return false; + + dialog->m_info = scraper; + if (iLabel != -1) dialog->m_strContentType = g_localizeStrings.Get(iLabel); + + dialog->m_scraperSettings = scraper.settings; + dialog->m_bRunScan = bRunScan; + dialog->m_bScanRecursive = (settings.recurse > 0 && !settings.parent_name) || (settings.recurse > 1 && settings.parent_name); + dialog->m_bUseDirNames = settings.parent_name; + dialog->m_bExclude = scraper.strContent.Equals("None"); + dialog->m_bSingleItem = settings.parent_name_root; + dialog->m_bNeedSave = false; + dialog->m_bUpdate = settings.noupdate; + dialog->DoModal(); + + if (dialog->m_bNeedSave) { + scraper = dialog->m_info; + settings.noupdate = dialog->m_bUpdate; + + if (scraper.strContent.Equals("games")) { + if (dialog->m_bUseDirNames) { + settings.parent_name = true; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 1; + + if (dialog->m_bSingleItem) { + settings.parent_name_root = true; + settings.recurse = 0; + } + } + else { + settings.parent_name = false; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 0; + } + + bRunScan = dialog->m_bRunScan; + } + + else if (scraper.strContent.IsEmpty() || scraper.strContent.Equals("None") ) { + if (dialog->m_bExclude) scraper.strContent = "None"; + else scraper.strContent = ""; + bRunScan = false; + } + + if (!scraper.strContent.IsEmpty() + && !scraper.strContent.Equals("None") + && (!scraper.settings.GetPluginRoot() + || scraper.settings.GetSettings().IsEmpty())) { + + // load default scraper settings + scraper.settings.LoadSettingsXML("special://xbmc/system/scrapers/programs/"+scraper.strPath); + scraper.settings.SaveFromDefault(); + } + + return true; + } + return false; +} + + + +SScraperInfo CGUIDialogProgramContentSettings::FindDefault(const CStdString& strType, const CStdString& strDefault) +{ + SScraperInfo result = m_scrapers[strType][0]; // default to first + for (unsigned int i=0;i > m_scrapers; // key = content type + CFileItemList* m_vecItems; + + SScraperInfo m_info; + CScraperSettings m_scraperSettings; // needed so we have a basis + CStdString m_strContentType; // used for artist/albums +}; + Index: xbmc/GUIDialogProgramScan.cpp =================================================================== --- xbmc/GUIDialogProgramScan.cpp (revision 0) +++ xbmc/GUIDialogProgramScan.cpp (revision 0) @@ -0,0 +1,286 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "GUIDialogProgramScan.h" +#include "GUIProgressControl.h" +#include "GUIUserMessages.h" +#include "Util.h" +#include "GUIWindowManager.h" +#include "GUISettings.h" +#include "utils/log.h" + + +#define CONTROL_LABELSTATUS 401 +#define CONTROL_LABELDIRECTORY 402 +#define CONTROL_PROGRESS 403 +#define CONTROL_CURRENT_PROGRESS 404 +#define CONTROL_LABELTITLE 405 + + +using namespace PROGRAM; + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Cunstructor +/////////////////////////////////////////////////////////////////////////////// +CGUIDialogProgramScan::CGUIDialogProgramScan(void) +: CGUIDialog(WINDOW_DIALOG_PROGRAM_SCAN, "DialogProgramScan.xml") +{ + m_programInfoScanner.SetObserver(this); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Destructor +/////////////////////////////////////////////////////////////////////////////// +CGUIDialogProgramScan::~CGUIDialogProgramScan(void) {} + +bool CGUIDialogProgramScan::OnMessage(CGUIMessage& message) +{ + switch ( message.GetMessage() ) + { + case GUI_MSG_WINDOW_INIT: + { + CGUIDialog::OnMessage(message); + + m_strCurrentDir.Empty(); + m_strTitle.Empty(); + + m_fPercentDone = -1.0f; + m_fCurrentPercentDone = -1.0f; + + UpdateState(); + return true; + } + break; + } + + return CGUIDialog::OnMessage(message); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Render dialog +/////////////////////////////////////////////////////////////////////////////// +void CGUIDialogProgramScan::Render() +{ + if (m_bRunning) + UpdateState(); + + CGUIDialog::Render(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Action performed when directory changes +/////////////////////////////////////////////////////////////////////////////// +void CGUIDialogProgramScan::OnDirectoryChanged(const CStdString& strDirectory) +{ + CSingleLock lock(m_critical); + + m_strCurrentDir = strDirectory; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Action performed when state changes +/////////////////////////////////////////////////////////////////////////////// +void CGUIDialogProgramScan::OnStateChanged(SCAN_STATE state) +{ + CSingleLock lock(m_critical); + + m_ScanState = state; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIDialogProgramScan::OnSetProgress(int currentItem, int itemCount) +{ + CSingleLock lock(m_critical); + + m_fPercentDone = (float)( (currentItem * 100) / itemCount ); + if (m_fPercentDone > 100.0F) + m_fPercentDone = 100.0F; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIDialogProgramScan::OnSetCurrentProgress(int currentItem, int itemCount) +{ + CSingleLock lock(m_critical); + + m_fCurrentPercentDone = (float)( (currentItem * 100) / itemCount ); + if (m_fCurrentPercentDone > 100.0F) + m_fCurrentPercentDone = 100.0F; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIDialogProgramScan::OnSetTitle(const CStdString& strTitle) +{ + CSingleLock lock(m_critical); + m_strTitle = strTitle; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIDialogProgramScan::StartScanning +( + const CStdString &strDirectory, + const SScraperInfo &info, + const SScanSettings &settings, + bool bUpdateAll) +{ + m_ScanState = PREPARING; + if (!g_guiSettings.GetBool("programlibrary.backgroundupdate")) + Show(); + m_programInfoScanner.Start(strDirectory, info, settings, bUpdateAll); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIDialogProgramScan::StopScanning() +{ + if (m_programInfoScanner.IsScanning()) + m_programInfoScanner.Stop(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIDialogProgramScan::IsScanning() +{ + return m_programInfoScanner.IsScanning(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIDialogProgramScan::OnDirectoryScanned(const CStdString& strDirectory) +{ + CGUIMessage msg(GUI_MSG_DIRECTORY_SCANNED, 0, 0, 0); + msg.SetStringParam(strDirectory); + m_gWindowManager.SendThreadMessage(msg); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIDialogProgramScan::OnFinished() +{ + // clear cache + CUtil::DeleteProgramDatabaseDirectoryCache(); + + // send message + CGUIMessage msg(GUI_MSG_SCAN_FINISHED, 0, 0, 0); + m_gWindowManager.SendThreadMessage(msg); + + // be sure to restore the settings + CLog::Log( LOGINFO, + "Program scan was stopped or finished ... " + "restoring FindRemoteThumbs" + ); + + if (!g_guiSettings.GetBool("programlibrary.backgroundupdate")) + Close(); + +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIDialogProgramScan::UpdateState() +{ + CSingleLock lock (m_critical); + + SET_CONTROL_LABEL(CONTROL_LABELSTATUS, GetStateString()); + + if (m_ScanState == FETCHING_GAME_INFO || + m_ScanState == CLEANING_UP_DATABASE) + { + CURL url(m_strCurrentDir); + CStdString strStrippedPath; + url.GetURLWithoutUserDetails(strStrippedPath); + CUtil::UrlDecode(strStrippedPath); + + SET_CONTROL_LABEL(CONTROL_LABELDIRECTORY, strStrippedPath); + SET_CONTROL_LABEL(CONTROL_LABELTITLE, m_strTitle); + + if (m_fCurrentPercentDone > -1.0f) + { + SET_CONTROL_VISIBLE(CONTROL_CURRENT_PROGRESS); + CGUIProgressControl* pProgressCtrl = \ + (CGUIProgressControl*)GetControl(CONTROL_CURRENT_PROGRESS); + if (pProgressCtrl) + pProgressCtrl->SetPercentage(m_fCurrentPercentDone); + } + if (m_fPercentDone>-1.0f) + { + SET_CONTROL_VISIBLE(CONTROL_PROGRESS); + CGUIProgressControl* pProgressCtrl = \ + (CGUIProgressControl*)GetControl(CONTROL_PROGRESS); + if (pProgressCtrl) + pProgressCtrl->SetPercentage(m_fPercentDone); + } + } + else + { + SET_CONTROL_LABEL( CONTROL_LABELDIRECTORY, ""); + SET_CONTROL_LABEL( CONTROL_LABELTITLE, ""); + SET_CONTROL_HIDDEN( CONTROL_PROGRESS); + SET_CONTROL_HIDDEN( CONTROL_CURRENT_PROGRESS); + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +int CGUIDialogProgramScan::GetStateString() +{ + if (m_ScanState == PREPARING) return 314; + else if (m_ScanState == REMOVING_OLD) return 701; + else if (m_ScanState == CLEANING_UP_DATABASE) return 700; + else if (m_ScanState == FETCHING_GAME_INFO) return 20374; + else if (m_ScanState == COMPRESSING_DATABASE) return 331; + else if (m_ScanState == WRITING_CHANGES) return 328; + + return -1; +} Index: xbmc/GUIDialogProgramScan.h =================================================================== --- xbmc/GUIDialogProgramScan.h (revision 0) +++ xbmc/GUIDialogProgramScan.h (revision 0) @@ -0,0 +1,70 @@ +#pragma once + +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GUIDialog.h" +#include "ProgramInfoScanner.h" +#include "utils/CriticalSection.h" + + +/// \class CGUIDialogProgramScan +/// \brief CGUIDialogProgramScan handles interaction within the scan dialog + +class CGUIDialogProgramScan: public CGUIDialog, public PROGRAM::IProgramInfoScannerObserver +{ +public: + CGUIDialogProgramScan(void); + virtual ~CGUIDialogProgramScan(void); + + virtual bool OnMessage(CGUIMessage& message); + virtual void Render(); + + void StartScanning(const CStdString& strDirectory, const SScraperInfo& info, const PROGRAM::SScanSettings& settings, bool bUpdateAll); + /// + /// Test if a scan is running + /// \return A boolean indicating if a scan is in progress + bool IsScanning(); + void StopScanning(); + void UpdateState(); + +protected: + int GetStateString(); + virtual void OnDirectoryChanged(const CStdString& strDirectory); + virtual void OnDirectoryScanned(const CStdString& strDirectory); + virtual void OnFinished(); + virtual void OnStateChanged(PROGRAM::SCAN_STATE state); + virtual void OnSetProgress(int currentItem, int itemCount); + virtual void OnSetCurrentProgress(int currentItem, int itemCount); + virtual void OnSetTitle(const CStdString& strTitle); + + PROGRAM::CProgramInfoScanner m_programInfoScanner; + PROGRAM::SCAN_STATE m_ScanState; + CStdString m_strCurrentDir; + CStdString m_strTitle; + + CCriticalSection m_critical; + + float m_fPercentDone; + float m_fCurrentPercentDone; + int m_currentItem; + int m_itemCount; +}; Index: xbmc/GUIDialogVideoContentSettings.cpp =================================================================== --- xbmc/GUIDialogVideoContentSettings.cpp (revision 0) +++ xbmc/GUIDialogVideoContentSettings.cpp (revision 0) @@ -0,0 +1,694 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "GUIDialogContentSettings.h" +#include "GUIDialogPluginSettings.h" +#include "Util.h" +#include "VideoDatabase.h" +#include "ProgramDatabase.h" +#include "VideoInfoScanner.h" +#include "ProgramInfoScanner.h" +#include "FileSystem/Directory.h" +#include "FileSystem/MultiPathDirectory.h" +#include "GUIWindowManager.h" +#include "utils/ScraperParser.h" +#include "FileItem.h" +#include "GUISettings.h" +#include "LocalizeStrings.h" + +#define CONTROL_CONTENT_TYPE 3 +#define CONTROL_SCRAPER_LIST 4 +#define CONTROL_SCRAPER_SETTINGS 6 +#define CONTROL_START 30 + +using namespace DIRECTORY; +using namespace std; + +CGUIDialogContentSettings::CGUIDialogContentSettings(void) + : CGUIDialogSettings(WINDOW_DIALOG_CONTENT_SETTINGS, "DialogContentSettings.xml") +{ + m_bNeedSave = false; + m_vecItems = new CFileItemList; +} + +CGUIDialogContentSettings::~CGUIDialogContentSettings(void) +{ + delete m_vecItems; +} + +bool CGUIDialogContentSettings::OnMessage(CGUIMessage &message) +{ + switch (message.GetMessage()) + { + case GUI_MSG_WINDOW_DEINIT: + { + m_scrapers.clear(); + m_vecItems->Clear(); + CGUIDialogSettings::OnMessage(message); + } + break; + + case GUI_MSG_ITEM_SELECT: + { + if (message.GetControlId() == CONTROL_SCRAPER_LIST) + { + if (!m_info.strContent.IsEmpty()) + m_info = m_scrapers[m_info.strContent][message.GetParam1()]; + } + } + break; + + case GUI_MSG_CLICKED: + int iControl = message.GetSenderId(); + if (iControl == 500) + Close(); + if (iControl == 501) + { + m_bNeedSave = false; + Close(); + } + + if (iControl == CONTROL_CONTENT_TYPE) + { + CGUIMessage msg(GUI_MSG_ITEM_SELECTED,GetID(),CONTROL_CONTENT_TYPE); + m_gWindowManager.SendMessage(msg); + int iSelected = msg.GetParam1(); + + m_bNeedSave = true; + CStdString strLabel; + switch (iSelected) + { + case 0: m_info.strContent.Empty(); + m_info.strPath.Empty(); + m_info.strThumb.Empty(); + m_info.strTitle.Empty(); + OnSettingChanged(0); + SetupPage(); + break; + case 1: strLabel = g_localizeStrings.Get(20342); + m_info = FindDefault("movies", g_guiSettings.GetString("scrapers.moviedefault")); + CreateSettings(); + SetupPage(); + break; + case 2: strLabel = g_localizeStrings.Get(20343); + m_info = FindDefault("tvshows", g_guiSettings.GetString("scrapers.tvshowdefault")); + CreateSettings(); + SetupPage(); + break; + case 3: strLabel = g_localizeStrings.Get(20389); + m_info = FindDefault("musicvideos", g_guiSettings.GetString("scrapers.musicvideodefault")); + CreateSettings(); + SetupPage(); + break; + case 4: strLabel = g_localizeStrings.Get(132); + m_info = FindDefault("albums", g_guiSettings.GetString("musiclibrary.defaultscraper")); + CreateSettings(); + SetupPage(); + break; + case 5: strLabel = g_localizeStrings.Get(350); + m_info = FindDefault("games", g_guiSettings.GetString("programscrapers.gamedefault")); + CreateSettings(); + SetupPage(); + break; + } + } + if (iControl == CONTROL_SCRAPER_LIST) + { + CGUIMessage msg(GUI_MSG_ITEM_SELECTED,GetID(),CONTROL_SCRAPER_LIST); + m_gWindowManager.SendMessage(msg); + int iSelected = msg.GetParam1(); + + m_info = m_scrapers[m_info.strContent][iSelected]; + FillListControl(); + SET_CONTROL_FOCUS(30,0); + } + if (iControl == CONTROL_SCRAPER_SETTINGS) + { + if (m_info.strContent.Equals("games")) + { + if (m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/programs/"+m_info.strPath)) + { + CGUIDialogPluginSettings::ShowAndGetInput(m_info); + m_bNeedSave = true; + return true; + } + } + else if (m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/video/"+m_info.strPath)) + { + CGUIDialogPluginSettings::ShowAndGetInput(m_info); + m_bNeedSave = true; + return true; + } + return false; + } + CScraperParser parser; + CStdString strPath; + if (!m_info.strContent.IsEmpty() && m_info.strContent.Equals("games")) + strPath = "special://xbmc/system/scrapers/programs/"+m_info.strPath; + else if (!m_info.strContent.IsEmpty()) + strPath = "special://xbmc/system/scrapers/video/"+m_info.strPath; + if (!strPath.IsEmpty() && parser.Load(strPath) && parser.HasFunction("GetSettings")) + CONTROL_ENABLE(CONTROL_SCRAPER_SETTINGS); + else + CONTROL_DISABLE(CONTROL_SCRAPER_SETTINGS); + break; + } + return CGUIDialogSettings::OnMessage(message); +} + +void CGUIDialogContentSettings::OnWindowLoaded() +{ + CGUIDialogSettings::OnWindowLoaded(); + + CFileItemList items; + if (m_info.strContent.Equals("albums")) + CDirectory::GetDirectory("special://xbmc/system/scrapers/music/",items,".xml",false); + else if (m_info.strContent.Equals("games")) + CDirectory::GetDirectory("special://xbmc/system/scrapers/programs/",items,".xml",false); + else{ + CDirectory::GetDirectory("special://xbmc/system/scrapers/video/",items,".xml",false); + CDirectory::GetDirectory("special://xbmc/system/scrapers/programs/",items,".xml",false); + } + for (int i=0;im_bIsFolder) + { + TiXmlDocument doc; + doc.LoadFile(items[i]->m_strPath); + if (doc.RootElement()) + { + bool IsDefaultScraper = false; + const char* content = doc.RootElement()->Attribute("content"); + const char* name = doc.RootElement()->Attribute("name"); + const char* thumb = doc.RootElement()->Attribute("thumb"); + if (content && name) + { + SScraperInfo info; + info.strTitle = name; + info.strPath = CUtil::GetFileName(items[i]->m_strPath); + if (thumb) + info.strThumb = thumb; + info.strContent = content; + info.settings = m_scraperSettings; + + if ( info.strPath == g_guiSettings.GetString("programscrapers.gamedefault") + || info.strPath == g_guiSettings.GetString("musiclibrary.defaultscraper") + || info.strPath == g_guiSettings.GetString("scrapers.moviedefault") + || info.strPath == g_guiSettings.GetString("scrapers.tvshowdefault") + || info.strPath == g_guiSettings.GetString("scrapers.musicvideodefault")) + { + IsDefaultScraper = true; + } + + map >::iterator iter=m_scrapers.find(content); + if (iter != m_scrapers.end()) + { + if (IsDefaultScraper) + iter->second.insert(iter->second.begin(),info); + else + iter->second.push_back(info); + } + else + { + vector vec; + vec.push_back(info); + m_scrapers.insert(make_pair(content,vec)); + } + } + } + } + } + + // now select the correct scraper + if (!m_info.strContent.IsEmpty()) + { + map >::iterator iter = m_scrapers.find(m_info.strContent); + if (iter != m_scrapers.end()) + { + for (vector::iterator iter2 = iter->second.begin();iter2 != iter->second.end();++iter2) + { + if (iter2->strPath == m_info.strPath) + { + m_info = *iter2; + break; + } + } + } + } + + CScraperParser parser; + CStdString strPath; + if (!m_info.strContent.IsEmpty() && m_info.strContent.Equals("games")) + strPath="special://xbmc/system/scrapers/programs/"+m_info.strPath; + else if (!m_info.strContent.IsEmpty()) + strPath="special://xbmc/system/scrapers/video/"+m_info.strPath; + if (!strPath.IsEmpty() && parser.Load(strPath) && parser.HasFunction("GetSettings")) + CONTROL_ENABLE(CONTROL_SCRAPER_SETTINGS); + else + CONTROL_DISABLE(CONTROL_SCRAPER_SETTINGS); +} + +void CGUIDialogContentSettings::SetupPage() +{ + CGUIDialogSettings::SetupPage(); + + CGUIMessage msg(GUI_MSG_LABEL_RESET,GetID(),CONTROL_CONTENT_TYPE); + g_graphicsContext.SendMessage(msg); + CGUIMessage msg2(GUI_MSG_LABEL_ADD,GetID(),CONTROL_CONTENT_TYPE); + + if (!m_info.strContent.Equals("albums")) // none does not apply to music + { + msg2.SetLabel("<"+g_localizeStrings.Get(231)+">"); + msg2.SetParam1(0); + g_graphicsContext.SendMessage(msg2); + } + + if (m_scrapers.find("movies") != m_scrapers.end()) + { + msg2.SetLabel(g_localizeStrings.Get(20342)); + msg2.SetParam1(1); + g_graphicsContext.SendMessage(msg2); + if (m_info.strContent.Equals("movies")) + { + SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,g_localizeStrings.Get(20342)); + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 1); + } + } + + if (m_scrapers.find("tvshows") != m_scrapers.end()) + { + msg2.SetLabel(g_localizeStrings.Get(20343)); + msg2.SetParam1(2); + g_graphicsContext.SendMessage(msg2); + if (m_info.strContent.Equals("tvshows")) + { + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 2); + } + } + if (m_scrapers.find("musicvideos") != m_scrapers.end()) + { + msg2.SetLabel(g_localizeStrings.Get(20389)); + msg2.SetParam1(3); + g_graphicsContext.SendMessage(msg2); + if (m_info.strContent.Equals("musicvideos")) + { + SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,g_localizeStrings.Get(20389)); + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 3); + } + } + if (m_scrapers.find("albums") != m_scrapers.end()) + { + msg2.SetLabel(m_strContentType); + msg2.SetParam1(4); + g_graphicsContext.SendMessage(msg2); + if (m_info.strContent.Equals("albums")) + { + SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,m_strContentType); + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 3); + } + } + if (m_scrapers.find("games") != m_scrapers.end()) + { + msg2.SetLabel(m_strContentType); + msg2.SetParam1(5); + g_graphicsContext.SendMessage(msg2); + if (m_info.strContent.Equals("games")) + { + SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,m_strContentType); + CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 3); + } + } + + SET_CONTROL_VISIBLE(CONTROL_CONTENT_TYPE); + // now add them scrapers to the list control + if (m_info.strContent.IsEmpty() || m_info.strContent.Equals("None")) + { + CGUIMessage msgReset(GUI_MSG_LABEL_RESET, GetID(), CONTROL_SCRAPER_LIST); + OnMessage(msgReset); + CONTROL_DISABLE(CONTROL_SCRAPER_LIST); + } + else + { + CONTROL_ENABLE(CONTROL_SCRAPER_LIST); + FillListControl(); + } + + OnSettingChanged(0); +} + +void CGUIDialogContentSettings::CreateSettings() +{ + // clear out any old settings + m_settings.clear(); + + if (m_info.strContent.IsEmpty() || m_info.strContent.Equals("None")) + { + AddBool(1,20380,&m_bExclude); + } + if (m_info.strContent.Equals("movies")) + { + AddBool(1,20345,&m_bRunScan); + AddBool(2,20330,&m_bUseDirNames); + AddBool(3,20346,&m_bScanRecursive); + AddBool(4,20383,&m_bSingleItem, m_bUseDirNames); + AddBool(5,20432,&m_bUpdate); + } + if (m_info.strContent.Equals("tvshows")) + { + AddBool(1,20345,&m_bRunScan); + AddBool(2,20379,&m_bSingleItem); + AddBool(3,20432,&m_bUpdate); + } + if (m_info.strContent.Equals("musicvideos")) + { + AddBool(1,20345,&m_bRunScan); + AddBool(2,20346,&m_bScanRecursive); + AddBool(3,20432,&m_bUpdate); + } + if (m_info.strContent.Equals("albums")) + { + AddBool(1,20345,&m_bRunScan); + } + if (m_info.strContent.Equals("games")) + { + AddBool(1,20345,&m_bRunScan); + AddBool(3,20346,&m_bScanRecursive); + AddBool(5,20432,&m_bUpdate); + } +} + +void CGUIDialogContentSettings::OnSettingChanged(unsigned int num) +{ + // setting has changed - update anything that needs it + if (num >= m_settings.size()) return; + SettingInfo &setting = m_settings.at(num); + OnSettingChanged(setting); +} + +void CGUIDialogContentSettings::OnSettingChanged(SettingInfo &setting) +{ + // check and update anything that needs it + if (setting.id == 1 || setting.id == 2) + { + CreateSettings(); + UpdateSetting(1); + UpdateSetting(2); + UpdateSetting(3); + UpdateSetting(4); + UpdateSetting(5); + } + + m_bNeedSave = true; +} + +void CGUIDialogContentSettings::OnCancel() +{ + m_bNeedSave = false; +} + +void CGUIDialogContentSettings::OnInitWindow() +{ + m_bNeedSave = false; + + CGUIDialogSettings::OnInitWindow(); + SET_CONTROL_FOCUS(CONTROL_CONTENT_TYPE,0); +} + +void CGUIDialogContentSettings::FillListControl() +{ + CGUIMessage msgReset(GUI_MSG_LABEL_RESET, GetID(), CONTROL_SCRAPER_LIST); + OnMessage(msgReset); + int iIndex=0; + m_vecItems->Clear(); + for (vector::iterator iter=m_scrapers.find(m_info.strContent)->second.begin();iter!=m_scrapers.find(m_info.strContent)->second.end();++iter) + { + CFileItemPtr item(new CFileItem(iter->strTitle)); + item->m_strPath = iter->strPath; + if (m_info.strContent.Equals("albums")) + item->SetThumbnailImage("special://xbmc/system/scrapers/music/"+iter->strThumb); + else if (m_info.strContent.Equals("games")) + item->SetThumbnailImage("special://xbmc/system/scrapers/programs/"+iter->strThumb); + else + item->SetThumbnailImage("special://xbmc/system/scrapers/video/"+iter->strThumb); + if (iter->strPath.Equals(m_info.strPath)) + { + CGUIMessage msg2(GUI_MSG_ITEM_SELECT, GetID(), CONTROL_SCRAPER_LIST, iIndex); + OnMessage(msg2); + item->Select(true); + } + m_vecItems->Add(item); + CGUIMessage msg(GUI_MSG_LABEL_ADD, GetID(), CONTROL_SCRAPER_LIST, 0, 0, item); + OnMessage(msg); + iIndex++; + } +} + +CFileItemPtr CGUIDialogContentSettings::GetCurrentListItem(int offset) +{ + int currentItem = -1; + if( m_info.strContent.IsEmpty()) + return CFileItemPtr(); + for (int i=0;iSize();++i ) + { + if (m_vecItems->Get(i)->IsSelected()) + { + currentItem = i; + break; + } + } + if (currentItem == -1) return CFileItemPtr(); + int item = (currentItem + offset) % m_vecItems->Size(); + if (item < 0) item += m_vecItems->Size(); + return m_vecItems->Get(item); +} + +bool CGUIDialogContentSettings::ShowForVideoDirectory(const CStdString& strDirectory, SScraperInfo& scraper, VIDEO::SScanSettings& settings, bool& bRunScan) +{ + CVideoDatabase database; + database.Open(); + int iFound; + database.GetScraperForPath(strDirectory,scraper,settings, iFound); + bool bResult = Show(scraper, settings, bRunScan); + if (bResult) + database.SetScraperForPath(strDirectory,scraper,settings); + + return bResult; +} + +bool CGUIDialogContentSettings::ShowForProgramDirectory(const CStdString& strDirectory, SScraperInfo& scraper, PROGRAM::SScanSettings& settings, bool& bRunScan) +{ + CProgramDatabase database; + database.Open(); + int iFound; + database.GetScraperForPath(strDirectory,scraper,settings, iFound); + bool bResult = Show(scraper,settings,bRunScan); + if (bResult) + database.SetScraperForPath(strDirectory,scraper,settings); + + return bResult; +} + + +bool CGUIDialogContentSettings::Show(SScraperInfo& scraper, bool& bRunScan, int iLabel) +{ + VIDEO::SScanSettings dummy; + dummy.recurse = -1; + dummy.parent_name = false; + dummy.parent_name_root = false; + dummy.noupdate = false; + return Show(scraper,dummy,bRunScan,iLabel); +} + +bool CGUIDialogContentSettings::Show(SScraperInfo& scraper, VIDEO::SScanSettings& settings, bool& bRunScan, int iLabel) +{ + CGUIDialogContentSettings *dialog = (CGUIDialogContentSettings *)m_gWindowManager.GetWindow(WINDOW_DIALOG_CONTENT_SETTINGS); + if (!dialog) return false; + + dialog->m_info = scraper; + if (iLabel != -1) // to switch between albums and artists + dialog->m_strContentType = g_localizeStrings.Get(iLabel); + + dialog->m_scraperSettings = scraper.settings; + dialog->m_bRunScan = bRunScan; + dialog->m_bScanRecursive = (settings.recurse > 0 && !settings.parent_name) || (settings.recurse > 1 && settings.parent_name); + dialog->m_bUseDirNames = settings.parent_name; + dialog->m_bExclude = scraper.strContent.Equals("None"); + dialog->m_bSingleItem = settings.parent_name_root; + dialog->m_bNeedSave = false; + dialog->m_bUpdate = settings.noupdate; + dialog->DoModal(); + if (dialog->m_bNeedSave) + { + scraper = dialog->m_info; + settings.noupdate = dialog->m_bUpdate; + + if (scraper.strContent.Equals("tvshows")) + { + settings.parent_name = dialog->m_bSingleItem; + settings.parent_name_root = dialog->m_bSingleItem; + settings.recurse = 0; + + bRunScan = dialog->m_bRunScan; + } + else if (scraper.strContent.Equals("movies")) + { + if (dialog->m_bUseDirNames) + { + settings.parent_name = true; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 1; + + if (dialog->m_bSingleItem) + { + settings.parent_name_root = true; + settings.recurse = 0; + } + } + else + { + settings.parent_name = false; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 0; + } + + bRunScan = dialog->m_bRunScan; + } + else if (scraper.strContent.Equals("musicvideos")) + { + settings.parent_name = false; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 0; + + bRunScan = dialog->m_bRunScan; + } + else if (scraper.strContent.Equals("albums")) + { + bRunScan = dialog->m_bRunScan; + } + else if (scraper.strContent.Equals("programs")) + { + bRunScan = dialog->m_bRunScan; + } + else if (scraper.strContent.IsEmpty() || scraper.strContent.Equals("None") ) + { + if (dialog->m_bExclude) + scraper.strContent = "None"; + else + scraper.strContent = ""; + + bRunScan = false; + } + + if (!scraper.strContent.IsEmpty() && !scraper.strContent.Equals("None") && (!scraper.settings.GetPluginRoot() || scraper.settings.GetSettings().IsEmpty())) + { // load default scraper settings + scraper.settings.LoadSettingsXML("special://xbmc/system/scrapers/video/"+scraper.strPath); + scraper.settings.SaveFromDefault(); + } + + return true; + } + return false; +} + + + + +bool CGUIDialogContentSettings::Show(SScraperInfo& scraper, PROGRAM::SScanSettings& settings, bool& bRunScan, int iLabel) +{ + CGUIDialogContentSettings *dialog = (CGUIDialogContentSettings *)m_gWindowManager.GetWindow(WINDOW_DIALOG_CONTENT_SETTINGS); + if (!dialog) return false; + + dialog->m_info = scraper; + if (iLabel != -1) dialog->m_strContentType = g_localizeStrings.Get(iLabel); + + dialog->m_scraperSettings = scraper.settings; + dialog->m_bRunScan = bRunScan; + dialog->m_bScanRecursive = (settings.recurse > 0 && !settings.parent_name) || (settings.recurse > 1 && settings.parent_name); + dialog->m_bUseDirNames = settings.parent_name; + dialog->m_bExclude = scraper.strContent.Equals("None"); + dialog->m_bSingleItem = settings.parent_name_root; + dialog->m_bNeedSave = false; + dialog->m_bUpdate = settings.noupdate; + dialog->DoModal(); + + if (dialog->m_bNeedSave) { + scraper = dialog->m_info; + settings.noupdate = dialog->m_bUpdate; + + if (scraper.strContent.Equals("games")) { + if (dialog->m_bUseDirNames) { + settings.parent_name = true; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 1; + + if (dialog->m_bSingleItem) { + settings.parent_name_root = true; + settings.recurse = 0; + } + } + else { + settings.parent_name = false; + settings.parent_name_root = false; + settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 0; + } + + bRunScan = dialog->m_bRunScan; + } + + else if (scraper.strContent.IsEmpty() || scraper.strContent.Equals("None") ) { + if (dialog->m_bExclude) scraper.strContent = "None"; + else scraper.strContent = ""; + bRunScan = false; + } + + if (!scraper.strContent.IsEmpty() + && !scraper.strContent.Equals("None") + && (!scraper.settings.GetPluginRoot() + || scraper.settings.GetSettings().IsEmpty())) { + + // load default scraper settings + scraper.settings.LoadSettingsXML("special://xbmc/system/scrapers/program/"+scraper.strPath); + scraper.settings.SaveFromDefault(); + } + + return true; + } + return false; +} + + + +SScraperInfo CGUIDialogContentSettings::FindDefault(const CStdString& strType, const CStdString& strDefault) +{ + SScraperInfo result = m_scrapers[strType][0]; // default to first + for (unsigned int i=0;i > m_scrapers; // key = content type + CFileItemList* m_vecItems; + + SScraperInfo m_info; + CScraperSettings m_scraperSettings; // needed so we have a basis + CStdString m_strContentType; // used for artist/albums +}; + Index: xbmc/GUIMediaWindow.cpp =================================================================== --- xbmc/GUIMediaWindow.cpp (revision 24004) +++ xbmc/GUIMediaWindow.cpp (working copy) @@ -722,16 +722,19 @@ // This function calls OnPlayMedia() bool CGUIMediaWindow::OnClick(int iItem) { + CLog::Log(LOGDEBUG, "MEDIAWINDOW::onclick()"); if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) return true; CFileItemPtr pItem = m_vecItems->Get(iItem); if (pItem->IsParentFolder()) { - GoParentFolder(); + CLog::Log(LOGDEBUG, "MEDIAWINDOW::onclick()->goto parent folder"); + GoParentFolder(); return true; } else if (pItem->m_bIsFolder) { + CLog::Log(LOGDEBUG, "MEDIAWINDOW::onclick()->isFolder=true"); if ( pItem->m_bIsShareOrDrive ) { const CStdString& strLockType=m_guiState->GetLockType(); Index: xbmc/GUISettings.cpp =================================================================== --- xbmc/GUISettings.cpp (revision 24004) +++ xbmc/GUISettings.cpp (working copy) @@ -215,16 +215,47 @@ AddBool(3, "slideshow.displayeffects", 12379, true); AddBool(0, "slideshow.shuffle", 13319, false); + + + ///////////////////////////////////////// // Programs settings + ///////////////////////////////////////// + AddGroup(1, 0); + + AddCategory(1,"programfiles", 744); + AddBool(1, "programfiles.waitforexit",18001 , true); + AddBool(2, "programfiles.minimizebeforelaunch",18002, true); + AddBool(3, "programfiles.releasesoundbeforelaunch",18003,true); + AddBool(5, "programfiles.hidecurseronlaunch",18003,true); + AddBool(5, "programfiles.hidelaunchersconsole",18003,true); + // AddInt(4, "programfiles.warpcursoronlaunch",18003,0,1,5,SPIN_CONTROL_TEXT); - AddCategory(1,"programfiles",744); - AddBool(4, "programfiles.savefolderviews", 583, true); - AddString(5, "programfiles.defaultscraper", 20194, "allgame.xml", SPIN_CONTROL_TEXT); - AddBool(6, "programfiles.waitforexit",18001 , true); - AddBool(7, "programfiles.minimizebeforelaunch",18002, true); - AddBool(8, "programfiles.releasesoundbeforelaunch",18003,true); + AddSeparator(4, "programfiles.sep1"); + AddBool(5, "programfiles.cleanstrings", 20418, false); + AddSeparator(6, "programfiles.sep2"); + AddBool(7, "programfiles.savefolderviews", 583, true); + //end category + + AddCategory(1, "programlibrary", 14022); + AddBool(1, "programlibrary.enabled", 418, false);; + AddBool(2, "programlibrary.updateonstartup", 22000, false); + AddBool(3, "programlibrary.backgroundupdate", 22001, false); + AddSeparator(4, "programlibrary.sep1"); + AddString(5, "programlibrary.cleanup", 334, "", BUTTON_CONTROL_STANDARD); + AddString(6, "programlibrary.export", 647, "", BUTTON_CONTROL_STANDARD); + AddString(7, "programlibrary.import", 648, "", BUTTON_CONTROL_STANDARD); + //end category + + AddCategory(1, "programscrapers", 20194); + AddString(1, "programscrapers.gamedefault", 20194, "allgame.xml", SPIN_CONTROL_TEXT); + AddSeparator(2, "programscrapers.sep2"); + AddBool(3, "programscrapers.langfallback", 21416, true); + //end category + + + // My Weather settings AddGroup(2, 8); AddCategory(2, "weather", 16000); Index: xbmc/GUIViewState.cpp =================================================================== --- xbmc/GUIViewState.cpp (revision 24004) +++ xbmc/GUIViewState.cpp (working copy) @@ -24,7 +24,7 @@ #include "GUIViewStateMusic.h" #include "GUIViewStateVideo.h" #include "GUIViewStatePictures.h" -#include "GUIViewStatePrograms.h" +#include "GUIViewStateProgram.h" #include "GUIViewStateScripts.h" #include "PlayListPlayer.h" #include "Util.h" @@ -110,8 +110,8 @@ if (windowId==WINDOW_PICTURES) return new CGUIViewStateWindowPictures(items); - if (windowId==WINDOW_PROGRAMS) - return new CGUIViewStateWindowPrograms(items); + if (windowId==WINDOW_PROGRAM_FILES) + return new CGUIViewStateWindowProgramFiles(items); if (windowId==WINDOW_PROGRAM_NAV) return new CGUIViewStateWindowProgramNav(items); Index: xbmc/GUIViewStateProgram.cpp =================================================================== --- xbmc/GUIViewStateProgram.cpp (revision 0) +++ xbmc/GUIViewStateProgram.cpp (revision 0) @@ -0,0 +1,393 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "GUIViewStateProgram.h" +#include "FileSystem/ProgramDatabaseDirectory.h" +#include "FileSystem/PluginDirectory.h" +#include "GUIBaseContainer.h" +#include "ProgramDatabase.h" +#include "GUISettings.h" +#include "AdvancedSettings.h" +#include "Settings.h" +#include "FileItem.h" +#include "Util.h" +#include "LocalizeStrings.h" + +using namespace DIRECTORY; +using namespace PROGRAMDATABASEDIRECTORY; + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CStdString CGUIViewStateWindowProgram::GetLockType() +{ + return "programs"; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIViewStateWindowProgram::UnrollArchives() +{ + return g_guiSettings.GetBool("filelists.unrollarchives"); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CStdString CGUIViewStateWindowProgram::GetExtensions() +{ + return g_stSettings.m_programExtensions; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CGUIViewStateWindowProgramFiles::CGUIViewStateWindowProgramFiles +( + const CFileItemList& items +) : CGUIViewStateWindowProgram(items) +{ + if (items.IsVirtualDirectoryRoot()) + { + // Preformated + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS()); + // Preformated + AddSortMethod(SORT_METHOD_DRIVE_TYPE, 564, LABEL_MASKS()); + + SetSortMethod(SORT_METHOD_LABEL); + + SetViewAsControl(DEFAULT_VIEW_LIST); + + SetSortOrder(SORT_ORDER_ASC); + } + else + { + if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + // FileName, Size | Foldername, empty + AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%L", "%I", "%L", "")); + else + // FileName, Size | Foldername, empty + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%L", "%I", "%L", "")); + + // FileName, Size | Foldername, Size + AddSortMethod(SORT_METHOD_SIZE, 553, LABEL_MASKS("%L", "%I", "%L", "%I")); + // FileName, Date | Foldername, Date + AddSortMethod(SORT_METHOD_DATE, 552, LABEL_MASKS("%L", "%J", "%L", "%J")); + // Filename, Size | FolderName, empty + AddSortMethod(SORT_METHOD_FILE, 561, LABEL_MASKS("%L", "%I", "%L", "")); + + SetSortMethod(g_stSettings.m_viewStateProgramFiles.m_sortMethod); + + SetViewAsControl(g_stSettings.m_viewStateProgramFiles.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramFiles.m_sortOrder); + } + LoadViewState(items.m_strPath, WINDOW_PROGRAM_FILES); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIViewStateWindowProgramFiles::SaveViewState() +{ + if (g_guiSettings.GetBool("programfiles.savefolderviews")) + SaveViewToDb(m_items.m_strPath, WINDOW_PROGRAM_FILES, &g_stSettings.m_viewStateProgramFiles); + else + { + g_stSettings.m_viewStateProgramFiles = CViewState(GetViewAsControl(), GetSortMethod(), GetSortOrder()); + g_settings.Save(); + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +VECSOURCES& CGUIViewStateWindowProgramFiles::GetSources() +{ + bool bIsSourceName = true; + // plugins share + if (CPluginDirectory::HasPlugins("programs") && + g_advancedSettings.m_bVirtualShares) + { + CMediaSource share; + share.strName = g_localizeStrings.Get(1037); + share.strPath = "plugin://programs/"; + share.m_ignore = true; + if (CUtil::GetMatchingSource( + share.strName, g_settings.m_programSources, bIsSourceName + ) < 0 + ) + g_settings.m_programSources.push_back(share); + } + return g_settings.m_programSources; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CGUIViewStateWindowProgramNav::CGUIViewStateWindowProgramNav +( + const CFileItemList& items +) : CGUIViewStateWindowProgram(items) +{ + if (items.IsVirtualDirectoryRoot()) + { + // Filename, Size | Foldername, empty + AddSortMethod( + SORT_METHOD_NONE, + 551, + LABEL_MASKS("%F", "%I", "%L", "") + ); + + SetSortMethod(SORT_METHOD_NONE); + + SetViewAsControl(DEFAULT_VIEW_LIST); + + SetSortOrder(SORT_ORDER_NONE); + } + else if (items.IsProgramDb()) + { + NODE_TYPE NodeType = CProgramDatabaseDirectory::\ + GetDirectoryChildType(items.m_strPath); + CQueryParams params; + CProgramDatabaseDirectory::GetQueryParams(items.m_strPath,params); + + switch (NodeType) + { + case NODE_TYPE_GAMES_OVERVIEW: + case NODE_TYPE_OVERVIEW: + { + // Filename, Size | Foldername, empty + AddSortMethod(SORT_METHOD_NONE, 551, LABEL_MASKS("%F", "%I", "%L", "")); + + SetSortMethod(SORT_METHOD_NONE); + + SetViewAsControl(DEFAULT_VIEW_LIST); + + SetSortOrder(SORT_ORDER_NONE); + } + break; + case NODE_TYPE_DEVELOPER: + { + // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R", "%L", "")); + SetSortMethod(SORT_METHOD_LABEL); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavDevelopers.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramNavDevelopers.m_sortOrder); + } + break; + case NODE_TYPE_YEAR: + { + // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_LABEL, 562, LABEL_MASKS("%T", "%R", "%L", "")); + SetSortMethod(SORT_METHOD_LABEL); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavYears.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramNavYears.m_sortOrder); + } + break; + case NODE_TYPE_GENRE: + case NODE_TYPE_PUBLISHER: + { + // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R", "%L", "")); + SetSortMethod(SORT_METHOD_LABEL); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavGenres.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramNavGenres.m_sortOrder); + } + break; + + case NODE_TYPE_TITLE_GAMES: + { + if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_PROGRAM_SORT_TITLE_IGNORE_THE, 551, LABEL_MASKS("%T", "%R")); + else + AddSortMethod(SORT_METHOD_PROGRAM_SORT_TITLE, 551, LABEL_MASKS("%T", "%R")); + + // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_PROGRAM_RATING, 563, LABEL_MASKS("%T", "%R")); + AddSortMethod(SORT_METHOD_YEAR,562, LABEL_MASKS("%T", "%Y")); + SetSortMethod(g_stSettings.m_viewStateProgramNavTitles.m_sortMethod); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavTitles.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramNavTitles.m_sortOrder); + } + break; + case NODE_TYPE_RECENTLY_ADDED_GAMES: + { + AddSortMethod(SORT_METHOD_NONE, 552, LABEL_MASKS("%T", "%R")); + SetSortMethod(SORT_METHOD_NONE); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavTitles.m_viewMode); + + SetSortOrder(SORT_ORDER_NONE); + } + break; + default: + break; + } + } + else + { + // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%F", "%D", "%L", "")); + SetSortMethod(SORT_METHOD_LABEL); + + SetViewAsControl(DEFAULT_VIEW_LIST); + + } + LoadViewState(items.m_strPath, WINDOW_PROGRAM_NAV); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIViewStateWindowProgramNav::SaveViewState() +{ + NODE_TYPE NodeType = CProgramDatabaseDirectory::\ + GetDirectoryChildType(m_items.m_strPath); + switch (NodeType) + { + case NODE_TYPE_YEAR: + SaveViewToDb( + m_items.m_strPath, + WINDOW_PROGRAM_NAV, + &g_stSettings.m_viewStateProgramNavYears + ); + break; + case NODE_TYPE_GENRE: + SaveViewToDb( + m_items.m_strPath, + WINDOW_PROGRAM_NAV, + &g_stSettings.m_viewStateProgramNavGenres + ); + break; + case NODE_TYPE_TITLE_GAMES: + SaveViewToDb( + m_items.m_strPath, + WINDOW_PROGRAM_NAV, + &g_stSettings.m_viewStateProgramNavTitles + ); + break; + default: + SaveViewToDb(m_items.m_strPath, WINDOW_PROGRAM_NAV); + break; + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +VECSOURCES& CGUIViewStateWindowProgramNav::GetSources() +{ + // Setup shares we want to have + m_sources.clear(); + // Musicdb shares + CFileItemList items; + CDirectory::GetDirectory("programdb://", items); + + for (int i=0; iGetLabel(); + share.strPath = item->m_strPath; + share.m_strThumbnailImage= item->GetThumbnailImage(); + share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL; + m_sources.push_back(share); + } + + CMediaSource share; + // plugins share + if (CPluginDirectory::HasPlugins("programs") && + g_advancedSettings.m_bVirtualShares) + { + share.strName = g_localizeStrings.Get(1037); + share.strPath = "plugin://programs/"; + share.m_strThumbnailImage = \ + CUtil::GetDefaultFolderThumb("DefaultProgramPlugins.png"); + m_sources.push_back(share); + } + + return CGUIViewStateWindowProgram::GetSources(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CGUIViewStateProgramGames::CGUIViewStateProgramGames +( + const CFileItemList &items +) : CGUIViewStateWindowProgram(items) +{ + if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%T", "%R")); + else + // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R")); + + // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_PROGRAM_RATING, 563, LABEL_MASKS("%T", "%R")); + + AddSortMethod(SORT_METHOD_YEAR,562, LABEL_MASKS("%T", "%Y")); + + if (items.IsSmartPlayList()) + AddSortMethod(SORT_METHOD_PLAYLIST_ORDER, 559, LABEL_MASKS("%T", "%R")); + + SetSortMethod(g_stSettings.m_viewStateProgramNavTitles.m_sortMethod); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavTitles.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramNavTitles.m_sortOrder); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIViewStateProgramGames::SaveViewState() +{ + SaveViewToDb( + m_items.m_strPath, + WINDOW_PROGRAM_NAV, + &g_stSettings.m_viewStateProgramNavTitles + ); +} Index: xbmc/GUIViewStateProgram.h =================================================================== --- xbmc/GUIViewStateProgram.h (revision 0) +++ xbmc/GUIViewStateProgram.h (revision 0) @@ -0,0 +1,66 @@ +#pragma once + +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GUIViewState.h" + + +class CGUIViewStateWindowProgram : public CGUIViewState +{ +public: + CGUIViewStateWindowProgram(const CFileItemList& items) : CGUIViewState(items) {} + +protected: + virtual CStdString GetLockType(); + virtual bool UnrollArchives(); + virtual CStdString GetExtensions(); +}; + +class CGUIViewStateWindowProgramFiles : public CGUIViewStateWindowProgram +{ +public: + CGUIViewStateWindowProgramFiles(const CFileItemList& items); + +protected: + virtual void SaveViewState(); + virtual VECSOURCES& GetSources(); +}; + +class CGUIViewStateWindowProgramNav : public CGUIViewStateWindowProgram +{ +public: + CGUIViewStateWindowProgramNav(const CFileItemList& items); + +protected: + virtual void SaveViewState(); + virtual VECSOURCES& GetSources(); +}; + + +class CGUIViewStateProgramGames : public CGUIViewStateWindowProgram +{ +public: + CGUIViewStateProgramGames(const CFileItemList& items); +protected: + virtual void SaveViewState(); +}; + Index: xbmc/GUIViewStatePrograms.cpp =================================================================== --- xbmc/GUIViewStatePrograms.cpp (revision 24004) +++ xbmc/GUIViewStatePrograms.cpp (working copy) @@ -70,14 +70,7 @@ CStdString CGUIViewStateWindowPrograms::GetExtensions() { -#ifdef _LINUX - return ""; -#endif -#ifdef _WIN32 - return ".exe|.lnk|.cmd|.bat"; -#else - return ".xbe|.cut"; -#endif + return g_stSettings.m_programExtensions; } VECSOURCES& CGUIViewStateWindowPrograms::GetSources() Index: xbmc/GUIViewStateWindowProgram.cpp =================================================================== --- xbmc/GUIViewStateWindowProgram.cpp (revision 0) +++ xbmc/GUIViewStateWindowProgram.cpp (revision 0) @@ -0,0 +1,319 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "GUIViewStateProgram.h" +#include "FileSystem/ProgramDatabaseDirectory.h" +#include "FileSystem/PluginDirectory.h" +#include "GUIBaseContainer.h" +#include "ProgramDatabase.h" +#include "GUISettings.h" +#include "AdvancedSettings.h" +#include "Settings.h" +#include "FileItem.h" +#include "Util.h" +#include "LocalizeStrings.h" + +using namespace DIRECTORY; +using namespace PROGRAMDATABASEDIRECTORY; + +CStdString CGUIViewStateWindowProgram::GetLockType() +{ + return "program"; +} + +bool CGUIViewStateWindowProgram::UnrollArchives() +{ + return g_guiSettings.GetBool("filelists.unrollarchives"); +} + +CStdString CGUIViewStateWindowProgram::GetExtensions() +{ + return g_stSettings.m_programExtensions; +} + + +CGUIViewStateWindowProgramFiles::CGUIViewStateWindowProgramFiles(const CFileItemList& items) : CGUIViewStateWindowProgram(items) +{ + if (items.IsVirtualDirectoryRoot()) + { + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS()); // Preformated + AddSortMethod(SORT_METHOD_DRIVE_TYPE, 564, LABEL_MASKS()); // Preformated + SetSortMethod(SORT_METHOD_LABEL); + + SetViewAsControl(DEFAULT_VIEW_LIST); + + SetSortOrder(SORT_ORDER_ASC); + } + else + { + if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%L", "%I", "%L", "")); // FileName, Size | Foldername, empty + else + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%L", "%I", "%L", "")); // FileName, Size | Foldername, empty + AddSortMethod(SORT_METHOD_SIZE, 553, LABEL_MASKS("%L", "%I", "%L", "%I")); // FileName, Size | Foldername, Size + AddSortMethod(SORT_METHOD_DATE, 552, LABEL_MASKS("%L", "%J", "%L", "%J")); // FileName, Date | Foldername, Date + AddSortMethod(SORT_METHOD_FILE, 561, LABEL_MASKS("%L", "%I", "%L", "")); // Filename, Size | FolderName, empty + + SetSortMethod(g_stSettings.m_viewStateProgramFiles.m_sortMethod); + SetViewAsControl(g_stSettings.m_viewStateProgramFiles.m_viewMode); + SetSortOrder(g_stSettings.m_viewStateProgramFiles.m_sortOrder); + } + LoadViewState(items.m_strPath, WINDOW_PROGRAM_FILES); +} + +void CGUIViewStateWindowProgramFiles::SaveViewState() +{ + if (g_guiSettings.GetBool("myprograms.savefolderviews")) + SaveViewToDb(m_items.m_strPath, WINDOW_PROGRAM_FILES, &g_stSettings.m_viewStateProgramFiles); + else + { + g_stSettings.m_viewStateProgramFiles = CViewState(GetViewAsControl(), GetSortMethod(), GetSortOrder()); + g_settings.Save(); + } +} + +VECSOURCES& CGUIViewStateWindowProgramFiles::GetSources() +{ + bool bIsSourceName = true; + // plugins share + if (CPluginDirectory::HasPlugins("program") && g_advancedSettings.m_bVirtualShares) + { + CMediaSource share; + share.strName = g_localizeStrings.Get(1037); + share.strPath = "plugin://program/"; + share.m_ignore = true; + if (CUtil::GetMatchingSource(share.strName, g_settings.m_programSources, bIsSourceName) < 0) + g_settings.m_programSources.push_back(share); + } + return g_settings.m_programSources; +} + +CGUIViewStateWindowProgramNav::CGUIViewStateWindowProgramNav(const CFileItemList& items) : CGUIViewStateWindowProgram(items) +{ + if (items.IsVirtualDirectoryRoot()) + { + AddSortMethod(SORT_METHOD_NONE, 551, LABEL_MASKS("%F", "%I", "%L", "")); // Filename, Size | Foldername, empty + SetSortMethod(SORT_METHOD_NONE); + + SetViewAsControl(DEFAULT_VIEW_LIST); + + SetSortOrder(SORT_ORDER_NONE); + } + else if (items.IsProgramDb()) + { + NODE_TYPE NodeType=CProgramDatabaseDirectory::GetDirectoryChildType(items.m_strPath); + CQueryParams params; + CProgramDatabaseDirectory::GetQueryParams(items.m_strPath,params); + + switch (NodeType) + { + case NODE_TYPE_GAMES_OVERVIEW: + case NODE_TYPE_CONSOLEGAMES_OVERVIEW: + case NODE_TYPE_ARCADEGAMES_OVERVIEW: + case NODE_TYPE_OVERVIEW: + { + AddSortMethod(SORT_METHOD_NONE, 551, LABEL_MASKS("%F", "%I", "%L", "")); // Filename, Size | Foldername, empty + + SetSortMethod(SORT_METHOD_NONE); + + SetViewAsControl(DEFAULT_VIEW_LIST); + + SetSortOrder(SORT_ORDER_NONE); + } + break; + case NODE_TYPE_DEVELOPER: + { + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R", "%L", "")); // Filename, Duration | Foldername, empty + SetSortMethod(SORT_METHOD_LABEL); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavCompanies.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramNavCompanies.m_sortOrder); + } + break; + case NODE_TYPE_YEAR: + { + AddSortMethod(SORT_METHOD_LABEL, 562, LABEL_MASKS("%T", "%R", "%L", "")); // Filename, Duration | Foldername, empty + SetSortMethod(SORT_METHOD_LABEL); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavYears.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramNavYears.m_sortOrder); + } + break; + case NODE_TYPE_GENRE: + case NODE_TYPE_PUBLISHER: + { + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R", "%L", "")); // Filename, Duration | Foldername, empty + SetSortMethod(SORT_METHOD_LABEL); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavGenres.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramNavGenres.m_sortOrder); + } + break; + case NODE_TYPE_EPISODES: + { + if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%T","%R")); // Filename, Duration | Foldername, empty + else + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R")); // Filename, Duration | Foldername, empty + if (params.GetSeason() > -1) + { + AddSortMethod(SORT_METHOD_PROGRAM_RATING, 563, LABEL_MASKS("%E. %T", "%R")); // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_EPISODE,20359,LABEL_MASKS("%E. %T","%R")); + AddSortMethod(SORT_METHOD_PRODUCTIONCODE,20368,LABEL_MASKS("%E. %T","%P", "%E. %T","%P")); + AddSortMethod(SORT_METHOD_DATE,552,LABEL_MASKS("%E. %T","%J","E. %T","%J")); + } + else + { + AddSortMethod(SORT_METHOD_PROGRAM_RATING, 563, LABEL_MASKS("%H. %T", "%R")); // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_EPISODE,20359,LABEL_MASKS("%H. %T","%R")); + AddSortMethod(SORT_METHOD_PRODUCTIONCODE,20368,LABEL_MASKS("%H. %T","%P", "%H. %T","%P")); + AddSortMethod(SORT_METHOD_DATE,552,LABEL_MASKS("%H. %T","%J","%H. %T","%J")); + } + + SetSortMethod(g_stSettings.m_viewStateProgramNavEpisodes.m_sortMethod); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavEpisodes.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramNavEpisodes.m_sortOrder); + break; + } + case NODE_TYPE_TITLE_GAMES: + { + if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + AddSortMethod(SORT_METHOD_PROGRAM_SORT_TITLE_IGNORE_THE, 551, LABEL_MASKS("%T", "%R")); // Filename, Duration | Foldername, empty + else + AddSortMethod(SORT_METHOD_PROGRAM_SORT_TITLE, 551, LABEL_MASKS("%T", "%R")); + + AddSortMethod(SORT_METHOD_PROGRAM_RATING, 563, LABEL_MASKS("%T", "%R")); // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_YEAR,562, LABEL_MASKS("%T", "%Y")); + SetSortMethod(g_stSettings.m_viewStateProgramNavTitles.m_sortMethod); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavTitles.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramNavTitles.m_sortOrder); + } + break; + case NODE_TYPE_RECENTLY_ADDED_GAMES: + { + AddSortMethod(SORT_METHOD_NONE, 552, LABEL_MASKS("%T", "%R")); + SetSortMethod(SORT_METHOD_NONE); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavTitles.m_viewMode); + + SetSortOrder(SORT_ORDER_NONE); + } + break; + default: + break; + } + } + else + { + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%F", "%D", "%L", "")); // Filename, Duration | Foldername, empty + SetSortMethod(SORT_METHOD_LABEL); + + SetViewAsControl(DEFAULT_VIEW_LIST); + + } + LoadViewState(items.m_strPath, WINDOW_PROGRAM_NAV); +} + +void CGUIViewStateWindowProgramNav::SaveViewState() +{ + NODE_TYPE NodeType = CProgramDatabaseDirectory::GetDirectoryChildType(m_items.m_strPath); + switch (NodeType) + { + case NODE_TYPE_YEAR: + SaveViewToDb(m_items.m_strPath, WINDOW_PROGRAM_NAV, &g_stSettings.m_viewStateProgramNavYears); + break; + case NODE_TYPE_GENRE: + SaveViewToDb(m_items.m_strPath, WINDOW_PROGRAM_NAV, &g_stSettings.m_viewStateProgramNavGenres); + break; + case NODE_TYPE_TITLE_GAMES: + SaveViewToDb(m_items.m_strPath, WINDOW_PROGRAM_NAV, &g_stSettings.m_viewStateProgramNavTitles); + break; + default: + SaveViewToDb(m_items.m_strPath, WINDOW_PROGRAM_NAV); + break; + } +} + +VECSOURCES& CGUIViewStateWindowProgramNav::GetSources() +{ + // Setup shares we want to have + m_sources.clear(); + // Musicdb shares + CFileItemList items; + CDirectory::GetDirectory("programdb://", items); + for (int i=0; iGetLabel(); + share.strPath = item->m_strPath; + share.m_strThumbnailImage= item->GetThumbnailImage(); + share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL; + m_sources.push_back(share); + } + + + // plugins share + if (CPluginDirectory::HasPlugins("program") && g_advancedSettings.m_bVirtualShares) + { + share.strName = g_localizeStrings.Get(1037); + share.strPath = "plugin://program/"; + share.m_strThumbnailImage = CUtil::GetDefaultFolderThumb("DefaultProgramPlugins.png"); + m_sources.push_back(share); + } + + return CGUIViewStateWindowProgram::GetSources(); +} + + + + +CGUIViewStateProgramGames::CGUIViewStateProgramGames(const CFileItemList& items) : CGUIViewStateWindowProgram(items) +{ + if (g_guiSettings.GetBool("filelists.ignorethewhensorting")) + AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%T", "%R")); // Filename, Duration | Foldername, empty + else + AddSortMethod(SORT_METHOD_LABEL, 551, LABEL_MASKS("%T", "%R")); // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_PROGRAM_RATING, 563, LABEL_MASKS("%T", "%R")); // Filename, Duration | Foldername, empty + AddSortMethod(SORT_METHOD_YEAR,562, LABEL_MASKS("%T", "%Y")); + + if (items.IsSmartPlayList()) + AddSortMethod(SORT_METHOD_PLAYLIST_ORDER, 559, LABEL_MASKS("%T", "%R")); + + SetSortMethod(g_stSettings.m_viewStateProgramNavTitles.m_sortMethod); + + SetViewAsControl(g_stSettings.m_viewStateProgramNavTitles.m_viewMode); + + SetSortOrder(g_stSettings.m_viewStateProgramNavTitles.m_sortOrder); +} + +void CGUIViewStateProgramGames::SaveViewState() +{ + SaveViewToDb(m_items.m_strPath, WINDOW_PROGRAM_NAV, &g_stSettings.m_viewStateProgramNavTitles); +} Index: xbmc/GUIViewStateWindowProgram.h =================================================================== --- xbmc/GUIViewStateWindowProgram.h (revision 0) +++ xbmc/GUIViewStateWindowProgram.h (revision 0) @@ -0,0 +1,66 @@ +#pragma once + +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GUIViewState.h" + + +class CGUIViewStateWindowProgram : public CGUIViewState +{ +public: + CGUIViewStateWindowProgram(const CFileItemList& items) : CGUIViewState(items) {} + +protected: + virtual CStdString GetLockType(); + virtual bool UnrollArchives(); + virtual CStdString GetExtensions(); +}; + +class CGUIViewStateWindowProgramFiles : public CGUIViewStateWindowProgram +{ +public: + CGUIViewStateWindowProgramFiles(const CFileItemList& items); + +protected: + virtual void SaveViewState(); + virtual VECSOURCES& GetSources(); +}; + +class CGUIViewStateWindowProgramNav : public CGUIViewStateWindowProgram +{ +public: + CGUIViewStateWindowProgramNav(const CFileItemList& items); + +protected: + virtual void SaveViewState(); + virtual VECSOURCES& GetSources(); +}; + + +class CGUIViewStateProgramGames : public CGUIViewStateWindowProgram +{ +public: + CGUIViewStateProgramGames(const CFileItemList& items); +protected: + virtual void SaveViewState(); +}; + Index: xbmc/GUIWindowProgramBase.cpp =================================================================== --- xbmc/GUIWindowProgramBase.cpp (revision 0) +++ xbmc/GUIWindowProgramBase.cpp (revision 0) @@ -0,0 +1,1434 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + + +#include "stdafx.h" +#include "GUIWindowProgramBase.h" +#include "Util.h" +#include "utils/RegExp.h" +#include "ProgramScraper.h" +#include "utils/GUIInfoManager.h" +#include "GUIWindowProgramInfo.h" +#include "GUIWindowProgramNav.h" +#include "GUIDialogFileBrowser.h" +#include "GUIDialogProgramScan.h" +#include "GUIDialogProgress.h" +#include "Application.h" +#include "NfoFile.h" +#include "Picture.h" +#include "utils/fstrcmp.h" +#include "GUIPassword.h" +#include "FileSystem/ZipManager.h" +#include "FileSystem/StackDirectory.h" +#include "FileSystem/MultiPathDirectory.h" +#include "GUIDialogFileStacking.h" +#include "GUIDialogMediaSource.h" +#include "GUIWindowFileManager.h" +#include "FileSystem/ProgramDatabaseDirectory.h" +#include "PartyModeManager.h" +#include "GUIWindowManager.h" +#include "GUIDialogOK.h" +#include "GUIDialogSelect.h" +#include "GUIDialogKeyboard.h" +#include "FileSystem/Directory.h" +#include "FileItem.h" +#include "Settings.h" +#include "AdvancedSettings.h" +#include "GUISettings.h" +#include "LocalizeStrings.h" +#include "SkinInfo.h" +#include "MediaManager.h" + + +using namespace std; +using namespace XFILE; +using namespace DIRECTORY; +using namespace PROGRAMDATABASEDIRECTORY; +using namespace PROGRAM; + + +#define CONTROL_BTNVIEWASICONS 2 +#define CONTROL_BTNSORTBY 3 +#define CONTROL_BTNSORTASC 4 +#define CONTROL_BTNTYPE 5 +#define CONTROL_LABELFILES 12 +#define CONTROL_STACK 7 +#define CONTROL_BTNSCAN 8 + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CGUIWindowProgramBase::CGUIWindowProgramBase +( + DWORD dwID, + const CStdString &xmlFile +) + : CGUIMediaWindow(dwID, xmlFile) +{ + m_thumbLoader.SetObserver(this); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CGUIWindowProgramBase::~CGUIWindowProgramBase() {} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramBase::OnAction(const CAction &action) +{ + if (action.wID == ACTION_SCAN_ITEM) + return OnContextButton( + m_viewControl.GetSelectedItem(), + CONTEXT_BUTTON_SCAN + ); + + return CGUIMediaWindow::OnAction(action); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramBase::OnMessage(CGUIMessage& message) +{ + switch ( message.GetMessage() ) + { + + case GUI_MSG_WINDOW_DEINIT: + if (m_thumbLoader.IsLoading()) + m_thumbLoader.StopThread(); + m_database.Close(); + break; + + + case GUI_MSG_WINDOW_INIT: + { + m_database.Open(); + m_dlgProgress = (CGUIDialogProgress*)m_gWindowManager.GetWindow + ( WINDOW_DIALOG_PROGRESS ); + + // save current window + if ( (DWORD)g_stSettings.m_iProgramStartWindow != GetID() ) + { + g_stSettings.m_iProgramStartWindow = GetID(); + g_settings.Save(); + } + + return CGUIMediaWindow::OnMessage(message); + } + break; + + + case GUI_MSG_CLICKED: + { + int iControl = message.GetSenderId(); + + if (iControl == CONTROL_BTNTYPE) + { + CGUIMessage msg( + GUI_MSG_ITEM_SELECTED, + GetID(), + CONTROL_BTNTYPE + ); + + m_gWindowManager.SendMessage(msg); + + int nSelected = msg.GetParam1(); + int nNewWindow = WINDOW_PROGRAM_FILES; + + switch (nSelected) { + case 0: // games + nNewWindow = WINDOW_PROGRAM_FILES; + break; + case 1: // Library + nNewWindow = WINDOW_PROGRAM_NAV; + break; + } + + if ((DWORD) nNewWindow != GetID()) + { + g_stSettings.m_iProgramStartWindow = nNewWindow; + g_settings.Save(); + + m_gWindowManager.ChangeActiveWindow(nNewWindow); + CGUIMessage msg2( + GUI_MSG_SETFOCUS, + nNewWindow, + CONTROL_BTNTYPE + ); + g_graphicsContext.SendMessage(msg2); + } + + return true; + } + else if (m_viewControl.HasControl(iControl)) + { + // get selected item + int iItem = m_viewControl.GetSelectedItem(); + int iAction = message.GetParam1(); + + if (iAction == ACTION_SHOW_INFO) + { + SScraperInfo info; + CStdString strDir; + SScanSettings settings; + + if (iItem < 0 || iItem >= m_vecItems->Size()) + return false; + + CFileItemPtr item = m_vecItems->Get(iItem); + + if (m_vecItems->IsPlugin()) + info.strContent = "plugin"; + else + { + if (item->IsProgramDb() && + item->HasProgramInfoTag() && + !item->GetProgramInfoTag()->m_strPath.IsEmpty()) + { + strDir = item->GetProgramInfoTag()->m_strPath; + } + else + CUtil::GetDirectory(item->m_strPath,strDir); + + int iFound; + m_database.GetScraperForPath(strDir, info, settings, iFound); + + if (info.strContent.IsEmpty() && + !m_database.HasGameInfo(item->m_strPath)) + { + // hack + CGUIDialogProgramScan* pDialog = \ + (CGUIDialogProgramScan*)m_gWindowManager.\ + GetWindow(WINDOW_DIALOG_PROGRAM_SCAN + ); + + if ( pDialog && pDialog->IsScanning() ) + return true; + + CStdString strOldPath = item->m_strPath; + item->m_strPath = strDir; + OnAssignContent(iItem, 1, info, settings); + item->m_strPath = strOldPath; + + return true; + } + } + + OnInfo(item.get(), info); + + return true; + } + + else if (iAction == ACTION_DELETE_ITEM) + { + // is delete allowed? + if (g_settings.m_vecProfiles[ + g_settings.m_iLastLoadedProfileIndex + ].canWriteDatabases()) + { + // ... must be at the title window + if (GetID() == WINDOW_PROGRAM_NAV) + OnDeleteItem(iItem); + + // ... or be at the files window and + // have file deletion enabled + else + if (GetID() == WINDOW_PROGRAM_FILES && + g_guiSettings.GetBool("filelists.allowfiledeletion")) + OnDeleteItem(iItem); + + else + return false; + + return true; + } + } + } + } + break; + } + + return CGUIMediaWindow::OnMessage(message); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::UpdateButtons() +{ + // Remove labels from the window selection + CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), CONTROL_BTNTYPE); + g_graphicsContext.SendMessage(msg); + + // Add labels to the window selection + CStdString strItem = g_localizeStrings.Get(744); // Files + CGUIMessage msg2(GUI_MSG_LABEL_ADD, GetID(), CONTROL_BTNTYPE); + + msg2.SetLabel(strItem); + g_graphicsContext.SendMessage(msg2); + + strItem = g_localizeStrings.Get(14022); // Library + msg2.SetLabel(strItem); + g_graphicsContext.SendMessage(msg2); + + // Select the current window as default item + int nWindow = g_stSettings.m_iProgramStartWindow + - WINDOW_PROGRAM_FILES; + CONTROL_SELECT_ITEM(CONTROL_BTNTYPE, nWindow); + + // disable scan and manual info controls + // if internet lookups are disabled + if (g_guiSettings.GetBool("network.enableinternet")) + CONTROL_ENABLE(CONTROL_BTNSCAN); + else + CONTROL_DISABLE(CONTROL_BTNSCAN); + + CGUIMediaWindow::UpdateButtons(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::OnInfo(CFileItem* pItem, const SScraperInfo& info) +{ + if (!pItem) + return; + + CFileItem item(*pItem); + if (item.IsProgramDb() && item.HasProgramInfoTag()) + { + if (item.GetProgramInfoTag()->m_strFileNameAndPath.IsEmpty()) + item.m_strPath = item.GetProgramInfoTag()->m_strPath; + else + item.m_strPath = item.GetProgramInfoTag()->m_strFileNameAndPath; + } + bool modified = ShowGameInfo(&item, info); + + // since we can be called from the music library we need this check + if (modified && !info.strContent.Equals("plugin") && + (m_gWindowManager.GetActiveWindow() == WINDOW_PROGRAM_FILES || + m_gWindowManager.GetActiveWindow() == WINDOW_PROGRAM_NAV)) + { + int itemNumber = m_viewControl.GetSelectedItem(); + Update(m_vecItems->m_strPath); + m_viewControl.SetSelectedItem(itemNumber); + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramBase::OnClick(int iItem) { + return CGUIMediaWindow::OnClick(iItem); + return true; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::OnRestartItem(int iItem) { + CGUIMediaWindow::OnClick(iItem); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramBase::ShowGameInfo(CFileItem *item, const SScraperInfo& info2) +{ + CGUIDialogProgress *pDlgProgress = (CGUIDialogProgress*)m_gWindowManager.\ + GetWindow(WINDOW_DIALOG_PROGRESS); + CGUIDialogSelect *pDlgSelect = (CGUIDialogSelect*)m_gWindowManager.\ + GetWindow(WINDOW_DIALOG_SELECT); + CGUIWindowProgramInfo *pDlgInfo = (CGUIWindowProgramInfo*)m_gWindowManager.\ + GetWindow(WINDOW_PROGRAM_INFO); + + CProgramInfoScanner scanner; + scanner.m_ProgramScraper.SetScraperInfo(info2); + SScraperInfo info(info2); // use this as nfo might change it.. + + if (!pDlgProgress) return false; + if (!pDlgSelect) return false; + if (!pDlgInfo) return false; + + CUtil::ClearCache(); + CScraperParser::ClearCache(); + + /////////// + // 1. Check for already downloaded information, + // and if we have it, display our dialog + // Return if no Refresh is needed. + // + bool bHasInfo = false; + + CProgramInfoTag gameDetails; + gameDetails.Reset(); + m_database.Open(); // since we can be called from the music library + + if (info.strContent.Equals("games")) + { + if (m_database.HasGameInfo(item->m_strPath)) + { + bHasInfo = true; + m_database.GetGameInfo(item->m_strPath, gameDetails); + } + } + + m_database.Close(); + + if (bHasInfo) + { + *item->GetProgramInfoTag() = gameDetails; + pDlgInfo->SetGame(item); + pDlgInfo->DoModal(); + if ( !pDlgInfo->NeedRefresh() ) + return pDlgInfo->HasUpdatedThumb(); + } + + // quietly return if Internet lookups are disabled + if (!g_guiSettings.GetBool("network.enableinternet")) + return false; + + if (!g_settings.m_vecProfiles[ + g_settings.m_iLastLoadedProfileIndex + ].canWriteDatabases() && + !g_passwordManager.bMasterUser + ) + return false; + + CGUIDialogProgramScan* pDialog = (CGUIDialogProgramScan*)m_gWindowManager.\ + GetWindow(WINDOW_DIALOG_PROGRAM_SCAN); + + if (pDialog && pDialog->IsScanning()) + { + CGUIDialogOK::ShowAndGetInput(13346,14057,-1,-1); + return false; + } + + CScraperUrl scrUrl; + bool hasDetails(false); + + m_database.Open(); + /////////// + // 2. Look for a nfo File to get the search URL + // + SScanSettings settings; + m_database.GetScraperForPath(item->m_strPath,info,settings); + CStdString nfoFile; + + if (!info.settings.GetPluginRoot() && info.settings.GetSettings().IsEmpty()) + { + // check for settings, if they are around load + // defaults - to workaround the nastyness + CScraperParser parser; + CStdString strPath; + + if (!info.strContent.IsEmpty()) + strPath = "special://xbmc/system/scrapers/programs/"+info.strPath; + + if (!strPath.IsEmpty() && parser.Load(strPath) && + parser.HasFunction("GetSettings")) + { + info.settings.LoadSettingsXML( + "special://xbmc/system/scrapers/programs/" + info.strPath); + info.settings.SaveFromDefault(); + } + } + + CNfoFile::NFOResult result = scanner.CheckForNFOFile( + item, settings.parent_name_root, + info, scrUrl + ); + if (result == CNfoFile::FULL_NFO) + hasDetails = true; + if (result == CNfoFile::URL_NFO || result == CNfoFile::COMBINED_NFO) + scanner.m_ProgramScraper.SetScraperInfo(info); + + // Get the correct game title + CStdString gameName = item->GetGameName(settings.parent_name); + + /////////// + // 3. Run a loop so that if we Refresh + // we re-run this block + // + bool listNeedsUpdating(false); + bool needsRefresh(false); + do + { + /////////// + // 4. if we don't have a url, or need to refresh the + // search then do the web search + // + if (!hasDetails && (scrUrl.m_url.size() == 0 || needsRefresh)) + { + /////////// + // 4a. show dialog that we're busy + // querying scraper site + // + CStdString strHeading; + scanner.m_ProgramScraper.SetScraperInfo(info); + strHeading.Format(g_localizeStrings.Get(197), info.strTitle.c_str()); + pDlgProgress->SetHeading(strHeading); + pDlgProgress->SetLine(0, gameName); + pDlgProgress->SetLine(1, ""); + pDlgProgress->SetLine(2, ""); + pDlgProgress->StartModal(); + pDlgProgress->Progress(); + + /////////// + // 4b. do the websearch + // + PROGRAMSCRAPER_GAMELIST gamelist; + + int returncode = 0; + if (!hasDetails && + (returncode = scanner.m_ProgramScraper.\ + FindGame(gameName, gamelist, pDlgProgress)) > 0) + { + pDlgProgress->Close(); + if (gamelist.size() > 0) + { + int iString = 196; + pDlgSelect->SetHeading(iString); + pDlgSelect->Reset(); + for (unsigned int i = 0; i < gamelist.size(); ++i) + pDlgSelect->Add(gamelist[i].strTitle); + pDlgSelect->EnableButton(true); + pDlgSelect->SetButtonLabel(413); // manual + pDlgSelect->DoModal(); + + // and wait till user selects one + int iSelectedGame = pDlgSelect->GetSelectedLabel(); + if (iSelectedGame >= 0) + scrUrl = gamelist[iSelectedGame]; + else if (!pDlgSelect->IsButtonPressed()) + { + m_database.Close(); + return listNeedsUpdating; // user backed out + } + } + } + if (returncode == -1) + { + pDlgProgress->Close(); + return false; + } + } + /////////// + // 4c. Check if url is still empty - occurs if + // user has selected to do a manual lookup, + // or if the Program Info lookup + // failed or was cancelled. + if (!hasDetails && scrUrl.m_url.size() == 0) + { + // Check for cancel of the progress dialog + pDlgProgress->Close(); + if (pDlgProgress->IsCanceled()) + { + m_database.Close(); + return listNeedsUpdating; + } + + // Prompt the user to input the gameName + int iString = 16009; + + if (!CGUIDialogKeyboard::ShowAndGetInput( + gameName, g_localizeStrings.Get(iString), false)) + { + m_database.Close(); + return listNeedsUpdating; // user backed out + } + + needsRefresh = true; + } + else + { + /////////// + // 5. Download the game information + // show dialog that we're downloading + // the movie info + CFileItemList list; + CStdString strPath = item->m_strPath; + if (item->IsProgramDb()) + { + CFileItemPtr newItem(new CFileItem(*item->GetProgramInfoTag())); + list.Add(newItem); + strPath = item->GetProgramInfoTag()->m_strPath; + } + else + { + CFileItemPtr newItem(new CFileItem(*item)); + list.Add(newItem); + } + + if (item->m_bIsFolder) + CUtil::GetParentPath(strPath,list.m_strPath); + else + CUtil::GetDirectory(strPath,list.m_strPath); + + int iString = 198; + + pDlgProgress->SetHeading(iString); + pDlgProgress->SetLine(0, gameName); + pDlgProgress->SetLine(1, scrUrl.strTitle); + pDlgProgress->SetLine(2, ""); + pDlgProgress->StartModal(); + pDlgProgress->Progress(); + + if (bHasInfo) + { + if (info.strContent.Equals("games")) + m_database.DeleteGame(item->m_strPath); + } + if (scanner.RetrieveProgramInfo( + list, settings.parent_name_root, + info, !pDlgInfo->RefreshAll(), + &scrUrl, pDlgProgress)) + { + if (info.strContent.Equals("games")) + m_database.GetGameInfo(item->m_strPath, gameDetails); + + // got all movie details :-) + OutputDebugString("got details\n"); + pDlgProgress->Close(); + + // now show the imdb info + OutputDebugString("show info\n"); + + // remove directory caches and reload images + CUtil::DeleteProgramDatabaseDirectoryCache(); + CGUIMessage reload(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS); + OnMessage(reload); + + *item->GetProgramInfoTag() = gameDetails; + pDlgInfo->SetGame(item); + pDlgInfo->DoModal(); + item->SetThumbnailImage(pDlgInfo->GetThumbnail()); + needsRefresh = pDlgInfo->NeedRefresh(); + listNeedsUpdating = true; + } + else + { + pDlgProgress->Close(); + if (pDlgProgress->IsCanceled()) + { + m_database.Close(); + return listNeedsUpdating; // user cancelled + } + OutputDebugString("failed to get details\n"); + // show dialog... + CGUIDialogOK *pDlgOK = (CGUIDialogOK*)m_gWindowManager.GetWindow(WINDOW_DIALOG_OK); + if (pDlgOK) + { + pDlgOK->SetHeading(195); + pDlgOK->SetLine(0, gameName); + pDlgOK->SetLine(1, ""); + pDlgOK->SetLine(2, ""); + pDlgOK->SetLine(3, ""); + pDlgOK->DoModal(); + } + m_database.Close(); + return listNeedsUpdating; + } + } + /////////// + // 6. Check for a refresh + } while (needsRefresh); + m_database.Close(); + + return listNeedsUpdating; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::GetContextButtons(int itemNumber, CContextButtons &buttons) +{ + + CFileItemPtr item; + if (itemNumber >= 0 && itemNumber < m_vecItems->Size()) + item = m_vecItems->Get(itemNumber); + + // contextual buttons + if (item && !item->GetPropertyBOOL("pluginreplacecontextitems")) + { + if (!item->IsParentFolder()) + { + CStdString path(item->m_strPath); + + if (item->IsProgramDb() && item->HasProgramInfoTag()) + path = item->GetProgramInfoTag()->m_strFileNameAndPath; + + if (CUtil::IsStack(path)) + { + vector times; + if (m_database.GetStackTimes(path,times)) + buttons.Add(CONTEXT_BUTTON_PLAY_PART, 20324); + } + + // get players + VECPLAYERCORES vecCores; + if (item->IsProgramDb()) + { + CFileItem item2; + item2.m_strPath = item->GetProgramInfoTag()->m_strFileNameAndPath; + CPlayerCoreFactory::GetPlayers(item2, vecCores); + } + else + CPlayerCoreFactory::GetPlayers(*item, vecCores); + if (vecCores.size() > 1) + buttons.Add(CONTEXT_BUTTON_PLAY_WITH, 15213); + } + } + CGUIMediaWindow::GetContextButtons(itemNumber, buttons); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::GetNonContextButtons +( + int itemNumber, + CContextButtons &buttons +) +{ + if (!m_vecItems->m_strPath.IsEmpty()) + buttons.Add(CONTEXT_BUTTON_GOTO_ROOT, 20128); + buttons.Add(CONTEXT_BUTTON_SETTINGS, 5); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button) +{ + CFileItemPtr item; + if (itemNumber >= 0 && itemNumber < m_vecItems->Size()) + item = m_vecItems->Get(itemNumber); + + switch (button) + { + case CONTEXT_BUTTON_PLAY_PART: + { + CFileItemList items; + + CStdString path(item->m_strPath); + if (item->IsProgramDb()) + path = item->GetProgramInfoTag()->m_strFileNameAndPath; + + CDirectory::GetDirectory(path, items); + CGUIDialogFileStacking* dlg = (CGUIDialogFileStacking*)\ + m_gWindowManager.GetWindow(WINDOW_DIALOG_FILESTACKING); + if (!dlg) + return true; + + dlg->SetNumberOfFiles(items.Size()); + dlg->DoModal(); + int btn2 = dlg->GetSelectedFile(); + if (btn2 > 0) + { + // call CGUIMediaWindow::OnClick() + // as otherwise autoresume will kick in + CGUIMediaWindow::OnClick(itemNumber); + } + + return true; + } + + case CONTEXT_BUTTON_PLAY_ITEM: + PlayItem(itemNumber); + + return true; + + case CONTEXT_BUTTON_PLAY_WITH: + { + VECPLAYERCORES vecCores; + + if (item->IsProgramDb()) + { + CFileItem item2(*item->GetProgramInfoTag()); + CPlayerCoreFactory::GetPlayers(item2, vecCores); + } + else + CPlayerCoreFactory::GetPlayers(*item, vecCores); + + g_application.m_eForcedNextPlayer = \ + CPlayerCoreFactory::SelectPlayerDialog(vecCores); + + if (g_application.m_eForcedNextPlayer != EPC_NONE) + OnClick(itemNumber); + + return true; + } + + case CONTEXT_BUTTON_GOTO_ROOT: + Update(""); + return true; + + case CONTEXT_BUTTON_SETTINGS: + m_gWindowManager.ActivateWindow(WINDOW_SETTINGS_MYPROGRAMS); + return true; + + case CONTEXT_BUTTON_INFO: + { + SScraperInfo info; + PROGRAM::SScanSettings settings; + + GetScraperForItem(item.get(), info, settings); + OnInfo(item.get(), info); + + return true; + } + + case CONTEXT_BUTTON_STOP_SCANNING: + { + CGUIDialogProgramScan *pScanDlg = \ + (CGUIDialogProgramScan *)m_gWindowManager.GetWindow( + WINDOW_DIALOG_PROGRAM_SCAN); + + if (pScanDlg && pScanDlg->IsScanning()) + pScanDlg->StopScanning(); + + return true; + } + + case CONTEXT_BUTTON_SCAN: + { + if( !item) + return false; + + SScraperInfo info; + SScanSettings settings; + + GetScraperForItem(item.get(), info, settings); + CStdString strPath = item->m_strPath; + + if (item->IsProgramDb() && (!item->m_bIsFolder || + item->GetProgramInfoTag()->m_strPath.IsEmpty()) + ) + return false; + + if (item->IsProgramDb()) + strPath = item->GetProgramInfoTag()->m_strPath; + + if (info.strContent.IsEmpty()) + return false; + + if (item->m_bIsFolder) + { + m_database.SetPathHash(strPath, ""); // to force scan + OnScan(strPath,info,settings); + } + else + OnInfo(item.get(),info); + + return true; + } + + case CONTEXT_BUTTON_DELETE: + OnDeleteItem(itemNumber); + return true; + + case CONTEXT_BUTTON_RENAME: + OnRenameItem(itemNumber); + return true; + + default: + break; + } + + return CGUIMediaWindow::OnContextButton(itemNumber, button); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Get stacked files +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::GetStackedFiles +( + const CStdString &strFilePath1, + vector &games +) +{ + // we're gonna be altering it + CStdString strFilePath = strFilePath1; + + games.clear(); + + CURL url(strFilePath); + if (url.GetProtocol() == "stack") + { + CStackDirectory dir; + CFileItemList items; + dir.GetDirectory(strFilePath, items); + + for (int i = 0; i < items.Size(); ++i) + games.push_back(items[i]->m_strPath); + } + + if (games.empty()) + games.push_back(strFilePath); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::OnDeleteItem(int iItem) +{ + if (iItem < 0 || iItem >= m_vecItems->Size()) + return; + + CFileItemPtr item = m_vecItems->Get(iItem); + + // HACK: stacked files need to be treated as + // folders in order to be deleted + if (item->IsStack()) + item->m_bIsFolder = true; + + if (g_settings.m_vecProfiles[ + g_settings.m_iLastLoadedProfileIndex + ].getLockMode() != LOCK_MODE_EVERYONE && + g_settings.m_vecProfiles[ + g_settings.m_iLastLoadedProfileIndex + ].filesLocked()) + { + if ( !g_passwordManager.IsMasterLockUnlocked(true) ) + return; + } + + if (!CGUIWindowFileManager::DeleteItem(item.get())) + return; + + Update(m_vecItems->m_strPath); + m_viewControl.SetSelectedItem(iItem); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Add change a title's name +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::UpdateProgramTitle(const CFileItem* pItem) +{ + + // dont allow update while scanning + CGUIDialogProgramScan* pDialogScan = \ + (CGUIDialogProgramScan*)m_gWindowManager.\ + GetWindow(WINDOW_DIALOG_PROGRAM_SCAN); + + if (pDialogScan && pDialogScan->IsScanning()) + { + CGUIDialogOK::ShowAndGetInput(257, 0, 14057, 0); + return; + } + + CProgramInfoTag detail; + CProgramDatabase database; + database.Open(); + + PROGRAMDB_CONTENT_TYPE iType = PROGRAMDB_CONTENT_GAMES; + + if (iType == PROGRAMDB_CONTENT_GAMES) + database.GetGameInfo("", detail, pItem->GetProgramInfoTag()->m_iDbId); + + + CStdString strInput; + strInput = detail.m_strTitle; + + //Get the new title + if (!CGUIDialogKeyboard::ShowAndGetInput\ + (strInput, g_localizeStrings.Get(16105), false)) + return; + + database.UpdateGameTitle\ + (pItem->GetProgramInfoTag()->m_iDbId, strInput, iType); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramBase::Update(const CStdString &strDirectory) +{ + + if (m_thumbLoader.IsLoading()) + m_thumbLoader.StopThread(); + + if (!CGUIMediaWindow::Update(strDirectory)) + return false; + + m_thumbLoader.Load(*m_vecItems); + + return true; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramBase::GetDirectory +( + const CStdString &strDirectory, + CFileItemList &items +) +{ + bool bResult = CGUIMediaWindow::GetDirectory(strDirectory, items); + return bResult; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::OnPrepareFileItems(CFileItemList &items) +{ + if (!items.m_strPath.Equals("plugin://programs/")) + items.SetCachedProgramThumbs(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::AddToDatabase(int iItem) +{ + + if (iItem < 0 || iItem >= m_vecItems->Size()) + return; + + CFileItemPtr pItem = m_vecItems->Get(iItem); + + if (pItem->IsParentFolder() || pItem->m_bIsFolder) + return; + + bool bGotXml = false; + CProgramInfoTag game; + game.Reset(); + + // look for matching xml file first + CStdString strXml = pItem->m_strPath + ".xml"; + if (pItem->IsStack()) + { + // for a stack, use the first file in the stack + CStackDirectory stack; + strXml = stack.GetFirstStackedFile(pItem->m_strPath) + ".xml"; + } + + CStdString strCache = CUtil::AddFileToFolder( + "special://temp/", + CUtil::MakeLegalFileName( + CUtil::GetFileName(strXml) + ) + ); + + if (CFile::Exists(strXml)) + { + bGotXml = true; + + CLog::Log( LOGDEBUG, + "%s: found matching xml file:[%s]", + __FUNCTION__, strXml.c_str() + ); + + CFile::Cache(strXml, strCache); + CProgramScraper gameInfo; + + if (!gameInfo.LoadXML(strCache, game, false)) + { + CLog::Log( LOGERROR, + "%s: Could not parse info in file:[%s]", + __FUNCTION__, strXml.c_str() + ); + + bGotXml = false; + } + } + + // prompt for data + if (!bGotXml) + { + // enter a new title + CStdString strTitle = pItem->GetLabel(); + if (!CGUIDialogKeyboard::ShowAndGetInput\ + (strTitle, g_localizeStrings.Get(528), false)) // Enter Title + return; + + // pick genre + CGUIDialogSelect* pSelect = (CGUIDialogSelect*)m_gWindowManager.\ + GetWindow(WINDOW_DIALOG_SELECT); + if (!pSelect) + return; + + // Select Genre + pSelect->SetHeading(530); + pSelect->Reset(); + CFileItemList items; + if (!CDirectory::GetDirectory("programdb://1/1/", items)) + return; + pSelect->SetItems(&items); + pSelect->EnableButton(true); + // New Genre + pSelect->SetButtonLabel(531); + pSelect->DoModal(); + + CStdString strGenre; + int iSelected = pSelect->GetSelectedLabel(); + + if (iSelected >= 0) + strGenre = items[iSelected]->GetLabel(); + else if (!pSelect->IsButtonPressed()) + return; + + // enter new genre string + if (strGenre.IsEmpty()) + { + // Manual Addition + strGenre = g_localizeStrings.Get(532); + // Enter Genre + if (!CGUIDialogKeyboard::ShowAndGetInput\ + (strGenre, g_localizeStrings.Get(533), false)) + // user backed out + return; + + if (strGenre.IsEmpty()) + // no genre string + return; + } + + // set game info + game.m_strTitle = strTitle; + game.m_strGenre = strGenre; + } + + // everything is ok, so add to database + m_database.Open(); + long lGameId = m_database.AddGame(pItem->m_strPath); + m_database.SetDetailsForGame(pItem->m_strPath, game); + m_database.Close(); + + // done... + CGUIDialogOK *pDialog = \ + (CGUIDialogOK*)m_gWindowManager.GetWindow(WINDOW_DIALOG_OK); + if (pDialog) + { + pDialog->SetHeading(20177); // Done + pDialog->SetLine(0, game.m_strTitle); + pDialog->SetLine(1, game.m_strGenre); + pDialog->SetLine(2, ""); + pDialog->DoModal(); + } + + // library view cache needs to be cleared + CUtil::DeleteProgramDatabaseDirectoryCache(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +int CGUIWindowProgramBase::GetScraperForItem +( + CFileItem *item, + SScraperInfo &info, + SScanSettings &settings +) +{ + if (!item) + return 0; + + if (m_vecItems->IsPlugin()) + { + info.strContent = "plugin"; + return 0; + } + + int found = 0; + // files view shouldn't need this check I think? + if (item->HasProgramInfoTag()) + m_database.GetScraperForPath\ + (item->GetProgramInfoTag()->m_strPath, info, settings, found); + else + m_database.GetScraperForPath(item->m_strPath, info, settings, found); + + return found; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::OnScan +( + const CStdString &strPath, + const SScraperInfo &info, + const SScanSettings &settings +) +{ + CGUIDialogProgramScan* pDialog = (CGUIDialogProgramScan*)m_gWindowManager.\ + GetWindow(WINDOW_DIALOG_PROGRAM_SCAN); + if (pDialog) + pDialog->StartScanning(strPath, info, settings, false); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Search the current directory for a string got from +/// the virtual keyboard +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::OnSearch() +{ + CStdString strSearch; + + if ( + !CGUIDialogKeyboard::ShowAndGetInput( + strSearch, g_localizeStrings.Get(16017), false + ) + ) return; + + strSearch.ToLower(); + if (m_dlgProgress) + { + m_dlgProgress->SetHeading(194); + m_dlgProgress->SetLine(0, strSearch); + m_dlgProgress->SetLine(1, ""); + m_dlgProgress->SetLine(2, ""); + m_dlgProgress->StartModal(); + m_dlgProgress->Progress(); + } + CFileItemList items; + DoSearch(strSearch, items); + + if (items.Size()) + { + CGUIDialogSelect* pDlgSelect = (CGUIDialogSelect*)m_gWindowManager.\ + GetWindow(WINDOW_DIALOG_SELECT); + pDlgSelect->Reset(); + pDlgSelect->SetHeading(283); + items.Sort(SORT_METHOD_LABEL, SORT_ORDER_ASC); + + for (int i = 0; i < (int)items.Size(); i++) + { + CFileItemPtr pItem = items[i]; + pDlgSelect->Add(pItem->GetLabel()); + } + + pDlgSelect->DoModal(); + + int iItem = pDlgSelect->GetSelectedLabel(); + if (iItem < 0) + { + if (m_dlgProgress) + m_dlgProgress->Close(); + + return ; + } + + CFileItemPtr pSelItem = items[iItem]; + + OnSearchItemFound(pSelItem.get()); + + if (m_dlgProgress) + m_dlgProgress->Close(); + } + else + { + if (m_dlgProgress) + m_dlgProgress->Close(); + + CGUIDialogOK::ShowAndGetInput(194, 284, 0, 0); + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief React on the selected search item +/// \param pItem Search result item +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::OnSearchItemFound(const CFileItem* pSelItem) +{ + if (pSelItem->m_bIsFolder) + { + CStdString strPath = pSelItem->m_strPath; + CStdString strParentPath; + CUtil::GetParentPath(strPath, strParentPath); + + Update(strParentPath); + + SetHistoryForPath(strParentPath); + + strPath = pSelItem->m_strPath; + CURL url(strPath); + if (pSelItem->IsSmb() && !CUtil::HasSlashAtEnd(strPath)) + strPath += "/"; + + for (int i = 0; i < m_vecItems->Size(); i++) + { + CFileItemPtr pItem = m_vecItems->Get(i); + if (pItem->m_strPath == strPath) + { + m_viewControl.SetSelectedItem(i); + break; + } + } + } + else + { + CStdString strPath; + CUtil::GetDirectory(pSelItem->m_strPath, strPath); + + Update(strPath); + + SetHistoryForPath(strPath); + + for (int i = 0; i < (int)m_vecItems->Size(); i++) + { + CFileItemPtr pItem = m_vecItems->Get(i); + if (pItem->m_strPath == pSelItem->m_strPath) + { + m_viewControl.SetSelectedItem(i); + break; + } + } + } + m_viewControl.SetFocused(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramBase::OnPlayMedia(int iItem) +{ + if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) + return false; + + CFileItemPtr pItem = m_vecItems->Get(iItem); + + // 'add source button' in empty root + if (pItem->m_strPath == "add" && + pItem->GetLabel() == g_localizeStrings.Get(1026)) + { + if (CGUIDialogMediaSource::ShowAndAddMediaSource("programs")) + { + Update(""); + return true; + } + return false; + } + + CFileItem item(*pItem); + if (pItem->IsProgramDb()) + { + item = CFileItem(*pItem->GetProgramInfoTag()); + item.m_lStartOffset = pItem->m_lStartOffset; + } + + PlayGame(&item); + + return true; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::PlayGame(const CFileItem *item) +{ + CFileItemList gameList; + int selectedFile = 1; + long startoffset = item->m_lStartOffset; + + if (item->IsStack() && + !g_guiSettings.GetBool("programfiles.treatstackasfile")) + { + CStdStringArray games; + GetStackedFiles(item->m_strPath, games); + + // show file stacking dialog + CGUIDialogFileStacking* dlg = \ + (CGUIDialogFileStacking*)m_gWindowManager.\ + GetWindow(WINDOW_DIALOG_FILESTACKING); + + if (dlg) + { + dlg->SetNumberOfFiles(games.size()); + dlg->DoModal(); + selectedFile = dlg->GetSelectedFile(); + + if (selectedFile < 1) + return; + } + + // add to our gane list + for (unsigned int i = 0; i < games.size(); i++) + { + CFileItemPtr gameItem(new CFileItem(games[i], false)); + gameList.Add(gameItem); + } + } + else + { + CFileItemPtr gameItem(new CFileItem(*item)); + gameList.Add(gameItem); + } + + bool bWait = g_guiSettings.GetBool( + "programfiles.waitforexit" + ); + bool bMinimize = g_guiSettings.GetBool( + "programfiles.minimizebeforelaunch" + ); + bool bReleaseSound = g_guiSettings.GetBool( + "programfiles.releasesoundbeforelaunch" + ); + + CUtil::SystemExecute( + "\"" + item->m_strPath + "\"", + bWait, bMinimize, bReleaseSound + ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramBase::PlayItem(int iItem) +{ + const CFileItemPtr pItem = m_vecItems->Get(iItem); + OnClick(iItem); +} \ No newline at end of file Index: xbmc/GUIWindowProgramBase.h =================================================================== --- xbmc/GUIWindowProgramBase.h (revision 0) +++ xbmc/GUIWindowProgramBase.h (revision 0) @@ -0,0 +1,55 @@ +#pragma once +#include "GUIMediaWindow.h" +#include "ProgramDatabase.h" +#include "PlayListPlayer.h" +#include "ThumbLoader.h" + +class CGUIWindowProgramBase : public CGUIMediaWindow, public IBackgroundLoaderObserver +{ +public: + CGUIWindowProgramBase(DWORD dwID, const CStdString &xmlFile); + virtual ~CGUIWindowProgramBase(void); + virtual bool OnMessage(CGUIMessage& message); + virtual bool OnAction(const CAction &action); + + void PlayGame(const CFileItem *item); + int GetResumeItemOffset(const CFileItem *item); + + void AddToDatabase(int iItem); + static void OnScan(const CStdString& strPath, const SScraperInfo& info, const PROGRAM::SScanSettings& settings); + virtual void OnInfo(CFileItem* pItem, const SScraperInfo& info); + static void UpdateProgramTitle(const CFileItem* pItem); + +protected: + virtual void UpdateButtons(); + virtual bool Update(const CStdString &strDirectory); + virtual bool GetDirectory(const CStdString &strDirectory, CFileItemList &items); + virtual void OnItemLoaded(CFileItem* pItem) {}; + virtual void OnPrepareFileItems(CFileItemList &items); + + virtual void GetContextButtons(int itemNumber, CContextButtons &buttons); + void GetNonContextButtons(int itemNumber, CContextButtons &buttons); + virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button); + virtual void OnAssignContent(int iItem, int iFound, SScraperInfo& info, PROGRAM::SScanSettings& settings) {}; + virtual void OnUnAssignContent(int iItem) {}; + //virtual void OnQueueItem(int iItem); + virtual void OnDeleteItem(int iItem); + virtual void DoSearch(const CStdString& strSearch, CFileItemList& items) {}; + virtual CStdString GetQuickpathName(const CStdString& strPath) const {return strPath;}; + + bool OnClick(int iItem); + void OnRestartItem(int iItem); + void PlayItem(int iItem); + virtual bool OnPlayMedia(int iItem); + bool ShowGameInfo(CFileItem *item, const SScraperInfo& info); + void GetStackedFiles(const CStdString &strFileName, std::vector &games); + + void OnSearch(); + void OnSearchItemFound(const CFileItem* pSelItem); + int GetScraperForItem(CFileItem *item, SScraperInfo &info, PROGRAM::SScanSettings& settings); + + CGUIDialogProgress* m_dlgProgress; + CProgramDatabase m_database; + + CProgramThumbLoader m_thumbLoader; +}; Index: xbmc/GUIWindowProgramFiles.cpp =================================================================== --- xbmc/GUIWindowProgramFiles.cpp (revision 0) +++ xbmc/GUIWindowProgramFiles.cpp (revision 0) @@ -0,0 +1,806 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "GUIWindowProgramFiles.h" +#include "Util.h" +#include "Picture.h" +#include "utils/GUIInfoManager.h" +#include "PlayListFactory.h" +#include "Application.h" +#include "NfoFile.h" +#include "PlayListPlayer.h" +#include "GUIPassword.h" +#include "GUIDialogMediaSource.h" +#include "GUIDialogContentSettings.h" +#include "GUIDialogProgramScan.h" +#include "FileSystem/MultiPathDirectory.h" +#include "utils/RegExp.h" +#include "GUIWindowManager.h" +#include "GUIDialogOK.h" +#include "GUIDialogYesNo.h" +#include "FileSystem/File.h" +#include "PlayList.h" +#include "Settings.h" +#include "GUISettings.h" +#include "LocalizeStrings.h" + +using namespace std; +using namespace XFILE; +using namespace PROGRAM; + + +#define CONTROL_STACK 7 +#define CONTROL_BTNSCAN 8 + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CGUIWindowProgramFiles::CGUIWindowProgramFiles() +: CGUIWindowProgramBase(WINDOW_PROGRAM_FILES, "MyPrograms.xml") +{ + m_stackingAvailable = true; + m_cleaningAvailable = true; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CGUIWindowProgramFiles::~CGUIWindowProgramFiles() +{ +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramFiles::OnMessage(CGUIMessage& message) +{ + + switch ( message.GetMessage() ) + { + + case GUI_MSG_WINDOW_INIT: + { + // check for a passed destination path + CStdString strDestination = message.GetStringParam(); + + if (!strDestination.IsEmpty()) + { + message.SetStringParam(""); + g_stSettings.m_iProgramStartWindow = GetID(); + + CLog::Log(LOGINFO, "Attempting to quickpath to: %s", + strDestination.c_str()); + + // reset directory path, as we have effectively cleared it here + m_history.ClearPathHistory(); + } + + // is this the first time accessing this window? + // a quickpath overrides the a default parameter + if (m_vecItems->m_strPath == "?" && strDestination.IsEmpty()) + { + m_vecItems->m_strPath = strDestination = \ + g_settings.m_defaultProgramSource; + + CLog::Log(LOGINFO, "Attempting to default to: %s", + strDestination.c_str()); + } + + // try to open the destination path + if (!strDestination.IsEmpty()) + { + // open root + if (strDestination.Equals("$ROOT")) { + m_vecItems->m_strPath = ""; + CLog::Log(LOGINFO, " Success! Opening root listing."); + } + else + { + // default parameters if the jump fails + m_vecItems->m_strPath = ""; + + bool bIsSourceName = false; + + SetupShares(); + VECSOURCES shares; + m_rootDir.GetSources(shares); + int iIndex = CUtil::GetMatchingSource( + strDestination, shares, bIsSourceName); + if (iIndex > -1) + { + bool bDoStuff = true; + if (iIndex < (int)shares.size() && shares[iIndex].m_iHasLock == 2) + { + CFileItem item(shares[iIndex]); + if (!g_passwordManager.IsItemUnlocked(&item, "programs")) + { + m_vecItems->m_strPath = ""; // no u don't + bDoStuff = false; + CLog::Log(LOGINFO, " Failure!" + " Failed to unlock destination path: %s", + strDestination.c_str()); + } + } + // set current directory to matching share + if (bDoStuff) + { + if (bIsSourceName) + m_vecItems->m_strPath = shares[iIndex].strPath; + else + m_vecItems->m_strPath = strDestination; + CLog::Log(LOGINFO, " Success!" + " Opened destination path: %s", + strDestination.c_str()); + } + } + else + { + CLog::Log(LOGERROR, " Failed!" + "Destination parameter (%s)" + " does not match a valid source!", + strDestination.c_str()); + } + } + + // check for network up + if (CUtil::IsRemote(m_vecItems->m_strPath) && !WaitForNetwork()) + m_vecItems->m_strPath.Empty(); + + SetHistoryForPath(m_vecItems->m_strPath); + } + + return CGUIWindowProgramBase::OnMessage(message); + } + break; + + + case GUI_MSG_CLICKED: + int iControl = message.GetSenderId(); + + if (iControl == CONTROL_STACK) + { + g_stSettings.m_iMyProgramStack++; + + if (g_stSettings.m_iMyProgramStack > STACK_SIMPLE) + g_stSettings.m_iMyProgramStack = STACK_NONE; + + g_settings.Save(); + UpdateButtons(); + Update( m_vecItems->m_strPath ); + } + + // list/thumb panel + else if ( m_viewControl.HasControl(iControl) ) + { + int iItem = m_viewControl.GetSelectedItem(); + int iAction = message.GetParam1(); + const CFileItemPtr pItem = m_vecItems->Get(iItem); + + if (iAction == ACTION_PLAYER_PLAY && pItem->m_bIsFolder && + !pItem->IsParentFolder() ) + { + if (pItem->m_bIsShareOrDrive) + return false; + + if (pItem->m_bIsFolder && !pItem->IsParentFolder()) + PlayItem(iItem); + + return true; + } + } + + if (m_viewControl.HasControl(message.GetSenderId())) + { + // list/thumb control + if (message.GetParam1() == ACTION_PLAYER_PLAY) + { + OnPlayMedia(m_viewControl.GetSelectedItem()); + return true; + } + } + } + + + return CGUIWindowProgramBase::OnMessage(message); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramFiles::UpdateButtons() +{ + + CGUIWindowProgramBase::UpdateButtons(); + const CGUIControl *stack = GetControl(CONTROL_STACK); + if (stack) + { + if (m_stackingAvailable) + { + CONTROL_ENABLE(CONTROL_STACK); + if (stack->GetControlType() == CGUIControl::GUICONTROL_RADIO) + { + SET_CONTROL_SELECTED( + GetID(), + CONTROL_STACK, + g_stSettings.m_iMyProgramStack == STACK_SIMPLE + ); + // Stack + SET_CONTROL_LABEL(CONTROL_STACK, 14000); + } + else + { + SET_CONTROL_LABEL( + CONTROL_STACK, + g_stSettings.m_iMyProgramStack + 14000 + ); + } + } + else + { + if (stack->GetControlType() == CGUIControl::GUICONTROL_RADIO) + { + // Stack + SET_CONTROL_LABEL(CONTROL_STACK, 14000); + } + + CONTROL_DISABLE(CONTROL_STACK); + } + } + +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramFiles::GetDirectory(const CStdString &strDirectory, CFileItemList &items) +{ + + if (!CGUIWindowProgramBase::GetDirectory(strDirectory, items)) + return false; + + SScraperInfo info2; + + m_stackingAvailable = false; + m_cleaningAvailable = false; + + if (!items.IsStack() && g_stSettings.m_iMyProgramStack != STACK_NONE) + items.Stack(); + + if ((!info2.strContent.IsEmpty() && + !info2.strContent.Equals("None")) && + items.GetContent().IsEmpty()) items.SetContent(info2.strContent.c_str()); + else items.SetContent("files"); + + items.SetThumbnailImage(""); + items.SetProgramThumb(); + + return true; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramFiles::OnPrepareFileItems(CFileItemList &items) +{ + CGUIWindowProgramBase::OnPrepareFileItems(items); + if (g_guiSettings.GetBool("programfiles.cleanstrings")) + { + for (int i = 0; i < (int)items.Size(); ++i) + { + CFileItemPtr item = items[i]; + + if ((item->m_bIsFolder && + !CUtil::IsInArchive(item->m_strPath)) || + m_cleaningAvailable) + item->CleanString(); + } + } + +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramFiles::OnClick(int iItem) +{ + if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) + return true; + + CFileItemPtr pItem = m_vecItems->Get(iItem); + CStdString strExtension; + CUtil::GetExtension(pItem->m_strPath, strExtension); + + if (strcmpi(strExtension.c_str(), ".nfo") == 0) // WTF?? + { + SScraperInfo info; + info.strPath = "allgames.xml"; + info.strContent = "games"; + info.strTitle = "GameInfo"; + OnInfo(pItem.get(), info); + return true; + } + + return CGUIWindowProgramBase::OnClick(iItem); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramFiles::OnPlayMedia(int iItem) +{ + if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) + return false; + + CFileItemPtr pItem = m_vecItems->Get(iItem); + + if (pItem->m_bIsShareOrDrive) + return false; + + if (pItem->m_strPath == "add" && + pItem->GetLabel() == g_localizeStrings.Get(1026)) + { + // 'add source button' in empty root + if (CGUIDialogMediaSource::ShowAndAddMediaSource("programs")) + { + Update(""); + return true; + } + return false; + } + else + { + AddFileToDatabase(pItem.get()); + + return CGUIWindowProgramBase::OnPlayMedia(iItem); + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramFiles::OnInfo(CFileItem* pItem, const SScraperInfo& info) +{ + if ( !pItem ) + return ; + + bool bFolder(false); + CStdString strFolder = ""; + CStdString strFile = pItem->m_strPath; + + if (pItem->m_bIsFolder && pItem->IsParentFolder()) + return; + + if (pItem->m_bIsShareOrDrive) + // oh no u don't + return; + + if (pItem->m_bIsFolder) + { + bFolder = true; + CFileItemList vecitems; + GetStackedDirectory(pItem->m_strPath, vecitems); + bool bFoundFile(false); + for (int i = 0; i < (int)vecitems.Size(); ++i) + { + CFileItemPtr item = vecitems[i]; + if (!item->m_bIsFolder) + { + if (item->IsProgram() && !item->IsNFO() && !item->IsPlayList() && + item->m_strPath.Find("-preview.") == -1) + { + bFoundFile = true; + strFile = item->m_strPath; + break; + } + } + } + + if (!bFoundFile) { + // no program file in this folder? + if (info.strContent.Equals("games")) + // + // 'game information', + // 'found no program files for this path', + // '', + // '' + // + CGUIDialogOK::ShowAndGetInput(14504, 14505, 20022, 20022); + + return; + } + } + + // setup our item with the label and thumb information + CFileItem item(strFile, false); + item.SetLabel(pItem->GetLabel()); + + // hack since our label sometimes contains extensions + if(!pItem->m_bIsFolder && + !g_guiSettings.GetBool("filelists.hideextensions") && + !pItem->IsLabelPreformated()) { + item.RemoveExtension(); + } + + item.SetCachedProgramThumb(); + if (!item.HasThumbnail()) + // inherit from the original item if it exists + item.SetThumbnailImage(pItem->GetThumbnailImage()); + + if(!info.strContent.Equals("plugin")) + AddFileToDatabase(&item); + else { + if (pItem->HasProgramInfoTag()) + *item.GetProgramInfoTag() = *pItem->GetProgramInfoTag(); + } + // we need to also request any thumbs also be applied to the folder item + if (pItem->m_bIsFolder) + item.SetProperty("set_folder_thumb", pItem->m_strPath); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramFiles::AddFileToDatabase(const CFileItem* pItem) +{ + if (!pItem->IsProgram()) + return; + if ( pItem->IsNFO()) + return; + + m_database.AddFile(pItem->m_strPath); + + if (pItem->IsStack()) + { + vector games; + GetStackedFiles(pItem->m_strPath, games); + for (unsigned int i = 0; i < games.size(); i++) { + CFileItem item(games[i], false); + m_database.AddFile(item.m_strPath); + } + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramFiles::OnUnAssignContent(int iItem) +{ + bool bCanceled; + if (CGUIDialogYesNo::ShowAndGetInput(20375, 20340, 20341, 20022, bCanceled)) + { + m_database.RemoveContentForPath\ + (m_vecItems->Get(iItem)->m_strPath,m_dlgProgress); + CUtil::DeleteProgramDatabaseDirectoryCache(); + } + else + { + if (!bCanceled) + { + SScraperInfo info; + SScanSettings settings; + m_database.SetScraperForPath\ + (m_vecItems->Get(iItem)->m_strPath,info,settings); + } + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramFiles::OnAssignContent +( + int iItem, + int iFound, + SScraperInfo &info, + SScanSettings &settings +) +{ + if (!g_guiSettings.GetBool("programlibrary.enabled")) + return; + + CFileItemPtr item = m_vecItems->Get(iItem); + bool bScan=false; + if (iFound == 0) + m_database.GetScraperForPath(item->m_strPath,info, settings,iFound); + SScraperInfo info2 = info; + SScanSettings settings2 = settings; + + if (CGUIDialogContentSettings::Show(info2, settings2, bScan)) + { + if((info2.strContent.IsEmpty() || info2.strContent.Equals("None")) && + (!info.strContent.IsEmpty() && !info.strContent.Equals("None"))) + OnUnAssignContent(iItem); + + m_database.Open(); + m_database.SetScraperForPath(item->m_strPath,info2,settings2); + m_database.Close(); + + if (bScan) + { + GetScraperForItem(item.get(), info2, settings2); + OnScan(item->m_strPath, info2, settings2); + } + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramFiles::GetStackedDirectory +( + const CStdString &strPath, + CFileItemList &items +) +{ + items.Clear(); + m_rootDir.GetDirectory(strPath, items); + items.Stack(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramFiles::GetContextButtons +( + int itemNumber, + CContextButtons &buttons +) +{ + CFileItemPtr item; + if (itemNumber >= 0 && itemNumber < m_vecItems->Size()) + item = m_vecItems->Get(itemNumber); + + CGUIDialogProgramScan *pScanDlg = (CGUIDialogProgramScan *)\ + m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRAM_SCAN); + if (item) + { + // are we in the playlists location? + if (m_vecItems->IsVirtualDirectoryRoot()) + { + // get the usual shares, and anything for all media windows + CGUIDialogContextMenu::GetContextButtons( + "programs", + item, + buttons + ); + CGUIMediaWindow::GetContextButtons( + itemNumber, + buttons + ); + // add scan button somewhere here + if (pScanDlg && pScanDlg->IsScanning()) + // Stop Scanning + buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353); + + if + ( + g_guiSettings.GetBool("programlibrary.enabled") && + !item->IsDVD() && item->m_strPath != "add" && + ( + g_settings.m_vecProfiles[ + g_settings.m_iLastLoadedProfileIndex + ].canWriteDatabases() || + g_passwordManager.bMasterUser + ) + ) + { + CGUIDialogProgramScan *pScanDlg = \ + (CGUIDialogProgramScan*)m_gWindowManager.\ + GetWindow(WINDOW_DIALOG_PROGRAM_SCAN + ); + + if ( !pScanDlg || (pScanDlg && !pScanDlg->IsScanning()) ) + buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20333); + + CProgramDatabase database; + database.Open(); + SScraperInfo info; + + if (item && database.GetScraperForPath(item->m_strPath,info)) + { + if (!info.strPath.IsEmpty() && !info.strContent.IsEmpty()) + if (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning())) + buttons.Add(CONTEXT_BUTTON_SCAN, 13349); + } + } + } + else + { + CGUIWindowProgramBase::GetContextButtons(itemNumber, buttons); + if (!item->GetPropertyBOOL("pluginreplacecontextitems")) + { + // Game Info button + if (pScanDlg && pScanDlg->IsScanning()) + buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353); + + if (g_guiSettings.GetBool("programlibrary.enabled") && + ( + g_settings.m_vecProfiles[ + g_settings.m_iLastLoadedProfileIndex + ].canWriteDatabases() || + g_passwordManager.bMasterUser + ) + ) + { + SScraperInfo info; + PROGRAM::SScanSettings settings; + int iFound = GetScraperForItem(item.get(), info, settings); + + int infoString = 14504; + if (item->m_bIsFolder) + { + if ( !pScanDlg || (pScanDlg && !pScanDlg->IsScanning()) ) + buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20333); + + if ( iFound == 0 ) + { + // scraper not set - allow game information or set content + CStdString strPath(item->m_strPath); + CUtil::AddSlashAtEnd(strPath); + if ((info.strContent.Equals("games") && + m_database.HasGameInfo(strPath) )) + buttons.Add(CONTEXT_BUTTON_INFO, infoString); + } + else + { + // scraper found - allow game information, scan for new content, + // or set different type of content + buttons.Add(CONTEXT_BUTTON_INFO, infoString); + if (!info.strPath.IsEmpty() && !info.strContent.IsEmpty()) + if (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning())) + buttons.Add(CONTEXT_BUTTON_SCAN, 13349); + } + } + else + { + // single file + if ((info.strContent.Equals("games") && + (iFound > 0 || m_database.HasGameInfo(item->m_strPath)))) + { + buttons.Add(CONTEXT_BUTTON_INFO, infoString); + } + m_database.Open(); + if (!item->IsParentFolder()) + { + if (!m_database.HasGameInfo(item->m_strPath)) + // 'Add to Database' button + buttons.Add(CONTEXT_BUTTON_ADD_TO_LIBRARY, 527); + } + m_database.Close(); + } + } + } + if (!item->IsParentFolder()) + { + if (g_guiSettings.GetBool("filelists.allowfiledeletion")) + { // file operations are allowed + if (!item->IsReadOnly()) + { + buttons.Add(CONTEXT_BUTTON_DELETE, 117); + buttons.Add(CONTEXT_BUTTON_RENAME, 118); + } + } + } + if (m_vecItems->IsPlugin() && item->HasProgramInfoTag() && + !item->GetPropertyBOOL("pluginreplacecontextitems")) + // only game information for now + buttons.Add(CONTEXT_BUTTON_INFO,13346); + } + } + else + { + if (pScanDlg && pScanDlg->IsScanning()) + // Stop Scanning + buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353); + } + + if(!(item && item->GetPropertyBOOL("pluginreplacecontextitems"))) + { + if (!m_vecItems->IsVirtualDirectoryRoot()) + buttons.Add(CONTEXT_BUTTON_SWITCH_MEDIA, 523); + + CGUIWindowProgramBase::GetNonContextButtons(itemNumber, buttons); + } + +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramFiles::OnContextButton +( + int itemNumber, + CONTEXT_BUTTON button +) +{ + CFileItemPtr item; + + if (itemNumber >= 0 && itemNumber < m_vecItems->Size()) + item = m_vecItems->Get(itemNumber); + + if ( m_vecItems->IsVirtualDirectoryRoot() && item) + { + if (CGUIDialogContextMenu::OnContextButton("programs", item, button)) + { + if (button == CONTEXT_BUTTON_REMOVE_SOURCE) + OnUnAssignContent(itemNumber); + Update(""); + return true; + } + } + + switch (button) + { + case CONTEXT_BUTTON_SWITCH_MEDIA: + CGUIDialogContextMenu::SwitchMedia\ + ("programs", m_vecItems->m_strPath); + return true; + + case CONTEXT_BUTTON_SET_CONTENT: + { + SScraperInfo info; + SScanSettings settings; + + // files view shouldn't need this check I think? + if (item->HasProgramInfoTag()) + m_database.GetScraperForPath( + item->GetProgramInfoTag()->m_strPath, info, settings + ); + else + m_database.GetScraperForPath(item->m_strPath, info, settings); + OnAssignContent(itemNumber,0, info, settings); + + return true; + } + + case CONTEXT_BUTTON_ADD_TO_LIBRARY: + AddToDatabase(itemNumber); + return true; + + default: + break; + } + return CGUIWindowProgramBase::OnContextButton(itemNumber, button); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramFiles::LoadPlayList(const CStdString& strPlayList) +{ +} Index: xbmc/GUIWindowProgramFiles.h =================================================================== --- xbmc/GUIWindowProgramFiles.h (revision 0) +++ xbmc/GUIWindowProgramFiles.h (revision 0) @@ -0,0 +1,60 @@ +#pragma once + +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GUIWindowProgramBase.h" + +namespace PROGRAM +{ + class CProgramInfoScanner; +} + +class CGUIWindowProgramFiles : public CGUIWindowProgramBase +{ +public: + CGUIWindowProgramFiles(void); + virtual ~CGUIWindowProgramFiles(void); + virtual bool OnMessage(CGUIMessage& message); + + void GetStackedDirectory(const CStdString &strPath, CFileItemList &items); + virtual void OnInfo(CFileItem* pItem, const SScraperInfo& info); +protected: + virtual bool GetDirectory(const CStdString &strDirectory, CFileItemList &items); + virtual bool OnPlayMedia(int iItem); + virtual void AddFileToDatabase(const CFileItem* pItem); + virtual void OnPrepareFileItems(CFileItemList &items); + virtual void UpdateButtons(); + virtual bool OnClick(int iItem); + virtual void GetContextButtons(int itemNumber, CContextButtons &buttons); + virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button); + + //virtual void OnQueueItem(int iItem); + virtual void OnAssignContent(int iItem, int iFound, SScraperInfo& info, PROGRAM::SScanSettings& settings); + virtual void OnUnAssignContent(int iItem); + + virtual void LoadPlayList(const CStdString& strFileName); + void PlayFolder(const CFileItem* pItem); + +private: + bool m_stackingAvailable; + bool m_cleaningAvailable; +}; Index: xbmc/GUIWindowProgramInfo.cpp =================================================================== --- xbmc/GUIWindowProgramInfo.cpp (revision 0) +++ xbmc/GUIWindowProgramInfo.cpp (revision 0) @@ -0,0 +1,771 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "GUIWindow.h" +#include "GUIWindowProgramInfo.h" +#include "Util.h" +#include "Picture.h" +#include "GUIImage.h" +#include "StringUtils.h" +#include "GUIWindowProgramBase.h" +#include "GUIWindowProgramFiles.h" +#include "GUIDialogFileBrowser.h" +#include "utils/GUIInfoManager.h" +#include "ProgramInfoScanner.h" +#include "Application.h" +#include "ProgramInfoTag.h" +#include "GUIWindowManager.h" +#include "GUIDialogOK.h" +#include "GUIDialogYesNo.h" +#include "GUIDialogSelect.h" +#include "GUIDialogProgress.h" +#include "FileSystem/Directory.h" +#include "FileSystem/File.h" +#include "FileItem.h" +#include "MediaManager.h" +#include "utils/AsyncFileCopy.h" +#include "Settings.h" +#include "AdvancedSettings.h" +#include "GUISettings.h" +#include "LocalizeStrings.h" + + +using namespace std; +using namespace XFILE; + + +#define CONTROL_TITLE 20 +#define CONTROL_DEVELOPER 21 +#define CONTROL_PUBLISHER 22 +#define CONTROL_GENRE 23 +#define CONTROL_YEAR 24 +#define CONTROL_DESCRIPTION 25 +#define CONTROL_PLOT 26 +#define CONTROL_TAGLINE 25 +#define CONTROL_RATING_AND_VOTES 30 +#define CONTROL_TITLE_AND_YEAR 33 +#define CONTROL_PREVIEW 38 +#define CONTROL_IMAGE 3 +#define CONTROL_TEXTAREA 4 +#define CONTROL_BTN_REFRESH 6 +#define CONTROL_DISC 7 +#define CONTROL_BTN_PLAY 8 +#define CONTROL_BTN_GET_THUMB 10 +#define CONTROL_BTN_PLAY_PREVIEW 11 +#define CONTROL_BTN_GET_FANART 12 +#define CONTROL_LIST 50 + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CGUIWindowProgramInfo::CGUIWindowProgramInfo(void) + : CGUIDialog(WINDOW_PROGRAM_INFO, "DialogProgramInfo.xml"), + m_gameItem(new CFileItem) +{ + m_hasUpdatedThumb = false; + m_bRefreshAll = true; + m_bRefresh = false; + m_castList = new CFileItemList; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CGUIWindowProgramInfo::~CGUIWindowProgramInfo(void) {} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramInfo::OnMessage(CGUIMessage& message) +{ + switch (message.GetMessage()) + { + case GUI_MSG_WINDOW_DEINIT: + { + } + break; + + case GUI_MSG_WINDOW_INIT: + { + m_dlgProgress = (CGUIDialogProgress*)m_gWindowManager.\ + GetWindow(WINDOW_DIALOG_PROGRESS); + + m_bRefresh = false; + m_bRefreshAll = true; + m_hasUpdatedThumb = false; + m_bViewReview = true; + + CGUIDialog::OnMessage(message); + CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), CONTROL_DISC); + OnMessage(msg); + + for (int i = 0; i < 1000; ++i) + { + CStdString strItem; + strItem.Format("DVD#%03i", i); + CGUIMessage msg2(GUI_MSG_LABEL_ADD, GetID(), CONTROL_DISC); + msg2.SetLabel(strItem); + OnMessage(msg2); + } + + SET_CONTROL_HIDDEN(CONTROL_DISC); + Refresh(); + + CONTROL_ENABLE_ON_CONDITION( + CONTROL_BTN_REFRESH, + ( + g_settings.m_vecProfiles[ + g_settings.m_iLastLoadedProfileIndex + ].canWriteDatabases() || + g_passwordManager.bMasterUser + ) + ); + + CONTROL_ENABLE_ON_CONDITION( + CONTROL_BTN_GET_THUMB, + ( + g_settings.m_vecProfiles[ + g_settings.m_iLastLoadedProfileIndex + ].canWriteDatabases() || + g_passwordManager.bMasterUser + ) + ); + + PROGRAMDB_CONTENT_TYPE type = GetContentType(m_gameItem.get()); + if (type == PROGRAMDB_CONTENT_GAMES) + CONTROL_ENABLE_ON_CONDITION( + CONTROL_BTN_GET_FANART, + ( + g_settings.m_vecProfiles[ + g_settings.m_iLastLoadedProfileIndex + ].canWriteDatabases() || + g_passwordManager.bMasterUser + ) + ); + else + CONTROL_DISABLE(CONTROL_BTN_GET_FANART); + + return true; + } + break; + + + case GUI_MSG_CLICKED: + { + int iControl = message.GetSenderId(); + if (iControl == CONTROL_BTN_REFRESH) + { + m_bRefresh = true; + Close(); + return true; + } + else if (iControl == CONTROL_BTN_PLAY) Play(); + else if (iControl == CONTROL_BTN_GET_THUMB) OnGetThumb(); + else if (iControl == CONTROL_BTN_PLAY_PREVIEW) PlayPreview(); + else if (iControl == CONTROL_BTN_GET_FANART) OnGetFanart(); + else if (iControl == CONTROL_LIST) + { + int iAction = message.GetParam1(); + if (ACTION_SELECT_ITEM == iAction || + ACTION_MOUSE_LEFT_CLICK == iAction) + { + CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), iControl); + OnMessage(msg); + int iItem = msg.GetParam1(); + if (iItem < 0) break; + CStdString strFind; + strFind.Format(" %s ", g_localizeStrings.Get(20347)); + } + } + } break; + } + + return CGUIDialog::OnMessage(message); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramInfo::SetGame(const CFileItem *item) +{ + CProgramThumbLoader loader; + *m_gameItem = *item; + + PROGRAMDB_CONTENT_TYPE type = GetContentType(m_gameItem.get()); + + // set fanart property for games + if (type == PROGRAMDB_CONTENT_GAMES) + { + m_gameItem->CacheFanart(); + if (CFile::Exists(m_gameItem->GetCachedFanart())) + m_gameItem->SetProperty("fanart_image", m_gameItem->GetCachedFanart()); + } + loader.LoadItem(m_gameItem.get()); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramInfo::Update() +{ + CStdString strTmp; + strTmp = m_gameItem->GetProgramInfoTag()->m_strTitle; + strTmp.Trim(); + SetLabel(CONTROL_TITLE, strTmp); + + strTmp = m_gameItem->GetProgramInfoTag()->m_strDeveloper; + strTmp.Trim(); + SetLabel(CONTROL_DEVELOPER, strTmp); + + strTmp = m_gameItem->GetProgramInfoTag()->m_strPublisher; + strTmp.Trim(); + SetLabel(CONTROL_PUBLISHER, strTmp); + + strTmp = m_gameItem->GetProgramInfoTag()->m_strGenre; + strTmp.Trim(); + SetLabel(CONTROL_GENRE, strTmp); + + strTmp = m_gameItem->GetProgramInfoTag()->m_strDescription; + strTmp.Trim(); + SetLabel(CONTROL_DESCRIPTION, strTmp); + + strTmp = m_gameItem->GetProgramInfoTag()->m_strTagLine; + strTmp.Trim(); + SetLabel(CONTROL_TAGLINE, strTmp); + + strTmp = m_gameItem->GetProgramInfoTag()->m_strPlot; + strTmp.Trim(); + SetLabel(CONTROL_PLOT, strTmp); + + strTmp = m_gameItem->GetProgramInfoTag()->m_strPreviewVideo; + strTmp.Trim(); + SetLabel(CONTROL_PREVIEW, strTmp); + + CStdString strYear; + if (m_gameItem->GetProgramInfoTag()->m_iYear) + strYear.Format("%i", m_gameItem->GetProgramInfoTag()->m_iYear); + SetLabel(CONTROL_YEAR, strYear); + + CStdString strRating_And_Votes; + // only non-zero ratings are of interest + if (m_gameItem->GetProgramInfoTag()->m_fRating != 0.0f) + strRating_And_Votes.Format("%03.1f (%s %s)", + m_gameItem->GetProgramInfoTag()->m_fRating, + m_gameItem->GetProgramInfoTag()->m_strVotes, + g_localizeStrings.Get(20350)); + SetLabel(CONTROL_RATING_AND_VOTES, strRating_And_Votes); + + // setup plot text area + strTmp = m_gameItem->GetProgramInfoTag()->m_strPlot; + strTmp.Trim(); + SetLabel(CONTROL_TEXTAREA, strTmp); + + if (m_bViewReview) + { + SET_CONTROL_HIDDEN(CONTROL_TEXTAREA); + SET_CONTROL_VISIBLE(CONTROL_LIST); + } + + CONTROL_ENABLE(CONTROL_BTN_PLAY); + + // update the thumbnail + const CGUIControl* pControl = GetControl(CONTROL_IMAGE); + if (pControl) + { + CGUIImage* pImageControl = (CGUIImage*)pControl; + pImageControl->FreeResources(); + pImageControl->SetFileName(m_gameItem->GetThumbnailImage()); + } + // tell our GUI to completely reload all controls (as some of them + // are likely to have had this image in use so will need refreshing) + if (m_hasUpdatedThumb) + { + CGUIMessage reload(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS); + g_graphicsContext.SendMessage(reload); + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramInfo::Refresh() +{ + // quietly return if Internet lookups are disabled + if (!g_guiSettings.GetBool("network.enableinternet")) { + Update(); + return ; + } + + try + { + OutputDebugString("Refresh\n"); + + CStdString strImage = \ + m_gameItem->GetProgramInfoTag()->m_strPictureURL.GetFirstThumb().m_url; + + bool hasUpdatedThumb = false; + CStdString thumbImage = m_gameItem->GetThumbnailImage(); + + if (thumbImage.IsEmpty()) + thumbImage = m_gameItem->GetCachedProgramThumb(); + + if (!CFile::Exists(thumbImage)) { + // don't have a thumb already, try and grab one + m_gameItem->SetUserProgramThumb(); + if (m_gameItem->GetThumbnailImage() != thumbImage) + thumbImage = m_gameItem->GetThumbnailImage(); + + if (!CFile::Exists(thumbImage) && strImage.size() > 0) + CScraperUrl::DownloadThumbnail( + thumbImage, + m_gameItem->GetProgramInfoTag()->m_strPictureURL.GetFirstThumb() + ); + } + Update(); + } + catch (...) + { + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramInfo::NeedRefresh() const { return m_bRefresh; } + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramInfo::RefreshAll() const { return m_bRefreshAll; } + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +PROGRAMDB_CONTENT_TYPE CGUIWindowProgramInfo::GetContentType +( + const CFileItem *pItem +)const +{ + PROGRAMDB_CONTENT_TYPE type = PROGRAMDB_CONTENT_GAMES; + return type; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief React on the selected search item +/// \param pItem Search result item +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramInfo::OnSearchItemFound(const CFileItem* pItem) +{ + PROGRAMDB_CONTENT_TYPE type = GetContentType(pItem); + + CProgramDatabase db; + + if (!db.Open()) + return; + + CProgramInfoTag gameDetails; + + if (type == PROGRAMDB_CONTENT_GAMES) + db.GetGameInfo(pItem->m_strPath, gameDetails, + pItem->GetProgramInfoTag()->m_iDbId); + db.Close(); + + CFileItem item(*pItem); + *item.GetProgramInfoTag() = gameDetails; + SetGame(&item); + + // refresh our window entirely + Close(); + DoModal(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramInfo::Play(bool resume) +{ + CFileItem game(*m_gameItem->GetProgramInfoTag()); + + if (m_gameItem->GetProgramInfoTag()->m_strFileNameAndPath.IsEmpty()) + game.m_strPath = m_gameItem->m_strPath; + + CGUIWindowProgramFiles* pWindow = \ + (CGUIWindowProgramFiles*)m_gWindowManager.GetWindow(WINDOW_PROGRAM_FILES); + + if (pWindow) { + // close our dialog + Close(true); + //pWindow->PlayMedia(&game); + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Get Thumb from user choice. +/// +/// Options are: +/// 1. Current thumb +/// 2. IMDb thumb +/// 3. Local thumb +/// 4. No thumb (if no Local thumb is available) +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramInfo::OnGetThumb() +{ + CFileItemList items; + + // Current thumb + if (CFile::Exists(m_gameItem->GetThumbnailImage())) { + CFileItemPtr item(new CFileItem("thumb://Current", false)); + item->SetThumbnailImage(m_gameItem->GetThumbnailImage()); + item->SetLabel(g_localizeStrings.Get(20016)); + items.Add(item); + } + + // Grab the thumbnails from the web + int i=1; + for (std::vector::iterator iter = \ + m_gameItem->GetProgramInfoTag()->m_strPictureURL.m_url.begin();iter != \ + m_gameItem->GetProgramInfoTag()->m_strPictureURL.m_url.end();++iter) + { + if (iter->m_type == CScraperUrl::URL_TYPE_SEASON) + continue; + + CStdString strItemPath; + strItemPath.Format("thumb://Remote%i",i++); + + CFileItemPtr item( + new CFileItem(strItemPath, false) + ); + + item->SetThumbnailImage("http://this.is/a/thumb/from/the/web"); + item->SetIconImage("DefaultPicture.png"); + item->GetProgramInfoTag()->m_strPictureURL.m_url.push_back(*iter); + item->SetLabel(g_localizeStrings.Get(415)); + item->SetProperty("labelonthumbload", g_localizeStrings.Get(20015)); + + // make sure any previously cached thumb is removed + if (CFile::Exists(item->GetCachedPictureThumb())) + CFile::Delete(item->GetCachedPictureThumb()); + items.Add(item); + } + + CStdString cachedLocalThumb; + CStdString localThumb(m_gameItem->GetUserProgramThumb()); + if (CFile::Exists(localThumb)) + { + CUtil::AddFileToFolder( + g_advancedSettings.m_cachePath, + "localthumb.jpg", + cachedLocalThumb + ); + CPicture pic; + pic.DoCreateThumbnail(localThumb, cachedLocalThumb); + CFileItemPtr item( + new CFileItem("thumb://Local", false) + ); + item->SetThumbnailImage(cachedLocalThumb); + item->SetLabel(g_localizeStrings.Get(20017)); + items.Add(item); + } + else + { + // no local thumb exists, so we are just using + // the IMDb thumb or cached thumb which is + // probably the IMDb thumb. These could be wrong, + // so allow the user to delete the incorrect thumb + CFileItemPtr item(new CFileItem("thumb://None", false)); + item->SetIconImage("DefaultProgram.png"); + item->SetLabel(g_localizeStrings.Get(20018)); + items.Add(item); + } + + CStdString result; + VECSOURCES sources(g_settings.m_programSources); + g_mediaManager.GetLocalDrives(sources); + if (!CGUIDialogFileBrowser::ShowAndGetImage\ + (items, sources, g_localizeStrings.Get(20019), result)) + // user cancelled + return; + + if (result == "thumb://Current") + // user chose the one they have + return; + + // delete the thumbnail if that's what the user wants, + // else overwrite with the new thumbnail + CFileItem item(*m_gameItem->GetProgramInfoTag()); + CStdString cachedThumb(item.GetCachedProgramThumb()); + + if (result.Left(14) == "thumb://Remote") + { + CStdString strFile; + CFileItem chosen(result, false); + CStdString thumb = chosen.GetCachedPictureThumb(); + if (CFile::Exists(thumb)) + { + // NOTE: This could fail if the thumbloader + // was too slow and the user too impatient + CFile::Cache(thumb, cachedThumb); + } + else + result = "thumb://None"; + } + else if (result == "thumb://Local") + CFile::Cache(cachedLocalThumb, cachedThumb); + else if (CFile::Exists(result)) + { + CPicture pic; + pic.DoCreateThumbnail(result, cachedThumb); + } + else + result = "thumb://None"; + + if (result == "thumb://None") { + CFile::Delete(m_gameItem->GetCachedProgramThumb()); + cachedThumb.Empty(); + } + + // to get them new thumbs to show + CUtil::DeleteProgramDatabaseDirectoryCache(); + m_gameItem->SetThumbnailImage(cachedThumb); + if (m_gameItem->HasProperty("set_folder_thumb")) + { + // have a folder thumb to set as well + } + + m_hasUpdatedThumb = true; + + // Update our screen + Update(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Allow user to select a Fanart +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramInfo::OnGetFanart() +{ + CFileItemList items; + + // ensure the fanart is unpacked + m_gameItem->GetProgramInfoTag()->m_fanart.Unpack(); + + // Grab the thumbnails from the web + CStdString strPath; + CUtil::AddFileToFolder(g_advancedSettings.m_cachePath,"fanartthumbs",strPath); + CUtil::WipeDir(strPath); + + DIRECTORY::CDirectory::Create(strPath); + + for ( + unsigned int i = 0; + i < m_gameItem->GetProgramInfoTag()->m_fanart.GetNumFanarts(); + i++ + ) + { + CStdString strItemPath; + strItemPath.Format("fanart://Remote%i",i); + CFileItemPtr item(new CFileItem(strItemPath, false)); + + item->SetThumbnailImage("http://this.is/a/thumb/from/the/web"); + item->SetIconImage("DefaultPicture.png"); + item->GetProgramInfoTag()->m_fanart = \ + m_gameItem->GetProgramInfoTag()->m_fanart; + item->SetProperty("fanart_number", (int)i); + item->SetLabel(g_localizeStrings.Get(415)); + item->SetProperty("labelonthumbload", g_localizeStrings.Get(20015)); + + // make sure any previously cached thumb is removed + if (CFile::Exists(item->GetCachedPictureThumb())) + CFile::Delete(item->GetCachedPictureThumb()); + items.Add(item); + } + + CFileItem item(*m_gameItem->GetProgramInfoTag()); + CStdString cachedThumb(item.GetCachedFanart()); + + CStdString strLocal = item.CacheFanart(true); + if (!strLocal.IsEmpty()) + { + CFileItemPtr itemLocal( + new CFileItem("fanart://Local", false) + ); + itemLocal->SetThumbnailImage(strLocal); + itemLocal->SetLabel(g_localizeStrings.Get(20017)); + items.Add(itemLocal); + } + + if (CFile::Exists(cachedThumb)) + { + CFileItemPtr itemCurrent( + new CFileItem("fanart://Current", false) + ); + itemCurrent->SetThumbnailImage(cachedThumb); + itemCurrent->SetLabel(g_localizeStrings.Get(20016)); + items.Add(itemCurrent); + } + + CFileItemPtr itemNone( + new CFileItem("fanart://None", false) + ); + itemNone->SetIconImage("DefaultProgram.png"); + itemNone->SetLabel(g_localizeStrings.Get(20018)); + items.Add(itemNone); + + CStdString result; + VECSOURCES sources(g_settings.m_programSources); + g_mediaManager.GetLocalDrives(sources); + bool flip = false; + + if (!CGUIDialogFileBrowser::ShowAndGetImage(items, sources, + g_localizeStrings.Get(20019), result, &flip) || + result.Equals("fanart://Current")) + // user cancelled + return; + + if (CFile::Exists(cachedThumb)) + CFile::Delete(cachedThumb); + + if (result.Equals("fanart://Local")) + result = strLocal; + + if (result.Left(15) == "fanart://Remote") + { + int iFanart = atoi(result.Mid(15).c_str()); + // set new primary fanart, and update our database accordingly + m_gameItem->GetProgramInfoTag()->m_fanart.SetPrimaryFanart(iFanart); + CProgramDatabase db; + if (db.Open()) { + db.UpdateFanart(*m_gameItem, GetContentType(m_gameItem.get())); + db.Close(); + } + + // download the fullres fanart image + CStdString tempFile = "special://temp/fanart_download.jpg"; + CAsyncFileCopy downloader; + bool succeeded = downloader.Copy( + m_gameItem->GetProgramInfoTag()->m_fanart.GetImageURL(), + tempFile, g_localizeStrings.Get(13413)); + if (succeeded) + { + CPicture pic; + if (flip) + pic.ConvertFile(tempFile, cachedThumb, 0, 1920, -1, 100, true); + else + pic.CacheImage(tempFile, cachedThumb); + } + CFile::Delete(tempFile); + + if (!succeeded) + // failed or cancelled download, + // so don't do anything + return; + } + else if (CFile::Exists(result)) + { + // local file... + + CPicture pic; + + if (flip) + pic.ConvertFile(result, cachedThumb,0,1920,-1,100,true); + else + pic.CacheImage(result, cachedThumb); + } + + // to get them new thumbs to show + CUtil::DeleteProgramDatabaseDirectoryCache(); + if (CFile::Exists(cachedThumb)) + m_gameItem->SetProperty("fanart_image", cachedThumb); + else + m_gameItem->ClearProperty("fanart_image"); + m_hasUpdatedThumb = true; + + // Update our screen + Update(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramInfo::PlayPreview() +{ + CFileItem item; + item.m_strPath = m_gameItem->GetProgramInfoTag()->m_strPreviewVideo; + + *item.GetProgramInfoTag() = *m_gameItem->GetProgramInfoTag(); + + item.GetProgramInfoTag()->m_strTitle.Format( + "%s (%s)", + m_gameItem->GetProgramInfoTag()->m_strTitle.c_str(), + g_localizeStrings.Get(20410) + ); + + item.SetThumbnailImage(m_gameItem->GetThumbnailImage()); + + item.GetProgramInfoTag()->m_iDbId = -1; + + // Close the dialog. + Close(true); + + if (item.IsPlayList()) + g_application.getApplicationMessenger().MediaPlay(item); + else + g_application.getApplicationMessenger().PlayFile(item); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramInfo::SetLabel(int iControl, const CStdString &strLabel) +{ + if (strLabel.IsEmpty()) + // "Not available" + SET_CONTROL_LABEL(iControl, 416); + else + SET_CONTROL_LABEL(iControl, strLabel); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +const CStdString& CGUIWindowProgramInfo::GetThumbnail() const +{ + return m_gameItem->GetThumbnailImage(); +} Index: xbmc/GUIWindowProgramInfo.h =================================================================== --- xbmc/GUIWindowProgramInfo.h (revision 0) +++ xbmc/GUIWindowProgramInfo.h (revision 0) @@ -0,0 +1,68 @@ +#pragma once + +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GUIDialog.h" +#include "GUIListItem.h" +#include "GUIWindowProgramBase.h" +#include "GUIWindowProgramFiles.h" + +class CFileItem; + +class CGUIWindowProgramInfo : + public CGUIDialog +{ +public: + CGUIWindowProgramInfo(void); + virtual ~CGUIWindowProgramInfo(void); + virtual bool OnMessage(CGUIMessage& message); + void SetGame(const CFileItem *item); + bool NeedRefresh() const; + bool RefreshAll() const; + bool HasUpdatedThumb() const { return m_hasUpdatedThumb; }; + + const CStdString &GetThumbnail() const; + virtual CFileItemPtr GetCurrentListItem(int offset = 0) { return m_gameItem; } + const CFileItemList& CurrentDirectory() const { return *m_castList; }; + virtual bool HasListItems() const { return true; }; +protected: + void Refresh(); + void Update(); + void SetLabel(int iControl, const CStdString& strLabel); + PROGRAMDB_CONTENT_TYPE GetContentType(const CFileItem *pItem) const; + + void OnSearch(CStdString& strSearch); + void DoSearch(CStdString& strSearch, CFileItemList& items); + void OnSearchItemFound(const CFileItem* pItem); + void Play(bool resume = false); + void OnGetThumb(); + void OnGetFanart(); + void PlayPreview(); + + CFileItemPtr m_gameItem; + CFileItemList *m_castList; + bool m_bViewReview; + bool m_bRefresh; + bool m_bRefreshAll; + bool m_hasUpdatedThumb; + CGUIDialogProgress* m_dlgProgress; +}; Index: xbmc/GUIWindowProgramNav.cpp =================================================================== --- xbmc/GUIWindowProgramNav.cpp (revision 24004) +++ xbmc/GUIWindowProgramNav.cpp (working copy) @@ -1,434 +1,737 @@ -/* - * Copyright (C) 2005-2009 Team XBMC - * http://www.xbmc.org - * - * 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, 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 XBMC; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * http://www.gnu.org/copyleft/gpl.html - * - */ +/////////////////////////////////////////////////////////// +/// \file GUIProgramNav.cpp +/////////////////////////////////////////////////////////// + +//includes #include "stdafx.h" #include "GUIUserMessages.h" #include "GUIWindowProgramNav.h" +#include "GUIWindowProgramFiles.h" +#include "utils/GUIInfoManager.h" #include "Util.h" -#include "utils/GUIInfoManager.h" -#include "utils/log.h" +#include "utils/RegExp.h" +#include "PlayListM3U.h" +#include "PlayListPlayer.h" #include "GUIPassword.h" #include "GUIDialogFileBrowser.h" -#include "GUIDialogContentSettings.h" #include "Picture.h" +#include "FileSystem/ProgramDatabaseDirectory.h" #include "PlayListFactory.h" +#include "GUIDialogProgramScan.h" +#include "GUIDialogOK.h" +#include "PartyModeManager.h" +#include "MusicDatabase.h" #include "GUIWindowManager.h" -#include "GUIDialogOK.h" +#include "GUIDialogYesNo.h" +#include "GUIDialogSelect.h" #include "GUIDialogKeyboard.h" #include "GUIEditControl.h" +#include "FileSystem/Directory.h" #include "FileSystem/File.h" #include "FileItem.h" #include "Application.h" -#include "Application.h" #include "Settings.h" #include "AdvancedSettings.h" #include "GUISettings.h" #include "LocalizeStrings.h" + +using namespace XFILE; +using namespace DIRECTORY; +using namespace PROGRAMDATABASEDIRECTORY; using namespace std; -using namespace DIRECTORY; -using namespace PLAYLIST; + #define CONTROL_BTNVIEWASICONS 2 #define CONTROL_BTNSORTBY 3 #define CONTROL_BTNSORTASC 4 #define CONTROL_BTNTYPE 5 +#define CONTROL_BTNSEARCH 8 #define CONTROL_LABELFILES 12 - -#define CONTROL_SEARCH 8 +#define CONTROL_BTN_FILTER 19 +#define CONTROL_BTNSHOWMODE 10 +#define CONTROL_BTNSHOWALL 14 +#define CONTROL_UNLOCK 11 #define CONTROL_FILTER 15 -#define CONTROL_BTN_FILTER 19 +#define CONTROL_BTNFLATTEN 17 #define CONTROL_LABELEMPTY 18 + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// CGUIWindowProgramNav::CGUIWindowProgramNav(void) - : CGUIMediaWindow(WINDOW_PROGRAM_NAV, "MyProgramsNav.xml") + : CGUIWindowProgramBase(WINDOW_PROGRAM_NAV, "MyProgramsNav.xml") { - m_vecItems->m_strPath = "?"; + m_vecItems->m_strPath = "?"; m_bDisplayEmptyDatabaseMessage = false; - m_unfilteredItems = new CFileItemList; - m_searchWithEdit = false; + m_unfilteredItems = new CFileItemList; + m_thumbLoader.SetObserver(this); } + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// CGUIWindowProgramNav::~CGUIWindowProgramNav(void) { delete m_unfilteredItems; } -bool CGUIWindowProgramNav::OnMessage(CGUIMessage& message) + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramNav::OnAction(const CAction &action) { - switch (message.GetMessage()) + if (action.wID == ACTION_PARENT_DIR) { - case GUI_MSG_WINDOW_RESET: - m_vecItems->m_strPath = "?"; - break; - case GUI_MSG_WINDOW_DEINIT: - m_programdatabase.Close(); - break; - case GUI_MSG_WINDOW_INIT: + if (g_advancedSettings.m_bUseEvilB && + m_vecItems->m_strPath == m_startDirectory) { - m_programdatabase.Open(); -/* We don't want to show Autosourced items (ie removable pendrives, memorycards) in Library mode */ - m_rootDir.AllowNonLocalSources(false); - // check for valid quickpath parameter - CStdStringArray params; - StringUtils::SplitString(message.GetStringParam(), ",", params); - bool returning = params.size() > 1 && params[1].Equals("return"); + m_gWindowManager.PreviousWindow(); + return true; + } + } + return CGUIWindowProgramBase::OnAction(action); +} - CStdString strDestination = params.size() ? params[0] : ""; - if (!strDestination.IsEmpty()) - { - message.SetStringParam(""); - CLog::Log(LOGINFO, "Attempting to quickpath to: %s", strDestination.c_str()); - } - // is this the first time the window is opened? - if (m_vecItems->m_strPath == "?" && strDestination.IsEmpty()) + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramNav::OnMessage(CGUIMessage& message) +{ + switch (message.GetMessage()) + { + + case GUI_MSG_WINDOW_RESET: + m_vecItems->m_strPath = "?"; + break; + + case GUI_MSG_WINDOW_DEINIT: + if (m_thumbLoader.IsLoading()) + m_thumbLoader.StopThread(); + break; + + case GUI_MSG_WINDOW_INIT: { - strDestination = g_settings.m_defaultProgramLibSource; - m_vecItems->m_strPath = strDestination; - CLog::Log(LOGINFO, "Attempting to default to: %s", strDestination.c_str()); - } + m_rootDir.AllowNonLocalSources(false); + + // check for valid quickpath parameter + CStdStringArray params; + StringUtils::SplitString(message.GetStringParam(), ",", params); - CStdString destPath; - if (!strDestination.IsEmpty()) - { - if (strDestination.Equals("$ROOT") || strDestination.Equals("Root")) - destPath = ""; -/* else if (strDestination.Equals("Genres")) - destPath = "musicdb://1/"; - else if (strDestination.Equals("Artists")) - destPath = "musicdb://2/"; - else if (strDestination.Equals("Albums")) - destPath = "musicdb://3/"; - else if (strDestination.Equals("Songs")) - destPath = "musicdb://4/"; - else if (strDestination.Equals("Top100")) - destPath = "musicdb://5/"; - else if (strDestination.Equals("Top100Songs")) - destPath = "musicdb://5/2/"; - else if (strDestination.Equals("Top100Albums")) - destPath = "musicdb://5/1/"; - else if (strDestination.Equals("RecentlyAddedAlbums")) - destPath = "musicdb://6/"; - else if (strDestination.Equals("RecentlyPlayedAlbums")) - destPath = "musicdb://7/"; - else if (strDestination.Equals("Compilations")) - destPath = "musicdb://8/"; - else if (strDestination.Equals("Playlists")) - destPath = "special://musicplaylists/"; - else if (strDestination.Equals("Years")) - destPath = "musicdb://9/";*/ - else if (strDestination.Equals("Plugins")) - destPath = "plugin://programs/"; - else + bool returning = params.size() > 1 && params[1].Equals("return"); + + CStdString strDestination = params.size() ? params[0] : ""; + if (!strDestination.IsEmpty()) { - CLog::Log(LOGWARNING, "Warning, destination parameter (%s) may not be valid", strDestination.c_str()); - destPath = strDestination; + message.SetStringParam(""); + + CLog::Log( LOGINFO, + "Attempting to %s to: %s", + returning ? "return" : "quickpath", + strDestination.c_str() + ); } - if (!returning || m_vecItems->m_strPath.Left(destPath.GetLength()) != destPath) - { // we're not returning to the same path, so set our directory to the requested path - m_vecItems->m_strPath = destPath; + + // is this the first time the window is opened? + if (m_vecItems->m_strPath == "?" && strDestination.IsEmpty()) { + strDestination = g_settings.m_defaultProgramLibSource; + m_vecItems->m_strPath = strDestination; + CLog::Log( LOGINFO, + "Attempting to default to: %s", + strDestination.c_str() + ); } - SetHistoryForPath(m_vecItems->m_strPath); - } - DisplayEmptyDatabaseMessage(false); // reset message state + CStdString destPath; + if (!strDestination.IsEmpty()) + { + if ( + strDestination.Equals("$ROOT") || + strDestination.Equals("Root") + ) + destPath = ""; + else if (strDestination.Equals("GameGenres")) + destPath = "programdb://1/1/"; + else if (strDestination.Equals("GameTitles")) + destPath = "programdb://1/2/"; + else if (strDestination.Equals("GameYears")) + destPath = "programdb://1/3/"; + else if (strDestination.Equals("GameDevelopers")) + destPath = "programdb://1/5/"; + else if (strDestination.Equals("GamePublishers")) + destPath = "programdb://1/6/"; + else if (strDestination.Equals("GamePerspectives")) + destPath = "programdb://1/4/"; + else if (strDestination.Equals("Games")) + destPath = "programdb://1/"; + else if (strDestination.Equals("RecentlyAddedGames")) + destPath = "programdb://2/"; + else if (strDestination.Equals("Plugins")) + destPath = "plugin://programs/"; + else + { + CLog::Log( LOGWARNING, + "Warning, destination parameter (%s) may not be valid", + strDestination.c_str() + ); + destPath = strDestination; + } - if (message.GetParam1() != WINDOW_INVALID) - { // first time to this window - make sure we set the root path - m_startDirectory = returning ? destPath : ""; - } + if (!returning || + m_vecItems->m_strPath.Left(destPath.GetLength()) != destPath) + { + // we're not returning to the same path, + // so set our directory to the requested path + m_vecItems->m_strPath = destPath; + } + SetHistoryForPath(m_vecItems->m_strPath); + } - // base class has opened the database, do our check - DisplayEmptyDatabaseMessage(m_programdatabase.GetProgramsCount() <= 0); + // reset message state + DisplayEmptyDatabaseMessage(false); - if (m_bDisplayEmptyDatabaseMessage) - { - // no library - make sure we focus on a known control, and default to the root. - SET_CONTROL_FOCUS(CONTROL_BTNTYPE, 0); - m_vecItems->m_strPath = ""; - SetHistoryForPath(""); - Update(""); + if (!CGUIWindowProgramBase::OnMessage(message)) + return false; + + if (message.GetParam1() != WINDOW_INVALID) + { + // first time to this window + // - make sure we set the root path + m_startDirectory = returning ? destPath : ""; + } + + // base class has opened the + // database, do our check + m_database.Open(); + DisplayEmptyDatabaseMessage(!m_database.HasContent()); + + if (m_bDisplayEmptyDatabaseMessage) + { + // no library - make sure we focus on a + // known control, and default to the root. + SET_CONTROL_FOCUS(CONTROL_BTNTYPE, 0); + m_vecItems->m_strPath = ""; + SetHistoryForPath(""); + Update(""); + } + + m_database.Close(); + + return true; } + break; - return true; - } - break; - - case GUI_MSG_CLICKED: + case GUI_MSG_CLICKED: { int iControl = message.GetSenderId(); - if (iControl == CONTROL_BTN_FILTER) + + if (iControl == CONTROL_BTNSEARCH) + OnSearch(); + + else if (iControl == CONTROL_BTN_FILTER) { - if (GetControl(iControl)->GetControlType() == CGUIControl::GUICONTROL_EDIT) - { // filter updated - CGUIMessage selected(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_BTN_FILTER); + if ( + GetControl(iControl)->GetControlType() + == + CGUIControl::GUICONTROL_EDIT + ) + { + // filter updated + CGUIMessage selected( + GUI_MSG_ITEM_SELECTED, + GetID(), + CONTROL_BTN_FILTER + ); OnMessage(selected); m_filter = selected.GetLabel(); OnFilterItems(); + return true; } if (m_filter.IsEmpty()) CGUIDialogKeyboard::ShowAndGetFilter(m_filter, false); - else + else { m_filter.Empty(); OnFilterItems(); } + return true; } - else if (iControl == CONTROL_SEARCH) + + else if (iControl == CONTROL_BTNFLATTEN) { - if (m_searchWithEdit) - { - // search updated - reset timer - m_searchTimer.StartZero(); - // grab our search string - CGUIMessage selected(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_SEARCH); - OnMessage(selected); - m_search = selected.GetLabel(); - return true; - } - CGUIDialogKeyboard::ShowAndGetFilter(m_search, true); + g_stSettings.m_bMyProgramNavFlatten =\ + !g_stSettings.m_bMyProgramNavFlatten; + g_settings.Save(); + CUtil::DeleteProgramDatabaseDirectoryCache(); + SetupShares(); + Update(""); + return true; } } break; - case GUI_MSG_NOTIFY_ALL: + + // update the display + case GUI_MSG_SCAN_FINISHED: + case GUI_MSG_REFRESH_THUMBS: + { + Update(m_vecItems->m_strPath); + } + break; + + case GUI_MSG_NOTIFY_ALL: { if (message.GetParam1() == GUI_MSG_FILTER_ITEMS && IsActive()) { - if (message.GetParam2() == 1) // append + if (message.GetParam2() == 1) // append m_filter += message.GetStringParam(); - else if (message.GetParam2() == 2) - { // delete + else if (message.GetParam2() == 2) // delete + { if (m_filter.size()) - m_filter = m_filter.Left(m_filter.size() - 1); + m_filter.erase(m_filter.end() - 1); } else m_filter = message.GetStringParam(); + OnFilterItems(); - return true; } - if (message.GetParam1() == GUI_MSG_SEARCH_UPDATE && IsActive()) - { - // search updated - reset timer - m_searchTimer.StartZero(); - m_search = message.GetStringParam(); - } } + break; } - return CGUIMediaWindow::OnMessage(message); + + return CGUIWindowProgramBase::OnMessage(message); } -bool CGUIWindowProgramNav::OnAction(const CAction& action) -{ - if (action.wID == ACTION_PARENT_DIR) - { - if (g_advancedSettings.m_bUseEvilB && m_vecItems->m_strPath == m_startDirectory) - { - m_gWindowManager.PreviousWindow(); - return true; - } - } - return CGUIMediaWindow::OnAction(action); -} -CStdString CGUIWindowProgramNav::GetQuickpathName(const CStdString& strPath) const +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +CStdString CGUIWindowProgramNav::GetQuickpathName +( + const CStdString& strPath +)const { -/* if (strPath.Equals("musicdb://1/")) - return "Genres"; - else if (strPath.Equals("musicdb://2/")) - return "Artists"; - else if (strPath.Equals("musicdb://3/")) - return "Albums"; - else if (strPath.Equals("musicdb://4/")) - return "Songs"; - else if (strPath.Equals("musicdb://5/")) - return "Top100"; - else if (strPath.Equals("musicdb://5/2/")) - return "Top100Songs"; - else if (strPath.Equals("musicdb://5/1/")) - return "Top100Albums"; - else if (strPath.Equals("musicdb://6/")) - return "RecentlyAddedAlbums"; - else if (strPath.Equals("musicdb://7/")) - return "RecentlyPlayedAlbums"; - else if (strPath.Equals("musicdb://8/")) - return "Compilations"; - else if (strPath.Equals("musicdb://9/")) - return "Years"; - else if (strPath.Equals("special://musicplaylists/")) - return "Playlists"; - else*/ - { - CLog::Log(LOGERROR, " %s: Unknown parameter (%s)", __FUNCTION__,strPath.c_str()); + if (strPath.Equals("programdb://1/1/")) return "GameGenres"; + else if (strPath.Equals("programdb://1/2/")) return "GameTitles"; + else if (strPath.Equals("programdb://1/3/")) return "GameYears"; + else if (strPath.Equals("programdb://1/4/")) return "GamePerspectives"; + else if (strPath.Equals("programdb://1/5/")) return "GameDevelopers"; + else if (strPath.Equals("programdb://1/6/")) return "GamePublishers"; + else if (strPath.Equals("programdb://1/")) return "Games"; + else if (strPath.Equals("programdb://2/")) return "RecentlyAddedGames"; + else { + CLog::Log(LOGERROR, + " CGUIWindowProgramNav::%s" + " Unknown parameter (%s)", + __FUNCTION__, strPath.c_str() + ); + return strPath; } } -bool CGUIWindowProgramNav::OnClick(int iItem) -{ - if (iItem < 0 || iItem >= m_vecItems->Size()) return false; - CFileItemPtr item = m_vecItems->Get(iItem); - if (item->m_strPath.Left(14) == "programsearch://") - { - if (m_searchWithEdit) - OnSearchUpdate(); - else - CGUIDialogKeyboard::ShowAndGetFilter(m_search, true); - return true; - } - return CGUIMediaWindow::OnClick(iItem); -} +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramNav::OnItemLoaded(CFileItem* pItem) {} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// bool CGUIWindowProgramNav::GetDirectory(const CStdString &strDirectory, CFileItemList &items) { - if (m_bDisplayEmptyDatabaseMessage) + if (m_bDisplayEmptyDatabaseMessage) return true; - if (strDirectory.IsEmpty()) - AddSearchFolder(); - bool bResult = CGUIMediaWindow::GetDirectory(strDirectory, items); + CFileItem directory(strDirectory, true); - // update our content in the info manager - if (strDirectory.Equals("plugin://music/")) - items.SetContent("plugins"); + if (m_thumbLoader.IsLoading()) + m_thumbLoader.StopThread(); + m_rootDir.SetCacheDirectory(DIR_CACHE_NEVER); + items.ClearProperties(); + + bool bResult = CGUIWindowProgramBase::GetDirectory(strDirectory, items); + if (bResult) + { + if (items.IsProgramDb()) + { + DIRECTORY::CProgramDatabaseDirectory dir; + CQueryParams params; + + dir.GetQueryParams(items.m_strPath, params); + + PROGRAMDATABASEDIRECTORY::NODE_TYPE node =\ + dir.GetDirectoryChildType(items.m_strPath); + + items.SetThumbnailImage(""); + + if (node == NODE_TYPE_TITLE_GAMES + || node == NODE_TYPE_RECENTLY_ADDED_GAMES) items.SetContent("games"); + else if (node == NODE_TYPE_GENRE) items.SetContent("genres"); + else if (node == NODE_TYPE_DEVELOPER) items.SetContent("developers"); + else if (node == NODE_TYPE_PUBLISHER) items.SetContent("publishers"); + else if (node == NODE_TYPE_PERSPECTIVE) items.SetContent("perspectives"); + else if (node == NODE_TYPE_YEAR) items.SetContent("years"); + else items.SetContent(""); + } + } + // clear the filter m_filter.Empty(); return bResult; } + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// void CGUIWindowProgramNav::UpdateButtons() { - CGUIMediaWindow::UpdateButtons(); + CGUIWindowProgramBase::UpdateButtons(); // Update object count int iItems = m_vecItems->Size(); - if (iItems) + if (iItems) { // check for parent dir and "all" items // should always be the first two items - for (int i = 0; i <= (iItems>=2 ? 1 : 0); i++) + for (int i = 0; i <= (iItems>=2 ? 1 : 0); i++) { CFileItemPtr pItem = m_vecItems->Get(i); - if (pItem->IsParentFolder()) iItems--; - if (pItem->m_strPath.Left(4).Equals("/-1/")) iItems--; + if (pItem->IsParentFolder() || pItem->m_strPath.Left(4).Equals("/-1/")) + iItems--; } // or the last item if (m_vecItems->Size() > 2 && m_vecItems->Get(m_vecItems->Size()-1)->m_strPath.Left(4).Equals("/-1/")) iItems--; } + CStdString items; items.Format("%i %s", iItems, g_localizeStrings.Get(127).c_str()); SET_CONTROL_LABEL(CONTROL_LABELFILES, items); - SET_CONTROL_SELECTED(GetID(),CONTROL_BTN_FILTER, !m_filter.IsEmpty()); + // set the filter label + CStdString strLabel; + CProgramDatabaseDirectory dir; + dir.GetLabel(m_vecItems->m_strPath, strLabel); + + SET_CONTROL_LABEL(CONTROL_FILTER, strLabel); + + SET_CONTROL_SELECTED( + GetID(), + CONTROL_BTN_FILTER, + !m_filter.IsEmpty() + ); + SET_CONTROL_LABEL2(CONTROL_BTN_FILTER, m_filter); - if (m_searchWithEdit) + SET_CONTROL_SELECTED( + GetID(), + CONTROL_BTNFLATTEN, + g_stSettings.m_bMyProgramNavFlatten + ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Search for genres, developers, publishers, names, and plots with +/// \brief search string \e strSearch in the program databases and return +/// \brief the found \e items +/// +/// \param strSearch The search string +/// \param items Items Found +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramNav::DoSearch +( + const CStdString &strSearch, + CFileItemList &items +) +{ + CFileItemList tempItems; + CStdString strGenre = g_localizeStrings.Get(515); // Genre + CStdString strDeveloper = g_localizeStrings.Get(20339); // Developer + CStdString strGame = g_localizeStrings.Get(20338); // Game + + // get matching genres + m_database.GetGameGenresByName(strSearch, tempItems); + + if (tempItems.Size()) { - SendMessage(GUI_MSG_SET_TYPE, CONTROL_SEARCH, CGUIEditControl::INPUT_TYPE_SEARCH); - SET_CONTROL_LABEL2(CONTROL_SEARCH, m_search); + for (int i = 0; i < (int)tempItems.Size(); i++) + { + tempItems[i]->SetLabel( + "[" + strGenre + + " - " + g_localizeStrings.Get(20342) + + "] " + tempItems[i]->GetLabel() + ); + } + items.Append(tempItems); } + + tempItems.Clear(); + m_database.GetGameDevelopersByName(strSearch, tempItems); + if (tempItems.Size()) + { + for (int i = 0; i < (int)tempItems.Size(); i++) + { + tempItems[i]->SetLabel( + "[" + strDeveloper + + " - " + g_localizeStrings.Get(20342) + + "] " + tempItems[i]->GetLabel()); + } + items.Append(tempItems); + } + + tempItems.Clear(); + m_database.GetGamesByName(strSearch, tempItems); + if (tempItems.Size()) + { + for (int i = 0; i < (int)tempItems.Size(); i++) + { + tempItems[i]->SetLabel( + "[" + g_localizeStrings.Get(20338) + + "] " + tempItems[i]->GetLabel()); + } + items.Append(tempItems); + } + + tempItems.Clear(); + m_database.GetGamesByPlot(strSearch, tempItems); + if (tempItems.Size()) + { + for (int i = 0; i < (int)tempItems.Size(); i++) + { + tempItems[i]->SetLabel( + "[" + strGame + + " " + g_localizeStrings.Get(207) + + "] " + tempItems[i]->GetLabel()); + } + items.Append(tempItems); + } } + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Play item +/////////////////////////////////////////////////////////////////////////////// void CGUIWindowProgramNav::PlayItem(int iItem) { - // root is not allowed - if (m_vecItems->IsVirtualDirectoryRoot()) + if (m_vecItems->IsVirtualDirectoryRoot()) return; + CGUIWindowProgramBase::PlayItem(iItem); } + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief On window loaded +/////////////////////////////////////////////////////////////////////////////// void CGUIWindowProgramNav::OnWindowLoaded() { - const CGUIControl *control = GetControl(CONTROL_SEARCH); - m_searchWithEdit = (control && control->GetControlType() == CGUIControl::GUICONTROL_EDIT); + SendMessage( + GUI_MSG_SET_TYPE, + CONTROL_BTN_FILTER, + CGUIEditControl::INPUT_TYPE_FILTER + ); + CGUIWindowProgramBase::OnWindowLoaded(); +} - SendMessage(GUI_MSG_SET_TYPE, CONTROL_BTN_FILTER, CGUIEditControl::INPUT_TYPE_FILTER); - CGUIMediaWindow::OnWindowLoaded(); + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Display "empty database" message +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramNav::DisplayEmptyDatabaseMessage(bool bDisplay) +{ + m_bDisplayEmptyDatabaseMessage = bDisplay; } -void CGUIWindowProgramNav::GetContextButtons(int itemNumber, CContextButtons &buttons) + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Render window +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramNav::Render() { - CGUIMediaWindow::GetContextButtons(itemNumber, buttons); -// CGUIMediaWindow::GetNonContextButtons(buttons); + if (m_bDisplayEmptyDatabaseMessage) + SET_CONTROL_LABEL(CONTROL_LABELEMPTY, g_localizeStrings.Get(745) + + '\n' + g_localizeStrings.Get(746)); + else + SET_CONTROL_LABEL(CONTROL_LABELEMPTY, ""); + CGUIWindowProgramBase::Render(); } -bool CGUIWindowProgramNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button) + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Action performed when information for item requested +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramNav::OnInfo +( + CFileItem *pItem, + const SScraperInfo &info +) { - CFileItemPtr item; - if (itemNumber >= 0 && itemNumber < m_vecItems->Size()) - item = m_vecItems->Get(itemNumber); + SScraperInfo info2(info); + CStdString strPath, strFile; - switch (button) + // since we can be called from the + // music library without being inited + m_database.Open(); + + if (pItem->IsProgramDb()) + m_database.GetScraperForPath( + pItem->GetProgramInfoTag()->m_strPath, info2 + ); + else if (m_vecItems->IsPlugin()) + info2.strContent = "plugin"; + else { - default: - break; + CUtil::Split(pItem->m_strPath,strPath,strFile); + m_database.GetScraperForPath(strPath,info2); } - return CGUIMediaWindow::OnContextButton(itemNumber, button); + m_database.Close(); + CGUIWindowProgramBase::OnInfo(pItem, info2); } -void CGUIWindowProgramNav::DisplayEmptyDatabaseMessage(bool bDisplay) + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramNav::OnDeleteItem(int iItem) { - m_bDisplayEmptyDatabaseMessage = bDisplay; + if (iItem < 0 || iItem >= (int)m_vecItems->Size()) + return; + + if (m_vecItems->IsPlugin()) + return; + + CFileItemPtr pItem = m_vecItems->Get(iItem); + if (!DeleteItem(pItem.get())) + return; + + CStdString strDeletePath; + if (pItem->m_bIsFolder) + strDeletePath=pItem->GetProgramInfoTag()->m_strPath; + else + strDeletePath=pItem->GetProgramInfoTag()->m_strFileNameAndPath; + + if (g_guiSettings.GetBool("filelists.allowfiledeletion") && + CUtil::SupportsFileOperations(strDeletePath)) + { + pItem->m_strPath = strDeletePath; + CGUIWindowProgramBase::OnDeleteItem(iItem); + } + + CUtil::DeleteProgramDatabaseDirectoryCache(); + DisplayEmptyDatabaseMessage(!m_database.HasContent()); + Update( m_vecItems->m_strPath ); + m_viewControl.SetSelectedItem(iItem); } -void CGUIWindowProgramNav::OnSearchUpdate() + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramNav::DeleteItem +( + CFileItem *pItem, + bool bUnavailable // = false +) { - CStdString search(m_search); - CUtil::URLEncode(search); - if (!search.IsEmpty()) + // dont allow update while scanning + CGUIDialogProgramScan* pDialogScan = \ + (CGUIDialogProgramScan*)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRAM_SCAN); + + if (pDialogScan && pDialogScan->IsScanning()) { - CStdString path = "programsearch://" + search + "/"; - m_history.ClearPathHistory(); - Update(path); + CGUIDialogOK::ShowAndGetInput(257, 0, 14057, 0); + return false; } - else if (m_vecItems->IsVirtualDirectoryRoot()) + + PROGRAMDB_CONTENT_TYPE iType = PROGRAMDB_CONTENT_GAMES; + + CGUIDialogYesNo* pDialog = \ + (CGUIDialogYesNo*)m_gWindowManager.GetWindow(WINDOW_DIALOG_YES_NO); + + if (!pDialog) + return false; + + if (iType == PROGRAMDB_CONTENT_GAMES) + pDialog->SetHeading(432); + + if (bUnavailable) { - Update(""); + pDialog->SetLine(0, g_localizeStrings.Get(662)); + pDialog->SetLine(1, g_localizeStrings.Get(663)); + pDialog->SetLine(2, "");; + pDialog->DoModal(); } -} + else + { + CStdString strLine; + strLine.Format(g_localizeStrings.Get(433),pItem->GetLabel()); + pDialog->SetLine(0, strLine); + pDialog->SetLine(1, ""); + pDialog->SetLine(2, "");; + pDialog->DoModal(); + } -void CGUIWindowProgramNav::Render() -{ - static const int search_timeout = 2000; - // update our searching - if (m_searchTimer.IsRunning() && m_searchTimer.GetElapsedMilliseconds() > search_timeout) + if (!pDialog->IsConfirmed()) + return false; + + CStdString path; + CProgramDatabase database; + database.Open(); + + database.GetFilePathById(pItem->GetProgramInfoTag()->m_iDbId, path, iType); + if (path.IsEmpty()) + return false; + + if (iType == PROGRAMDB_CONTENT_GAMES) + database.DeleteGame(path); + else { - OnSearchUpdate(); - m_searchTimer.Stop(); + CStdString strDirectory; + CUtil::GetDirectory(path,strDirectory); + database.SetPathHash(strDirectory,""); } - if (m_bDisplayEmptyDatabaseMessage) - SET_CONTROL_LABEL(CONTROL_LABELEMPTY,g_localizeStrings.Get(745)+'\n'+g_localizeStrings.Get(746)); - else - SET_CONTROL_LABEL(CONTROL_LABELEMPTY,""); - CGUIMediaWindow::Render(); + + return true; } + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramNav::OnFinalizeFileItems(CFileItemList& items) +{ + m_unfilteredItems->Append(items); + // now filter as necessary + CProgramDatabaseDirectory dir; + CQueryParams params; + + dir.GetQueryParams(items.m_strPath, params); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// void CGUIWindowProgramNav::ClearFileItems() { m_viewControl.Clear(); @@ -436,105 +739,373 @@ m_unfilteredItems->Clear(); } -void CGUIWindowProgramNav::OnFilterItems() -{ - CStdString currentItem; - int item = m_viewControl.GetSelectedItem(); - if (item >= 0) - currentItem = m_vecItems->Get(item)->m_strPath; - m_viewControl.Clear(); - FilterItems(*m_vecItems); +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramNav::GetContextButtons(int itemNumber, CContextButtons &buttons) +{ + CFileItemPtr item; + if (itemNumber >= 0 && itemNumber < m_vecItems->Size()) + item = m_vecItems->Get(itemNumber); - // and update our view control + buttons - m_viewControl.SetItems(*m_vecItems); - m_viewControl.SetSelectedItem(currentItem); - UpdateButtons(); -} + CGUIWindowProgramBase::GetContextButtons(itemNumber, buttons); -void CGUIWindowProgramNav::FilterItems(CFileItemList &items) -{ - if (m_vecItems->IsVirtualDirectoryRoot()) + if (item && item->GetPropertyBOOL("pluginreplacecontextitems")) return; - items.ClearItems(); + CProgramDatabaseDirectory dir; + NODE_TYPE node = dir.GetDirectoryChildType(m_vecItems->m_strPath); - CStdString filter(m_filter); - filter.TrimLeft().ToLower(); - bool numericMatch = StringUtils::IsNaturalNumber(filter); + if (!item) + { + CGUIDialogProgramScan *pScanDlg = \ + (CGUIDialogProgramScan *)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRAM_SCAN); + if (pScanDlg && pScanDlg->IsScanning()) + buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353); + else + buttons.Add(CONTEXT_BUTTON_UPDATE_LIBRARY, 653); + } + else + { + SScraperInfo info; + PROGRAM::SScanSettings settings; - for (int i = 0; i < m_unfilteredItems->Size(); i++) - { - CFileItemPtr item = m_unfilteredItems->Get(i); - if (item->IsParentFolder() || filter.IsEmpty()) //|| -// CMusicDatabaseDirectory::IsAllItem(item->m_strPath)) + GetScraperForItem(item.get(), info, settings); + + if (!item->IsParentFolder()) { - items.Add(item); - continue; - } - // TODO: Need to update this to get all labels, ideally out of the displayed info (ie from m_layout and m_focusedLayout) - // though that isn't practical. Perhaps a better idea would be to just grab the info that we should filter on based on - // where we are in the library tree. - // Another idea is tying the filter string to the current level of the tree, so that going deeper disables the filter, - // but it's re-enabled on the way back out. - CStdString match; -/* if (item->GetFocusedLayout()) - match = item->GetFocusedLayout()->GetAllText(); - else if (item->GetLayout()) - match = item->GetLayout()->GetAllText(); - else*/ - match = item->GetLabel(); + // can we update the database? + if (g_settings.m_vecProfiles[g_settings.m_iLastLoadedProfileIndex].\ + canWriteDatabases() || g_passwordManager.bMasterUser) + { + if (m_vecItems->m_strPath.Equals("plugin://programs/")) + buttons.Add(CONTEXT_BUTTON_SET_PLUGIN_THUMB, 1044); - if (numericMatch) - StringUtils::WordToDigits(match); - size_t pos = StringUtils::FindWords(match.c_str(), filter.c_str()); + if (item->IsProgramDb() && item->HasProgramInfoTag() && !item->m_bIsFolder) + { + buttons.Add(CONTEXT_BUTTON_DELETE, 646); + } - if (pos != CStdString::npos) - items.Add(item); + // this should ideally be non-contextual + // (though we need some context for non-tv show node I guess) + CGUIDialogProgramScan *pScanDlg = \ + (CGUIDialogProgramScan *)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRAM_SCAN); + if (pScanDlg && pScanDlg->IsScanning()) + { + buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353); + } + else + buttons.Add(CONTEXT_BUTTON_UPDATE_LIBRARY, 653); + } + + //Set default and/or clear default + NODE_TYPE nodetype = CProgramDatabaseDirectory::GetDirectoryType(item->m_strPath); + + if (!item->IsParentFolder() && + (nodetype == NODE_TYPE_ROOT || + nodetype == NODE_TYPE_OVERVIEW || + nodetype == NODE_TYPE_GAMES_OVERVIEW)) + { + if (!item->m_strPath.Equals(g_settings.m_defaultProgramLibSource)) + buttons.Add(CONTEXT_BUTTON_SET_DEFAULT, 13335); // set default + + if (strcmp(g_settings.m_defaultProgramLibSource, "")) + buttons.Add(CONTEXT_BUTTON_CLEAR_DEFAULT, 13403); // clear default + } + + } } + CGUIWindowProgramBase::GetNonContextButtons(itemNumber, buttons); } -void CGUIWindowProgramNav::OnFinalizeFileItems(CFileItemList &items) + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramNav::OnContextButton +( + int itemNumber, + CONTEXT_BUTTON button +) { - CGUIMediaWindow::OnFinalizeFileItems(items); -// m_unfilteredItems->Append(items); -// now filter as necessary -// if (!m_filter.IsEmpty()) -// FilterItems(items); -} + CFileItemPtr item; -void CGUIWindowProgramNav::AddSearchFolder() -{ - if (m_guiState.get()) + if (itemNumber >= 0 && itemNumber < m_vecItems->Size()) + item = m_vecItems->Get(itemNumber); + + + switch (button) { - // add our remove the musicsearch source - VECSOURCES &sources = m_guiState->GetSources(); - bool haveSearchSource = false; - bool needSearchSource = !m_search.IsEmpty() || !m_searchWithEdit; // we always need it if we don't have the edit control - for (IVECSOURCES it = sources.begin(); it != sources.end(); ++it) + + case CONTEXT_BUTTON_SET_DEFAULT: + g_settings.m_defaultProgramLibSource = GetQuickpathName(item->m_strPath); + g_settings.Save(); + return true; + + + case CONTEXT_BUTTON_CLEAR_DEFAULT: + g_settings.m_defaultProgramLibSource.Empty(); + g_settings.Save(); + return true; + + + case CONTEXT_BUTTON_EDIT: + UpdateProgramTitle(item.get()); + CUtil::DeleteProgramDatabaseDirectoryCache(); + Update(m_vecItems->m_strPath); + return true; + + + case CONTEXT_BUTTON_SET_PLUGIN_THUMB: { - CMediaSource& share = *it; - if (share.strPath == "programsearch://") + // Grab the thumbnails from the web + CStdString strPath; + CStdString cachedThumb; + CFileItemList items; + + CUtil::AddFileToFolder( + g_advancedSettings.m_cachePath, "imdbthumbs", strPath + ); + CUtil::WipeDir(strPath); + DIRECTORY::CDirectory::Create(strPath); + CFileItemPtr noneitem(new CFileItem("thumb://None", false)); + + int i = 1; + CProgramInfoTag tag; + + if (button != CONTEXT_BUTTON_SET_PLUGIN_THUMB) { - haveSearchSource = true; - if (!needSearchSource) - { // remove it - sources.erase(it); - break; + tag = *m_vecItems->Get(itemNumber)->GetProgramInfoTag(); + + for (vector::iterator iter = \ + tag.m_strPictureURL.m_url.begin(); + iter != tag.m_strPictureURL.m_url.end();++iter) + { + CStdString strItemPath; + + strItemPath.Format("thumb://Remote%i",i++); + CFileItemPtr item(new CFileItem(strItemPath, false)); + + item->SetThumbnailImage("http://this.is/a/thumb/from/the/web"); + item->SetIconImage("DefaultPicture.png"); + item->GetProgramInfoTag()->m_strPictureURL.m_url.push_back(*iter); + item->SetLabel(g_localizeStrings.Get(415)); + item->SetProperty("labelonthumbload", g_localizeStrings.Get(20015)); + + // make sure any previously cached thumb is removed + if (CFile::Exists(item->GetCachedPictureThumb())) + CFile::Delete(item->GetCachedPictureThumb()); + items.Add(item); } } + + if (button == CONTEXT_BUTTON_SET_PLUGIN_THUMB) + { + strPath = m_vecItems->Get(itemNumber)->m_strPath; + strPath.Replace( + "plugin://programs/", "special://home/plugins/programs/" + ); + CFileItem item(strPath,true); + cachedThumb = item.GetCachedProgramThumb(); + } + + if (CFile::Exists(cachedThumb)) + { + CFileItemPtr item(new CFileItem("thumb://Current", false)); + item->SetThumbnailImage(cachedThumb); + item->SetLabel(g_localizeStrings. Get(20016)); + items.Add(item); + } + else + { + noneitem->SetIconImage("DefaultFolder.png"); + noneitem->SetLabel(g_localizeStrings.Get(20018)); + } + + if (button == CONTEXT_BUTTON_SET_PLUGIN_THUMB) + { + if (items.Size() == 0) + { + CFileItem item2(strPath,false); + CUtil::AddFileToFolder(strPath,"default.py", item2.m_strPath); + if (CFile::Exists(item2.GetCachedProgramThumb())) + { + CFileItemPtr item(new CFileItem("thumb://Current", false)); + item->SetThumbnailImage(item2.GetCachedProgramThumb()); + item->SetLabel(g_localizeStrings.Get(20016)); + items.Add(item); + } + else + { + noneitem->SetIconImage("DefaultFolder.png"); + noneitem->SetLabel(g_localizeStrings.Get(20018)); + } + } + + CStdString strThumb; + CUtil::AddFileToFolder(strPath,"folder.jpg",strThumb); + if (CFile::Exists(strThumb)) + { + CFileItemPtr item(new CFileItem(strThumb, false)); + item->SetThumbnailImage(strThumb); + item->SetLabel(g_localizeStrings.Get(20017)); + items.Add(item); + } + else + { + noneitem->SetIconImage("DefaultFolder.png"); + noneitem->SetLabel(g_localizeStrings.Get(20018)); + } + CUtil::AddFileToFolder(strPath, "default.tbn", strThumb); + if (CFile::Exists(strThumb)) + { + CFileItemPtr item(new CFileItem(strThumb,false)); + item->SetThumbnailImage(strThumb); + item->SetLabel(g_localizeStrings.Get(20017)); + items.Add(item); + } + else + { + noneitem->SetIconImage("DefaultFolder.png"); + noneitem->SetLabel(g_localizeStrings.Get(20018)); + } + } + + if (button == CONTEXT_BUTTON_SET_ACTOR_THUMB) + { + CStdString picturePath; + CStdString strThumb; + CUtil::AddFileToFolder(picturePath,"folder.jpg",strThumb); + if (XFILE::CFile::Exists(strThumb)) + { + CFileItemPtr pItem(new CFileItem(strThumb,false)); + pItem->SetLabel(g_localizeStrings.Get(20017)); + pItem->SetThumbnailImage(strThumb); + items.Add(pItem); + } + else + { + noneitem->SetIconImage("DefaultActor.png"); + noneitem->SetLabel(g_localizeStrings.Get(20018)); + } + } + + items.Add(noneitem); + + CStdString result; + if (!CGUIDialogFileBrowser::ShowAndGetImage( + items, g_settings.m_programSources, + g_localizeStrings.Get(20019), result)) + { + // user cancelled + return false; + } + + if (result == "thumb://Current") + // user chose the one they have + return false; + + // delete the thumbnail if that's what + // the user wants, else overwrite with the + // new thumbnail + if (result.Left(14) == "thumb://Remote") + { + CFileItem chosen(result,false); + CStdString thumb = chosen.GetCachedPictureThumb(); + if (CFile::Exists(thumb)) + { + // NOTE: This could fail if the thumbloader was + // too slow and the user too impatient + CFile::Cache(thumb, cachedThumb); + } + else + result = "thumb://None"; + } + if (result == "thumb://None") + { + CFile::Delete(cachedThumb); + if (button == CONTEXT_BUTTON_SET_PLUGIN_THUMB) + { + CFileItem item2(strPath,false); + CUtil::AddFileToFolder(strPath,"default.py",item2.m_strPath); + CFile::Delete(item2.GetCachedProgramThumb()); + } + } + else + CFile::Cache(result,cachedThumb); + + CUtil::DeleteProgramDatabaseDirectoryCache(); + CGUIMessage msg(GUI_MSG_NOTIFY_ALL, 0, 0, GUI_MSG_REFRESH_THUMBS); + g_graphicsContext.SendMessage(msg); + Update(m_vecItems->m_strPath); + + return true; } - if (!haveSearchSource && needSearchSource) + + + case CONTEXT_BUTTON_UPDATE_LIBRARY: { - // add earch share - CMediaSource share; - share.strName=g_localizeStrings.Get(137); // Search - share.strPath = "programsearch://"; - share.m_strThumbnailImage="defaultFolderBig.png"; - share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL; - sources.push_back(share); + SScraperInfo info; + PROGRAM::SScanSettings settings; + + OnScan("", info, settings); + return true; } - m_rootDir.SetSources(sources); + + + default: + break; + } + + return CGUIWindowProgramBase::OnContextButton(itemNumber, button); } + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CGUIWindowProgramNav::OnClick(int iItem) +{ + CFileItemPtr item = m_vecItems->Get(iItem); + if (!item->m_bIsFolder && item->IsProgramDb() && !item->Exists()) + { + if (!DeleteItem(item.get(), true)) + return true; + + // update list + m_vecItems->RemoveDiscCache(); + Update(m_vecItems->m_strPath); + m_viewControl.SetSelectedItem(iItem); + return true; + } + + return CGUIWindowProgramBase::OnClick(iItem); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramNav::OnFilterItems() +{ + CStdString currentItem; + int item = m_viewControl.GetSelectedItem(); + if (item >= 0) + currentItem = m_vecItems->Get(item)->m_strPath; + + m_viewControl.Clear(); + FilterItems(*m_vecItems); + + // and update our view control + buttons + m_viewControl.SetItems(*m_vecItems); + m_viewControl.SetSelectedItem(currentItem); + UpdateButtons(); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +void CGUIWindowProgramNav::FilterItems(CFileItemList &items){} Index: xbmc/GUIWindowProgramNav.h =================================================================== --- xbmc/GUIWindowProgramNav.h (revision 24004) +++ xbmc/GUIWindowProgramNav.h (working copy) @@ -1,75 +1,73 @@ -#pragma once - -/* - * Copyright (C) 2005-2008 Team XBMC - * http://www.xbmc.org - * - * 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, 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 XBMC; see the file COPYING. If not, write to - * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. - * http://www.gnu.org/copyleft/gpl.html - * - */ - -#include "GUIMediaWindow.h" -#include "utils/Stopwatch.h" -#include "ProgramDatabase.h" - -class CFileItemList; - -class CGUIWindowProgramNav : public CGUIMediaWindow -{ -public: - CGUIWindowProgramNav(void); - virtual ~CGUIWindowProgramNav(void); - - virtual bool OnMessage(CGUIMessage& message); - virtual bool OnAction(const CAction& action); - virtual void Render(); - - virtual void ClearFileItems(); - virtual void OnFinalizeFileItems(CFileItemList &items); - -protected: - virtual void OnItemLoaded(CFileItem* pItem) {}; - // override base class methods - virtual bool GetDirectory(const CStdString &strDirectory, CFileItemList &items); - virtual void UpdateButtons(); - virtual void PlayItem(int iItem); - virtual void OnWindowLoaded(); - virtual void GetContextButtons(int itemNumber, CContextButtons &buttons); - virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button); - virtual void OnFilterItems(); - virtual bool OnClick(int iItem); - void FilterItems(CFileItemList &items); - - void DisplayEmptyDatabaseMessage(bool bDisplay); - CStdString GetQuickpathName(const CStdString& strPath) const; - - VECSOURCES m_shares; - - bool m_bDisplayEmptyDatabaseMessage; ///< If true we display a message informing the user to switch back to the Files view. - - // filtered item views - CFileItemList* m_unfilteredItems; - CStdString m_filter; - - // searching - void OnSearchUpdate(); - void AddSearchFolder(); - CStdString m_search; ///< current search string - CStdString m_startDirectory; - CStopWatch m_searchTimer; ///< Timer to delay a search while more characters are entered - bool m_searchWithEdit; ///< Whether the skin supports the new edit control searching - CProgramDatabase m_programdatabase; -}; +#pragma once + +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "GUIWindowProgramBase.h" +#include "ThumbLoader.h" + +class CFileItemList; + +class CGUIWindowProgramNav : public CGUIWindowProgramBase +{ +public: + + CGUIWindowProgramNav(void); + virtual ~CGUIWindowProgramNav(void); + + virtual bool OnAction(const CAction &action); + virtual bool OnMessage(CGUIMessage& message); + virtual void Render(); + + virtual void ClearFileItems(); + virtual void OnFinalizeFileItems(CFileItemList &items); + virtual void OnInfo(CFileItem* pItem, const SScraperInfo&info); + static bool DeleteItem(CFileItem* pItem, bool bUnavailable=false); + +protected: + virtual void OnItemLoaded(CFileItem* pItem); + // override base class methods + virtual bool GetDirectory(const CStdString &strDirectory, CFileItemList &items); + virtual void UpdateButtons(); + virtual void DoSearch(const CStdString& strSearch, CFileItemList& items); + virtual void PlayItem(int iItem); + virtual void OnDeleteItem(int iItem); + virtual void OnWindowLoaded(); + virtual void OnFilterItems(); + virtual void GetContextButtons(int itemNumber, CContextButtons &buttons); + virtual bool OnContextButton(int itemNumber, CONTEXT_BUTTON button); + virtual bool OnClick(int iItem); + + virtual CStdString GetQuickpathName(const CStdString& strPath) const; + void FilterItems(CFileItemList &items); + + void DisplayEmptyDatabaseMessage(bool bDisplay); + + VECSOURCES m_shares; + + bool m_bDisplayEmptyDatabaseMessage; ///< If true we display a message informing the user to switch back to the Files view. + + // filtered item views + CFileItemList* m_unfilteredItems; + CStdString m_filter; + + CStdString m_startDirectory; +}; Index: xbmc/GUIWindowPrograms.cpp =================================================================== --- xbmc/GUIWindowPrograms.cpp (revision 24004) +++ xbmc/GUIWindowPrograms.cpp (working copy) @@ -39,6 +39,7 @@ #include "FileSystem/File.h" #include "FileSystem/RarManager.h" #include "FileItem.h" +#include "AdvancedSettings.h" #include "Settings.h" #include "GUISettings.h" #include "LocalizeStrings.h" @@ -210,7 +211,9 @@ CStdString strLaunch = g_localizeStrings.Get(518); // Launch buttons.Add(CONTEXT_BUTTON_LAUNCH, strLaunch); - if (g_passwordManager.IsMasterLockUnlocked(false) || g_settings.m_vecProfiles[g_settings.m_iLastLoadedProfileIndex].canWriteDatabases()) + if (g_passwordManager.IsMasterLockUnlocked(false) + || g_settings.m_vecProfiles[ + g_settings.m_iLastLoadedProfileIndex].canWriteDatabases()) { if (item->IsShortCut()) buttons.Add(CONTEXT_BUTTON_RENAME, 16105); // rename @@ -234,80 +237,68 @@ bool CGUIWindowPrograms::OnContextButton(int itemNumber, CONTEXT_BUTTON button) { - CFileItemPtr item = (itemNumber >= 0 && itemNumber < m_vecItems->Size()) ? m_vecItems->Get(itemNumber) : CFileItemPtr(); + CFileItemPtr item = (itemNumber >= 0 && itemNumber < m_vecItems->Size()) ? + m_vecItems->Get(itemNumber) : CFileItemPtr(); SScraperInfo info; bool bRunScan; - if (item && m_vecItems->IsVirtualDirectoryRoot()) - { - if (CGUIDialogContextMenu::OnContextButton("programs", item, button)) - { + if (item && m_vecItems->IsVirtualDirectoryRoot()) { + if (CGUIDialogContextMenu::OnContextButton("programs", item, button)) { Update(""); return true; } } - switch (button) - { - case CONTEXT_BUTTON_RENAME: - { - CStdString strDescription; - CShortcut cut; - if (item->IsShortCut()) - { - cut.Create(item->m_strPath); - strDescription = cut.m_strLabel; - } - else - strDescription = item->GetLabel(); + switch (button) { + case CONTEXT_BUTTON_RENAME: { + CStdString strDescription; + CShortcut cut; + if (item->IsShortCut()) { + cut.Create(item->m_strPath); + strDescription = cut.m_strLabel; + } + else strDescription = item->GetLabel(); - if (CGUIDialogKeyboard::ShowAndGetInput(strDescription, g_localizeStrings.Get(16008), false)) - { - if (item->IsShortCut()) - { - cut.m_strLabel = strDescription; - cut.Save(item->m_strPath); - } - else - { - // SetXBEDescription will truncate to 40 characters. - //CUtil::SetXBEDescription(item->m_strPath,strDescription); - //m_database.SetDescription(item->m_strPath,strDescription); - } - Update(m_vecItems->m_strPath); + if (CGUIDialogKeyboard::ShowAndGetInput( + strDescription, g_localizeStrings.Get(16008), false)) { + if (item->IsShortCut()) { + cut.m_strLabel = strDescription; + cut.Save(item->m_strPath); + } + Update(m_vecItems->m_strPath); + } + return true; } - return true; - } - case CONTEXT_BUTTON_SETTINGS: - m_gWindowManager.ActivateWindow(WINDOW_SETTINGS_MYPROGRAMS); - return true; + case CONTEXT_BUTTON_SETTINGS: + m_gWindowManager.ActivateWindow(WINDOW_SETTINGS_MYPROGRAMS); + return true; - case CONTEXT_BUTTON_GOTO_ROOT: - Update(""); - return true; + case CONTEXT_BUTTON_GOTO_ROOT: + Update(""); + return true; - case CONTEXT_BUTTON_LAUNCH: - OnClick(itemNumber); - return true; + case CONTEXT_BUTTON_LAUNCH: + OnClick(itemNumber); + return true; - case CONTEXT_BUTTON_SET_CONTENT: - if (CGUIDialogContentSettings::ShowForProgramsDirectory(item->m_strPath, info, bRunScan)) - { - if (bRunScan) - { - // TODO - run recursive scan - // unimplemented - } - return true; - } - else - return false; + case CONTEXT_BUTTON_SET_CONTENT: + if (CGUIDialogContentSettings::ShowForProgramsDirectory(item->m_strPath, info, bRunScan)) + { + if (bRunScan) + { + // TODO - run recursive scan + // unimplemented + } + return true; + } + else + return false; - case CONTEXT_BUTTON_SCAN: - return GetProgramInfo(item); + case CONTEXT_BUTTON_SCAN: + return GetProgramInfo(item); - default: - break; + default: + break; } return CGUIMediaWindow::OnContextButton(itemNumber, button); } Index: xbmc/GUIWindowScripts.cpp =================================================================== --- xbmc/GUIWindowScripts.cpp (revision 24004) +++ xbmc/GUIWindowScripts.cpp (working copy) @@ -205,7 +205,7 @@ } } - items.SetProgramThumbs(); + items.SetProgramThumb(); return true; } Index: xbmc/GUIWindowSettingsCategory.cpp =================================================================== --- xbmc/GUIWindowSettingsCategory.cpp (revision 24004) +++ xbmc/GUIWindowSettingsCategory.cpp (working copy) @@ -58,7 +58,7 @@ #include "GUIDialogKeyboard.h" #include "GUIDialogYesNo.h" #include "GUIDialogOK.h" -#include "GUIWindowPrograms.h" + #include "MediaManager.h" #include "utils/Network.h" #ifdef HAS_WEB_SERVER @@ -405,7 +405,7 @@ CSetting *pSetting = settings[i]; AddSetting(pSetting, group->GetWidth(), iControlID); CStdString strSetting = pSetting->GetSetting(); - if (strSetting.Equals("myprograms.ntscmode")) + if (strSetting.Equals("programfiles.ntscmode")) { CSettingInt *pSettingInt = (CSettingInt*)pSetting; CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(strSetting)->GetID()); @@ -424,10 +424,10 @@ CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); FillInScrapers(pControl, g_guiSettings.GetString("musiclibrary.defaultscraper"), "music"); } - else if (strSetting.Equals("programfiles.defaultscraper")) + else if (strSetting.Equals("programscrapers.gamedefault")) { CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID()); - FillInScrapers(pControl, g_guiSettings.GetString("programfiles.defaultscraper"), "programs"); + FillInScrapers(pControl, g_guiSettings.GetString("programscrapers.gamedefault"), "games"); } else if (strSetting.Equals("scrapers.moviedefault")) { @@ -1628,6 +1628,11 @@ CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); FillInScrapers(pControl, pControl->GetCurrentLabel(), "musicvideos"); } + else if (strSetting.Equals("programscrapers.gamedefault")) + { + CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID()); + FillInScrapers(pControl, pControl->GetCurrentLabel(), "games"); + } else if (strSetting.Equals("videolibrary.cleanup")) { if (CGUIDialogYesNo::ShowAndGetInput(313, 333, 0, 0)) @@ -3707,8 +3712,8 @@ { if (strContent.Equals("music")) // native strContent would be albums or artists but we're using the same scraper for both g_guiSettings.SetString("musiclibrary.defaultscraper", CUtil::GetFileName(items[i]->m_strPath)); - else if (strContent.Equals("programs")) - g_guiSettings.SetString("programfiles.defaultscraper", CUtil::GetFileName(items[i]->m_strPath)); + else if (strContent.Equals("games")) + g_guiSettings.SetString("programscrapers.gamedefault", CUtil::GetFileName(items[i]->m_strPath)); else if (strContent.Equals("movies")) g_guiSettings.SetString("scrapers.moviedefault", CUtil::GetFileName(items[i]->m_strPath)); else if (strContent.Equals("tvshows")) Index: xbmc/lib/libGoAhead/XBMChttp.cpp =================================================================== --- xbmc/lib/libGoAhead/XBMChttp.cpp (revision 24004) +++ xbmc/lib/libGoAhead/XBMChttp.cpp (working copy) @@ -653,7 +653,7 @@ } VECSOURCES *pShares = NULL; - enum SHARETYPES { MUSIC, VIDEO, PICTURES, FILES }; + enum SHARETYPES { MUSIC, VIDEO, PICTURES, FILES, PROGRAMS }; switch(iType) { case MUSIC: @@ -668,6 +668,12 @@ strMask = g_stSettings.m_videoExtensions; } break; + case PROGRAMS: + { + pShares = &g_settings.m_programSources; + strMask = g_stSettings.m_programExtensions; + } + break; case PICTURES: { pShares = &g_settings.m_pictureSources; Index: xbmc/lib/libPython/xbmcmodule/infotagprogram.cpp =================================================================== --- xbmc/lib/libPython/xbmcmodule/infotagprogram.cpp (revision 0) +++ xbmc/lib/libPython/xbmcmodule/infotagprogram.cpp (revision 0) @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#include "stdafx.h" +#include "infotagprogram.h" +#include "pyutil.h" + +#ifndef __GNUC__ +#pragma code_seg("PY_TEXT") +#pragma data_seg("PY_DATA") +#pragma bss_seg("PY_BSS") +#pragma const_seg("PY_RDATA") +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +namespace PYXBMC +{ + /* + * allocate a new InfoTagProgram. Used for c++ and not the python user + * returns a new reference + */ + InfoTagProgram* InfoTagProgram_FromCProgramInfoTag(const CProgramInfoTag& infoTag) + { + InfoTagProgram* self = (InfoTagProgram*)InfoTagProgram_Type.tp_alloc(&InfoTagProgram_Type, 0); + if (!self) return NULL; + new(&self->infoTag) CProgramInfoTag(); + self->infoTag = infoTag; + + return self; + } + + void InfoTagProgram_Dealloc(InfoTagProgram* self) + { + self->infoTag.~CProgramInfoTag(); + self->ob_type->tp_free((PyObject*)self); + } + + // InfoTagProgram_GetDirector + PyDoc_STRVAR(getDeveloper__doc__, + "getDeveloper() -- returns a string.\n"); + + PyObject* InfoTagProgram_GetDeveloper(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"s", self->infoTag.m_strDeveloper.c_str()); + } + + // InfoTagProgram_GetWritingCredits + PyDoc_STRVAR(getPublisher__doc__, + "getPublisher() -- returns a string.\n"); + + PyObject* InfoTagProgram_GetPublisher(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"s", self->infoTag.m_strPublisher.c_str()); + } + + // InfoTagProgram_GetGenre + PyDoc_STRVAR(getGenre__doc__, + "getGenre() -- returns a string.\n"); + + PyObject* InfoTagProgram_GetGenre(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"s", self->infoTag.m_strGenre.c_str()); + } + + // InfoTagProgram_GetDescription + PyDoc_STRVAR(getDescription__doc__, + "getDescription() -- returns a string.\n"); + + PyObject* InfoTagProgram_GetDescription(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"s", self->infoTag.m_strDescription.c_str()); + } + + // InfoTagProgram_GetPlatform + PyDoc_STRVAR(getPlatform__doc__, + "getPlotOutline() -- returns a string.\n"); + + PyObject* InfoTagProgram_GetPlatform(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"s", self->infoTag.m_strPlatform.c_str()); + } + + // InfoTagProgram_GetPlot + PyDoc_STRVAR(getPlot__doc__, + "getPlot() -- returns a string.\n"); + + PyObject* InfoTagProgram_GetPlot(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"s", self->infoTag.m_strPlot.c_str()); + } + + // InfoTagProgram_GetPictureURL + PyDoc_STRVAR(getPictureURL__doc__, + "getPictureURL() -- returns a string.\n"); + + PyObject* InfoTagProgram_GetPictureURL(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"s", self->infoTag.m_strPictureURL.GetFirstThumb().m_url.c_str()); + } + + // InfoTagProgram_GetTitle + PyDoc_STRVAR(getTitle__doc__, + "getTitle() -- returns a string.\n"); + + PyObject* InfoTagProgram_GetTitle(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"s", self->infoTag.m_strTitle.c_str()); + } + + // InfoTagProgram_GetVotes + PyDoc_STRVAR(getVotes__doc__, + "getVotes() -- returns a string.\n"); + + PyObject* InfoTagProgram_GetVotes(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"s", self->infoTag.m_strVotes.c_str()); + } + + + + // InfoTagProgram_GetFile + PyDoc_STRVAR(getFile__doc__, + "getFile() -- returns a string.\n"); + + PyObject* InfoTagProgram_GetFile(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"s", self->infoTag.m_strFile.c_str()); + } + + // InfoTagProgram_GetPath + PyDoc_STRVAR(getPath__doc__, + "getPath() -- returns a string.\n"); + + PyObject* InfoTagProgram_GetPath(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"s", self->infoTag.m_strPath.c_str()); + } + + + // InfoTagProgram_GetIMDBNumber + PyDoc_STRVAR(getRating__doc__, + "getRating() -- returns a float.\n"); + + PyObject* InfoTagProgram_GetRating(InfoTagProgram *self, PyObject *args) + { + return Py_BuildValue((char*)"f", self->infoTag.m_fRating); + } + + PyMethodDef InfoTagProgram_methods[] = { + {(char*)"getDeveloper", (PyCFunction)InfoTagProgram_GetDeveloper, METH_VARARGS, getDeveloper__doc__}, + {(char*)"getPublisher", (PyCFunction)InfoTagProgram_GetPublisher, METH_VARARGS, getPublisher__doc__}, + {(char*)"getGenre", (PyCFunction)InfoTagProgram_GetGenre, METH_VARARGS, getGenre__doc__}, + {(char*)"getDescription", (PyCFunction)InfoTagProgram_GetDescription, METH_VARARGS, getDescription__doc__}, + {(char*)"getPlatform", (PyCFunction)InfoTagProgram_GetPlatform, METH_VARARGS, getPlatform__doc__}, + {(char*)"getPlot", (PyCFunction)InfoTagProgram_GetPlot, METH_VARARGS, getPlot__doc__}, + {(char*)"getPictureURL", (PyCFunction)InfoTagProgram_GetPictureURL, METH_VARARGS, getPictureURL__doc__}, + {(char*)"getTitle", (PyCFunction)InfoTagProgram_GetTitle, METH_VARARGS, getTitle__doc__}, + {(char*)"getFile", (PyCFunction)InfoTagProgram_GetFile, METH_VARARGS, getFile__doc__}, + {(char*)"getPath", (PyCFunction)InfoTagProgram_GetPath, METH_VARARGS, getPath__doc__}, + {(char*)"getRating", (PyCFunction)InfoTagProgram_GetRating, METH_VARARGS, getRating__doc__}, + {NULL, NULL, 0, NULL} + }; + + PyDoc_STRVAR(programInfoTag__doc__, + "InfoTagProgram class.\n" + "\n" + ""); + +// Restore code and data sections to normal. +#ifndef __GNUC__ +#pragma code_seg() +#pragma data_seg() +#pragma bss_seg() +#pragma const_seg() +#endif + + PyTypeObject InfoTagProgram_Type; + + void initInfoTagProgram_Type() + { + PyInitializeTypeObject(&InfoTagProgram_Type); + + InfoTagProgram_Type.tp_name = (char*)"xbmc.InfoTagProgram"; + InfoTagProgram_Type.tp_basicsize = sizeof(InfoTagProgram); + InfoTagProgram_Type.tp_dealloc = (destructor)InfoTagProgram_Dealloc; + InfoTagProgram_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; + InfoTagProgram_Type.tp_doc = programInfoTag__doc__; + InfoTagProgram_Type.tp_methods = InfoTagProgram_methods; + InfoTagProgram_Type.tp_base = 0; + InfoTagProgram_Type.tp_new = 0; + } +} + +#ifdef __cplusplus +} +#endif Index: xbmc/lib/libPython/xbmcmodule/infotagprogram.h =================================================================== --- xbmc/lib/libPython/xbmcmodule/infotagprogram.h (revision 0) +++ xbmc/lib/libPython/xbmcmodule/infotagprogram.h (revision 0) @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2005-2008 Team XBMC + * http://www.xbmc.org + * + * 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, 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 XBMC; see the file COPYING. If not, write to + * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. + * http://www.gnu.org/copyleft/gpl.html + * + */ + +#if (defined HAVE_CONFIG_H) && (!defined WIN32) + #include "config.h" +#endif +#if (defined USE_EXTERNAL_PYTHON) + #if (defined HAVE_LIBPYTHON2_6) + #include + #elif (defined HAVE_LIBPYTHON2_5) + #include + #elif (defined HAVE_LIBPYTHON2_4) + #include + #else + #error "Could not determine version of Python to use." + #endif +#else + #include "lib/libPython/Python/Include/Python.h" +#endif +#include "ProgramInfoTag.h" +#include "../../../utils/IMDB.h" + +#pragma once + +#ifdef __cplusplus +extern "C" { +#endif + +namespace PYXBMC +{ + typedef struct { + PyObject_HEAD + CProgramInfoTag infoTag; + } InfoTagProgram; + + extern PyTypeObject InfoTagProgram_Type; + extern InfoTagProgram* InfoTagProgram_FromCProgramInfoTag(const CProgramInfoTag& infoTag); + void initInfoTagProgram_Type(); +} + +#ifdef __cplusplus +} +#endif Index: xbmc/lib/libPython/xbmcmodule/listitem.cpp =================================================================== --- xbmc/lib/libPython/xbmcmodule/listitem.cpp (revision 24004) +++ xbmc/lib/libPython/xbmcmodule/listitem.cpp (working copy) @@ -40,6 +40,7 @@ #include "listitem.h" #include "pyutil.h" #include "VideoInfoTag.h" +#include "ProgramInfoTag.h" #include "PictureInfoTag.h" #include "MusicInfoTag.h" #include "FileItem.h" @@ -458,6 +459,52 @@ } } } + else if (strcmpi(cType, "programs") == 0) + { + // TODO: add the rest of the infolabels + if (strcmpi(PyString_AsString(key), "year") == 0) + self->item->GetProgramInfoTag()->m_iYear = PyInt_AsLong(value); + else if (strcmpi(PyString_AsString(key), "count") == 0) + self->item->m_iprogramCount = PyInt_AsLong(value); + else if (strcmpi(PyString_AsString(key), "rating") == 0) + self->item->GetProgramInfoTag()->m_fRating = (float)PyFloat_AsDouble(value); + else if (strcmpi(PyString_AsString(key), "size") == 0) + self->item->m_dwSize = (__int64)PyLong_AsLongLong(value); + else if (strcmpi(PyString_AsString(key), "playcount") == 0) + self->item->GetProgramInfoTag()->m_playCount = PyInt_AsLong(value); + else if (strcmpi(PyString_AsString(key), "overlay") == 0) + // TODO: Add a check for a valid overlay value + self->item->SetOverlayImage((CGUIListItem::GUIIconOverlay)PyInt_AsLong(value)); + else + { + if (!PyGetUnicodeString(tmp, value, 1)) continue; + if (strcmpi(PyString_AsString(key), "genre") == 0) + self->item->GetProgramInfoTag()->m_strGenre = tmp; + else if (strcmpi(PyString_AsString(key), "developer") == 0) + self->item->GetProgramInfoTag()->m_strDeveloper = tmp; + else if (strcmpi(PyString_AsString(key), "publisher") == 0) + self->item->GetProgramInfoTag()->m_strPublisher = tmp; + else if (strcmpi(PyString_AsString(key), "plot") == 0) + self->item->GetProgramInfoTag()->m_strPlot = tmp; + else if (strcmpi(PyString_AsString(key), "description") == 0) + self->item->GetProgramInfoTag()->m_strDescription = tmp; + else if (strcmpi(PyString_AsString(key), "title") == 0) + self->item->GetProgramInfoTag()->m_strTitle = tmp; + else if (strcmpi(PyString_AsString(key), "platform") == 0) + self->item->GetProgramInfoTag()->m_strPlatform = tmp; + else if (strcmpi(PyString_AsString(key), "region") == 0) + self->item->GetProgramInfoTag()->m_strRegion = tmp; + else if (strcmpi(PyString_AsString(key), "votes") == 0) + self->item->GetProgramInfoTag()->m_strVotes = tmp; + else if (strcmpi(PyString_AsString(key), "preview") == 0) + self->item->GetProgramInfoTag()->m_strPreviewVideo = tmp; + else if (strcmpi(PyString_AsString(key), "date") == 0) + { + if (strlen(tmp) == 10) + self->item->m_dateTime.SetDate(atoi(tmp.Right(4)), atoi(tmp.Mid(3,4)), atoi(tmp.Left(2))); + } + } + } else if (strcmpi(cType, "music") == 0) { // TODO: add the rest of the infolabels Index: xbmc/lib/libPython/xbmcmodule/player.cpp =================================================================== --- xbmc/lib/libPython/xbmcmodule/player.cpp (revision 24004) +++ xbmc/lib/libPython/xbmcmodule/player.cpp (working copy) @@ -28,6 +28,7 @@ #include "pyutil.h" #include "infotagvideo.h" #include "infotagmusic.h" +#include "infotagprogram.h" #include "listitem.h" #include "FileItem.h" #include "Settings.h" Index: xbmc/NfoFile.cpp =================================================================== --- xbmc/NfoFile.cpp (revision 24004) +++ xbmc/NfoFile.cpp (working copy) @@ -25,7 +25,9 @@ #include "stdafx.h" #include "NfoFile.h" #include "VideoDatabase.h" +#include "programDatabase.h" #include "utils/IMDB.h" +#include "ProgramScraper.h" #include "FileSystem/File.h" #include "FileSystem/Directory.h" #include "Util.h" @@ -69,7 +71,8 @@ CFileItemList items; CStdString strURL, strScraperBasePath, strDefault, strSelected; - bool bNfo=false; + bool bNfo = false; + if (m_strContent.Equals("albums")) { CAlbum album; @@ -78,14 +81,16 @@ strScraperBasePath = "special://xbmc/system/scrapers/music/"; CUtil::AddFileToFolder(strScraperBasePath, g_guiSettings.GetString("musiclibrary.defaultscraper"), strDefault); } - else if (m_strContent.Equals("programs")) + + else if (m_strContent.Equals("games")) { - //CProgram program; - //bNfo = GetDetails(program); + CProgramInfoTag program; + bNfo = GetDetails(program); CDirectory::GetDirectory("special://xbmc/system/scrapers/programs/",items,".xml",false); strScraperBasePath = "special://xbmc/system/scrapers/programs/"; - CUtil::AddFileToFolder(strScraperBasePath, g_guiSettings.GetString("programfiles.defaultscraper"), strDefault); + CUtil::AddFileToFolder(strScraperBasePath, g_guiSettings.GetString("programscrapers.gamedefault"), strDefault); } + else if (m_strContent.Equals("artists")) { CArtist artist; @@ -94,6 +99,7 @@ strScraperBasePath = "special://xbmc/system/scrapers/music/"; CUtil::AddFileToFolder(strScraperBasePath, g_guiSettings.GetString("musiclibrary.defaultscraper"), strDefault); } + else if (m_strContent.Equals("tvshows") || m_strContent.Equals("movies") || m_strContent.Equals("musicvideos")) { // first check if it's an XML file with the info we need @@ -130,10 +136,22 @@ } // Get Selected Scraper - CVideoDatabase database; - database.Open(); - database.GetScraperForPath(strPath,info); - database.Close(); + if (m_strContent.Equals("games")) + { + CProgramDatabase db; + db.Open(); + db.GetScraperForPath(strPath, info); + db.Close(); + } + else + { + //asume video + CVideoDatabase db; + db.Open(); + db.GetScraperForPath(strPath, info); + db.Close(); + } + CUtil::AddFileToFolder(strScraperBasePath, info.strPath, strSelected); vector vecScrapers; @@ -154,7 +172,7 @@ SScraperInfo info2; CScraperParser parser2; parser2.Load(items[i]->m_strPath); - info2.strContent = parser2.GetContent(); + info2.strContent = parser2.GetContent(); info2.strLanguage = parser2.GetLanguage(); // skip wrong content type @@ -248,15 +266,25 @@ if (doc.RootElement() && doc.RootElement()->FirstChildElement()) { CVideoInfoTag details; - if (GetDetails(details,m_strImDbUrl.c_str())) + if (GetDetails(details, m_strImDbUrl.c_str())) { Close(); - m_size = m_strImDbUrl.size(); - m_doc = new char[m_size+1]; + m_size = m_strImDbUrl.size(); + m_doc = new char[m_size+1]; m_headofdoc = m_doc; - strcpy(m_doc,m_strImDbUrl.c_str()); + strcpy(m_doc, m_strImDbUrl.c_str()); return S_OK; } + CProgramInfoTag progDetails; + if (GetDetails(progDetails, m_strImDbUrl.c_str())) + { + Close(); + m_size = m_strImDbUrl.size(); + m_doc = new char[m_size+1]; + m_headofdoc = m_doc; + strcpy(m_doc, m_strImDbUrl.c_str()); + return S_OK; + } } DoScrape(m_parser); @@ -268,7 +296,7 @@ } else // we check to identify the episodeguide url { - m_parser.m_param[0] = strURL; + m_parser.m_param[0] = strURL; CStdString strEpGuide = m_parser.Parse("EpisodeGuideUrl", m_strScraper.CompareNoCase(m_info.strPath) == 0 ? &m_info.settings : 0); // allow corrections? if (strEpGuide.IsEmpty()) return E_FAIL; Index: xbmc/NfoFile.h =================================================================== --- xbmc/NfoFile.h (revision 24004) +++ xbmc/NfoFile.h (working copy) @@ -34,6 +34,7 @@ #include "utils/CharsetConverter.h" class CVideoInfoTag; +class CProgramInfoTag; class CScraperParser; class CScraperUrl; Index: xbmc/PowerManager.cpp =================================================================== --- xbmc/PowerManager.cpp (revision 24004) +++ xbmc/PowerManager.cpp (working copy) @@ -24,6 +24,7 @@ #include "Application.h" #include "GUIWindowManager.h" #include "GUIDialogVideoScan.h" +#include "GUIDialogProgramScan.h" #include "GUIDialogMusicScan.h" #include "KeyboardStat.h" #include "MouseStat.h" @@ -183,6 +184,17 @@ scanner->StartScanning("",info,settings,false); } + // update program library + if (g_guiSettings.GetBool("programlibrary.updateonstartup")) + { + CLog::Log(LOGNOTICE, "%s: Updating program library on resume", __FUNCTION__); + CGUIDialogProgramScan *scanner = (CGUIDialogProgramScan *)m_gWindowManager.GetWindow(WINDOW_DIALOG_PROGRAM_SCAN); + SScraperInfo info; + PROGRAM::SScanSettings settings; + if (scanner && !scanner->IsScanning()) + scanner->StartScanning("",info,settings,false); + } + // update music library if (g_guiSettings.GetBool("musiclibrary.updateonstartup")) { Index: xbmc/ProgramDatabase.cpp =================================================================== --- xbmc/ProgramDatabase.cpp (revision 24004) +++ xbmc/ProgramDatabase.cpp (working copy) @@ -19,579 +19,4810 @@ * */ + + +/////////////////////////////////////////////////////////////////////////////// +/// \file ProgramDatabase.cpp +/// +/// Quick Paths Overview: +/// - Games : programdb:// +/// - Genres : programdb://1/1/ +/// - Plot : programdb://1/2/ +/// - Years : programdb://1/3/ +/// - Perspectives : programdb://1/4/ +/// - Developers : programdb://1/5/ +/// - Publishers : programdb://1/6/ +/// +/////////////////////////////////////////////////////////////////////////////// + + + +// includes #include "stdafx.h" #include "ProgramDatabase.h" -#include "FileSystem/MultiPathDirectory.h" +#include "GUIWindowProgramBase.h" #include "utils/fstrcmp.h" +#include "utils/RegExp.h" +#include "utils/GUIInfoManager.h" #include "Util.h" -#include "GUIWindowFileManager.h" -#include "VideoInfoScanner.h" +#include "XMLUtils.h" +#include "GUIPassword.h" +#include "FileSystem/StackDirectory.h" +#include "FileSystem/MultiPathDirectory.h" +#include "ProgramInfoScanner.h" +#include "GUIWindowManager.h" +#include "FileSystem/Directory.h" +#include "FileSystem/File.h" +#include "GUIDialogProgress.h" +#include "GUIDialogYesNo.h" #include "FileItem.h" +#include "AdvancedSettings.h" #include "GUISettings.h" #include "Settings.h" -#include "log.h" +#include "LocalizeStrings.h" + +using namespace std; +using namespace dbiplus; using namespace XFILE; +using namespace DIRECTORY; +using namespace PROGRAM; -#define PROGRAM_DATABASE_OLD_VERSION 0.9f -#define PROGRAM_DATABASE_VERSION 3 -//******************************************************************************************************************************** +// TODO: Fix versioning of the database +#define PROGRAM_DATABASE_OLD_VERSION 0.9f +#define PROGRAM_DATABASE_VERSION 32 +#define PROGRAM_DATABASE_NAME "MyPrograms34.db" + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Constructor +/////////////////////////////////////////////////////////////////////////////// CProgramDatabase::CProgramDatabase(void) { - m_preV2version=PROGRAM_DATABASE_OLD_VERSION; - m_version=PROGRAM_DATABASE_VERSION; - m_strDatabaseFile=PROGRAM_DATABASE_NAME; + m_preV2version = PROGRAM_DATABASE_OLD_VERSION; + m_version = PROGRAM_DATABASE_VERSION; + m_strDatabaseFile = PROGRAM_DATABASE_NAME; } -//******************************************************************************************************************************** -CProgramDatabase::~CProgramDatabase(void) + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Destructor +/////////////////////////////////////////////////////////////////////////////// +CProgramDatabase::~CProgramDatabase(void) {} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Create and build the SQL for creating the tables used by the +/// programs database +/////////////////////////////////////////////////////////////////////////////// +bool CProgramDatabase::CreateTables() { + try { + CDatabase::CreateTables(); + /////////////// :: settings :: //////////////////////////////////////////// + CLog::Log( LOGINFO, "create settings table"); + + m_pDS->exec( + "CREATE TABLE settings" + " ( idFile integer, ConfArgv text, ConfPath text )" + ); + + m_pDS->exec( + "CREATE UNIQUE INDEX ix_settings ON settings ( idFile )\n" + ); + + /////////////// :: stacktimes :: ////////////////////////////////////////// + CLog::Log( LOGINFO, "create stacktimes table"); + + m_pDS->exec( + "CREATE TABLE stacktimes ( idFile integer, times text )\n" + ); + + m_pDS->exec( + "CREATE UNIQUE INDEX ix_stacktimes" + " ON stacktimes ( idFile )\n" + ); + + /////////////// :: Genre :: /////////////////////////////////////////////// + CLog::Log( LOGINFO, "create genre table"); + + m_pDS->exec( + "CREATE TABLE genre" + " ( idGenre integer primary key, strGenre text )\n" + ); + + CLog::Log( LOGINFO, "create genrelinkgame table"); + + // genre *.* game relation + m_pDS->exec( + "CREATE TABLE genrelinkgame" + " (idGenre integer, idGame integer)\n" + ); + + m_pDS->exec( + "CREATE UNIQUE INDEX ix_genrelinkgame_1 " + "ON genrelinkgame ( idGenre, idGame )\n" + ); + + m_pDS->exec( + "CREATE UNIQUE INDEX ix_genrelinkgame_2 " + "ON genrelinkgame ( idGame, idGenre )\n" + ); + + /////////////// :: perspective :: ///////////////////////////////////////// + CLog::Log( LOGINFO, "create perspective table"); + + m_pDS->exec( + "CREATE TABLE perspective" + " (idPerspective integer primary key, strPerspective text)\n"); + + CLog::Log( LOGINFO, "create perspectivelinkgame table"); + // perspective *.* game relation + m_pDS->exec( + "CREATE TABLE perspectivelinkgame (" + " idPerspective integer, idGame integer)\n" + ); + m_pDS->exec( + "CREATE UNIQUE INDEX ix_perspectivelinkgame_1" + " ON perspectivelinkgame ( idPerspective, idGame)\n" + ); + m_pDS->exec( + "CREATE UNIQUE INDEX ix_perspectivelinkgame_2" + " ON perspectivelinkgame ( idGame, idPerspective)\n" + ); + + /////////////// :: games :: /////////////////////////////////////////////// + CLog::Log( LOGINFO, "create game table"); + + CStdString columns = "CREATE TABLE game ( idGame integer primary key"; + + for (int i = 0; i < PROGRAMDB_MAX_COLUMNS; i++) { + CStdString column; + column.Format(", c%02d text", i); + columns += column; + } + columns += ",idFile integer)"; + m_pDS->exec(columns.c_str()); + + m_pDS->exec("CREATE UNIQUE INDEX ix_game_file_1 ON game (idFile, idGame)"); + m_pDS->exec("CREATE UNIQUE INDEX ix_game_file_2 ON game (idGame, idFile)"); + + /////////////// :: companies :: /////////////////////////////////////////// + // Developers/publishers are both companies and + // developer/publisher and/or publisher/developer + CLog::Log( LOGINFO, "create companies table"); + + m_pDS->exec( + "CREATE TABLE companies ("" idCompany integer primary key," + " strCompany text, strThumb text )\n" + ); + + // game *.* developer relation + CLog::Log( LOGINFO, "create developerlinkgame table"); + + m_pDS->exec( + "CREATE TABLE developerlinkgame (" + " idDeveloper integer, idGame integer)\n" + ); + m_pDS->exec( + "CREATE UNIQUE INDEX ix_developerlinkgame_1" + " ON developerlinkgame ( idDeveloper, idGame )\n" + ); + m_pDS->exec( + "CREATE UNIQUE INDEX ix_developerlinkgame_2" + " ON developerlinkgame ( idGame, idDeveloper )\n" + ); + + // game *.* publisher relation + CLog::Log( LOGINFO, "create publisherlinkgame table"); + + m_pDS->exec( + "CREATE TABLE publisherlinkgame (" + " idPublisher integer, idGame integer)\n" + ); + m_pDS->exec( + "CREATE UNIQUE INDEX ix_publisherlinkgame_1" + " ON publisherlinkgame ( idPublisher, idGame )\n" + ); + m_pDS->exec( + "CREATE UNIQUE INDEX ix_publisherlinkgame_2" + " ON publisherlinkgame ( idGame, idPublisher )\n" + ); + + /////////////// :: platforms :: /////////////////////////////////////////// + CLog::Log( LOGINFO, "create platforms table"); + + m_pDS->exec( + "CREATE TABLE platforms (" + " idPlatform integer primary key," + " strPlatform text," + " strLogo text" + ")\n" + ); + + m_pDS->exec("CREATE UNIQUE INDEX ix_platform ON platforms ( strPlatform )\n"); + + /////////////// :: path :: //////////////////////////////////////////////// + CLog::Log( LOGINFO, "create path table"); + + m_pDS->exec( + "CREATE TABLE path (" + " idPath integer primary key, strPath text, strContent text," + " strScraper text, strHash text, scanRecursive integer," + " useFolderNames bool, strSettings text, noUpdate bool)\n" + ); + + m_pDS->exec("CREATE UNIQUE INDEX ix_path ON path ( strPath )\n"); + + /////////////// :: files :: //////////////////////////////////////////////// + CLog::Log( LOGINFO, "create files table"); + + m_pDS->exec( + "CREATE TABLE files ( idFile integer primary key, idPath integer," + " strFilename text, playCount integer, lastPlayed text)\n" + ); + + m_pDS->exec( + "CREATE UNIQUE INDEX ix_files ON files ( idPath, strFilename )\n" + ); + + /////////////// :: gameview :: //////////////////////////////////////////// + CLog::Log( LOGINFO, "create gameview"); + m_pDS->exec( + "CREATE VIEW gameview AS SELECT game.*, files.strFileName" + " AS strFileName, path.strPath AS strPath, files.playCount" + " AS playCount, files.lastPlayed AS lastPlayed" + " FROM game JOIN files ON files.idFile = game.idFile JOIN path" + " ON path.idPath = files.idPath" + ); + } + catch(...) + { + CLog::Log( LOGERROR, + " %s::unable to create tables: %u", + __FUNCTION__, GetLastError() + ); + return false; + } + + return true; } -//******************************************************************************************************************************** -bool CProgramDatabase::CreateTables() + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Get ID for a given path +/////////////////////////////////////////////////////////////////////////////// +long CProgramDatabase::GetPathId(const CStdString &strPath) { + CStdString strSQL; + try + { + long lPathId = -1; + if (NULL == m_pDB.get()) return -1; + if (NULL == m_pDS.get()) return -1; + + CStdString strPath1(strPath); + + if (CUtil::IsStack(strPath) || + strPath.Mid(0, 6).Equals("rar://") || + strPath.Mid(0, 6).Equals("zip://") + ) + CUtil::GetParentPath(strPath,strPath1); + + CUtil::AddSlashAtEnd(strPath1); + + strSQL = FormatSQL( + "SELECT idPath from path WHERE strPath LIKE '%s'", + strPath1.c_str() + ); + + m_pDS->query(strSQL.c_str()); + if (!m_pDS->eof()) + lPathId = m_pDS->fv("path.idPath").get_asLong(); + m_pDS->close(); + + return lPathId; + } + catch(...) { + CLog::Log(LOGERROR, "%s unable to getpath (%s)", + __FUNCTION__, strSQL.c_str()); + } + + return -1; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Get paths from the database +/////////////////////////////////////////////////////////////////////////////// +bool CProgramDatabase::GetPaths(map &paths) +{ try { - CDatabase::CreateTables(); + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; - CLog::Log(LOGINFO, "create files table"); - m_pDS->exec("CREATE TABLE files ( idFile integer primary key, strFilename text, titleId integer, xbedescription text, iTimesPlayed integer, lastAccessed integer, iRegion integer, iSize integer)\n"); - CLog::Log(LOGINFO, "create files index"); - m_pDS->exec("CREATE INDEX idxFiles ON files(strFilename)"); - CLog::Log(LOGINFO, "create files - titleid index"); - m_pDS->exec("CREATE INDEX idxTitleIdFiles ON files(titleId)"); - CLog::Log(LOGINFO, "create titles table"); + paths.clear(); - m_pDS->exec("CREATE TABLE titles ( idTitle integer primary key, strTitle text, strDescription text, iType integer, strGenre text, strStyle text, strPublisher text, strDateOfRelease text, strYear text, thumbURL text, fanartURL text )\n"); - CLog::Log(LOGINFO, "create titles index"); - m_pDS->exec("CREATE INDEX idxTitles ON titles(idTitle)"); + SScanSettings settings; + SScraperInfo info; - CLog::Log(LOGINFO, "create path table"); - m_pDS->exec("CREATE TABLE path ( idPath integer primary key, strPath text, strContent text, strScraper text)\n"); - m_pDS->exec("CREATE UNIQUE INDEX idxPath ON path ( strPath )\n"); + memset(&settings, 0, sizeof(settings)); + + // grab all paths with game content set + if (!m_pDS->query( + "SELECT strPath, scanRecursive, useFolderNames, noUpdate" + " FROM path WHERE (strContent = 'games')" + " AND strPath NOT LIKE 'multipath://%%'" + " ORDER BY strPath") + ) + return false; + + while ( !m_pDS->eof() ) + { + if (!m_pDS->fv("noUpdate").get_asBool()) + { + CStdString strPath = m_pDS->fv("strPath").get_asString(); + settings.parent_name = m_pDS->fv("useFolderNames").get_asBool(); + settings.recurse = m_pDS->fv("scanRecursive").get_asInteger(); + settings.parent_name_root = settings.parent_name && !settings.recurse; + + paths.insert(pair (strPath, settings)); + } + + m_pDS->next(); + } + m_pDS->close(); + + + // finally grab all other paths holding a game which is ; + // not a stack or a rar archive ; + // * - this isnt perfect but it should do fine in most situations. ; + // reason we need it to hold a game is stacks from different ; + // directories (cdx folders for instancee not making mistakes ; + // must take priority + + if (!m_pDS->query( + "SELECT strPath, noUpdate FROM path WHERE idPath IN" + " (SELECT idPath FROM files" + " JOIN game ON game.idFile = files.idFile)" + " AND strPath NOT LIKE 'multipath://%%'" + " AND strContent NOT IN ('games', 'None')" + " ORDER BY strPath") + ) + return false; + + while ( !m_pDS->eof() ) + { + if ( !m_pDS->fv("noUpdate").get_asBool() ) + { + CStdString strPath = m_pDS->fv("strPath").get_asString(); + settings.parent_name = false; + settings.recurse = 0; + settings.parent_name_root = settings.parent_name && !settings.recurse; + paths.insert(pair (strPath, settings)); + } + m_pDS->next(); + } + m_pDS->close(); + + return true; } - catch (...) + catch(...) { + CLog::Log(LOGERROR, "%s failed", __FUNCTION__); + } + + return false; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Adds a path to the database +/////////////////////////////////////////////////////////////////////////////// +long CProgramDatabase::AddPath(const CStdString &strPath) +{ + CStdString strSQL; + + try { - CLog::Log(LOGERROR, "programdatabase::unable to create tables:%u", - GetLastError()); - return false; + long lPathId; + + if (NULL == m_pDB.get()) return -1; + if (NULL == m_pDS.get()) return -1; + + CStdString strPath1(strPath); + if ( + CUtil::IsStack(strPath) || + strPath.Mid(0,6).Equals("rar://") || + strPath.Mid(0,6).Equals("zip://") + ) + CUtil::GetParentPath(strPath,strPath1); + + CUtil::AddSlashAtEnd(strPath1); + + strSQL = FormatSQL( + "INSERT INTO path (idPath, strPath, strContent, strScraper)" + " VALUES (NULL, '%s', '', '')", + strPath1.c_str() + ); + + m_pDS->exec( strSQL.c_str() ); + + lPathId = (long)sqlite3_last_insert_rowid( m_pDB->getHandle() ); + + return lPathId; } + catch(...) + { + CLog::Log( LOGERROR, "%s unable to addpath (%s)", + __FUNCTION__, strSQL.c_str()); + } - return true; + return -1; } -bool CProgramDatabase::UpdateOldVersion(int version) + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Get path hash +/////////////////////////////////////////////////////////////////////////////// +bool CProgramDatabase::GetPathHash(const CStdString &path, CStdString &hash) { - if (NULL == m_pDB.get()) return false; - if (NULL == m_pDS.get()) return false; - if (NULL == m_pDS2.get()) return false; + CStdString strSQL; + try + { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + CStdString strSQL = FormatSQL( + "SELECT strHash FROM path WHERE strPath LIKE '%s'", + path.c_str() + ); + + m_pDS->query(strSQL.c_str()); + + if (m_pDS->num_rows() == 0) + return false; + + hash = m_pDS->fv("strHash").get_asString(); + + return true; + } + catch(...) + { + CLog::Log(LOGERROR, "%s (%s) failed", __FUNCTION__, path.c_str()); + } + + return false; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/////////////////////////////////////////////////////////////////////////////// +bool CProgramDatabase::SetPathHash +( + const CStdString &path, + const CStdString &hash +) +{ try { + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + + if (hash.IsEmpty()) + { + // this is an empty folder ; + // we need only add it to the path + // table if the path actually exists + if (!CDirectory::Exists(path)) + return false; + } + + long pathId = GetPathId(path); + + if (pathId < 0) + pathId = AddPath(path); + + if (pathId < 0) + return false; + + CStdString strSQL = FormatSQL( + "UPDATE path SET strHash = '%s' WHERE idPath = %ld", + hash.c_str(), pathId); + + m_pDS->exec( strSQL.c_str() ); + + return true; } + catch(...) + { + CLog::Log(LOGERROR, "%s (%s, %s) failed", + __FUNCTION__, path.c_str(), hash.c_str()); + } + + return false; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Links a Many to Many relationship +/////////////////////////////////////////////////////////////////////////////// +void CProgramDatabase::AddToLinkTable +( + const char *table, + const char *firstField, + long firstID, + const char *secondField, + long secondID +) +{ + try + { + if (NULL == m_pDB.get()) return ; + if (NULL == m_pDS.get()) return ; + + CStdString strSQL = FormatSQL( + "SELECT * FROM %s WHERE %s = %u AND %s = %u", + table, firstField, firstID, secondField, secondID); + + m_pDS->query(strSQL.c_str()); + + if (m_pDS->num_rows() == 0) + { + // doesnt exists, add it + strSQL = FormatSQL( + "INSERT INTO %s (%s, %s) VALUES(%i, %i)", + table, firstField, secondField, firstID, secondID); + + m_pDS->exec(strSQL.c_str()); + } + m_pDS->close(); + } catch (...) { - CLog::Log(LOGERROR, "Error attempting to update the database version!"); - return false; + CLog::Log(LOGERROR, "%s failed", __FUNCTION__); } - return true; } -DWORD CProgramDatabase::GetTitleId(const CStdString& strFilenameAndPath) + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Add a file to the database +/////////////////////////////////////////////////////////////////////////////// +long CProgramDatabase::AddFile(const CStdString &strFileNameAndPath) { - if (NULL == m_pDB.get()) return 0; - if (NULL == m_pDS.get()) return 0; + CStdString strSQL = ""; + try + { + long lFileId; + if (NULL == m_pDB.get()) return -1; + if (NULL == m_pDS.get()) return -1; + + CStdString strFileName, strPath; + SplitPath(strFileNameAndPath,strPath,strFileName); + + long lPathId = GetPathId(strPath); + + if (lPathId < 0) + lPathId = AddPath(strPath); + if (lPathId < 0) + return -1; + + CStdString strSQL = FormatSQL( + "SELECT idFile FROM files WHERE strFileName" + " LIKE '%s' AND idPath = %u", + strFileName.c_str(), lPathId + ); + + m_pDS->query(strSQL.c_str()); + + if (m_pDS->num_rows() > 0) + { + lFileId = m_pDS->fv("idFile").get_asLong(); + m_pDS->close(); + + return lFileId; + } + + m_pDS->close(); + + strSQL = FormatSQL( + "INSERT INTO files (idFile, idPath, strFileName)" + " VALUES(NULL, %u, '%s')", + lPathId, strFileName.c_str() + ); + m_pDS->exec( strSQL.c_str() ); + lFileId = (long)sqlite3_last_insert_rowid( m_pDB->getHandle() ); + + return lFileId; + } + catch(...) + { + CLog::Log(LOGERROR, "%s unable to addfile (%s)", + __FUNCTION__,strSQL.c_str() + ); + } + + return -1; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Get a file identificaton for a given file from the database +/////////////////////////////////////////////////////////////////////////////// +long CProgramDatabase::GetFileId(const CStdString &strFilenameAndPath) +{ try { - CStdString strSQL = FormatSQL("select * from files where files.strFileName like '%s'", strFilenameAndPath.c_str()); - if (!m_pDS->query(strSQL.c_str())) - return 0; + if (NULL == m_pDB.get()) return -1; + if (NULL == m_pDS.get()) return -1; - int iRowsFound = m_pDS->num_rows(); - if (iRowsFound == 0) + CStdString strPath, strFileName; + SplitPath(strFilenameAndPath,strPath,strFileName); + + long lPathId = GetPathId(strPath); + if (lPathId < 0) return -1; + + CStdString strSQL; + strSQL = FormatSQL( + "SELECT idFile FROM files WHERE strFileName LIKE '%s'" + " AND idPath = %u", + strFileName.c_str(), lPathId + ); + m_pDS->query( strSQL.c_str() ); + + if (m_pDS->num_rows() > 0) { + long lFileId = m_pDS->fv("files.idFile").get_asLong(); m_pDS->close(); - return 0; + + return lFileId; + } + } + catch(...) + { + CLog::Log( LOGERROR, "%s (%s) failed", + __FUNCTION__, strFilenameAndPath.c_str() + ); + } + + return -1; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Find a identification for a given game from the database +/////////////////////////////////////////////////////////////////////////////// +long CProgramDatabase::GetGameId(const CStdString &strFilenameAndPath) +{ + try + { + if (NULL == m_pDB.get()) return -1; + if (NULL == m_pDS.get()) return -1; + + long lGameId = -1; + + /* needed for query parameters */ + long lFileId = GetFileId(strFilenameAndPath); + long lPathId = -1; + CStdString strPath, strFile; + + if (lFileId < 0) + { + SplitPath(strFilenameAndPath,strPath,strFile); + + /* have to join gameinfo table for correct results */ + lPathId = GetPathId(strPath); + if (lPathId < 0 && strPath != strFilenameAndPath) + return -1; + } + + if (lFileId == -1 && strPath != strFilenameAndPath) + return -1; + + CStdString strSQL; + if (lFileId == -1) + { + strSQL = FormatSQL( + "SELECT idGame FROM game JOIN files" + " ON files.idFile = game.idFile WHERE files.idpath = %u", + lPathId + ); } - DWORD dwTitleId = m_pDS->fv("files.TitleId").get_asLong(); + else + strSQL = FormatSQL( + "SELECT idGame FROM game WHERE idFile = %u", + lFileId + ); + + CLog::Log( LOGDEBUG, + "%s (%s), query = %s", + __FUNCTION__, strFilenameAndPath.c_str(), strSQL.c_str() + ); + + m_pDS->query(strSQL.c_str()); + if (m_pDS->num_rows() > 0) + lGameId = m_pDS->fv("idGame").get_asLong(); + m_pDS->close(); - return dwTitleId; + + return lGameId; + } + catch(...) + { + CLog::Log(LOGERROR, "%s (%s) failed", + __FUNCTION__, strFilenameAndPath.c_str() + ); } + + return -1; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Add a game to the database +/////////////////////////////////////////////////////////////////////////////// +long CProgramDatabase::AddGame(const CStdString &strFilenameAndPath) +{ + try + { + if (NULL == m_pDB.get()) return -1; + if (NULL == m_pDS.get()) return -1; + + long lFileId, lGameId = -1; + lFileId = GetFileId( strFilenameAndPath ); + + if (lFileId < 0) + lFileId = AddFile( strFilenameAndPath ); + else + lGameId = GetGameId( strFilenameAndPath ); + + if (lGameId < 0) + { + CStdString strSQL; + strSQL = FormatSQL( + "INSERT INTO game (idGame, idFile)" + " VALUES (NULL, %u)", + lFileId + ); + m_pDS->exec( strSQL.c_str() ); + lGameId = (long)sqlite3_last_insert_rowid(m_pDB->getHandle()); + } + + return lGameId; + } + catch(...) + { + CLog::Log(LOGERROR, "%s (%s) failed", + __FUNCTION__, strFilenameAndPath.c_str() + ); + } + + return -1; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Add a genre to the database +/////////////////////////////////////////////////////////////////////////////// +long CProgramDatabase::AddGenre(const CStdString &strGenre) +{ + try + { + if (NULL == m_pDB.get()) return -1; + if (NULL == m_pDS.get()) return -1; + + CStdString strSQL = FormatSQL( + "SELECT idGenre FROM genre WHERE strGenre LIK '%s'", + strGenre.c_str() + ); + m_pDS->query(strSQL.c_str()); + + if (m_pDS->num_rows() == 0) + { + m_pDS->close(); + + // doesnt exists, add it + strSQL = FormatSQL( + "INSERT INTO genre(idGenre, strGenre) VALUES( NULL, '%s')", + strGenre.c_str() + ); + m_pDS->exec(strSQL.c_str()); + + long lGenreId = (long)sqlite3_last_insert_rowid(m_pDB->getHandle()); + + return lGenreId; + } + else + { + const field_value value = m_pDS->fv("idGenre"); + long lGenreId = value.get_asLong(); + m_pDS->close(); + + return lGenreId; + } + } + catch(...) + { + CLog::Log(LOGERROR, "%s (%s) failed", __FUNCTION__, strGenre.c_str()); + } + + return -1; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Link a given developer to a given game +/////////////////////////////////////////////////////////////////////////////// +void CProgramDatabase::AddDeveloperToGame(long lGameId, long lDeveloperId) +{ + AddToLinkTable( + "developerlinkgame", + "idDeveloper", + lDeveloperId, + "idGame", + lGameId + ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Links a given publisher to a given game +/////////////////////////////////////////////////////////////////////////////// +void CProgramDatabase::AddPublisherToGame(long lGameId, long lPublisherId) +{ + AddToLinkTable( + "publisherlinkgame", + "idPublisher", + lPublisherId, + "idGame", + lGameId + ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Link a given genre to a given game +/////////////////////////////////////////////////////////////////////////////// +void CProgramDatabase::AddGenreToGame(long lGameId, long lGenreId) +{ + AddToLinkTable( + "genrelinkgame", + "idGenre", + lGenreId, + "idGame", + lGameId + ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Links a given perspective to a given game +/////////////////////////////////////////////////////////////////////////////// +void CProgramDatabase::AddPerspectiveToGame(long lGameId, long lPerspectiveId) +{ + AddToLinkTable( + "perspectivelinkgame", + "idPerspective", + lPerspectiveId, + "idGame", + lGameId + ); +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Get company entries for navigation +/////////////////////////////////////////////////////////////////////////////// +bool CProgramDatabase::GetCompanyNav +( + const CStdString& strBaseDir, + CFileItemList &items, + const CStdString &type, + long idContent +) +{ + if (NULL == m_pDB.get()) return false; + if (NULL == m_pDS.get()) return false; + + try { + CStdString strSQL; + + if (g_settings.m_vecProfiles[0].getLockMode() != + LOCK_MODE_EVERYONE && !g_passwordManager.bMasterUser) + { + if (idContent == PROGRAMDB_CONTENT_GAMES) + strSQL = FormatSQL( + "SELECT companies.idCompany, companies.strCompany," + " companies.strThumb, path.strPath, files.playCount" + " FROM companies JOIN %slinkgame " + " ON companies.idCompany = %slinkGame.id%s" + " JOIN game ON %slinkGame.idGame = movie.idGame" + " JOIN files ON files.idFile = game.idFile" + " JOIN path ON path.idPath = files.idPath", + type.c_str(), type.c_str(), type.c_str(), type.c_str() + ); + } + else + { + if (idContent == PROGRAMDB_CONTENT_GAMES) + { + strSQL = FormatSQL( + "SELECT companies.idCompany, companies.strCompany," + " companies.strThumb, COUNT(1), COUNT(files.playCount)" + " FROM companies JOIN %slinkgame" + " ON companies.idCompany = %slinkGame.id%s" + " JOIN movie ON %slinkGame.idGame = game.idGame" + " JOIN files ON files.idFile = game.idFile", + type.c_str(), type.c_str(), type.c_str(), type.c_str() + ); + strSQL += " GROUP BY companies.idCompany"; + } + } + + // run query + unsigned int time = timeGetTime(); + if ( !m_pDS->query(strSQL.c_str()) ) + return false; + + CLog::Log(LOGDEBUG, "%s - query took %u ms", + __FUNCTION__, timeGetTime() - time); time = timeGetTime(); + + int iRowsFound = m_pDS->num_rows(); + if (iRowsFound == 0) + { + m_pDS->close(); + return true; + } + + if (g_settings.m_vecProfiles[0].getLockMode() != LOCK_MODE_EVERYONE && + !g_passwordManager.bMasterUser) + { + map mapCompanies; + map::iterator it; + + while (!m_pDS->eof()) + { + long lCompanyId = m_pDS->fv(0).get_asLong(); + + CCompany company; + company.name = m_pDS->fv(1).get_asString(); + company.thumb = m_pDS->fv(2).get_asString(); + + it = mapCompanies.find(lCompanyId); + if (it == mapCompanies.end()) + { + if (g_passwordManager.IsDatabasePathUnlocked( + CStdString(m_pDS->fv("path.strPath").get_asString()), + g_settings.m_programSources)) + mapCompanies.insert(pair(lCompanyId, company)); + } + m_pDS->next(); + } + m_pDS->close(); + + for (it=mapCompanies.begin();it != mapCompanies.end();++it) + { + CFileItemPtr pItem(new CFileItem(it->second.name)); + CStdString strDir; + strDir.Format("%ld/", it->first); + pItem->m_strPath = strBaseDir + strDir; + pItem->m_bIsFolder = true; + pItem->GetProgramInfoTag()->m_playCount = it->second.playcount; + pItem->GetProgramInfoTag()->m_strPictureURL.ParseString(it->second.thumb); + items.Add(pItem); + } + } + else + { + while (!m_pDS->eof()) + { + try + { + CFileItemPtr pItem( + new CFileItem(m_pDS->fv(1).get_asString()) + ); + CStdString strDir; + strDir.Format("%ld/", m_pDS->fv(0).get_asLong()); + pItem->m_strPath = strBaseDir + strDir; + pItem->m_bIsFolder = true; + pItem->GetProgramInfoTag()-> + m_strPictureURL.ParseString(m_pDS->fv(2).get_asString()); + items.Add(pItem); + m_pDS->next(); + } + catch (...) + { + m_pDS->close(); + + CLog::Log( LOGERROR, + "%s: out of memory - retrieved %i items", + __FUNCTION__, items.Size() + ); + + return items.Size() > 0; + } + } + m_pDS->close(); + } + + CLog::Log( LOGDEBUG, "%s item retrieval took %u ms", + __FUNCTION__, timeGetTime() - time); + time = timeGetTime(); + + return true; + } catch (...) { - CLog::Log(LOGERROR, "CProgramDatabase:GetTitleId(%s) failed", strFilenameAndPath.c_str()); + m_pDS->close(); + CLog::Log(LOGERROR, "%s failed", __FUNCTION__); } - return 0; + + return false; } -bool CProgramDatabase::SetTitleId(const CStdString& strFileName, DWORD dwTitleId) + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Checks if a given game has information in the game library +/////////////////////////////////////////////////////////////////////////////// +bool CProgramDatabase::HasGameInfo +( + const CStdString &strFilenameAndPath +) { try { if (NULL == m_pDB.get()) return false; if (NULL == m_pDS.get()) return false; - CStdString strSQL = FormatSQL("select * from files where files.strFileName like '%s'", strFileName.c_str()); - if (!m_pDS->query(strSQL.c_str())) return false; - int iRowsFound = m_pDS->num_rows(); - if (iRowsFound == 0) + long lGameId = GetGameId(strFilenameAndPath); + + return (lGameId > 0); + } + catch(...) + { + CLog::Log( LOGERROR, "%s (%s) failed", + __FUNCTION__, strFilenameAndPath.c_str()); + } + + return false; +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Find information for a game from the game library +/////////////////////////////////////////////////////////////////////////////// +void CProgramDatabase::GetGameInfo +( + const CStdString &strFilenameAndPath, + CProgramInfoTag &details, + long lGameId // = -1 +) +{ + try + { + // TODO: Optimize this - no need for all the queries! + if (lGameId < 0) + lGameId = GetGameId(strFilenameAndPath); + if (lGameId < 0) + return; + + CStdString sql = FormatSQL( + "SELECT * FROM gameview WHERE idGame = %i", + lGameId); + + if (!m_pDS->query(sql.c_str())) + return; + + details = GetDetailsForGame(m_pDS); + } + catch(...) + { + CLog::Log(LOGERROR, "%s (%s) failed", + __FUNCTION__, strFilenameAndPath.c_str()); + } +} + + + +/////////////////////////////////////////////////////////////////////////////// +/// \brief Add genre, developers and publishers to a game +/////////////////////////////////////////////////////////////////////////////// +void CProgramDatabase::AddGenreAndDevelopersAndPublishers +( + const CProgramInfoTag &details, + vector &vecDevelopers, + vector &vecGenres, + vector &vecPublishers + ) +{ + // add all developers + if (!details.m_strDeveloper.IsEmpty()) + { + CStdStringArray developers; + StringUtils::SplitString(details.m_strDeveloper,"/",developers); + + for