aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.in5
-rw-r--r--addons/libraries/scrapers/AllMusic/description.xml21
-rw-r--r--addons/libraries/scrapers/DTrailer/description.xml20
-rw-r--r--addons/libraries/scrapers/HTBackDrops/description.xml20
-rw-r--r--addons/libraries/scrapers/IMDB/description.xml20
-rw-r--r--addons/libraries/scrapers/IMPA/description.xml20
-rw-r--r--addons/libraries/scrapers/LastFM/description.xml21
-rw-r--r--addons/libraries/scrapers/MoviePosterDB/description.xml20
-rw-r--r--addons/libraries/scrapers/TMDB/description.xml20
-rw-r--r--addons/scrapers/AllMusic/default.tbnbin0 -> 2623 bytes
-rw-r--r--addons/scrapers/AllMusic/description.xml21
-rw-r--r--addons/scrapers/AmazonUK/default.tbnbin0 -> 31789 bytes
-rw-r--r--addons/scrapers/AmazonUK/description.xml20
-rw-r--r--addons/scrapers/IMDB/default.tbnbin0 -> 22110 bytes
-rw-r--r--addons/scrapers/IMDB/description.xml21
-rw-r--r--addons/scrapers/IMDB/resources/language/English/strings.xml12
-rw-r--r--addons/scrapers/LastFM/default.tbnbin0 -> 4045 bytes
-rw-r--r--addons/scrapers/LastFM/description.xml24
-rw-r--r--addons/scrapers/YahooMusic/default.tbnbin0 -> 8629 bytes
-rw-r--r--addons/scrapers/YahooMusic/description.xml20
-rw-r--r--addons/scrapers/YahooMusic/resources/language/English/strings.xml5
-rwxr-xr-xaddons/visualizations/GLSpectrum/default.tbnbin0 -> 2156 bytes
-rw-r--r--addons/visualizations/GLSpectrum/description.xml19
-rw-r--r--addons/visualizations/GLSpectrum/resources/language/English/strings.xml19
-rw-r--r--addons/visualizations/GLSpectrum/resources/language/German/strings.xml19
-rw-r--r--addons/visualizations/GLSpectrum/resources/settings.xml5
-rw-r--r--addons/visualizations/ProjectM/default.tbnbin0 -> 14860 bytes
-rw-r--r--addons/visualizations/ProjectM/description.xml19
-rw-r--r--addons/visualizations/ProjectM/resources/language/English/strings.xml13
-rw-r--r--addons/visualizations/ProjectM/resources/presets.zipbin0 -> 862209 bytes
-rwxr-xr-xaddons/visualizations/Waveform/default.tbnbin0 -> 1437 bytes
-rw-r--r--addons/visualizations/Waveform/description.xml19
-rw-r--r--addons/visualizations/iTunes/description.xml17
-rw-r--r--guilib/GUIControl.h1
-rw-r--r--guilib/GUIInfoTypes.cpp33
-rw-r--r--guilib/GUIInfoTypes.h7
-rw-r--r--guilib/GUIMessage.cpp10
-rw-r--r--guilib/GUIMessage.h2
-rw-r--r--guilib/GUIRenderingControl.cpp92
-rw-r--r--guilib/GUIRenderingControl.h43
-rw-r--r--guilib/GUIVisualisationControl.cpp457
-rw-r--r--guilib/GUIVisualisationControl.h63
-rw-r--r--guilib/Key.h4
-rw-r--r--guilib/Makefile.in1
-rw-r--r--language/English/strings.xml36
-rw-r--r--project/VS2008Express/XBMC.vcproj100
-rw-r--r--project/VS2008Express/guilib.vcproj8
-rw-r--r--skin/Confluence/720p/AddonBrowser.xml313
-rw-r--r--skin/Confluence/720p/DialogAddonSettings.xml166
-rw-r--r--skin/Confluence/720p/Settings.xml12
-rw-r--r--skin/Confluence/720p/VisualisationPresetList.xml4
-rw-r--r--skin/Confluence/720p/custom_SkinSetting_1111.xml18
-rw-r--r--skin/Confluence/language/English/strings.xml1
-rw-r--r--skin/PM3.HD/720p/DialogAddonSettings.xml (renamed from skin/PM3.HD/720p/DialogPluginSettings.xml)290
-rw-r--r--skin/PM3.HD/720p/DialogContentSettings.xml1
-rw-r--r--skin/PM3.HD/720p/MusicOSDVisSettings.xml105
-rw-r--r--system/keymaps/keyboard.xml5
-rw-r--r--system/keymaps/remote.xml5
-rw-r--r--visualisations/xbmc_vis.h108
-rw-r--r--xbmc/Application.cpp102
-rw-r--r--xbmc/ButtonTranslator.cpp4
-rw-r--r--xbmc/DllAddon.h64
-rw-r--r--xbmc/FileSystem/AddonsDirectory.cpp86
-rw-r--r--xbmc/FileSystem/AddonsDirectory.h (renamed from xbmc/ScriptSettings.h)42
-rw-r--r--xbmc/FileSystem/FactoryDirectory.cpp6
-rw-r--r--xbmc/FileSystem/Makefile.in3
-rw-r--r--xbmc/FileSystem/PluginDirectory.cpp219
-rw-r--r--xbmc/FileSystem/PluginDirectory.h13
-rw-r--r--xbmc/GUIDialogAddonSettings.cpp (renamed from xbmc/GUIDialogPluginSettings.cpp)213
-rw-r--r--xbmc/GUIDialogAddonSettings.h (renamed from xbmc/GUIDialogPluginSettings.h)24
-rw-r--r--xbmc/GUIDialogContentSettings.cpp585
-rw-r--r--xbmc/GUIDialogContentSettings.h35
-rw-r--r--xbmc/GUIDialogContextMenu.cpp44
-rw-r--r--xbmc/GUIDialogLockSettings.cpp7
-rw-r--r--xbmc/GUIDialogLockSettings.h3
-rw-r--r--xbmc/GUIDialogMediaSource.cpp14
-rw-r--r--xbmc/GUIDialogMediaSource.h2
-rw-r--r--xbmc/GUIDialogMusicOSD.cpp5
-rw-r--r--xbmc/GUIDialogMusicOSD.h8
-rw-r--r--xbmc/GUIDialogProfileSettings.cpp5
-rw-r--r--xbmc/GUIDialogProfileSettings.h1
-rw-r--r--xbmc/GUIDialogVideoScan.cpp2
-rw-r--r--xbmc/GUIDialogVideoScan.h2
-rw-r--r--xbmc/GUIDialogVisualisationPresetList.cpp88
-rw-r--r--xbmc/GUIDialogVisualisationPresetList.h12
-rw-r--r--xbmc/GUIDialogVisualisationSettings.cpp219
-rw-r--r--xbmc/GUIDialogVisualisationSettings.h53
-rw-r--r--xbmc/GUIMediaWindow.cpp38
-rw-r--r--xbmc/GUIPassword.cpp2
-rw-r--r--xbmc/GUISettings.cpp8
-rw-r--r--xbmc/GUIViewState.cpp30
-rw-r--r--xbmc/GUIViewState.h4
-rw-r--r--xbmc/GUIViewStateMusic.cpp24
-rw-r--r--xbmc/GUIViewStateMusic.h2
-rw-r--r--xbmc/GUIViewStatePictures.cpp13
-rw-r--r--xbmc/GUIViewStatePrograms.cpp13
-rw-r--r--xbmc/GUIViewStateScripts.cpp19
-rw-r--r--xbmc/GUIViewStateVideo.cpp22
-rw-r--r--xbmc/GUIViewStateVideo.h2
-rw-r--r--xbmc/GUIWindowAddonBrowser.cpp254
-rw-r--r--xbmc/GUIWindowAddonBrowser.h (renamed from xbmc/visualizations/VisualisationFactory.h)35
-rw-r--r--xbmc/GUIWindowMusicBase.cpp18
-rw-r--r--xbmc/GUIWindowMusicBase.h6
-rw-r--r--xbmc/GUIWindowMusicNav.cpp29
-rw-r--r--xbmc/GUIWindowScreensaver.cpp32
-rw-r--r--xbmc/GUIWindowScreensaver.h1
-rw-r--r--xbmc/GUIWindowScripts.cpp24
-rw-r--r--xbmc/GUIWindowSettingsCategory.cpp287
-rw-r--r--xbmc/GUIWindowSettingsCategory.h5
-rw-r--r--xbmc/GUIWindowVideoBase.cpp136
-rw-r--r--xbmc/GUIWindowVideoBase.h12
-rw-r--r--xbmc/GUIWindowVideoFiles.cpp84
-rw-r--r--xbmc/GUIWindowVideoFiles.h3
-rw-r--r--xbmc/GUIWindowVideoNav.cpp25
-rw-r--r--xbmc/GUIWindowVideoNav.h2
-rw-r--r--xbmc/GUIWindowVisualisation.cpp94
-rw-r--r--xbmc/GUIWindowVisualisation.h9
-rw-r--r--xbmc/GUIWindowWeather.cpp48
-rw-r--r--xbmc/GUIWindowWeather.h4
-rw-r--r--xbmc/Makefile.in8
-rw-r--r--xbmc/MediaSource.cpp19
-rw-r--r--xbmc/MediaSource.h1
-rw-r--r--xbmc/MusicDatabase.cpp78
-rw-r--r--xbmc/MusicDatabase.h7
-rw-r--r--xbmc/MusicInfoScanner.cpp16
-rw-r--r--xbmc/NfoFile.cpp119
-rw-r--r--xbmc/NfoFile.h16
-rw-r--r--xbmc/PluginSettings.cpp244
-rw-r--r--xbmc/PluginSettings.h65
-rw-r--r--xbmc/PowerManager.cpp6
-rw-r--r--xbmc/Profile.cpp2
-rw-r--r--xbmc/Profile.h5
-rw-r--r--xbmc/Scraper.cpp (renamed from xbmc/ScraperSettings.cpp)112
-rw-r--r--xbmc/Scraper.h58
-rw-r--r--xbmc/ScraperSettings.h62
-rw-r--r--xbmc/ScriptSettings.cpp134
-rw-r--r--xbmc/Settings.cpp10
-rw-r--r--xbmc/StringUtils.cpp59
-rw-r--r--xbmc/StringUtils.h4
-rw-r--r--xbmc/URL.cpp4
-rw-r--r--xbmc/Util.cpp4
-rw-r--r--xbmc/VideoDatabase.cpp218
-rw-r--r--xbmc/VideoDatabase.h13
-rw-r--r--xbmc/VideoInfoScanner.cpp169
-rw-r--r--xbmc/VideoInfoScanner.h18
-rw-r--r--xbmc/addons/include/NOTE9
-rw-r--r--xbmc/addons/include/xbmc_addon_cpp_dll.h171
-rw-r--r--xbmc/addons/include/xbmc_addon_dll.h46
-rw-r--r--xbmc/addons/include/xbmc_scr_dll.h26
-rw-r--r--xbmc/addons/include/xbmc_scr_types.h (renamed from xbmc/screensavers/ScreenSaverFactory.h)39
-rw-r--r--xbmc/addons/include/xbmc_vis_dll.h37
-rw-r--r--xbmc/addons/include/xbmc_vis_types.h113
-rw-r--r--xbmc/karaoke/karaokewindowbackground.cpp2
-rw-r--r--xbmc/lib/libPython/xbmcmodule/PythonSettings.cpp53
-rw-r--r--xbmc/lib/libPython/xbmcmodule/PythonSettings.h5
-rw-r--r--xbmc/lib/libPython/xbmcmodule/xbmcplugin.cpp91
-rw-r--r--xbmc/lib/libhttpapi/XBMChttp.cpp15
-rw-r--r--xbmc/screensavers/DllScreenSaver.h34
-rw-r--r--xbmc/screensavers/Makefile.in2
-rw-r--r--xbmc/screensavers/ScreenSaver.cpp49
-rw-r--r--xbmc/screensavers/ScreenSaver.h35
-rw-r--r--xbmc/screensavers/ScreenSaverFactory.cpp54
-rw-r--r--xbmc/screensavers/xbmc_scr.h58
-rw-r--r--xbmc/utils/Addon.cpp537
-rw-r--r--xbmc/utils/Addon.h176
-rw-r--r--xbmc/utils/AddonDll.h399
-rw-r--r--xbmc/utils/AddonManager.cpp1198
-rw-r--r--xbmc/utils/AddonManager.h151
-rw-r--r--xbmc/utils/Builtins.cpp53
-rw-r--r--xbmc/utils/DownloadQueue.cpp6
-rw-r--r--xbmc/utils/DownloadQueue.h6
-rw-r--r--xbmc/utils/DownloadQueueManager.cpp6
-rw-r--r--xbmc/utils/DownloadQueueManager.h6
-rw-r--r--xbmc/utils/GUIInfoManager.cpp18
-rw-r--r--xbmc/utils/IAddon.h111
-rw-r--r--xbmc/utils/IMDB.cpp26
-rw-r--r--xbmc/utils/IMDB.h8
-rw-r--r--xbmc/utils/Makefile6
-rw-r--r--xbmc/utils/MusicAlbumInfo.cpp10
-rw-r--r--xbmc/utils/MusicAlbumInfo.h4
-rw-r--r--xbmc/utils/MusicArtistInfo.cpp10
-rw-r--r--xbmc/utils/MusicArtistInfo.h4
-rw-r--r--xbmc/utils/MusicInfoScraper.cpp55
-rw-r--r--xbmc/utils/MusicInfoScraper.h10
-rw-r--r--xbmc/utils/ScraperParser.cpp136
-rw-r--r--xbmc/utils/ScraperParser.h19
-rw-r--r--xbmc/utils/ScraperUrl.cpp2
-rw-r--r--xbmc/visualizations/DirectXSpectrum/directx_spectrum.cpp155
-rw-r--r--xbmc/visualizations/DllVisualisation.h17
-rw-r--r--xbmc/visualizations/Makefile5
-rw-r--r--xbmc/visualizations/OpenGLSpectrum/Makefile.in4
-rw-r--r--xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp241
-rw-r--r--xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.vcproj353
-rw-r--r--xbmc/visualizations/Visualisation.cpp541
-rw-r--r--xbmc/visualizations/Visualisation.h126
-rw-r--r--xbmc/visualizations/VisualisationFactory.cpp86
-rw-r--r--xbmc/visualizations/VisualisationTypes.h262
-rw-r--r--xbmc/visualizations/WaveForm/Main.cpp116
-rw-r--r--xbmc/visualizations/WaveForm/Makefile.in4
-rw-r--r--xbmc/visualizations/XBMCProjectM/Main.cpp886
-rw-r--r--xbmc/visualizations/XBMCProjectM/Makefile.in5
-rw-r--r--xbmc/visualizations/XBMCProjectM/libprojectM/Preset.cpp27
-rw-r--r--xbmc/visualizations/iTunes/Main.cpp117
-rw-r--r--xbmc/visualizations/iTunes/Makefile.in4
-rw-r--r--xbmc/win32/PlatformDefs.h1
-rw-r--r--xbmc/win32/strverscmp.cpp135
206 files changed, 8364 insertions, 5419 deletions
diff --git a/Makefile.in b/Makefile.in
index 4feaca8102..885af4ce01 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -97,9 +97,6 @@ LIB_DIRS=\
lib/libmodplug \
lib/xbmc-dll-symbols
-SS_DIRS=\
- xbmc/screensavers/rsxs-0.9/xbmc
-
VIS_DIRS=\
xbmc/visualizations/OpenGLSpectrum \
xbmc/visualizations/WaveForm \
@@ -295,8 +292,6 @@ ifeq ($(or $(findstring powerpc-linux,$(ARCH)),$(findstring powerpc64-linux,$(AR
$(MAKE) -C xbmc/visualizations/Goom
endif
endif
-screensavers: exports
- $(MAKE) -C xbmc/screensavers/rsxs-0.9/xbmc
libpython: dllloader
$(MAKE) -C xbmc/lib/libPython
$(MAKE) -C xbmc/lib/libPython/xbmcmodule
diff --git a/addons/libraries/scrapers/AllMusic/description.xml b/addons/libraries/scrapers/AllMusic/description.xml
new file mode 100644
index 0000000000..a0ee0d688d
--- /dev/null
+++ b/addons/libraries/scrapers/AllMusic/description.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>49acf415-02ad-4281-8eb4-9278326f4a05</uuid>
+ <type>scraper-library</type>
+ <title>AllMusic</title>
+ <library>allmusic.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>AllMusic Music Scraper</summary>
+ <description>Download Music information from www.allmusic.com</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>albums</content>
+ <content>artists</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/libraries/scrapers/DTrailer/description.xml b/addons/libraries/scrapers/DTrailer/description.xml
new file mode 100644
index 0000000000..9f8ed800b0
--- /dev/null
+++ b/addons/libraries/scrapers/DTrailer/description.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>79ba05df-14b0-49ba-ad8d-b9eb8cafd038</uuid>
+ <type>scraper-library</type>
+ <title>DTrailer</title>
+ <library>dtrailer.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>DTrailer Scraper Library</summary>
+ <description>some description</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>movies</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/libraries/scrapers/HTBackDrops/description.xml b/addons/libraries/scrapers/HTBackDrops/description.xml
new file mode 100644
index 0000000000..d4edaee0a7
--- /dev/null
+++ b/addons/libraries/scrapers/HTBackDrops/description.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>20a6cd29-50f3-41c5-bd96-c9f967138365</uuid>
+ <type>scraper-library</type>
+ <title>HTBackdrops</title>
+ <library>htbackdrops.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>HTBackdrops Scraper Library</summary>
+ <description>some description</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>movies</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/libraries/scrapers/IMDB/description.xml b/addons/libraries/scrapers/IMDB/description.xml
new file mode 100644
index 0000000000..30e41f74ed
--- /dev/null
+++ b/addons/libraries/scrapers/IMDB/description.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>208d94d7-5c65-4b96-b207-e6b308717623</uuid>
+ <type>scraper-library</type>
+ <title>IMDb</title>
+ <library>imdb.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>IMDB Scraper Library</summary>
+ <description>Download Movie information from www.imdb.com</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>movies</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/libraries/scrapers/IMPA/description.xml b/addons/libraries/scrapers/IMPA/description.xml
new file mode 100644
index 0000000000..241110f20f
--- /dev/null
+++ b/addons/libraries/scrapers/IMPA/description.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>3cfce449-2e54-4a40-86cc-a6d2199c73b3</uuid>
+ <type>scraper-library</type>
+ <title>IMPA</title>
+ <library>impa.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>IMPA Scraper Library</summary>
+ <description>some description</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>movies</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/libraries/scrapers/LastFM/description.xml b/addons/libraries/scrapers/LastFM/description.xml
new file mode 100644
index 0000000000..2c59997bf7
--- /dev/null
+++ b/addons/libraries/scrapers/LastFM/description.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>56e2e02c-1b76-4c91-87bb-0e90b1cb7c72</uuid>
+ <type>scraper-library</type>
+ <title>LastFM</title>
+ <library>lastfm.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>LastFM Scraper Library</summary>
+ <description>Download Music information</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>albums</content>
+ <content>artists</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/libraries/scrapers/MoviePosterDB/description.xml b/addons/libraries/scrapers/MoviePosterDB/description.xml
new file mode 100644
index 0000000000..079c2ea29f
--- /dev/null
+++ b/addons/libraries/scrapers/MoviePosterDB/description.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>DD60AE50-5D67-4aa9-AF45-A7F2E5518B5F</uuid>
+ <type>scraper-library</type>
+ <title>MoviePostersDB</title>
+ <library>movieposterdb.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>MoviePosterDB Scraper Library</summary>
+ <description>some desription</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>movies</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/libraries/scrapers/TMDB/description.xml b/addons/libraries/scrapers/TMDB/description.xml
new file mode 100644
index 0000000000..7d469204fc
--- /dev/null
+++ b/addons/libraries/scrapers/TMDB/description.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>52f01b59-f059-4950-a133-dbd778fa9b23</uuid>
+ <type>scraper-library</type>
+ <title>TMDB</title>
+ <library>tmdb.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>TMDB Scraper Library</summary>
+ <description>some description</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>movies</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/scrapers/AllMusic/default.tbn b/addons/scrapers/AllMusic/default.tbn
new file mode 100644
index 0000000000..30c40ef318
--- /dev/null
+++ b/addons/scrapers/AllMusic/default.tbn
Binary files differ
diff --git a/addons/scrapers/AllMusic/description.xml b/addons/scrapers/AllMusic/description.xml
new file mode 100644
index 0000000000..9cdf11fa94
--- /dev/null
+++ b/addons/scrapers/AllMusic/description.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>86569F2D-2D5A-4022-8683-4D7CF224BE7B</uuid>
+ <type>scraper</type>
+ <title>AllMusic</title>
+ <library>allmusic.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>AllMusic Music Scraper</summary>
+ <description>Download Music information from www.allmusic.com</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>albums</content>
+ <content>artists</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/scrapers/AmazonUK/default.tbn b/addons/scrapers/AmazonUK/default.tbn
new file mode 100644
index 0000000000..e872b16315
--- /dev/null
+++ b/addons/scrapers/AmazonUK/default.tbn
Binary files differ
diff --git a/addons/scrapers/AmazonUK/description.xml b/addons/scrapers/AmazonUK/description.xml
new file mode 100644
index 0000000000..0ffc71a176
--- /dev/null
+++ b/addons/scrapers/AmazonUK/description.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>F0B735CA-F693-48e6-99DA-B3A66AE56E88</uuid>
+ <type>scraper</type>
+ <title>Amazon UK</title>
+ <library>amazonuk.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>Amazon Movie Scraper</summary>
+ <description>Download Movie information from www.amazon.uk</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>movies</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/scrapers/IMDB/default.tbn b/addons/scrapers/IMDB/default.tbn
new file mode 100644
index 0000000000..b2edac3fe7
--- /dev/null
+++ b/addons/scrapers/IMDB/default.tbn
Binary files differ
diff --git a/addons/scrapers/IMDB/description.xml b/addons/scrapers/IMDB/description.xml
new file mode 100644
index 0000000000..2e6e7e1c0b
--- /dev/null
+++ b/addons/scrapers/IMDB/description.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>2F2B9322-10BC-46f2-AC4C-72B2E8DD9694</uuid>
+ <type>scraper</type>
+ <title>IMDb</title>
+ <library>imdb.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>IMDB Movie Scraper</summary>
+ <description>Download Movie information from www.imdb.com</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>movies</content>
+ <content>musicvideos</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/scrapers/IMDB/resources/language/English/strings.xml b/addons/scrapers/IMDB/resources/language/English/strings.xml
new file mode 100644
index 0000000000..7fc277917e
--- /dev/null
+++ b/addons/scrapers/IMDB/resources/language/English/strings.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<strings>
+ <!-- settings labels -->
+ <string id="30000">Enable Full Cast Credits</string>
+ <string id="30001">Enable IMPAwards</string>
+ <string id="30002">Enable MoviePosterDB</string>
+ <string id="30003">Enable Trailer</string>
+ <string id="30004">Enable Fanart</string>
+ <string id="30005">IMDB Poster &amp;amp; Actor Thumb(s) Size</string>
+ <string id="30006">Input Alternative IMDb Source</string>
+</strings>
+
diff --git a/addons/scrapers/LastFM/default.tbn b/addons/scrapers/LastFM/default.tbn
new file mode 100644
index 0000000000..b4b14bf354
--- /dev/null
+++ b/addons/scrapers/LastFM/default.tbn
Binary files differ
diff --git a/addons/scrapers/LastFM/description.xml b/addons/scrapers/LastFM/description.xml
new file mode 100644
index 0000000000..4b04d1c8b8
--- /dev/null
+++ b/addons/scrapers/LastFM/description.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>DD60AE50-5D67-4aa9-AF45-A7F2E5518B5F</uuid>
+ <type>scraper</type>
+ <title>LastFM</title>
+ <library>lastfm.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>LastFM Music Scraper</summary>
+ <description>Download Music information</description>
+ <author>TEAMXBMC</author>
+ <dependencies>
+ <dependency minversion="1.0.0" maxversion="">56e2e02c-1b76-4c91-87bb-0e90b1cb7c72</dependency>
+ </dependencies>
+ <supportedcontent>
+ <content>albums</content>
+ <content>artists</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/scrapers/YahooMusic/default.tbn b/addons/scrapers/YahooMusic/default.tbn
new file mode 100644
index 0000000000..007c422028
--- /dev/null
+++ b/addons/scrapers/YahooMusic/default.tbn
Binary files differ
diff --git a/addons/scrapers/YahooMusic/description.xml b/addons/scrapers/YahooMusic/description.xml
new file mode 100644
index 0000000000..0e0243604d
--- /dev/null
+++ b/addons/scrapers/YahooMusic/description.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>EA0E975F-F57F-467a-B77B-2A9CC597873B</uuid>
+ <type>scraper</type>
+ <title>Yahoo! Music</title>
+ <library>yahoomusic.xml</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>all</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>Yahoo! Music Video Scraper</summary>
+ <description>Download Music Video information</description>
+ <author>TEAMXBMC</author>
+ <supportedcontent>
+ <content>musicvideos</content>
+ </supportedcontent>
+</addoninfo>
diff --git a/addons/scrapers/YahooMusic/resources/language/English/strings.xml b/addons/scrapers/YahooMusic/resources/language/English/strings.xml
new file mode 100644
index 0000000000..169bc00a9a
--- /dev/null
+++ b/addons/scrapers/YahooMusic/resources/language/English/strings.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<strings>
+ <!-- settings labels -->
+ <string id="30000">Thumbnail Size</string>
+</strings>
diff --git a/addons/visualizations/GLSpectrum/default.tbn b/addons/visualizations/GLSpectrum/default.tbn
new file mode 100755
index 0000000000..fd535ff4e3
--- /dev/null
+++ b/addons/visualizations/GLSpectrum/default.tbn
Binary files differ
diff --git a/addons/visualizations/GLSpectrum/description.xml b/addons/visualizations/GLSpectrum/description.xml
new file mode 100644
index 0000000000..1de970f317
--- /dev/null
+++ b/addons/visualizations/GLSpectrum/description.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>7A4551D9-2F50-4173-B224-EE209FC9EB1F</uuid>
+ <type>visualization</type>
+ <title>OpenGL Spectrum</title>
+ <library>opengl_spectrum.vis</library>
+ <librarywin32>opengl_spectrum_win32.vis</librarywin32>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>linux</platform>
+ <platform>windows</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>OpenGL Visualization</summary>
+ <description>Visualisation showing a rotating 3D Spectrum Analyzer</description>
+ <author>TEAMXBMC</author>
+</addoninfo>
diff --git a/addons/visualizations/GLSpectrum/resources/language/English/strings.xml b/addons/visualizations/GLSpectrum/resources/language/English/strings.xml
new file mode 100644
index 0000000000..17f5d723ad
--- /dev/null
+++ b/addons/visualizations/GLSpectrum/resources/language/English/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<strings>
+ <!-- settings labels -->
+ <string id="30000">Mode</string>
+ <string id="30001">Filled</string>
+ <string id="30002">Wireframe</string>
+ <string id="30003">Points</string>
+ <string id="30004">Bar Height</string>
+ <string id="30005">Small</string>
+ <string id="30006">Default</string>
+ <string id="30007">Big</string>
+ <string id="30008">Very Big</string>
+ <string id="30009">Speed</string>
+ <string id="30010">Very Slow</string>
+ <string id="30011">Slow</string>
+ <string id="30012">Default</string>
+ <string id="30013">Fast</string>
+ <string id="30014">Very Fast</string>
+</strings>
diff --git a/addons/visualizations/GLSpectrum/resources/language/German/strings.xml b/addons/visualizations/GLSpectrum/resources/language/German/strings.xml
new file mode 100644
index 0000000000..f40aa61ebc
--- /dev/null
+++ b/addons/visualizations/GLSpectrum/resources/language/German/strings.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<strings>
+ <!-- settings labels -->
+ <string id="30000">Balkenhöhe</string>
+ <string id="30001">Standart</string>
+ <string id="30002">Groß</string>
+ <string id="30003">Sehr groß</string>
+ <string id="30004">Klein</string>
+ <string id="30005">Modus</string>
+ <string id="30006">Ausgefüllt</string>
+ <string id="30007">Drahtgeflecht</string>
+ <string id="30008">Punkte</string>
+ <string id="30009">Geschwindigkeit</string>
+ <string id="30010">Standart</string>
+ <string id="30011">Langsam</string>
+ <string id="30012">Sehr langsam</string>
+ <string id="30013">Schnell</string>
+ <string id="30014">Sehr schnell</string>
+</strings>
diff --git a/addons/visualizations/GLSpectrum/resources/settings.xml b/addons/visualizations/GLSpectrum/resources/settings.xml
new file mode 100644
index 0000000000..a2c2cf7d61
--- /dev/null
+++ b/addons/visualizations/GLSpectrum/resources/settings.xml
@@ -0,0 +1,5 @@
+<settings>
+<setting id="mode" label="30000" type="enum" lvalues="30001|30002|30003" default="0"/>
+<setting id="bar_height" label="30004" type="enum" lvalues="30005|30006|30007|30008" default="1"/>
+<setting id="speed" label="30009" type="enum" lvalues="30010|30011|30012|30013|30014" default="2"/>
+</settings>
diff --git a/addons/visualizations/ProjectM/default.tbn b/addons/visualizations/ProjectM/default.tbn
new file mode 100644
index 0000000000..67e150d035
--- /dev/null
+++ b/addons/visualizations/ProjectM/default.tbn
Binary files differ
diff --git a/addons/visualizations/ProjectM/description.xml b/addons/visualizations/ProjectM/description.xml
new file mode 100644
index 0000000000..b154a3a9b6
--- /dev/null
+++ b/addons/visualizations/ProjectM/description.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>b67a5960-d956-11de-8a39-0800200c9a66</uuid>
+ <type>visualization</type>
+ <title>projectM</title>
+ <library>projectM.vis</library>
+ <librarywin32>projectM_win32.vis</librarywin32>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>linux</platform>
+ <platform>windows</platform>
+ </platforms>
+ <minversion>
+ <xbmc>25000</xbmc>
+ </minversion>
+ <summary>projectM Visualization</summary>
+ <description>projectM is an LGPL'ed reimplementation of Milkdrop under OpenGL</description>
+ <author>TEAMXBMC</author>
+</addoninfo>
diff --git a/addons/visualizations/ProjectM/resources/language/English/strings.xml b/addons/visualizations/ProjectM/resources/language/English/strings.xml
new file mode 100644
index 0000000000..eccbdfc0da
--- /dev/null
+++ b/addons/visualizations/ProjectM/resources/language/English/strings.xml
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<strings>
+ <!-- settings labels -->
+ <string id="30000">Render Quality</string>
+ <string id="30001">Low</string>
+ <string id="30002">Medium</string>
+ <string id="30003">High</string>
+ <string id="30004">Maximum</string>
+ <string id="30005">Shuffle Mode</string>
+ <string id="30006">Smooth Preset Duration</string>
+ <string id="30007">Preset Duration</string>
+ <string id="30008">Beat Sensitivity</string>
+</strings>
diff --git a/addons/visualizations/ProjectM/resources/presets.zip b/addons/visualizations/ProjectM/resources/presets.zip
new file mode 100644
index 0000000000..9ad08b4f40
--- /dev/null
+++ b/addons/visualizations/ProjectM/resources/presets.zip
Binary files differ
diff --git a/addons/visualizations/Waveform/default.tbn b/addons/visualizations/Waveform/default.tbn
new file mode 100755
index 0000000000..7d5974fd57
--- /dev/null
+++ b/addons/visualizations/Waveform/default.tbn
Binary files differ
diff --git a/addons/visualizations/Waveform/description.xml b/addons/visualizations/Waveform/description.xml
new file mode 100644
index 0000000000..55f5082240
--- /dev/null
+++ b/addons/visualizations/Waveform/description.xml
@@ -0,0 +1,19 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>9AFC128B-A6B6-4824-9BC4-B122966709B3</uuid>
+ <type>visualization</type>
+ <title>Waveform</title>
+ <library>Waveform.vis</library>
+ <librarywin32>Waveform_win32.vis</librarywin32>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>linux</platform>
+ <platform>windows</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>Visualization</summary>
+ <description>Visualization showing a Waveform Graph</description>
+ <author>MrC</author>
+</addoninfo>
diff --git a/addons/visualizations/iTunes/description.xml b/addons/visualizations/iTunes/description.xml
new file mode 100644
index 0000000000..cadfe4b690
--- /dev/null
+++ b/addons/visualizations/iTunes/description.xml
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
+<addoninfo>
+ <uuid>57675d11-0ae3-11df-8a39-0800200c9a66</uuid>
+ <type>visualization</type>
+ <title>iTunes Visualization</title>
+ <library>iTunes.mvis</library>
+ <version>1.0.0</version>
+ <platforms>
+ <platform>osx</platform>
+ </platforms>
+ <minversion>
+ <xbmc>20000</xbmc>
+ </minversion>
+ <summary>iTunes Visualization Wrapper</summary>
+ <description>Some description</description>
+ <author>TEAMXBMC</author>
+</addoninfo>
diff --git a/guilib/GUIControl.h b/guilib/GUIControl.h
index f7408e6784..ab98f5a7f9 100644
--- a/guilib/GUIControl.h
+++ b/guilib/GUIControl.h
@@ -235,6 +235,7 @@ public:
GUICONTROL_CONSOLE,
GUICONTROL_EDIT,
GUICONTROL_VISUALISATION,
+ GUICONTROL_RENDERADDON,
GUICONTROL_MULTI_IMAGE,
GUICONTROL_GROUP,
GUICONTROL_GROUPLIST,
diff --git a/guilib/GUIInfoTypes.cpp b/guilib/GUIInfoTypes.cpp
index a8212830d0..473cc0a495 100644
--- a/guilib/GUIInfoTypes.cpp
+++ b/guilib/GUIInfoTypes.cpp
@@ -22,6 +22,7 @@
#include "GUIInfoTypes.h"
#include "utils/CharsetConverter.h"
#include "utils/GUIInfoManager.h"
+#include "utils/AddonManager.h"
#include "utils/log.h"
#include "LocalizeStrings.h"
#include "GUIColorManager.h"
@@ -29,6 +30,7 @@
#include "StringUtils.h"
using namespace std;
+using ADDON::CAddonMgr;
CGUIInfoBool::CGUIInfoBool(bool value)
{
@@ -221,12 +223,41 @@ CStdString CGUIInfoLabel::ReplaceLocalize(const CStdString &label)
return work;
}
+CStdString CGUIInfoLabel::ReplaceAddonStrings(const CStdString &label)
+{
+ CStdString work(label);
+ // Replace all $ADDON[uuid number] with the real string
+ int pos1 = work.Find("$ADDON[");
+ while (pos1 >= 0)
+ {
+ int pos2 = StringUtils::FindEndBracket(work, '[', ']', pos1 + 7);
+ if (pos2 > pos1)
+ {
+ CStdString left = work.Left(pos1);
+ CStdString right = work.Mid(pos2 + 1);
+ CStdString uuid = work.substr(pos1+7, 36);
+ int stringid = atoi(work.substr(pos1+7+36+1, 5).c_str());
+ CStdString replace = CAddonMgr::Get()->GetString(uuid, stringid);
+ work = left + replace + right;
+ }
+ else
+ {
+ CLog::Log(LOGERROR, "Error parsing label - missing ']'");
+ return "";
+ }
+ pos1 = work.Find("$ADDON[", pos1);
+ }
+ return work;
+}
+
void CGUIInfoLabel::Parse(const CStdString &label)
{
m_info.clear();
// Step 1: Replace all $LOCALIZE[number] with the real string
CStdString work = ReplaceLocalize(label);
- // Step 2: Find all $INFO[info,prefix,postfix] blocks
+ // Step 2: Replace all $ADDON[uuid number] with the real string
+ work = ReplaceAddonStrings(work);
+ // Step 3: Find all $INFO[info,prefix,postfix] blocks
int pos1 = work.Find("$INFO[");
while (pos1 >= 0)
{
diff --git a/guilib/GUIInfoTypes.h b/guilib/GUIInfoTypes.h
index 3ceb7dbd0f..115bb85343 100644
--- a/guilib/GUIInfoTypes.h
+++ b/guilib/GUIInfoTypes.h
@@ -89,6 +89,13 @@ public:
*/
static CStdString ReplaceLocalize(const CStdString &label);
+ /*!
+ \brief Replaces instances of $ADDON[uuid number] with the appropriate localized addon string
+ \param label text to replace
+ \return text with any localized strings filled in.
+ */
+ static CStdString ReplaceAddonStrings(const CStdString &label);
+
private:
void Parse(const CStdString &label);
diff --git a/guilib/GUIMessage.cpp b/guilib/GUIMessage.cpp
index 6a08bd36b5..437aa9ff4f 100644
--- a/guilib/GUIMessage.cpp
+++ b/guilib/GUIMessage.cpp
@@ -57,16 +57,6 @@ CGUIMessage::CGUIMessage(int msg, int senderID, int controlID, int param1, int p
m_item = item;
}
-CGUIMessage::CGUIMessage(int msg, int senderID, int controlID, int param1, int param2, CVisualisation* vis)
-{
- m_message = msg;
- m_senderID = senderID;
- m_controlID = controlID;
- m_param1 = param1;
- m_param2 = param2;
- m_pointer = vis;
-}
-
CGUIMessage::CGUIMessage(const CGUIMessage& msg)
{
*this = msg;
diff --git a/guilib/GUIMessage.h b/guilib/GUIMessage.h
index 7efca3ec93..395f868584 100644
--- a/guilib/GUIMessage.h
+++ b/guilib/GUIMessage.h
@@ -257,7 +257,6 @@ do { \
// forwards
class CGUIListItem; typedef boost::shared_ptr<CGUIListItem> CGUIListItemPtr;
class CFileItemList;
-class CVisualisation;
/*!
\ingroup winmsg
@@ -269,7 +268,6 @@ public:
CGUIMessage(int dwMsg, int senderID, int controlID, int param1 = 0, int param2 = 0);
CGUIMessage(int msg, int senderID, int controlID, int param1, int param2, CFileItemList* item);
CGUIMessage(int msg, int senderID, int controlID, int param1, int param2, const CGUIListItemPtr &item);
- CGUIMessage(int msg, int senderID, int controlID, int param1, int param2, CVisualisation* vis);
CGUIMessage(const CGUIMessage& msg);
virtual ~CGUIMessage(void);
const CGUIMessage& operator = (const CGUIMessage& msg);
diff --git a/guilib/GUIRenderingControl.cpp b/guilib/GUIRenderingControl.cpp
new file mode 100644
index 0000000000..03ad6e1620
--- /dev/null
+++ b/guilib/GUIRenderingControl.cpp
@@ -0,0 +1,92 @@
+#include "GUIRenderingControl.h"
+#include "GUIUserMessages.h"
+#include "visualizations/Visualisation.h"
+#include "utils/SingleLock.h"
+
+using namespace std;
+using namespace ADDON;
+
+#define LABEL_ROW1 10
+#define LABEL_ROW2 11
+#define LABEL_ROW3 12
+
+CGUIRenderingControl::CGUIRenderingControl(int parentID, int controlID, float posX, float posY, float width, float height)
+ : CGUIControl(parentID, controlID, posX, posY, width, height)
+{
+ ControlType = GUICONTROL_RENDERADDON;
+}
+
+CGUIRenderingControl::CGUIRenderingControl(const CGUIRenderingControl &from)
+: CGUIControl(from)
+{
+ ControlType = GUICONTROL_RENDERADDON;
+}
+
+void CGUIRenderingControl::LoadAddon(const AddonPtr &addon)
+{
+ if (!addon)
+ return;
+
+ CSingleLock lock(m_rendering);
+ g_graphicsContext.CaptureStateBlock();
+ float x = g_graphicsContext.ScaleFinalXCoord(GetXPosition(), GetYPosition());
+ float y = g_graphicsContext.ScaleFinalYCoord(GetXPosition(), GetYPosition());
+ float w = g_graphicsContext.ScaleFinalXCoord(GetXPosition() + GetWidth(), GetYPosition() + GetHeight()) - x;
+ float h = g_graphicsContext.ScaleFinalYCoord(GetXPosition() + GetWidth(), GetYPosition() + GetHeight()) - y;
+ if (x < 0) x = 0;
+ if (y < 0) y = 0;
+ if (x + w > g_graphicsContext.GetWidth()) w = g_graphicsContext.GetWidth() - x;
+ if (y + h > g_graphicsContext.GetHeight()) h = g_graphicsContext.GetHeight() - y;
+
+ VizPtr viz = boost::dynamic_pointer_cast<CVisualisation>(addon);
+ if (viz && viz->Create((int)(x+0.5f), (int)(y+0.5f), (int)(w+0.5f), (int)(h+0.5f)))
+ {
+ m_addon = viz;
+ }
+
+ g_graphicsContext.ApplyStateBlock();
+ VerifyGLState();
+}
+
+void CGUIRenderingControl::UpdateVisibility(const CGUIListItem *item)
+{
+ // if made invisible, start timer, only free addonptr after
+ // some period, configurable by window class
+ CGUIControl::UpdateVisibility(item);
+ if (!IsVisible() && m_addon)
+ FreeResources();
+}
+
+void CGUIRenderingControl::Render()
+{
+ CSingleLock lock(m_rendering);
+ if (m_addon)
+ {
+ // set the viewport - note: We currently don't have any control over how
+ // the addon renders, so the best we can do is attempt to define
+ // a viewport??
+ g_graphicsContext.SetViewPort(m_posX, m_posY, m_width, m_height);
+ g_graphicsContext.CaptureStateBlock();
+ m_addon->Render();
+ g_graphicsContext.ApplyStateBlock();
+ g_graphicsContext.RestoreViewPort();
+ }
+
+ CGUIControl::Render();
+}
+
+void CGUIRenderingControl::FreeResources()
+{
+ if (!m_addon) return;
+
+ CSingleLock lock(m_rendering);
+ g_graphicsContext.CaptureStateBlock(); //TODO locking
+ m_addon->Stop();
+ g_graphicsContext.ApplyStateBlock();
+ m_addon.reset();
+}
+
+bool CGUIRenderingControl::CanFocusFromPoint(const CPoint &point) const
+{ // mouse is allowed to focus this control, but it doesn't actually receive focus
+ return IsVisible() && HitTest(point);
+}
diff --git a/guilib/GUIRenderingControl.h b/guilib/GUIRenderingControl.h
new file mode 100644
index 0000000000..639f36182a
--- /dev/null
+++ b/guilib/GUIRenderingControl.h
@@ -0,0 +1,43 @@
+#pragma once
+/*
+ * Copyright (C) 2005-2010 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 "GUIControl.h"
+#include "IAddon.h"
+
+class CGUIRenderingControl : public CGUIControl
+{
+public:
+ CGUIRenderingControl(int parentID, int controlID, float posX, float posY, float width, float height);
+ CGUIRenderingControl(const CGUIRenderingControl &from);
+ virtual CGUIRenderingControl *Clone() const { return new CGUIRenderingControl(*this); }; //TODO check for naughties
+
+ virtual void Render();
+ virtual void UpdateVisibility(const CGUIListItem *item = NULL);
+ virtual void FreeResources();
+ virtual bool CanFocus() const { return false; }
+ virtual bool CanFocusFromPoint(const CPoint &point) const;
+ void LoadAddon(const ADDON::AddonPtr &addon);
+
+protected:
+ CCriticalSection m_rendering;
+ ADDON::VizPtr m_addon;
+};
diff --git a/guilib/GUIVisualisationControl.cpp b/guilib/GUIVisualisationControl.cpp
index 0783c866d7..a7569bde84 100644
--- a/guilib/GUIVisualisationControl.cpp
+++ b/guilib/GUIVisualisationControl.cpp
@@ -2,473 +2,50 @@
#include "GUIWindowManager.h"
#include "GUIUserMessages.h"
#include "Application.h"
-#include "visualizations/Visualisation.h"
-#include "visualizations/VisualisationFactory.h"
-#include "visualizations/fft.h"
-#include "Util.h"
-#include "utils/CriticalSection.h"
+#include "utils/AddonManager.h"
#include "utils/log.h"
-#include "utils/SingleLock.h"
-#include "utils/GUIInfoManager.h"
-#include "GUISettings.h"
-#include "FileSystem/SpecialProtocol.h"
using namespace std;
-using namespace MUSIC_INFO;
+using namespace ADDON;
#define LABEL_ROW1 10
#define LABEL_ROW2 11
#define LABEL_ROW3 12
-// uggly hack, we can only allow one visualisation at one time or stuff starts crashing
-static CCriticalSection m_critSection;
-static bool m_globalvis = false;
-
-CAudioBuffer::CAudioBuffer(int iSize)
-{
- m_iLen = iSize;
- m_pBuffer = new short[iSize];
-}
-
-CAudioBuffer::~CAudioBuffer()
-{
- delete [] m_pBuffer;
-}
-
-const short* CAudioBuffer::Get() const
-{
- return m_pBuffer;
-}
-
-void CAudioBuffer::Set(const unsigned char* psBuffer, int iSize, int iBitsPerSample)
-{
- if (iSize<0)
- {
- return;
- }
-
- if (iBitsPerSample == 16)
- {
- iSize /= 2;
- for (int i = 0; i < iSize && i < m_iLen; i++)
- { // 16 bit -> convert to short directly
- m_pBuffer[i] = ((short *)psBuffer)[i];
- }
- }
- else if (iBitsPerSample == 8)
- {
- for (int i = 0; i < iSize && i < m_iLen; i++)
- { // 8 bit -> convert to signed short by multiplying by 256
- m_pBuffer[i] = ((short)((char *)psBuffer)[i]) << 8;
- }
- }
- else // assume 24 bit data
- {
- iSize /= 3;
- for (int i = 0; i < iSize && i < m_iLen; i++)
- { // 24 bit -> ignore least significant byte and convert to signed short
- m_pBuffer[i] = (((int)psBuffer[3 * i + 1]) << 0) + (((int)((char *)psBuffer)[3 * i + 2]) << 8);
- }
- }
- for (int i = iSize; i < m_iLen;++i) m_pBuffer[i] = 0;
-}
-
CGUIVisualisationControl::CGUIVisualisationControl(int parentID, int controlID, float posX, float posY, float width, float height)
- : CGUIControl(parentID, controlID, posX, posY, width, height)
+ : CGUIRenderingControl(parentID, controlID, posX, posY, width, height)
{
- m_pVisualisation = NULL;
- m_bInitialized = false;
- m_iNumBuffers = 0;
- m_currentVis = "";
ControlType = GUICONTROL_VISUALISATION;
}
CGUIVisualisationControl::CGUIVisualisationControl(const CGUIVisualisationControl &from)
-: CGUIControl(from)
+: CGUIRenderingControl(from)
{
- m_pVisualisation = NULL;
- m_bInitialized = false;
- m_iNumBuffers = 0;
- m_currentVis = "";
ControlType = GUICONTROL_VISUALISATION;
}
-CGUIVisualisationControl::~CGUIVisualisationControl(void)
-{
-}
-
-void CGUIVisualisationControl::FreeVisualisation()
-{
- if (!m_bInitialized) return;
- m_bInitialized = false;
- // tell our app that we're going
- CGUIMessage msg(GUI_MSG_VISUALISATION_UNLOADING, 0, 0);
- g_windowManager.SendMessage(msg);
-
- CSingleLock lock (m_critSection);
-
- CLog::Log(LOGDEBUG, "FreeVisualisation() started");
- if (g_application.m_pPlayer)
- g_application.m_pPlayer->UnRegisterAudioCallback();
- if (m_pVisualisation)
- {
- OutputDebugString("Visualisation::Stop()\n");
- g_graphicsContext.CaptureStateBlock();
- m_pVisualisation->Stop();
- g_graphicsContext.ApplyStateBlock();
-
- OutputDebugString("delete Visualisation()\n");
- delete m_pVisualisation;
-
- /* we released the global vis spot */
- m_globalvis = false;
- }
- m_pVisualisation = NULL;
- ClearBuffers();
- CLog::Log(LOGDEBUG, "FreeVisualisation() done");
-}
-
-void CGUIVisualisationControl::LoadVisualisation()
-{
- CSingleLock lock (m_critSection);
- if (m_pVisualisation)
- FreeVisualisation();
-
- m_bInitialized = false;
-
- /* check if any other control beat us to the punch */
- if(m_globalvis)
- return;
-
- CVisualisationFactory factory;
- CStdString strVisz;
- m_currentVis = g_guiSettings.GetString("musicplayer.visualisation");
-
- if (m_currentVis.Equals("None"))
- return;
-
- // check if it's a multi-vis and if it is , get it's module name
- {
- int colonPos = m_currentVis.ReverseFind(":");
- if ( colonPos > 0 )
- {
- CStdString strModule = m_currentVis.Mid( colonPos+1 );
- strVisz = m_currentVis.Mid( 0, colonPos );
- m_pVisualisation = factory.LoadVisualisation(strVisz, strModule);
- }
- else
- {
- strVisz = m_currentVis;
- m_pVisualisation = factory.LoadVisualisation(strVisz);
- }
- }
- if (m_pVisualisation)
- {
- g_graphicsContext.CaptureStateBlock();
- float x = g_graphicsContext.ScaleFinalXCoord(GetXPosition(), GetYPosition());
- float y = g_graphicsContext.ScaleFinalYCoord(GetXPosition(), GetYPosition());
- float w = g_graphicsContext.ScaleFinalXCoord(GetXPosition() + GetWidth(), GetYPosition() + GetHeight()) - x;
- float h = g_graphicsContext.ScaleFinalYCoord(GetXPosition() + GetWidth(), GetYPosition() + GetHeight()) - y;
- if (x < 0) x = 0;
- if (y < 0) y = 0;
- if (x + w > g_graphicsContext.GetWidth()) w = g_graphicsContext.GetWidth() - x;
- if (y + h > g_graphicsContext.GetHeight()) h = g_graphicsContext.GetHeight() - y;
-
- m_pVisualisation->Create((int)(x+0.5f), (int)(y+0.5f), (int)(w+0.5f), (int)(h+0.5f));
- g_graphicsContext.ApplyStateBlock();
- VerifyGLState();
- if (g_application.m_pPlayer)
- g_application.m_pPlayer->RegisterAudioCallback(this);
-
- // Create new audio buffers
- CreateBuffers();
-
- m_globalvis = true;
- }
-
- // tell our app that we're back
- CGUIMessage msg(GUI_MSG_VISUALISATION_LOADED, 0, 0, 0, 0, m_pVisualisation);
- g_windowManager.SendMessage(msg);
-}
-
-void CGUIVisualisationControl::UpdateVisibility(const CGUIListItem *item)
-{
- CGUIControl::UpdateVisibility(item);
- if (!IsVisible() && m_bInitialized)
- FreeVisualisation();
-}
-
-void CGUIVisualisationControl::SetInvalid()
-{
- FreeResources();
-}
-
void CGUIVisualisationControl::Render()
{
- if (m_pVisualisation == NULL)
- { // check if we need to load
- if (g_application.IsPlayingAudio())
- {
- LoadVisualisation();
- }
- CGUIControl::Render();
-
- return;
- }
- else
- { // check if we need to unload
- if (!g_application.IsPlayingAudio())
- { // deinit
- FreeVisualisation();
- CGUIControl::Render();
- return;
- }
- else if (!m_currentVis.Equals(g_guiSettings.GetString("musicplayer.visualisation")))
- { // vis changed - reload
- LoadVisualisation();
-
- CGUIControl::Render();
-
- return;
- }
- }
- CSingleLock lock (m_critSection);
- if (m_pVisualisation)
- {
- if (m_bInitialized)
- {
- // set the viewport - note: We currently don't have any control over how
- // the visualisation renders, so the best we can do is attempt to define
- // a viewport??
- g_graphicsContext.SetViewPort(m_posX, m_posY, m_width, m_height);
- try
- {
- g_graphicsContext.CaptureStateBlock();
- m_pVisualisation->Render();
- g_graphicsContext.ApplyStateBlock();
- }
- catch (...)
- {
- CLog::Log(LOGERROR, "Exception in Visualisation::Render()");
- }
- // clear the viewport
- g_graphicsContext.RestoreViewPort();
- }
- }
-
- CGUIControl::Render();
-}
-
-
-void CGUIVisualisationControl::OnInitialize(int iChannels, int iSamplesPerSec, int iBitsPerSample)
-{
- CSingleLock lock (m_critSection);
- if (!m_pVisualisation)
- return ;
- CLog::Log(LOGDEBUG, "OnInitialize() started");
-
- m_iChannels = iChannels;
- m_iSamplesPerSec = iSamplesPerSec;
- m_iBitsPerSample = iBitsPerSample;
-
- // Start the visualisation (this loads settings etc.)
- CStdString strFile = CUtil::GetFileName(g_application.CurrentFile());
- OutputDebugString("Visualisation::Start()\n");
- m_pVisualisation->Start(m_iChannels, m_iSamplesPerSec, m_iBitsPerSample, strFile);
- if (!m_bInitialized)
+ if (!m_addon && g_application.IsPlayingAudio())
{
- UpdateTrack();
- }
- m_bInitialized = true;
- CLog::Log(LOGDEBUG, "OnInitialize() done");
-}
-
-void CGUIVisualisationControl::OnAudioData(const unsigned char* pAudioData, int iAudioDataLength)
-{
- CSingleLock lock (m_critSection);
- if (!m_pVisualisation)
- return ;
- if (!m_bInitialized) return ;
-
- // FIXME: iAudioDataLength should never be less than 0
- if (iAudioDataLength<0)
- return;
-
- // Save our audio data in the buffers
- auto_ptr<CAudioBuffer> pBuffer ( new CAudioBuffer(2*AUDIO_BUFFER_SIZE) );
- pBuffer->Set(pAudioData, iAudioDataLength, m_iBitsPerSample);
- m_vecBuffers.push_back( pBuffer.release() );
-
- if ( (int)m_vecBuffers.size() < m_iNumBuffers) return ;
-
- auto_ptr<CAudioBuffer> ptrAudioBuffer ( m_vecBuffers.front() );
- m_vecBuffers.pop_front();
- // Fourier transform the data if the vis wants it...
- if (m_bWantsFreq)
- {
- // Convert to floats
- const short* psAudioData = ptrAudioBuffer->Get();
- for (int i = 0; i < 2*AUDIO_BUFFER_SIZE; i++)
- {
- m_fFreq[i] = (float)psAudioData[i];
- }
-
- // FFT the data
- twochanwithwindow(m_fFreq, AUDIO_BUFFER_SIZE);
-
- // Normalize the data
- float fMinData = (float)AUDIO_BUFFER_SIZE * AUDIO_BUFFER_SIZE * 3 / 8 * 0.5 * 0.5; // 3/8 for the Hann window, 0.5 as minimum amplitude
- float fInvMinData = 1.0f/fMinData;
- for (int i = 0; i < AUDIO_BUFFER_SIZE + 2; i++)
- {
- m_fFreq[i] *= fInvMinData;
- }
-
- // Transfer data to our visualisation
- try
- {
- m_pVisualisation->AudioData(ptrAudioBuffer->Get(), AUDIO_BUFFER_SIZE, m_fFreq, AUDIO_BUFFER_SIZE);
- }
- catch (...)
- {
- CLog::Log(LOGERROR, "Exception in Visualisation::AudioData()");
- }
+ AddonPtr viz;
+ if (ADDON::CAddonMgr::Get()->GetDefault(ADDON_VIZ, viz))
+ LoadAddon(viz);
}
else
- { // Transfer data to our visualisation
- try
- {
- m_pVisualisation->AudioData(ptrAudioBuffer->Get(), AUDIO_BUFFER_SIZE, NULL, 0);
- }
- catch (...)
- {
- CLog::Log(LOGERROR, "Exception in Visualisation::AudioData()");
- }
- }
- return ;
-}
-
-bool CGUIVisualisationControl::OnAction(const CAction &action)
-{
- if (!m_pVisualisation) return false;
- enum CVisualisation::VIS_ACTION visAction = CVisualisation::VIS_ACTION_NONE;
- if (action.GetID() == ACTION_VIS_PRESET_NEXT)
- visAction = CVisualisation::VIS_ACTION_NEXT_PRESET;
- else if (action.GetID() == ACTION_VIS_PRESET_PREV)
- visAction = CVisualisation::VIS_ACTION_PREV_PRESET;
- else if (action.GetID() == ACTION_VIS_PRESET_LOCK)
- visAction = CVisualisation::VIS_ACTION_LOCK_PRESET;
- else if (action.GetID() == ACTION_VIS_PRESET_RANDOM)
- visAction = CVisualisation::VIS_ACTION_RANDOM_PRESET;
- else if (action.GetID() == ACTION_VIS_RATE_PRESET_PLUS)
- visAction = CVisualisation::VIS_ACTION_RATE_PRESET_PLUS;
- else if (action.GetID() == ACTION_VIS_RATE_PRESET_MINUS)
- visAction = CVisualisation::VIS_ACTION_RATE_PRESET_MINUS;
-
- return m_pVisualisation->OnAction(visAction);
-}
-
-bool CGUIVisualisationControl::UpdateTrack()
-{
- bool handled = false;
-
- if ( m_pVisualisation )
- {
- // get the current album art filename
- m_AlbumThumb = _P(g_infoManager.GetImage(MUSICPLAYER_COVER, WINDOW_INVALID));
-
- // get the current track tag
- const CMusicInfoTag* tag = g_infoManager.GetCurrentSongTag();
-
- if (m_AlbumThumb == "DefaultAlbumCover.png")
- m_AlbumThumb = "";
- else
- CLog::Log(LOGDEBUG,"Updating visualisation albumart: %s", m_AlbumThumb.c_str());
-
- // inform the visulisation of the current album art
- if ( m_pVisualisation->OnAction( CVisualisation::VIS_ACTION_UPDATE_ALBUMART,
- (void*)( m_AlbumThumb.c_str() ) ) )
- handled = true;
-
- // inform the visualisation of the current track's tag information
- if ( tag && m_pVisualisation->OnAction( CVisualisation::VIS_ACTION_UPDATE_TRACK,
- (void*)tag ) )
- handled = true;
- }
- return handled;
-}
-
-bool CGUIVisualisationControl::OnMessage(CGUIMessage &message)
-{
- if (message.GetMessage() == GUI_MSG_GET_VISUALISATION)
- {
- message.SetPointer(GetVisualisation());
- return true;
- }
- else if (message.GetMessage() == GUI_MSG_VISUALISATION_ACTION)
- {
- return OnAction(CAction(message.GetParam1()));
- }
- else if (message.GetMessage() == GUI_MSG_PLAYBACK_STARTED)
- {
- if (IsVisible() && UpdateTrack()) return true;
- }
- return CGUIControl::OnMessage(message);
-}
-
-void CGUIVisualisationControl::CreateBuffers()
-{
- CSingleLock lock (m_critSection);
- ClearBuffers();
-
- // Get the number of buffers from the current vis
- VIS_INFO info;
- m_pVisualisation->GetInfo(&info);
- m_iNumBuffers = info.iSyncDelay + 1;
- m_bWantsFreq = info.bWantsFreq;
- if (m_iNumBuffers > MAX_AUDIO_BUFFERS)
- m_iNumBuffers = MAX_AUDIO_BUFFERS;
- if (m_iNumBuffers < 1)
- m_iNumBuffers = 1;
-}
-
-
-void CGUIVisualisationControl::ClearBuffers()
-{
- CSingleLock lock (m_critSection);
- m_bWantsFreq = false;
- m_iNumBuffers = 0;
-
- while (m_vecBuffers.size() > 0)
- {
- CAudioBuffer* pAudioBuffer = m_vecBuffers.front();
- delete pAudioBuffer;
- m_vecBuffers.pop_front();
- }
- for (int j = 0; j < AUDIO_BUFFER_SIZE*2; j++)
- {
- m_fFreq[j] = 0.0f;
- }
+ CGUIRenderingControl::Render();
}
void CGUIVisualisationControl::FreeResources()
{
- FreeVisualisation();
- CGUIControl::FreeResources();
-}
-
-CVisualisation *CGUIVisualisationControl::GetVisualisation()
-{
- CSingleLock lock (m_critSection);
- return m_pVisualisation;
-}
+ // tell our app that we're going
+ if (!m_addon)
+ return;
-bool CGUIVisualisationControl::CanFocus() const
-{ // unfocusable
- return false;
+ CGUIMessage msg(GUI_MSG_VISUALISATION_UNLOADING, m_controlID, 0);
+ g_windowManager.SendMessage(msg);
+ CLog::Log(LOGDEBUG, "FreeVisualisation() started");
+ CGUIRenderingControl::FreeResources();
+ CLog::Log(LOGDEBUG, "FreeVisualisation() done");
}
-bool CGUIVisualisationControl::CanFocusFromPoint(const CPoint &point) const
-{ // mouse is allowed to focus this control, but it doesn't actually receive focus
- return IsVisible() && HitTest(point);
-}
diff --git a/guilib/GUIVisualisationControl.h b/guilib/GUIVisualisationControl.h
index af06adac68..e782f6a945 100644
--- a/guilib/GUIVisualisationControl.h
+++ b/guilib/GUIVisualisationControl.h
@@ -1,5 +1,4 @@
#pragma once
-
/*
* Copyright (C) 2005-2008 Team XBMC
* http://www.xbmc.org
@@ -21,68 +20,14 @@
*
*/
-#include "GUIControl.h"
-#include "cores/IAudioCallback.h"
-
-#include <list>
-
-// forward definitions
-class CVisualisation;
-
-#define AUDIO_BUFFER_SIZE 512 // MUST BE A POWER OF 2!!!
-#define MAX_AUDIO_BUFFERS 16
+#include "GUIRenderingControl.h"
-class CAudioBuffer
-{
-public:
- CAudioBuffer(int iSize);
- virtual ~CAudioBuffer();
- const short* Get() const;
- void Set(const unsigned char* psBuffer, int iSize, int iBitsPerSample);
-private:
- CAudioBuffer();
- short* m_pBuffer;
- int m_iLen;
-};
-
-class CGUIVisualisationControl :
- public CGUIControl, public IAudioCallback
+class CGUIVisualisationControl : public CGUIRenderingControl
{
public:
CGUIVisualisationControl(int parentID, int controlID, float posX, float posY, float width, float height);
CGUIVisualisationControl(const CGUIVisualisationControl &from);
- virtual ~CGUIVisualisationControl(void);
- virtual CGUIVisualisationControl *Clone() const { return new CGUIVisualisationControl(*this); };
-
- virtual void Render();
- virtual void UpdateVisibility(const CGUIListItem *item = NULL);
+ virtual CGUIVisualisationControl *Clone() const { return new CGUIVisualisationControl(*this); }; //TODO check for naughties
virtual void FreeResources();
- virtual void SetInvalid();
- virtual void OnInitialize(int iChannels, int iSamplesPerSec, int iBitsPerSample);
- virtual void OnAudioData(const unsigned char* pAudioData, int iAudioDataLength);
- virtual bool OnAction(const CAction &action);
- virtual bool OnMessage(CGUIMessage& message);
- virtual bool CanFocus() const;
- virtual bool CanFocusFromPoint(const CPoint &point) const;
-
- CVisualisation *GetVisualisation();
-private:
- void FreeVisualisation();
- void LoadVisualisation();
- void CreateBuffers();
- void ClearBuffers();
- bool UpdateTrack();
- CStdString m_currentVis;
- CVisualisation* m_pVisualisation;
-
- int m_iChannels;
- int m_iSamplesPerSec;
- int m_iBitsPerSample;
- std::list<CAudioBuffer*> m_vecBuffers;
- int m_iNumBuffers; // Number of Audio buffers
- bool m_bWantsFreq;
- float m_fFreq[2*AUDIO_BUFFER_SIZE]; // Frequency data
- bool m_bCalculate_Freq; // True if the vis wants freq data
- bool m_bInitialized;
- CStdString m_AlbumThumb;
+ virtual void Render();
};
diff --git a/guilib/Key.h b/guilib/Key.h
index fd175d4b0e..b5f0113215 100644
--- a/guilib/Key.h
+++ b/guilib/Key.h
@@ -312,6 +312,8 @@
#define WINDOW_LOGIN_SCREEN 10029
#define WINDOW_SETTINGS_PROFILES 10034
+#define WINDOW_ADDON_BROWSER 10040
+
#define WINDOW_DIALOG_YES_NO 10100
#define WINDOW_DIALOG_PROGRESS 10101
#define WINDOW_DIALOG_KEYBOARD 10103
@@ -345,7 +347,7 @@
#define WINDOW_DIALOG_SMART_PLAYLIST_RULE 10137
#define WINDOW_DIALOG_BUSY 10138
#define WINDOW_DIALOG_PICTURE_INFO 10139
-#define WINDOW_DIALOG_PLUGIN_SETTINGS 10140
+#define WINDOW_DIALOG_ADDON_SETTINGS 10140
#define WINDOW_DIALOG_ACCESS_POINTS 10141
#define WINDOW_DIALOG_FULLSCREEN_INFO 10142
#define WINDOW_DIALOG_KARAOKE_SONGSELECT 10143
diff --git a/guilib/Makefile.in b/guilib/Makefile.in
index 95896d7be2..0fbe69d098 100644
--- a/guilib/Makefile.in
+++ b/guilib/Makefile.in
@@ -39,6 +39,7 @@ SRCS=AnimatedGif.cpp \
GUIProgressControl.cpp \
GUIRadioButtonControl.cpp \
GUIResizeControl.cpp \
+ GUIRenderingControl.cpp \
GUIRSSControl.cpp \
GUIScrollBarControl.cpp \
GUISelectButtonControl.cpp \
diff --git a/language/English/strings.xml b/language/English/strings.xml
index e7fb463484..a99f042e74 100644
--- a/language/English/strings.xml
+++ b/language/English/strings.xml
@@ -1933,6 +1933,7 @@
<string id="21416">Enable fallback based on scraper language</string>
<string id="21417">- Settings</string>
<string id="21418">Multilingual</string>
+ <string id="21419">No scrapers present</string>
<string id="21420">Value to match</string>
<string id="21421">Smart playlist rule</string>
@@ -2087,9 +2088,6 @@
<string id="22042">white/blue</string>
<string id="22043">black/white</string>
- <string id="23000">Weather plugin</string>
- <string id="23001">- Plugin settings</string>
-
<string id="23050">Activate Teletext</string>
<string id="23051">Part %i</string>
<string id="23052">Buffering %i bytes</string>
@@ -2102,6 +2100,38 @@
<string id="23104">Click OK when playback has ended</string>
+ <!-- strings 24000 thru 24299 reserved for the addons framework -->
+ <string id="24000">Add-on</string>
+ <string id="24001">Add-ons</string>
+
+ <string id="24005">Plugin</string>
+ <string id="24007">Scraper</string>
+ <string id="24008">Screensaver</string>
+ <string id="24009">Script</string>
+ <string id="24010">Visualization</string>
+
+ <string id="24020">Configure Add-on</string>
+ <string id="24021">Disable Add-on</string>
+ <string id="24022">Enable Add-on</string>
+ <string id="24030">This Add-on can not be configured</string>
+ <string id="24031">Error loading settings</string>
+
+ <string id="24050">Available Add-ons</string>
+ <string id="24051">Version:</string>
+ <string id="24052">Disclaimer:</string>
+ <string id="24053">License:</string>
+ <string id="24059">Would you like to install this Add-on?</string>
+
+ <string id="24070">Add-on can not used</string>
+ <string id="24071">An unknown error has occurred</string>
+ <string id="24072">Settings required</string>
+ <string id="24073">Could not connect</string>
+ <string id="24074">Needs to restart</string>
+ <string id="24080">Try to reconnect?</string>
+ <string id="24089">Add-on restarts</string>
+
+ <string id="24090">Lock Add-on manager</string>
+
<!-- strings 29800 thru 29998 reserved strings used only in the default Project Mayhem III skin and not c++ code -->
<string id="29800">Library Mode</string>
<string id="29801">QWERTY keyboard</string>
diff --git a/project/VS2008Express/XBMC.vcproj b/project/VS2008Express/XBMC.vcproj
index d9cc53b9d5..bfabccf447 100644
--- a/project/VS2008Express/XBMC.vcproj
+++ b/project/VS2008Express/XBMC.vcproj
@@ -467,6 +467,10 @@
>
</File>
<File
+ RelativePath="..\..\xbmc\win32\strverscmp.cpp"
+ >
+ </File>
+ <File
RelativePath="..\..\xbmc\win32\Win32DelayedDllLoad.cpp"
>
</File>
@@ -2097,14 +2101,6 @@
RelativePath="..\..\xbmc\visualizations\Visualisation.h"
>
</File>
- <File
- RelativePath="..\..\xbmc\visualizations\VisualisationFactory.cpp"
- >
- </File>
- <File
- RelativePath="..\..\xbmc\visualizations\VisualisationFactory.h"
- >
- </File>
</Filter>
<Filter
Name="VideoRenderers"
@@ -2230,14 +2226,6 @@
>
</File>
<File
- RelativePath="..\..\xbmc\screensavers\ScreenSaverFactory.cpp"
- >
- </File>
- <File
- RelativePath="..\..\xbmc\screensavers\ScreenSaverFactory.h"
- >
- </File>
- <File
RelativePath="..\..\xbmc\screensavers\xbmc_scr.h"
>
</File>
@@ -2358,14 +2346,6 @@
>
</File>
<File
- RelativePath="..\..\xbmc\GUIDialogPluginSettings.cpp"
- >
- </File>
- <File
- RelativePath="..\..\xbmc\GUIDialogPluginSettings.h"
- >
- </File>
- <File
RelativePath="..\..\xbmc\GUISettings.cpp"
>
</File>
@@ -2410,27 +2390,11 @@
>
</File>
<File
- RelativePath="..\..\xbmc\PluginSettings.cpp"
- >
- </File>
- <File
- RelativePath="..\..\xbmc\PluginSettings.h"
- >
- </File>
- <File
- RelativePath="..\..\xbmc\ScraperSettings.cpp"
+ RelativePath="..\..\xbmc\Scraper.cpp"
>
</File>
<File
- RelativePath="..\..\xbmc\ScraperSettings.h"
- >
- </File>
- <File
- RelativePath="..\..\xbmc\ScriptSettings.cpp"
- >
- </File>
- <File
- RelativePath="..\..\xbmc\ScriptSettings.h"
+ RelativePath="..\..\xbmc\Scraper.h"
>
</File>
<File
@@ -2882,6 +2846,26 @@
Name="Utils"
>
<File
+ RelativePath="..\..\xbmc\utils\Addon.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\xbmc\utils\Addon.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\xbmc\utils\AddonDll.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\xbmc\utils\AddonManager.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\xbmc\utils\AddonManager.h"
+ >
+ </File>
+ <File
RelativePath="..\..\xbmc\utils\AlarmClock.cpp"
>
</File>
@@ -3562,6 +3546,14 @@
>
</File>
<File
+ RelativePath="..\..\xbmc\GUIDialogAddonSettings.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\xbmc\GUIDialogAddonSettings.h"
+ >
+ </File>
+ <File
RelativePath="..\..\xbmc\GUIDialogAudioSubtitleSettings.cpp"
>
</File>
@@ -3786,14 +3778,6 @@
>
</File>
<File
- RelativePath="..\..\xbmc\GUIDialogVisualisationSettings.cpp"
- >
- </File>
- <File
- RelativePath="..\..\xbmc\GUIDialogVisualisationSettings.h"
- >
- </File>
- <File
RelativePath="..\..\xbmc\GUIDialogVolumeBar.cpp"
>
</File>
@@ -3846,6 +3830,14 @@
>
</File>
<File
+ RelativePath="..\..\xbmc\GUIWindowAddonBrowser.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\xbmc\GUIWindowAddonBrowser.h"
+ >
+ </File>
+ <File
RelativePath="..\..\xbmc\GUIWindowFileManager.cpp"
>
</File>
@@ -3966,6 +3958,14 @@
Name="Filesystem"
>
<File
+ RelativePath="..\..\xbmc\FileSystem\AddonsDirectory.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\xbmc\FileSystem\AddonsDirectory.h"
+ >
+ </File>
+ <File
RelativePath="..\..\xbmc\FileSystem\ASAPFileDirectory.cpp"
>
</File>
diff --git a/project/VS2008Express/guilib.vcproj b/project/VS2008Express/guilib.vcproj
index 0623d79646..f98320b4d6 100644
--- a/project/VS2008Express/guilib.vcproj
+++ b/project/VS2008Express/guilib.vcproj
@@ -486,6 +486,14 @@
>
</File>
<File
+ RelativePath="..\..\guilib\GUIRenderingControl.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\guilib\GUIRenderingControl.h"
+ >
+ </File>
+ <File
RelativePath="..\..\guilib\GUIResizeControl.cpp"
>
</File>
diff --git a/skin/Confluence/720p/AddonBrowser.xml b/skin/Confluence/720p/AddonBrowser.xml
new file mode 100644
index 0000000000..8f9ec8b984
--- /dev/null
+++ b/skin/Confluence/720p/AddonBrowser.xml
@@ -0,0 +1,313 @@
+<window id="40">
+ <defaultcontrol always="true">2</defaultcontrol>
+ <allowoverlay>no</allowoverlay>
+ <controls>
+ <include>CommonSettingsBackground</include>
+ <include>CommonMediaPlayingBackground</include>
+ <control type="group">
+ <posx>90</posx>
+ <posy>50</posy>
+ <animation type="WindowOpen" reversible="false">
+ <effect type="zoom" start="80" end="100" center="640,360" easing="out" tween="back" time="300" />
+ <effect type="fade" start="0" end="100" time="300" />
+ </animation>
+ <animation type="WindowClose" reversible="false">
+ <effect type="zoom" start="100" end="80" center="640,360" easing="in" tween="back" time="300" />
+ <effect type="fade" start="100" end="0" time="300" />
+ </animation>
+ <control type="image">
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>1100</width>
+ <height>640</height>
+ <texture border="20">DialogBack.png</texture>
+ </control>
+ <control type="image">
+ <description>LOGO</description>
+ <posx>30</posx>
+ <posy>15</posy>
+ <width>220</width>
+ <height>80</height>
+ <aspectratio>keep</aspectratio>
+ <texture>Confluence_Logo.png</texture>
+ </control>
+ <control type="image">
+ <posx>268</posx>
+ <posy>10</posy>
+ <width>790</width>
+ <height>618</height>
+ <texture border="5">black-back2.png</texture>
+ </control>
+ <control type="image">
+ <posx>268</posx>
+ <posy>10</posy>
+ <width>804</width>
+ <height>70</height>
+ <aspectratio>stretch</aspectratio>
+ <texture>GlassTitleBar.png</texture>
+ </control>
+ <control type="label">
+ <description>header label</description>
+ <posx>300</posx>
+ <posy>20</posy>
+ <width>740</width>
+ <height>30</height>
+ <font>font16caps</font>
+ <label>$LOCALIZE[24001]</label>
+ <align>left</align>
+ <aligny>center</aligny>
+ <textcolor>white</textcolor>
+ <shadowcolor>black</shadowcolor>
+ </control>
+ <control type="list" id="2">
+ <posx>283</posx>
+ <posy>70</posy>
+ <width>750</width>
+ <height>540</height>
+ <onup>2</onup>
+ <ondown>2</ondown>
+ <onleft>53</onleft>
+ <onright>60</onright>
+ <pagecontrol>60</pagecontrol>
+ <scrolltime>200</scrolltime>
+ <itemlayout height="75" width="750">
+ <control type="group">
+ <visible>![$INFO[ListItem.Property(Addon.Disabled)]]</visible>
+ <control type="image">
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>750</width>
+ <height>75</height>
+ <aspectratio>stretch</aspectratio>
+ <texture border="5">button-nofocus.png</texture>
+ </control>
+ <control type="image">
+ <posx>10</posx>
+ <posy>2</posy>
+ <width>90</width>
+ <height>66</height>
+ <texture>$INFO[ListItem.Icon]</texture>
+ </control>
+ <control type="label">
+ <posx>110</posx>
+ <posy>2</posy>
+ <width>450</width>
+ <height>28</height>
+ <font>font13</font>
+ <textcolor>grey2</textcolor>
+ <selectedcolor>selected</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>[B]$INFO[ListItem.Property(Addon.Name)][/B] - $INFO[ListItem.Property(Addon.Version)]</label>
+ </control>
+ <control type="label">
+ <posx>110</posx>
+ <posy>25</posy>
+ <width>450</width>
+ <height>25</height>
+ <font>font12</font>
+ <textcolor>grey2</textcolor>
+ <selectedcolor>selected</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Property(Addon.Summary)]</label>
+ </control>
+ </control>
+ <control type="group">
+ <visible>$INFO[ListItem.Property(Addon.Disabled)]</visible>
+ <control type="image">
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>750</width>
+ <height>75</height>
+ <aspectratio>stretch</aspectratio>
+ <texture border="5">button-nofocus.png</texture>
+ </control>
+ <control type="image">
+ <posx>10</posx>
+ <posy>2</posy>
+ <width>90</width>
+ <height>66</height>
+ <texture>$INFO[ListItem.Icon]</texture>
+ </control>
+ <control type="image">
+ <posx>10</posx>
+ <posy>2</posy>
+ <width>90</width>
+ <height>66</height>
+ <texture>Fanart-Diffuse.png</texture>
+ </control>
+ <control type="label">
+ <posx>110</posx>
+ <posy>2</posy>
+ <width>450</width>
+ <height>28</height>
+ <font>font13</font>
+ <textcolor>grey3</textcolor>
+ <selectedcolor>selected</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>[B]$INFO[ListItem.Property(Addon.Name)][/B] - $INFO[ListItem.Property(Addon.Version)]</label>
+ </control>
+ <control type="label">
+ <posx>110</posx>
+ <posy>25</posy>
+ <width>450</width>
+ <height>25</height>
+ <font>font12</font>
+ <textcolor>grey3</textcolor>
+ <selectedcolor>selected</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Property(Addon.Summary)]</label>
+ </control>
+ <control type="image">
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>750</width>
+ <height>75</height>
+ <texture>black-back2.png</texture>
+ </control>
+ </control>
+ </itemlayout>
+ <focusedlayout height="75" width="750">
+ <control type="group">
+ <visible>![$INFO[ListItem.Property(Addon.Disabled)]]</visible>
+ <control type="image">
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>750</width>
+ <height>75</height>
+ <aspectratio>stretch</aspectratio>
+ <texture border="5">button-focus.png</texture>
+ </control>
+ <control type="image">
+ <posx>10</posx>
+ <posy>2</posy>
+ <width>90</width>
+ <height>66</height>
+ <texture>$INFO[ListItem.Icon]</texture>
+ </control>
+ <control type="label">
+ <posx>110</posx>
+ <posy>2</posy>
+ <width>450</width>
+ <height>28</height>
+ <font>font13</font>
+ <textcolor>white</textcolor>
+ <selectedcolor>selected</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>[B]$INFO[ListItem.Property(Addon.Name)][/B] - $INFO[ListItem.Property(Addon.Version)]</label>
+ </control>
+ <control type="label">
+ <posx>110</posx>
+ <posy>25</posy>
+ <width>450</width>
+ <height>25</height>
+ <font>font12</font>
+ <textcolor>white</textcolor>
+ <selectedcolor>selected</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Property(Addon.Summary)]</label>
+ </control>
+ </control>
+ <control type="group">
+ <visible>$INFO[ListItem.Property(Addon.Disabled)]</visible>
+ <control type="image">
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>750</width>
+ <height>75</height>
+ <aspectratio>stretch</aspectratio>
+ <texture border="5">button-focus.png</texture>
+ </control>
+ <control type="image">
+ <posx>10</posx>
+ <posy>2</posy>
+ <width>90</width>
+ <height>66</height>
+ <texture>$INFO[ListItem.Icon]</texture>
+ </control>
+ <control type="image">
+ <posx>10</posx>
+ <posy>2</posy>
+ <width>90</width>
+ <height>66</height>
+ <texture>Fanart-Diffuse.png</texture>
+ </control>
+ <control type="label">
+ <posx>110</posx>
+ <posy>2</posy>
+ <width>450</width>
+ <height>28</height>
+ <font>font13</font>
+ <textcolor>grey3</textcolor>
+ <selectedcolor>grey3</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>[B]$INFO[ListItem.Property(Addon.Name)][/B] - $INFO[ListItem.Property(Addon.Version)]</label>
+ </control>
+ <control type="label">
+ <posx>110</posx>
+ <posy>25</posy>
+ <width>450</width>
+ <height>25</height>
+ <font>font12</font>
+ <textcolor>grey3</textcolor>
+ <selectedcolor>grey3</selectedcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ <label>$INFO[ListItem.Property(Addon.Summary)]</label>
+ </control>
+ <control type="image">
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>750</width>
+ <height>75</height>
+ <texture>black-back2.png</texture>
+ <visible>$INFO[ListItem.Property(Addon.Disabled)]</visible>
+ </control>
+ </control>
+ </focusedlayout>
+ </control>
+ <control type="scrollbar" id="60">
+ <posx>1060</posx>
+ <posy>60</posy>
+ <width>25</width>
+ <height>530</height>
+ <texturesliderbackground border="0,14,0,14">ScrollBarV.png</texturesliderbackground>
+ <texturesliderbar border="0,14,0,14">ScrollBarV_bar.png</texturesliderbar>
+ <texturesliderbarfocus border="0,14,0,14">ScrollBarV_bar_focus.png</texturesliderbarfocus>
+ <textureslidernib>ScrollBarNib.png</textureslidernib>
+ <textureslidernibfocus>ScrollBarNib.png</textureslidernibfocus>
+ <onleft>2</onleft>
+ <onright>4</onright>
+ <showonepage>false</showonepage>
+ <orientation>vertical</orientation>
+ </control>
+ </control>
+ <include>BehindDialogFadeOut</include>
+ <control type="group">
+ <posx>60</posx>
+ <posy>0</posy>
+ <animation effect="slide" end="-310,0" time="400" tween="quadratic" easing="out" condition="Window.Next(Home) | Window.Next(1111)">WindowClose</animation>
+ <animation effect="slide" start="-310,0" time="400" tween="quadratic" easing="out" condition="Window.Previous(Home) | Window.Previous(1111)">WindowOpen</animation>
+ <control type="image">
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>250</width>
+ <height>35</height>
+ <texture border="0,0,32,0">header.png</texture>
+ </control>
+ <control type="label">
+ <include>WindowTitleCommons</include>
+ <posx>220</posx>
+ <label>$LOCALIZE[5]</label>
+ </control>
+ </control>
+ <include>WindowTitleHomeButton</include>
+ <include>Clock</include>
+ </controls>
+</window>
diff --git a/skin/Confluence/720p/DialogAddonSettings.xml b/skin/Confluence/720p/DialogAddonSettings.xml
new file mode 100644
index 0000000000..d3c1593a94
--- /dev/null
+++ b/skin/Confluence/720p/DialogAddonSettings.xml
@@ -0,0 +1,166 @@
+<window id="10140">
+ <defaultcontrol always="true">2</defaultcontrol>
+ <coordinates>
+ <system>1</system>
+ <posx>240</posx>
+ <posy>55</posy>
+ </coordinates>
+ <include>dialogeffect</include>
+ <controls>
+ <control type="image">
+ <description>background image</description>
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>800</width>
+ <height>610</height>
+ <texture border="40">DialogBack.png</texture>
+ </control>
+ <control type="image">
+ <posx>80</posx>
+ <posy>10</posy>
+ <width>640</width>
+ <height>90</height>
+ <aspectratio>stretch</aspectratio>
+ <texture>GlassTitleBar.png</texture>
+ </control>
+ <control type="button">
+ <description>Close Window button</description>
+ <posx>710</posx>
+ <posy>9</posy>
+ <width>64</width>
+ <height>32</height>
+ <label>-</label>
+ <font>-</font>
+ <onclick>PreviousMenu</onclick>
+ <texturefocus>DialogCloseButton-focus.png</texturefocus>
+ <texturenofocus>DialogCloseButton.png</texturenofocus>
+ <onleft>2</onleft>
+ <onright>2</onright>
+ <onup>2</onup>
+ <ondown>2</ondown>
+ <visible>system.getbool(input.enablemouse)</visible>
+ </control>
+ <control type="label" id="20">
+ <description>header label</description>
+ <posx>20</posx>
+ <posy>18</posy>
+ <width>760</width>
+ <height>30</height>
+ <font>font13_title</font>
+ <label>-</label>
+ <align>center</align>
+ <aligny>center</aligny>
+ <textcolor>white</textcolor>
+ <shadowcolor>black</shadowcolor>
+ </control>
+ <control type="grouplist" id="2">
+ <description>control area</description>
+ <posx>30</posx>
+ <posy>80</posy>
+ <width>740</width>
+ <height>420</height>
+ <itemgap>-1</itemgap>
+ <onup>2</onup>
+ <ondown>2</ondown>
+ <onleft>10</onleft>
+ <onright>10</onright>
+ </control>
+ <control type="button" id="3">
+ <description>Default Button</description>
+ <height>40</height>
+ <font>font13</font>
+ <textcolor>grey2</textcolor>
+ <focusedcolor>white</focusedcolor>
+ <texturefocus border="0,2,0,2">MenuItemFO.png</texturefocus>
+ <texturenofocus border="0,2,0,2">MenuItemNF.png</texturenofocus>
+ </control>
+ <control type="radiobutton" id="4">
+ <description>Default RadioButton</description>
+ <height>40</height>
+ <font>font13</font>
+ <textcolor>grey2</textcolor>
+ <focusedcolor>white</focusedcolor>
+ <texturefocus border="0,2,0,2">MenuItemFO.png</texturefocus>
+ <texturenofocus border="0,2,0,2">MenuItemNF.png</texturenofocus>
+ </control>
+ <control type="spincontrolex" id="5">
+ <description>Default spincontrolex</description>
+ <height>40</height>
+ <textcolor>grey2</textcolor>
+ <focusedcolor>white</focusedcolor>
+ <texturefocus border="0,2,0,2">MenuItemFO.png</texturefocus>
+ <texturenofocus border="0,2,0,2">MenuItemNF.png</texturenofocus>
+ <font>font13</font>
+ <aligny>center</aligny>
+ <reverse>yes</reverse>
+ </control>
+ <control type="label" id="7">
+ <height>45</height>
+ <font>font13_title</font>
+ <label>-</label>
+ <textcolor>blue</textcolor>
+ <shadowcolor>black</shadowcolor>
+ <align>left</align>
+ <aligny>center</aligny>
+ </control>
+ <control type="image" id="6">
+ <description>Default Seperator</description>
+ <height>2</height>
+ <texture>separator2.png</texture>
+ </control>
+ <control type="group" id="9001">
+ <posy>540</posy>
+ <control type="button" id="10">
+ <description>OK Button</description>
+ <posx>300</posx>
+ <posy>0</posy>
+ <width>200</width>
+ <height>40</height>
+ <align>center</align>
+ <aligny>center</aligny>
+ <texturenofocus border="5">MenuItemNF.png</texturenofocus>
+ <texturefocus border="5">button-focus.png</texturefocus>
+ <font>font12_title</font>
+ <label>186</label>
+ <onleft>12</onleft>
+ <onright>11</onright>
+ <onup>2</onup>
+ <ondown>2</ondown>
+ </control>
+ <control type="button" id="11">
+ <description>Cancel Button</description>
+ <posx>510</posx>
+ <posy>0</posy>
+ <width>200</width>
+ <height>40</height>
+ <align>center</align>
+ <aligny>center</aligny>
+ <texturenofocus border="5">MenuItemNF.png</texturenofocus>
+ <texturefocus border="5">button-focus.png</texturefocus>
+ <font>font12_title</font>
+ <label>222</label>
+ <onleft>10</onleft>
+ <onright>12</onright>
+ <onup>2</onup>
+ <ondown>2</ondown>
+ </control>
+ <control type="button" id="12">
+ <description>Defaults Button</description>
+ <posx>90</posx>
+ <posy>0</posy>
+ <width>200</width>
+ <height>40</height>
+ <align>center</align>
+ <aligny>center</aligny>
+ <texturenofocus border="5">MenuItemNF.png</texturenofocus>
+ <texturefocus border="5">button-focus.png</texturefocus>
+ <font>font12_title</font>
+ <label>409</label>
+ <onleft>11</onleft>
+ <onright>10</onright>
+ <onup>2</onup>
+ <ondown>2</ondown>
+ </control>
+ </control>
+ </controls>
+</window>
diff --git a/skin/Confluence/720p/Settings.xml b/skin/Confluence/720p/Settings.xml
index 58d9d135d8..6aa3ea6a91 100644
--- a/skin/Confluence/720p/Settings.xml
+++ b/skin/Confluence/720p/Settings.xml
@@ -35,7 +35,7 @@
<posx>10</posx>
<posy>90</posy>
<width>260</width>
- <height>481</height>
+ <height>541</height>
<onleft>9000</onleft>
<onright>9001</onright>
<onup>9000</onup>
@@ -114,18 +114,24 @@
<icon>special://skin/backgrounds/weather.jpg</icon>
</item>
<item id="6">
+ <label>24001</label>
+ <label2>31408</label2>
+ <onclick>ActivateWindow(AddonBrowser)</onclick>
+ <icon>special://skin/backgrounds/addons.jpg</icon>
+ </item>
+ <item id="7">
<label>705</label>
<label2>31405</label2>
<onclick>ActivateWindow(NetworkSettings)</onclick>
<icon>special://skin/backgrounds/network.jpg</icon>
</item>
- <item id="7">
+ <item id="8">
<label>13000</label>
<label2>31406</label2>
<onclick>ActivateWindow(SystemSettings)</onclick>
<icon>special://skin/backgrounds/system.jpg</icon>
</item>
- <item id="8">
+ <item id="9">
<label>166</label>
<label2>31407</label2>
<onclick>ActivateWindow(1111)</onclick>
diff --git a/skin/Confluence/720p/VisualisationPresetList.xml b/skin/Confluence/720p/VisualisationPresetList.xml
index 64d3d5f7b1..cace47e7d0 100644
--- a/skin/Confluence/720p/VisualisationPresetList.xml
+++ b/skin/Confluence/720p/VisualisationPresetList.xml
@@ -61,7 +61,7 @@
<posy>180</posy>
<width>760</width>
<align>center</align>
- <label>13390</label>
+ <label>13389</label>
<font>font13caps</font>
</control>
<control type="list" id="2">
@@ -148,4 +148,4 @@
</control>
</control>
</controls>
-</window> \ No newline at end of file
+</window>
diff --git a/skin/Confluence/720p/custom_SkinSetting_1111.xml b/skin/Confluence/720p/custom_SkinSetting_1111.xml
index 0ca9845bcf..ce045ebc91 100644
--- a/skin/Confluence/720p/custom_SkinSetting_1111.xml
+++ b/skin/Confluence/720p/custom_SkinSetting_1111.xml
@@ -1363,7 +1363,7 @@
<focusedcolor>white</focusedcolor>
<texturefocus>MenuItemFO.png</texturefocus>
<texturenofocus>MenuItemNF.png</texturenofocus>
- <onclick>Skin.SetFile(HomeScriptButton1_Path,.py)</onclick>
+ <onclick>Skin.SetFile(HomeScriptButton1_Path,Script)</onclick>
<visible>Skin.HasSetting(HomeScriptButton1)</visible>
</control>
@@ -1402,7 +1402,7 @@
<focusedcolor>white</focusedcolor>
<texturefocus>MenuItemFO.png</texturefocus>
<texturenofocus>MenuItemNF.png</texturenofocus>
- <onclick>Skin.SetFile(HomeScriptButton2_Path,.py)</onclick>
+ <onclick>Skin.SetFile(HomeScriptButton2_Path,Script)</onclick>
<visible>Skin.HasSetting(HomeScriptButton2)</visible>
</control>
@@ -1441,7 +1441,7 @@
<focusedcolor>white</focusedcolor>
<texturefocus>MenuItemFO.png</texturefocus>
<texturenofocus>MenuItemNF.png</texturenofocus>
- <onclick>Skin.SetFile(HomeScriptButton3_Path,.py)</onclick>
+ <onclick>Skin.SetFile(HomeScriptButton3_Path,Script)</onclick>
<visible>Skin.HasSetting(HomeScriptButton3)</visible>
</control>
@@ -1480,7 +1480,7 @@
<focusedcolor>white</focusedcolor>
<texturefocus>MenuItemFO.png</texturefocus>
<texturenofocus>MenuItemNF.png</texturenofocus>
- <onclick>Skin.SetFile(HomeScriptButton4_Path,.py)</onclick>
+ <onclick>Skin.SetFile(HomeScriptButton4_Path,Script)</onclick>
<visible>Skin.HasSetting(HomeScriptButton4)</visible>
</control>
@@ -1519,7 +1519,7 @@
<focusedcolor>white</focusedcolor>
<texturefocus>MenuItemFO.png</texturefocus>
<texturenofocus>MenuItemNF.png</texturenofocus>
- <onclick>Skin.SetFile(HomeScriptButton5_Path,.py)</onclick>
+ <onclick>Skin.SetFile(HomeScriptButton5_Path,Script)</onclick>
<visible>Skin.HasSetting(HomeScriptButton5)</visible>
</control>
@@ -1558,7 +1558,7 @@
<focusedcolor>white</focusedcolor>
<texturefocus>MenuItemFO.png</texturefocus>
<texturenofocus>MenuItemNF.png</texturenofocus>
- <onclick>Skin.SetFile(HomeScriptButton6_Path,.py)</onclick>
+ <onclick>Skin.SetFile(HomeScriptButton6_Path,Script)</onclick>
<visible>Skin.HasSetting(HomeScriptButton6)</visible>
</control>
@@ -1608,7 +1608,7 @@
<focusedcolor>white</focusedcolor>
<texturefocus>MenuItemFO.png</texturefocus>
<texturenofocus>MenuItemNF.png</texturenofocus>
- <onclick>Skin.SetFile(WeatherScript_Path,.py)</onclick>
+ <onclick>Skin.SetFile(WeatherScript_Path,Plugin,Weather)</onclick>
<visible>Skin.HasSetting(WeatherScript_Enable)</visible>
</control>
@@ -1645,7 +1645,7 @@
<focusedcolor>white</focusedcolor>
<texturefocus>MenuItemFO.png</texturefocus>
<texturenofocus>MenuItemNF.png</texturenofocus>
- <onclick>Skin.SetFile(LyricScript_Path,.py)</onclick>
+ <onclick>Skin.SetFile(LyricScript_Path,Script)</onclick>
<visible>Skin.HasSetting(LyricScript_Enable)</visible>
</control>
@@ -1682,7 +1682,7 @@
<focusedcolor>white</focusedcolor>
<texturefocus>MenuItemFO.png</texturefocus>
<texturenofocus>MenuItemNF.png</texturenofocus>
- <onclick>Skin.SetFile(SubtitleScript_Path,.py)</onclick>
+ <onclick>Skin.SetFile(SubtitleScript_Path,Script)</onclick>
<visible>Skin.HasSetting(SubtitleDownload_Enable)</visible>
</control>
</control>
diff --git a/skin/Confluence/language/English/strings.xml b/skin/Confluence/language/English/strings.xml
index a3e9c330fb..25745c749a 100644
--- a/skin/Confluence/language/English/strings.xml
+++ b/skin/Confluence/language/English/strings.xml
@@ -149,6 +149,7 @@
<string id="31405">[B]CONFIGURE NETWORK SETTINGS[/B][CR][CR]Setup control of XBMC via UPnP and HTTP · Configure file sharing[CR]Set internet access options</string>
<string id="31406">[B]CONFIGURE SYSTEM SETTINGS[/B][CR][CR]Setup and calibrate displays · Configure audio output · Setup remote controls[CR]Set power saving options · Enable debugging · Setup master lock</string>
<string id="31407">[B]CONFIGURE SKIN SETTINGS[/B][CR][CR]Setup the Confluence skin · Add and remove home menu items[CR]Change skin backgrounds</string>
+ <string id="31408">[B]CONFIGURE ADD-ONS[/B][CR][CR]Manage your installed Add-ons · Browse for and install Add-ons from xbmc.org[CR]Modify Add-on settings</string>
<string id="31421">Select your XBMC user Profile[CR]to login and continue</string>
</strings>
diff --git a/skin/PM3.HD/720p/DialogPluginSettings.xml b/skin/PM3.HD/720p/DialogAddonSettings.xml
index ed57e8ade4..1c2c42b8cc 100644
--- a/skin/PM3.HD/720p/DialogPluginSettings.xml
+++ b/skin/PM3.HD/720p/DialogAddonSettings.xml
@@ -1,145 +1,145 @@
-<window id="10140">
- <defaultcontrol>2</defaultcontrol>
- <coordinates>
- <system>1</system>
- <posx>240</posx>
- <posy>55</posy>
- </coordinates>
- <include>dialogeffect</include>
- <controls>
- <control type="image">
- <description>background image</description>
- <posx>0</posx>
- <posy>0</posy>
- <width>800</width>
- <height>610</height>
- <texture border="40">DialogBack.png</texture>
- </control>
- <control type="image">
- <description>background image</description>
- <posx>0</posx>
- <posy>0</posy>
- <width>800</width>
- <height>610</height>
- <texture border="40">DialogFront.png</texture>
- </control>
- <control type="label" id="20">
- <description>heading label</description>
- <posx>40</posx>
- <posy>40</posy>
- <width>720</width>
- <height>30</height>
- <align>center</align>
- <aligny>center</aligny>
- <font>font18</font>
- <label>-</label>
- <textcolor>dialogheader</textcolor>
- </control>
- <control type="image">
- <posx>40</posx>
- <posy>78</posy>
- <width>720</width>
- <height>2</height>
- <texture>separator.png</texture>
- </control>
- <control type="grouplist" id="2">
- <description>control area</description>
- <posx>40</posx>
- <posy>85</posy>
- <width>720</width>
- <height>420</height>
- <itemgap>5</itemgap>
- <onup>2</onup>
- <ondown>2</ondown>
- <onleft>10</onleft>
- <onright>10</onright>
- </control>
- <control type="button" id="3">
- <description>Default Button</description>
- <height>35</height>
- <font>font12</font>
- <texturefocus border="3">button-focus.png</texturefocus>
- <texturenofocus border="3">button-nofocus.png</texturenofocus>
- </control>
- <control type="radiobutton" id="4">
- <description>Default RadioButton</description>
- <height>35</height>
- <font>font12</font>
- <texturefocus border="3">button-focus.png</texturefocus>
- <texturenofocus border="3">button-nofocus.png</texturenofocus>
- </control>
- <control type="spincontrolex" id="5">
- <description>Default spincontrolex</description>
- <height>35</height>
- <texturefocus border="3">button-focus.png</texturefocus>
- <texturenofocus border="3">button-nofocus.png</texturenofocus>
- <font>font12</font>
- <aligny>center</aligny>
- <reverse>yes</reverse>
- </control>
- <control type="image" id="6">
- <description>Default Seperator</description>
- <height>2</height>
- <texture>separator.png</texture>
- </control>
- <control type="label" id="7">
- <description>Separator label</description>
- <label></label>
- <height>25</height>
- <font>font12</font>
- <align>center</align>
- <aligny>bottom</aligny>
- <textcolor>green</textcolor>
- </control>
- <control type="group" id="9001">
- <control type="button" id="10">
- <description>OK Button</description>
- <posx>300</posx>
- <posy>525</posy>
- <width>200</width>
- <height>35</height>
- <align>center</align>
- <aligny>center</aligny>
- <texturenofocus>button-nofocus.png</texturenofocus>
- <texturefocus>button-focus2.png</texturefocus>
- <label>186</label>
- <onleft>12</onleft>
- <onright>11</onright>
- <onup>2</onup>
- <ondown>2</ondown>
- </control>
- <control type="button" id="11">
- <description>Cancel Button</description>
- <posx>510</posx>
- <posy>525</posy>
- <width>200</width>
- <height>35</height>
- <align>center</align>
- <aligny>center</aligny>
- <texturenofocus>button-nofocus.png</texturenofocus>
- <texturefocus>button-focus2.png</texturefocus>
- <label>222</label>
- <onleft>10</onleft>
- <onright>12</onright>
- <onup>2</onup>
- <ondown>2</ondown>
- </control>
- <control type="button" id="12">
- <description>Defaults Button</description>
- <posx>90</posx>
- <posy>525</posy>
- <width>200</width>
- <height>35</height>
- <align>center</align>
- <aligny>center</aligny>
- <texturenofocus>button-nofocus.png</texturenofocus>
- <texturefocus>button-focus2.png</texturefocus>
- <label>409</label>
- <onleft>11</onleft>
- <onright>10</onright>
- <onup>2</onup>
- <ondown>2</ondown>
- </control>
- </control>
- </controls>
-</window>
+<window id="10140">
+ <defaultcontrol>2</defaultcontrol>
+ <coordinates>
+ <system>1</system>
+ <posx>240</posx>
+ <posy>55</posy>
+ </coordinates>
+ <include>dialogeffect</include>
+ <controls>
+ <control type="image">
+ <description>background image</description>
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>800</width>
+ <height>610</height>
+ <texture border="40">DialogBack.png</texture>
+ </control>
+ <control type="image">
+ <description>background image</description>
+ <posx>0</posx>
+ <posy>0</posy>
+ <width>800</width>
+ <height>610</height>
+ <texture border="40">DialogFront.png</texture>
+ </control>
+ <control type="label" id="20">
+ <description>heading label</description>
+ <posx>40</posx>
+ <posy>40</posy>
+ <width>720</width>
+ <height>30</height>
+ <align>center</align>
+ <aligny>center</aligny>
+ <font>font18</font>
+ <label>-</label>
+ <textcolor>dialogheader</textcolor>
+ </control>
+ <control type="image">
+ <posx>40</posx>
+ <posy>78</posy>
+ <width>720</width>
+ <height>2</height>
+ <texture>separator.png</texture>
+ </control>
+ <control type="grouplist" id="2">
+ <description>control area</description>
+ <posx>40</posx>
+ <posy>85</posy>
+ <width>720</width>
+ <height>420</height>
+ <itemgap>5</itemgap>
+ <onup>2</onup>
+ <ondown>2</ondown>
+ <onleft>10</onleft>
+ <onright>10</onright>
+ </control>
+ <control type="button" id="3">
+ <description>Default Button</description>
+ <height>35</height>
+ <font>font12</font>
+ <texturefocus border="3">button-focus.png</texturefocus>
+ <texturenofocus border="3">button-nofocus.png</texturenofocus>
+ </control>
+ <control type="radiobutton" id="4">
+ <description>Default RadioButton</description>
+ <height>35</height>
+ <font>font12</font>
+ <texturefocus border="3">button-focus.png</texturefocus>
+ <texturenofocus border="3">button-nofocus.png</texturenofocus>
+ </control>
+ <control type="spincontrolex" id="5">
+ <description>Default spincontrolex</description>
+ <height>35</height>
+ <texturefocus border="3">button-focus.png</texturefocus>
+ <texturenofocus border="3">button-nofocus.png</texturenofocus>
+ <font>font12</font>
+ <aligny>center</aligny>
+ <reverse>yes</reverse>
+ </control>
+ <control type="image" id="6">
+ <description>Default Seperator</description>
+ <height>2</height>
+ <texture>separator.png</texture>
+ </control>
+ <control type="label" id="7">
+ <description>Separator label</description>
+ <label></label>
+ <height>25</height>
+ <font>font12</font>
+ <align>center</align>
+ <aligny>bottom</aligny>
+ <textcolor>green</textcolor>
+ </control>
+ <control type="group" id="9001">
+ <control type="button" id="10">
+ <description>OK Button</description>
+ <posx>300</posx>
+ <posy>525</posy>
+ <width>200</width>
+ <height>35</height>
+ <align>center</align>
+ <aligny>center</aligny>
+ <texturenofocus>button-nofocus.png</texturenofocus>
+ <texturefocus>button-focus2.png</texturefocus>
+ <label>186</label>
+ <onleft>12</onleft>
+ <onright>11</onright>
+ <onup>2</onup>
+ <ondown>2</ondown>
+ </control>
+ <control type="button" id="11">
+ <description>Cancel Button</description>
+ <posx>510</posx>
+ <posy>525</posy>
+ <width>200</width>
+ <height>35</height>
+ <align>center</align>
+ <aligny>center</aligny>
+ <texturenofocus>button-nofocus.png</texturenofocus>
+ <texturefocus>button-focus2.png</texturefocus>
+ <label>222</label>
+ <onleft>10</onleft>
+ <onright>12</onright>
+ <onup>2</onup>
+ <ondown>2</ondown>
+ </control>
+ <control type="button" id="12">
+ <description>Defaults Button</description>
+ <posx>90</posx>
+ <posy>525</posy>
+ <width>200</width>
+ <height>35</height>
+ <align>center</align>
+ <aligny>center</aligny>
+ <texturenofocus>button-nofocus.png</texturenofocus>
+ <texturefocus>button-focus2.png</texturefocus>
+ <label>409</label>
+ <onleft>11</onleft>
+ <onright>10</onright>
+ <onup>2</onup>
+ <ondown>2</ondown>
+ </control>
+ </control>
+ </controls>
+</window>
diff --git a/skin/PM3.HD/720p/DialogContentSettings.xml b/skin/PM3.HD/720p/DialogContentSettings.xml
index 6ab32f87f7..9f1ec1f8ba 100644
--- a/skin/PM3.HD/720p/DialogContentSettings.xml
+++ b/skin/PM3.HD/720p/DialogContentSettings.xml
@@ -67,6 +67,7 @@
<height>200</height>
<aspectratio>keep</aspectratio>
<info>ListItem.Icon</info>
+ <visible>Control.IsVisible(4)</visible>
</control>
<control type="list" id="4">
<posx>40</posx>
diff --git a/skin/PM3.HD/720p/MusicOSDVisSettings.xml b/skin/PM3.HD/720p/MusicOSDVisSettings.xml
deleted file mode 100644
index ac4fd7056f..0000000000
--- a/skin/PM3.HD/720p/MusicOSDVisSettings.xml
+++ /dev/null
@@ -1,105 +0,0 @@
-<window id="121">
- <defaultcontrol>2</defaultcontrol>
- <coordinates>
- <system>1</system>
- <posx>400</posx>
- <posy>55</posy>
- </coordinates>
- <include>dialogeffect</include>
- <controls>
- <control type="image">
- <description>background image</description>
- <posx>0</posx>
- <posy>0</posy>
- <width>800</width>
- <height>610</height>
- <colordiffuse>DDFFFFFF</colordiffuse>
- <texture border="40">DialogBack.png</texture>
- </control>
- <control type="image">
- <description>background image</description>
- <posx>0</posx>
- <posy>0</posy>
- <width>800</width>
- <height>610</height>
- <texture border="40">DialogFront.png</texture>
- </control>
- <control type="button">
- <description>Close Window button</description>
- <posx>731</posx>
- <posy>35</posy>
- <width>35</width>
- <height>25</height>
- <label>-</label>
- <font>-</font>
- <onclick>Dialog.Close(121)</onclick>
- <texturefocus>close-windowFO.png</texturefocus>
- <texturenofocus>close-window.png</texturenofocus>
- <onleft>5</onleft>
- <onright>5</onright>
- <onup>5</onup>
- <ondown>5</ondown>
- <visible>system.getbool(input.enablemouse)</visible>
- </control>
- <control type="label" id="2">
- <description>heading label</description>
- <posx>40</posx>
- <posy>40</posy>
- <width>720</width>
- <height>30</height>
- <align>center</align>
- <aligny>center</aligny>
- <font>font18</font>
- <label>-</label>
- <textcolor>dialogheader</textcolor>
- </control>
- <control type="image">
- <posx>40</posx>
- <posy>78</posy>
- <width>720</width>
- <height>2</height>
- <texture>separator.png</texture>
- </control>
- <control type="grouplist" id="5">
- <description>control area</description>
- <posx>45</posx>
- <posy>85</posy>
- <width>710</width>
- <height>480</height>
- <itemgap>5</itemgap>
- <pagecontrol>60</pagecontrol>
- <onleft>5</onleft>
- <onright>5</onright>
- <onup>5</onup>
- <ondown>5</ondown>
- </control>
- <control type="button" id="7">
- <description>Default Button</description>
- <height>35</height>
- <font>font12</font>
- <textcolor>grey2</textcolor>
- <focusedcolor>white</focusedcolor>
- <texturefocus border="5">button-focus.png</texturefocus>
- <texturenofocus border="5">button-nofocus.png</texturenofocus>
- </control>
- <control type="radiobutton" id="8">
- <description>Default RadioButton</description>
- <height>35</height>
- <font>font12</font>
- <textcolor>grey2</textcolor>
- <focusedcolor>white</focusedcolor>
- <texturefocus border="5">button-focus.png</texturefocus>
- <texturenofocus border="5">button-nofocus.png</texturenofocus>
- </control>
- <control type="spincontrolex" id="9">
- <description>Default spincontrolex</description>
- <height>35</height>
- <texturefocus border="5">button-focus.png</texturefocus>
- <texturenofocus border="5">button-nofocus.png</texturenofocus>
- <font>font12</font>
- <textcolor>grey2</textcolor>
- <focusedcolor>white</focusedcolor>
- <reverse>yes</reverse>
- </control>
- </controls>
-</window> \ No newline at end of file
diff --git a/system/keymaps/keyboard.xml b/system/keymaps/keyboard.xml
index 67888bd658..ac0bbd0c2e 100644
--- a/system/keymaps/keyboard.xml
+++ b/system/keymaps/keyboard.xml
@@ -412,6 +412,11 @@
<backspace>PreviousMenu</backspace>
</keyboard>
</Settings>
+ <AddonBrowser>
+ <keyboard>
+ <backspace>PreviousMenu</backspace>
+ </keyboard>
+ </AddonBrowser>
<MyPicturesSettings>
<keyboard>
<backspace>PreviousMenu</backspace>
diff --git a/system/keymaps/remote.xml b/system/keymaps/remote.xml
index 07275cbc55..d9ebed1b6e 100644
--- a/system/keymaps/remote.xml
+++ b/system/keymaps/remote.xml
@@ -363,6 +363,11 @@
<back>PreviousMenu</back>
</remote>
</Settings>
+ <AddonBrowser>
+ <remote>
+ <back>PreviousMenu</back>
+ </remote>
+ </AddonBrowser>
<MyPicturesSettings>
<remote>
<back>PreviousMenu</back>
diff --git a/visualisations/xbmc_vis.h b/visualisations/xbmc_vis.h
deleted file mode 100644
index ecb19c38ca..0000000000
--- a/visualisations/xbmc_vis.h
+++ /dev/null
@@ -1,108 +0,0 @@
-#ifndef __XBMC_VIS_H__
-#define __XBMC_VIS_H__
-
-#include <vector>
-#include <ctype.h>
-#ifdef _LINUX
-#include "../xbmc/linux/PlatformInclude.h"
-#ifndef __APPLE__
-#include <sys/sysinfo.h>
-#endif
-#else
-#ifndef WIN32_LEAN_AND_MEAN
-#define WIN32_LEAN_AND_MEAN
-#endif
-#include <windows.h>
-#endif
-#include "../xbmc/utils/log.h"
-#include "../xbmc/visualizations/VisualisationTypes.h"
-#include <sys/stat.h>
-#include <errno.h>
-
-using namespace std;
-
-int htoi(const char *str) /* Convert hex string to integer */
-{
- unsigned int digit, number = 0;
- while (*str)
- {
- if (isdigit(*str))
- digit = *str - '0';
- else
- digit = tolower(*str)-'a'+10;
- number<<=4;
- number+=digit;
- str++;
- }
- return number;
-}
-
-// the settings vector
-vector<VisSetting> m_vecSettings;
-
-
-extern "C"
-{
- // exports for d3d hacks
-#ifdef HAS_DX
- void d3dSetTextureStageState( int x, DWORD dwY, DWORD dwZ);
- void d3dSetRenderState(DWORD dwY, DWORD dwZ);
-#endif
-
-#ifdef HAS_GL
-#ifndef D3DCOLOR_RGBA
-#define D3DCOLOR_RGBA(r,g,b,a) (r|(g<<8)|(b<<16)|(a<<24))
-#endif
-#endif
-
- // Settings struct
- StructSetting** m_structSettings;
- unsigned int m_uiVisElements;
-
- // the action commands ( see Visualisation.h )
- #define VIS_ACTION_NEXT_PRESET 1
- #define VIS_ACTION_PREV_PRESET 2
- #define VIS_ACTION_LOAD_PRESET 3
- #define VIS_ACTION_RANDOM_PRESET 4
- #define VIS_ACTION_LOCK_PRESET 5
- #define VIS_ACTION_RATE_PRESET_PLUS 6
- #define VIS_ACTION_RATE_PRESET_MINUS 7
- #define VIS_ACTION_UPDATE_ALBUMART 8
- #define VIS_ACTION_UPDATE_TRACK 9
-
- #define VIS_ACTION_USER 100
-
- // Functions that your visualisation must implement
- void Create(void* unused, int iPosX, int iPosY, int iWidth, int iHeight, const char* szVisualisationName,
- float fPixelRatio, const char *szSubModuleName);
- void Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, const char* szSongName);
- void AudioData(short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength);
- void Render();
- void Stop();
- bool OnAction(long action, void *param);
- void GetInfo(VIS_INFO* pInfo);
- void FreeSettings();
- unsigned int GetSettings(StructSetting*** sSet);
- void UpdateSetting(int num, StructSetting*** sSet);
- void GetPresets(char ***pPresets, int *currentPreset, int *numPresets, bool *locked);
- int GetSubModules(char ***names, char ***paths);
-
- // function to export the above structure to XBMC
- void __declspec(dllexport) get_module(struct Visualisation* pVisz)
- {
- pVisz->Create = Create;
- pVisz->Start = Start;
- pVisz->AudioData = AudioData;
- pVisz->Render = Render;
- pVisz->Stop = Stop;
- pVisz->GetInfo = GetInfo;
- pVisz->OnAction = OnAction;
- pVisz->GetSettings = GetSettings;
- pVisz->UpdateSetting = UpdateSetting;
- pVisz->GetPresets = GetPresets;
- pVisz->GetSubModules = GetSubModules;
- pVisz->FreeSettings = FreeSettings;
- };
-};
-
-#endif
diff --git a/xbmc/Application.cpp b/xbmc/Application.cpp
index 4f6443e5a3..714c9c14cf 100644
--- a/xbmc/Application.cpp
+++ b/xbmc/Application.cpp
@@ -167,6 +167,7 @@
#include "GUIWindowScripts.h"
#include "GUIWindowWeather.h"
#include "GUIWindowLoginScreen.h"
+#include "GUIWindowAddonBrowser.h"
#include "GUIWindowVisualisation.h"
#include "GUIWindowSystemInfo.h"
#include "GUIWindowScreensaver.h"
@@ -179,7 +180,6 @@
// Dialog includes
#include "GUIDialogMusicOSD.h"
-#include "GUIDialogVisualisationSettings.h"
#include "GUIDialogVisualisationPresetList.h"
#include "GUIWindowScriptsInfo.h"
#include "GUIDialogNetworkSetup.h"
@@ -210,7 +210,7 @@
#include "GUIDialogSmartPlaylistEditor.h"
#include "GUIDialogSmartPlaylistRule.h"
#include "GUIDialogPictureInfo.h"
-#include "GUIDialogPluginSettings.h"
+#include "GUIDialogAddonSettings.h"
#ifdef HAS_LINUX_NETWORK
#include "GUIDialogAccessPoints.h"
#endif
@@ -782,31 +782,29 @@ CProfile* CApplication::InitDirectoriesLinux()
g_settings.m_logFolder = strTempPath;
bool bCopySystemPlugins = false;
- if (!CDirectory::Exists("special://home/plugins") )
+ if (!CDirectory::Exists("special://home/addons/plugins") )
bCopySystemPlugins = true;
CDirectory::Create("special://home/");
CDirectory::Create("special://temp/");
CDirectory::Create("special://home/skin");
+ CDirectory::Create("special://home/addons");
+ CDirectory::Create("special://home/addons/visualizations");
+ CDirectory::Create("special://home/addons/scripts");
+ CDirectory::Create("special://home/addons/scrapers");
+ CDirectory::Create("special://home/addons/screensavers");
+ CDirectory::Create("special://home/addons/plugins");
+ CDirectory::Create("special://home/addons/libraries");
+ CDirectory::Create("special://home/addons/libraries/scrapers");
CDirectory::Create("special://home/media");
- CDirectory::Create("special://home/visualisations");
- CDirectory::Create("special://home/screensavers");
CDirectory::Create("special://home/sounds");
CDirectory::Create("special://home/system");
- CDirectory::Create("special://home/plugins");
- CDirectory::Create("special://home/plugins/video");
- CDirectory::Create("special://home/plugins/music");
- CDirectory::Create("special://home/plugins/pictures");
- CDirectory::Create("special://home/plugins/programs");
- CDirectory::Create("special://home/plugins/weather");
- CDirectory::Create("special://home/scripts");
- CDirectory::Create("special://home/scripts/My Scripts"); // FIXME: both scripts should be in 1 directory
-
- if (!CFile::Exists("special://home/scripts/Common Scripts"))
+
+ /*if (!CFile::Exists("special://home/scripts/Common Scripts"))
{
if (symlink( INSTALL_PATH "/scripts", _P("special://home/scripts/Common Scripts").c_str() ) != 0)
CLog::Log(LOGERROR, "Failed to create common scripts symlink.");
- }
+ }*/
CDirectory::Create("special://masterprofile");
@@ -818,7 +816,7 @@ CProfile* CApplication::InitDirectoriesLinux()
// copy system-wide plugins into userprofile
if ( bCopySystemPlugins )
- CUtil::CopyDirRecursive("special://xbmc/plugins", "special://home/plugins");
+ CUtil::CopyDirRecursive("special://xbmc/addons/plugins", "special://home/addons/plugins");
}
else
{
@@ -895,25 +893,23 @@ CProfile* CApplication::InitDirectoriesOSX()
g_settings.m_logFolder = strTempPath;
bool bCopySystemPlugins = false;
- if (!CDirectory::Exists("special://home/plugins") )
+ if (!CDirectory::Exists("special://home/addons/plugins") )
bCopySystemPlugins = true;
CDirectory::Create("special://home/");
CDirectory::Create("special://temp/");
CDirectory::Create("special://home/skin");
+ CDirectory::Create("special://home/addons");
+ CDirectory::Create("special://home/addons/visualizations");
+ CDirectory::Create("special://home/addons/scripts");
+ CDirectory::Create("special://home/addons/scrapers");
+ CDirectory::Create("special://home/addons/screensavers");
+ CDirectory::Create("special://home/addons/plugins");
+ CDirectory::Create("special://home/addons/libraries");
+ CDirectory::Create("special://home/addons/libraries/scrapers");
CDirectory::Create("special://home/media");
- CDirectory::Create("special://home/visualisations");
- CDirectory::Create("special://home/screensavers");
CDirectory::Create("special://home/sounds");
CDirectory::Create("special://home/system");
- CDirectory::Create("special://home/plugins");
- CDirectory::Create("special://home/plugins/video");
- CDirectory::Create("special://home/plugins/music");
- CDirectory::Create("special://home/plugins/pictures");
- CDirectory::Create("special://home/plugins/programs");
- CDirectory::Create("special://home/plugins/weather");
- CDirectory::Create("special://home/scripts");
- CDirectory::Create("special://home/scripts/My Scripts"); // FIXME: both scripts should be in 1 directory
#ifdef __APPLE__
strTempPath = strHomePath + "/scripts";
#else
@@ -931,7 +927,7 @@ CProfile* CApplication::InitDirectoriesOSX()
// copy system-wide plugins into userprofile
if ( bCopySystemPlugins )
- CUtil::CopyDirRecursive("special://xbmc/plugins", "special://home/plugins");
+ CUtil::CopyDirRecursive("special://xbmc/addons/plugins", "special://home/addons/plugins");
}
else
{
@@ -993,23 +989,22 @@ CProfile* CApplication::InitDirectoriesWin32()
SetEnvironmentVariable("XBMC_PROFILE_USERDATA",_P("special://masterprofile").c_str());
bool bCopySystemPlugins = false;
- if (!CDirectory::Exists("special://home/plugins") )
+ if (!CDirectory::Exists("special://home/addons/plugins") )
bCopySystemPlugins = true;
CDirectory::Create("special://home/");
CDirectory::Create("special://home/skin");
+ CDirectory::Create("special://home/addons");
+ CDirectory::Create("special://home/addons/visualizations");
+ CDirectory::Create("special://home/addons/scripts");
+ CDirectory::Create("special://home/addons/scrapers");
+ CDirectory::Create("special://home/addons/screensavers");
+ CDirectory::Create("special://home/addons/plugins");
+ CDirectory::Create("special://home/addons/libraries");
+ CDirectory::Create("special://home/addons/libraries/scrapers");
CDirectory::Create("special://home/media");
- CDirectory::Create("special://home/visualisations");
- CDirectory::Create("special://home/screensavers");
CDirectory::Create("special://home/sounds");
CDirectory::Create("special://home/system");
- CDirectory::Create("special://home/plugins");
- CDirectory::Create("special://home/plugins/video");
- CDirectory::Create("special://home/plugins/music");
- CDirectory::Create("special://home/plugins/pictures");
- CDirectory::Create("special://home/plugins/programs");
- CDirectory::Create("special://home/plugins/weather");
- CDirectory::Create("special://home/scripts");
CDirectory::Create("special://masterprofile");
@@ -1022,7 +1017,7 @@ CProfile* CApplication::InitDirectoriesWin32()
// copy system-wide plugins into userprofile
if ( bCopySystemPlugins )
- CUtil::CopyDirRecursive("special://xbmc/plugins", "special://home/plugins");
+ CUtil::CopyDirRecursive("special://xbmc/addons/plugins", "special://home/addons/plugins");
// create user/app data/XBMC/cache
CSpecialProtocol::SetTempPath(CUtil::AddFileToFolder(homePath,"cache"));
@@ -1109,16 +1104,17 @@ bool CApplication::Initialize()
#endif
{
CDirectory::Create("special://xbmc/scripts");
- CDirectory::Create("special://xbmc/plugins");
- CDirectory::Create("special://xbmc/plugins/music");
- CDirectory::Create("special://xbmc/plugins/video");
- CDirectory::Create("special://xbmc/plugins/pictures");
- CDirectory::Create("special://xbmc/plugins/programs");
CDirectory::Create("special://xbmc/plugins/weather");
CDirectory::Create("special://xbmc/language");
- CDirectory::Create("special://xbmc/visualisations");
+ CDirectory::Create("special://xbmc/addons");
+ CDirectory::Create("special://xbmc/addons/visualizations");
+ CDirectory::Create("special://xbmc/addons/scripts");
+ CDirectory::Create("special://xbmc/addons/scrapers");
+ CDirectory::Create("special://xbmc/addons/screensavers");
+ CDirectory::Create("special://xbmc/addons/plugins");
+ CDirectory::Create("special://home/addons/libraries");
+ CDirectory::Create("special://home/addons/libraries/scrapers");
CDirectory::Create("special://xbmc/sounds");
- CDirectory::Create(CUtil::AddFileToFolder(g_settings.GetUserDataFolder(),"visualisations"));
}
StartServices();
@@ -1153,6 +1149,7 @@ bool CApplication::Initialize()
g_windowManager.Add(new CGUIWindowVideoPlaylist); // window id = 28
g_windowManager.Add(new CGUIWindowLoginScreen); // window id = 29
g_windowManager.Add(new CGUIWindowSettingsProfile); // window id = 34
+ g_windowManager.Add(new CGUIWindowAddonBrowser); // window id = 40
g_windowManager.Add(new CGUIDialogYesNo); // window id = 100
g_windowManager.Add(new CGUIDialogProgress); // window id = 101
g_windowManager.Add(new CGUIDialogKeyboard); // window id = 103
@@ -1172,7 +1169,6 @@ bool CApplication::Initialize()
#endif
g_windowManager.Add(new CGUIDialogSlider); // window id = 145
g_windowManager.Add(new CGUIDialogMusicOSD); // window id = 120
- g_windowManager.Add(new CGUIDialogVisualisationSettings); // window id = 121
g_windowManager.Add(new CGUIDialogVisualisationPresetList); // window id = 122
g_windowManager.Add(new CGUIDialogVideoSettings); // window id = 123
g_windowManager.Add(new CGUIDialogAudioSubtitleSettings); // window id = 124
@@ -1188,7 +1184,7 @@ bool CApplication::Initialize()
g_windowManager.Add(new CGUIDialogSmartPlaylistRule); // window id = 137
g_windowManager.Add(new CGUIDialogBusy); // window id = 138
g_windowManager.Add(new CGUIDialogPictureInfo); // window id = 139
- g_windowManager.Add(new CGUIDialogPluginSettings); // window id = 140
+ g_windowManager.Add(new CGUIDialogAddonSettings); // window id = 140
#ifdef HAS_LINUX_NETWORK
g_windowManager.Add(new CGUIDialogAccessPoints); // window id = 141
#endif
@@ -3141,7 +3137,6 @@ bool CApplication::Cleanup()
g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SONGSELECT);
g_windowManager.Delete(WINDOW_DIALOG_KARAOKE_SELECTOR);
g_windowManager.Delete(WINDOW_DIALOG_MUSIC_OSD);
- g_windowManager.Delete(WINDOW_DIALOG_VIS_SETTINGS);
g_windowManager.Delete(WINDOW_DIALOG_VIS_PRESET_LIST);
g_windowManager.Delete(WINDOW_DIALOG_SELECT);
g_windowManager.Delete(WINDOW_DIALOG_OK);
@@ -3163,7 +3158,7 @@ bool CApplication::Cleanup()
g_windowManager.Delete(WINDOW_DIALOG_SMART_PLAYLIST_RULE);
g_windowManager.Delete(WINDOW_DIALOG_BUSY);
g_windowManager.Delete(WINDOW_DIALOG_PICTURE_INFO);
- g_windowManager.Delete(WINDOW_DIALOG_PLUGIN_SETTINGS);
+ g_windowManager.Delete(WINDOW_DIALOG_ADDON_SETTINGS);
g_windowManager.Delete(WINDOW_DIALOG_ACCESS_POINTS);
g_windowManager.Delete(WINDOW_DIALOG_SLIDER);
@@ -5229,10 +5224,7 @@ void CApplication::UpdateLibraries()
CGUIDialogVideoScan *scanner = (CGUIDialogVideoScan *)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
VIDEO::SScanSettings settings;
if (scanner && !scanner->IsScanning())
- {
- SScraperInfo info;
- scanner->StartScanning("",info,settings,false);
- }
+ scanner->StartScanning("",ADDON::ScraperPtr(),settings,false);
}
if (g_guiSettings.GetBool("musiclibrary.updateonstartup"))
diff --git a/xbmc/ButtonTranslator.cpp b/xbmc/ButtonTranslator.cpp
index f3a2b99acc..055c819da9 100644
--- a/xbmc/ButtonTranslator.cpp
+++ b/xbmc/ButtonTranslator.cpp
@@ -831,6 +831,7 @@ int CButtonTranslator::TranslateWindowString(const char *szWindow)
else if (strWindow.Equals("videofiles")) windowID = WINDOW_VIDEO_FILES;
else if (strWindow.Equals("videolibrary")) windowID = WINDOW_VIDEO_NAV;
else if (strWindow.Equals("videoplaylist")) windowID = WINDOW_VIDEO_PLAYLIST;
+ else if (strWindow.Equals("addonbrowser")) windowID = WINDOW_ADDON_BROWSER;
else if (strWindow.Equals("systeminfo")) windowID = WINDOW_SYSTEM_INFORMATION;
else if (strWindow.Equals("teletext")) windowID = WINDOW_DIALOG_OSD_TELETEXT;
else if (strWindow.Equals("guicalibration")) windowID = WINDOW_SCREEN_CALIBRATION;
@@ -862,7 +863,6 @@ int CButtonTranslator::TranslateWindowString(const char *szWindow)
else if (strWindow.Equals("playercontrols")) windowID = WINDOW_DIALOG_PLAYER_CONTROLS;
else if (strWindow.Equals("seekbar")) windowID = WINDOW_DIALOG_SEEK_BAR;
else if (strWindow.Equals("musicosd")) windowID = WINDOW_DIALOG_MUSIC_OSD;
- else if (strWindow.Equals("visualisationsettings")) windowID = WINDOW_DIALOG_VIS_SETTINGS;
else if (strWindow.Equals("visualisationpresetlist")) windowID = WINDOW_DIALOG_VIS_PRESET_LIST;
else if (strWindow.Equals("osdvideosettings")) windowID = WINDOW_DIALOG_VIDEO_OSD_SETTINGS;
else if (strWindow.Equals("osdaudiosettings")) windowID = WINDOW_DIALOG_AUDIO_OSD_SETTINGS;
@@ -893,7 +893,7 @@ int CButtonTranslator::TranslateWindowString(const char *szWindow)
else if (strWindow.Equals("musicoverlay")) windowID = WINDOW_MUSIC_OVERLAY;
else if (strWindow.Equals("videooverlay")) windowID = WINDOW_VIDEO_OVERLAY;
else if (strWindow.Equals("pictureinfo")) windowID = WINDOW_DIALOG_PICTURE_INFO;
- else if (strWindow.Equals("pluginsettings")) windowID = WINDOW_DIALOG_PLUGIN_SETTINGS;
+ else if (strWindow.Equals("addonsettings") || strWindow.Equals("visualisationsettings")) windowID = WINDOW_DIALOG_ADDON_SETTINGS;
else if (strWindow.Equals("fullscreeninfo")) windowID = WINDOW_DIALOG_FULLSCREEN_INFO;
else if (strWindow.Equals("karaokeselector")) windowID = WINDOW_DIALOG_KARAOKE_SONGSELECT;
else if (strWindow.Equals("karaokelargeselector")) windowID = WINDOW_DIALOG_KARAOKE_SELECTOR;
diff --git a/xbmc/DllAddon.h b/xbmc/DllAddon.h
new file mode 100644
index 0000000000..abeb9107fe
--- /dev/null
+++ b/xbmc/DllAddon.h
@@ -0,0 +1,64 @@
+#pragma once
+/*
+* 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
+*
+*/
+
+#include "DynamicDll.h"
+#include "addons/include/xbmc_addon_cpp_dll.h"
+
+template <typename TheStruct, typename Props>
+class DllAddonInterface
+{
+public:
+ virtual void GetAddon(TheStruct* pAddon) =0;
+ virtual ADDON_STATUS Create(void *cb, Props *info) =0;
+ virtual ADDON_STATUS GetStatus() =0;
+ virtual bool HasSettings() =0;
+ virtual unsigned int GetSettings(StructSetting*** sSet)=0;
+ virtual void FreeSettings()=0;
+ virtual ADDON_STATUS SetSetting(const char *settingName, const void *settingValue) =0;
+ virtual void Remove() =0;
+};
+
+template <typename TheStruct, typename Props>
+class DllAddon : public DllDynamic, public DllAddonInterface<TheStruct, Props>
+{
+public:
+ DECLARE_DLL_WRAPPER_TEMPLATE(DllAddon)
+ DEFINE_METHOD2(ADDON_STATUS, Create, (void* p1, Props* p2))
+ DEFINE_METHOD0(ADDON_STATUS, GetStatus)
+ DEFINE_METHOD0(bool, HasSettings)
+ DEFINE_METHOD1(unsigned int, GetSettings, (StructSetting ***p1))
+ DEFINE_METHOD0(void, FreeSettings)
+ DEFINE_METHOD2(ADDON_STATUS, SetSetting, (const char *p1, const void *p2))
+ DEFINE_METHOD0(void, Remove)
+ DEFINE_METHOD1(void, GetAddon, (TheStruct* p1))
+ BEGIN_METHOD_RESOLVE()
+ RESOLVE_METHOD_RENAME(get_addon,GetAddon)
+ RESOLVE_METHOD(Create)
+ RESOLVE_METHOD(GetStatus)
+ RESOLVE_METHOD(SetSetting)
+ RESOLVE_METHOD(GetSettings)
+ RESOLVE_METHOD(FreeSettings)
+ RESOLVE_METHOD(HasSettings)
+ RESOLVE_METHOD(Remove)
+ END_METHOD_RESOLVE()
+};
+
diff --git a/xbmc/FileSystem/AddonsDirectory.cpp b/xbmc/FileSystem/AddonsDirectory.cpp
new file mode 100644
index 0000000000..39fc36ca60
--- /dev/null
+++ b/xbmc/FileSystem/AddonsDirectory.cpp
@@ -0,0 +1,86 @@
+/*
+ * 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 "AddonsDirectory.h"
+#include "FactoryDirectory.h"
+#include "Directory.h"
+#include "DirectoryCache.h"
+#include "FileItem.h"
+
+using namespace ADDON;
+
+namespace XFILE
+{
+
+CAddonsDirectory::CAddonsDirectory(void)
+{
+ m_allowPrompting = true;
+ m_cacheDirectory = DIR_CACHE_ONCE;
+}
+
+CAddonsDirectory::~CAddonsDirectory(void)
+{}
+
+bool CAddonsDirectory::GetDirectory(const CStdString& strPath, CFileItemList &items)
+{
+ CURL path(strPath);
+ if (!path.GetProtocol().Equals("addons"))
+ return false;
+
+ VECADDONS addons;
+
+ if (path.GetPassWord().empty())
+ CAddonMgr::Get()->GetAddons(TranslateType(path.GetHostName()), addons);
+ else
+ CAddonMgr::Get()->GetAddons(TranslateType(path.GetHostName()), addons, TranslateContent(path.GetPassWord()));
+
+ GenerateListing(path, addons, items);
+
+ return !items.IsEmpty();
+}
+
+void CAddonsDirectory::GenerateListing(CURL &path, VECADDONS& addons, CFileItemList &items)
+{
+ items.ClearItems();
+ for (unsigned i=0; i < addons.size(); i++)
+ {
+ AddonPtr addon = addons[i];
+ path.SetFileName(addon->UUID());
+ CFileItemPtr pItem(new CFileItem(path.Get(), false));
+ pItem->SetLabel(addon->Name());
+ pItem->SetLabel2(addon->Summary());
+ pItem->SetProperty("Addon.Type", TranslateType(addon->Type()));
+ pItem->SetProperty("Addon.Name", addon->Name());
+ pItem->SetProperty("Addon.Summary", addon->Summary());
+ pItem->SetProperty("Addon.Description", addon->Description());
+ pItem->SetProperty("Addon.Creator", addon->Author());
+ pItem->SetProperty("Addon.Disclaimer", addon->Disclaimer());
+ pItem->SetProperty("Addon.Rating", addon->Stars());
+ pItem->SetThumbnailImage(addon->Icon());
+ items.Add(pItem);
+ }
+ items.FillInDefaultIcons();
+ items.Sort(SORT_METHOD_LABEL, SORT_ORDER_ASC);
+}
+
+}
+
diff --git a/xbmc/ScriptSettings.h b/xbmc/FileSystem/AddonsDirectory.h
index 9a81561da4..e002d9e4a3 100644
--- a/xbmc/ScriptSettings.h
+++ b/xbmc/FileSystem/AddonsDirectory.h
@@ -1,7 +1,6 @@
-#ifndef SCRIPTSETTINGS_H_
-#define SCRIPTSETTINGS_H_
+#pragma once
/*
- * Copyright (C) 2005-2008 Team XBMC
+ * Copyright (C) 2005-2009 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
@@ -21,23 +20,28 @@
*
*/
-#include "PluginSettings.h"
+#include "IDirectory.h"
+#include "AddonManager.h"
-class CScriptSettings : public CBasicSettings
+class CURL;
+
+namespace XFILE
{
-public:
- CScriptSettings();
- virtual ~CScriptSettings();
- bool Load(const CStdString& strPath);
- bool Save(void);
- static bool SettingsExist(const CStdString& strPath);
- virtual CStdString getPath() { return m_scriptPath; }
- CScriptSettings& operator =(const CBasicSettings&);
-private:
- CStdString m_id;
- CStdString m_scriptPath;
- CStdString m_userFileName;
-};
+ /*!
+ \ingroup windows
+ \brief Get access to shares and it's directories.
+ */
+ class CAddonsDirectory : public IDirectory
+ {
+ public:
+ CAddonsDirectory(void);
+ virtual ~CAddonsDirectory(void);
+ virtual bool GetDirectory(const CStdString& strPath, CFileItemList &items);
+ virtual bool Create(const char* strPath) { return true; }
+ virtual bool Exists(const char* strPath) { return true; }
-#endif
+ private:
+ void GenerateListing(CURL &path, ADDON::VECADDONS& addons, CFileItemList &items);
+ };
+}
diff --git a/xbmc/FileSystem/FactoryDirectory.cpp b/xbmc/FileSystem/FactoryDirectory.cpp
index 45afde9020..3681f7411c 100644
--- a/xbmc/FileSystem/FactoryDirectory.cpp
+++ b/xbmc/FileSystem/FactoryDirectory.cpp
@@ -34,12 +34,15 @@
#include "MusicDatabaseDirectory.h"
#include "MusicSearchDirectory.h"
#include "VideoDatabaseDirectory.h"
+#include "AddonsDirectory.h"
#include "ShoutcastDirectory.h"
#include "LastFMDirectory.h"
#include "FTPDirectory.h"
#include "HTTPDirectory.h"
#include "DAVDirectory.h"
#include "Application.h"
+#include "StringUtils.h"
+#include "utils/Addon.h"
#ifdef HAS_FILESYSTEM_SMB
#ifdef _WIN32
@@ -115,13 +118,14 @@ IDirectory* CFactoryDirectory::Create(const CStdString& strPath)
if (strProtocol.size() == 0 || strProtocol == "file") return new CHDDirectory();
if (strProtocol == "special") return new CSpecialProtocolDirectory();
+ if (strProtocol == "addons") return new CAddonsDirectory();
#if defined(HAS_FILESYSTEM_CDDA) && defined(HAS_DVD_DRIVE)
if (strProtocol == "cdda") return new CCDDADirectory();
#endif
#ifdef HAS_FILESYSTEM
if (strProtocol == "iso9660") return new CISO9660Directory();
#endif
- if (strProtocol == "plugin") return new CPluginDirectory();
+ if (StringUtils::ValidateUUID(url.GetHostName())) return new CPluginDirectory(ADDON::TranslateContent(strProtocol));
if (strProtocol == "zip") return new CZipDirectory();
#ifdef HAS_FILESYSTEM_RAR
if (strProtocol == "rar") return new CRarDirectory();
diff --git a/xbmc/FileSystem/Makefile.in b/xbmc/FileSystem/Makefile.in
index 413c2a3c0e..ffb26404f6 100644
--- a/xbmc/FileSystem/Makefile.in
+++ b/xbmc/FileSystem/Makefile.in
@@ -8,7 +8,8 @@ endif
CXXFLAGS+=-D__STDC_FORMAT_MACROS \
-SRCS=ASAPFileDirectory.cpp \
+SRCS=AddonsDirectory.cpp \
+ ASAPFileDirectory.cpp \
CacheMemBuffer.cpp \
CacheStrategy.cpp \
CDDADirectory.cpp \
diff --git a/xbmc/FileSystem/PluginDirectory.cpp b/xbmc/FileSystem/PluginDirectory.cpp
index 8a37f1fdf7..b7c16f57c6 100644
--- a/xbmc/FileSystem/PluginDirectory.cpp
+++ b/xbmc/FileSystem/PluginDirectory.cpp
@@ -23,11 +23,12 @@
#include "system.h"
#include "PluginDirectory.h"
#include "Util.h"
+#include "utils/AddonManager.h"
+#include "utils/IAddon.h"
#ifdef HAS_PYTHON
#include "lib/libPython/XBPython.h"
#endif
#include "../utils/SingleLock.h"
-#include "PluginSettings.h"
#include "GUIWindowManager.h"
#include "GUIDialogProgress.h"
#include "FileSystem/File.h"
@@ -36,15 +37,18 @@
#include "LocalizeStrings.h"
#include "utils/log.h"
#include "utils/TimeUtils.h"
+#include "StringUtils.h"
using namespace XFILE;
using namespace std;
+using namespace ADDON;
vector<CPluginDirectory *> CPluginDirectory::globalHandles;
CCriticalSection CPluginDirectory::m_handleLock;
-CPluginDirectory::CPluginDirectory(void)
+CPluginDirectory::CPluginDirectory(const CONTENT_TYPE &content)
{
+ m_content = content;
m_fetchComplete = CreateEvent(NULL, false, false, NULL);
m_listItems = new CFileItemList;
m_fileResult = new CFileItem;
@@ -76,29 +80,23 @@ bool CPluginDirectory::StartScript(const CStdString& strPath)
{
CURL url(strPath);
- // path is special://home/plugins/<path from here>
- CStdString pathToScript = "special://home/plugins/";
- CUtil::AddFileToFolder(pathToScript, url.GetHostName(), pathToScript);
- CUtil::AddFileToFolder(pathToScript, url.GetFileName(), pathToScript);
- CUtil::AddFileToFolder(pathToScript, "default.py", pathToScript);
+ if (!CAddonMgr::Get()->GetAddon(ADDON_PLUGIN, url.GetHostName(), m_addon))
+ {
+ CLog::Log(LOGERROR, "Unable to find plugin %s", url.GetHostName().c_str());
+ return false;
+ }
- // base path
- CStdString basePath = "plugin://";
- CUtil::AddFileToFolder(basePath, url.GetHostName(), basePath);
- CUtil::AddFileToFolder(basePath, url.GetFileName(), basePath);
+ if (m_addon->HasSettings())
+ m_addon->LoadSettings();
- // options
+ // get options
CStdString options = url.GetOptions();
CUtil::RemoveSlashAtEnd(options); // This MAY kill some scripts (eg though with a URL ending with a slash), but
// is needed for all others, as XBMC adds slashes to "folders"
+ url.SetOptions(""); // do this because we can then use the url to generate the basepath
+ // which is passed to the plugin (and represents the share)
- // Load the plugin settings
- CLog::Log(LOGDEBUG, "%s - URL for plugin settings: %s", __FUNCTION__, url.GetFileName().c_str() );
- g_currentPluginSettings.Load(url);
-
- // Load language strings
- LoadPluginStrings(url);
-
+ CStdString basePath(url.Get());
// reset our wait event, and grab a new handle
ResetEvent(m_fetchComplete);
int handle = getNewHandle(this);
@@ -117,18 +115,18 @@ bool CPluginDirectory::StartScript(const CStdString& strPath)
const char *plugin_argv[] = {basePath.c_str(), strHandle.c_str(), options.c_str(), NULL };
// run the script
- CLog::Log(LOGDEBUG, "%s - calling plugin %s('%s','%s','%s')", __FUNCTION__, pathToScript.c_str(), plugin_argv[0], plugin_argv[1], plugin_argv[2]);
+ CLog::Log(LOGDEBUG, "%s - calling plugin %s('%s','%s','%s')", __FUNCTION__, m_addon->Name().c_str(), plugin_argv[0], plugin_argv[1], plugin_argv[2]);
bool success = false;
#ifdef HAS_PYTHON
- if (g_pythonParser.evalFile(pathToScript.c_str(), 3, (const char**)plugin_argv) >= 0)
+ CStdString file = m_addon->Path() + m_addon->LibName();
+ if (g_pythonParser.evalFile(file.c_str(), 3, (const char**)plugin_argv) >= 0)
{ // wait for our script to finish
- CStdString scriptName = url.GetFileName();
- CUtil::RemoveSlashAtEnd(scriptName);
- success = WaitOnScriptResult(pathToScript, scriptName);
+ CStdString scriptName = m_addon->Name();
+ success = WaitOnScriptResult(file, scriptName);
}
else
#endif
- CLog::Log(LOGERROR, "Unable to run plugin %s", pathToScript.c_str());
+ CLog::Log(LOGERROR, "Unable to run plugin %s", m_addon->Name().c_str());
// free our handle
removeHandle(handle);
@@ -138,7 +136,8 @@ bool CPluginDirectory::StartScript(const CStdString& strPath)
bool CPluginDirectory::GetPluginResult(const CStdString& strPath, CFileItem &resultItem)
{
- CPluginDirectory* newDir = new CPluginDirectory();
+ CURL url(strPath);
+ CPluginDirectory* newDir = new CPluginDirectory(TranslateContent(url.GetProtocol()));
bool success = newDir->StartScript(strPath);
@@ -202,9 +201,6 @@ void CPluginDirectory::EndOfDirectory(int handle, bool success, bool replaceList
if (!dir->m_listItems->HasSortDetails())
dir->m_listItems->AddSortMethod(SORT_METHOD_NONE, 552, LABEL_MASKS("%L", "%D"));
- // Unload temporary language strings
- ClearPluginStrings();
-
// set the event to mark that we're done
SetEvent(dir->m_fetchComplete);
}
@@ -375,9 +371,9 @@ void CPluginDirectory::AddSortMethod(int handle, SORT_METHOD sortMethod)
bool CPluginDirectory::GetDirectory(const CStdString& strPath, CFileItemList& items)
{
CURL url(strPath);
- if (url.GetFileName().IsEmpty())
- { // called with no script - should never happen
- return GetPluginsDirectory(url.GetHostName(), items);
+ if (!StringUtils::ValidateUUID(url.GetHostName()))
+ { // called with no script - we must be browsing root of plugins dir
+ return GetPluginsDirectory(ADDON::TranslateContent(url.GetHostName()), items);
}
bool success = this->StartScript(strPath);
@@ -391,29 +387,27 @@ bool CPluginDirectory::GetDirectory(const CStdString& strPath, CFileItemList& it
bool CPluginDirectory::RunScriptWithParams(const CStdString& strPath)
{
CURL url(strPath);
- if (url.GetFileName().IsEmpty()) // called with no script - should never happen
+ if (url.GetHostName().IsEmpty()) // called with no script - should never happen
return false;
- // Load the settings incase they changed while in the plugins directory
- g_currentPluginSettings.Load(url);
-
- // Load language strings
- LoadPluginStrings(url);
+ AddonPtr addon;
+ if (!CAddonMgr::Get()->GetAddon(ADDON_PLUGIN, url.GetHostName(), addon))
+ {
+ CLog::Log(LOGERROR, "Unable to find plugin %s", url.GetHostName().c_str());
+ return false;
+ }
- // path is special://home/plugins/<path from here>
- CStdString pathToScript = "special://home/plugins/";
- CUtil::AddFileToFolder(pathToScript, url.GetHostName(), pathToScript);
- CUtil::AddFileToFolder(pathToScript, url.GetFileName(), pathToScript);
- CUtil::AddFileToFolder(pathToScript, "default.py", pathToScript);
+ if (addon->HasSettings())
+ addon->LoadSettings();
// options
CStdString options = url.GetOptions();
CUtil::RemoveSlashAtEnd(options); // This MAY kill some scripts (eg though with a URL ending with a slash), but
// is needed for all others, as XBMC adds slashes to "folders"
- // base path
- CStdString basePath = "plugin://";
- CUtil::AddFileToFolder(basePath, url.GetHostName(), basePath);
- CUtil::AddFileToFolder(basePath, url.GetFileName(), basePath);
+ url.SetOptions(""); // do this because we can then use the url to generate the basepath
+ // which is passed to the plugin (and represents the share)
+
+ CStdString basePath(url.Get());
// setup our parameters to send the script
CStdString strHandle;
@@ -425,75 +419,60 @@ bool CPluginDirectory::RunScriptWithParams(const CStdString& strPath)
// run the script
#ifdef HAS_PYTHON
- CLog::Log(LOGDEBUG, "%s - calling plugin %s('%s','%s','%s')", __FUNCTION__, pathToScript.c_str(), argv[0], argv[1], argv[2]);
- if (g_pythonParser.evalFile(pathToScript.c_str(), 3, (const char**)argv) >= 0)
+ CStdString file = addon->Path() + addon->LibName();
+ CLog::Log(LOGDEBUG, "%s - calling plugin %s('%s','%s','%s')", __FUNCTION__, addon->Name().c_str(), argv[0], argv[1], argv[2]);
+ if (g_pythonParser.evalFile(file.c_str(), 3, (const char**)argv) >= 0)
return true;
else
#endif
- CLog::Log(LOGERROR, "Unable to run plugin %s", pathToScript.c_str());
+ CLog::Log(LOGERROR, "Unable to run plugin %s", addon->Name().c_str());
return false;
}
-bool CPluginDirectory::HasPlugins(const CStdString &type)
+bool CPluginDirectory::HasPlugins(const CONTENT_TYPE &type)
{
- CStdString path = "special://home/plugins/";
- CUtil::AddFileToFolder(path, type, path);
- CFileItemList items;
- if (CDirectory::GetDirectory(path, items, "/", false))
- {
- for (int i = 0; i < items.Size(); i++)
- {
- CFileItemPtr item = items[i];
- if (item->m_bIsFolder && !item->IsParentFolder() && !item->m_bIsShareOrDrive)
- {
- CStdString defaultPY;
- CUtil::AddFileToFolder(item->m_strPath, "default.py", defaultPY);
- if (XFILE::CFile::Exists(defaultPY))
- return true;
- }
- }
- }
- return false;
+ return CAddonMgr::Get()->HasAddons(ADDON_PLUGIN, type);
}
-bool CPluginDirectory::GetPluginsDirectory(const CStdString &type, CFileItemList &items)
+bool CPluginDirectory::GetPluginsDirectory(const CONTENT_TYPE &type, CFileItemList &items)
{
- // retrieve our folder
- CStdString pluginsFolder = "special://home/plugins";
- CUtil::AddFileToFolder(pluginsFolder, type, pluginsFolder);
- CUtil::AddSlashAtEnd(pluginsFolder);
+ VECADDONS addons;
- if (!CDirectory::GetDirectory(pluginsFolder, items, "*.py", false))
+ if(!CAddonMgr::Get()->GetAddons(ADDON_PLUGIN, addons, type))
return false;
- items.m_strPath.Replace("special://home/plugins/", "plugin://");
-
- // flatten any folders - TODO: Assigning of thumbs
- for (int i = 0; i < items.Size(); i++)
+ for (IVECADDONS it = addons.begin(); it != addons.end(); it++)
{
- CFileItemPtr item = items[i];
- item->SetThumbnailImage("");
- item->SetCachedProgramThumb();
- if (!item->HasThumbnail())
- item->SetUserProgramThumb();
- if (!item->HasThumbnail())
+ CStdString path("plugin://");
+ path.append((*it)->UUID());
+
+ CFileItemPtr newItem(new CFileItem(path,true));
+ newItem->SetLabel((*it)->Name());
+
+ newItem->SetThumbnailImage("");
+ newItem->SetCachedProgramThumb();
+ if (!newItem->HasThumbnail())
+ newItem->SetUserProgramThumb();
+ if (!newItem->HasThumbnail())
{
- CFileItem item2(item->m_strPath);
- CUtil::AddFileToFolder(item->m_strPath,"default.py",item2.m_strPath);
+ CFileItem item2((*it)->Path());
+ CUtil::AddFileToFolder((*it)->Path(), (*it)->LibName(), item2.m_strPath);
item2.m_bIsFolder = false;
item2.SetCachedProgramThumb();
if (!item2.HasThumbnail())
item2.SetUserProgramThumb();
+ if (!item2.HasThumbnail())
+ item2.SetThumbnailImage((*it)->Icon());
if (item2.HasThumbnail())
{
- XFILE::CFile::Cache(item2.GetThumbnailImage(),item->GetCachedProgramThumb());
- item->SetThumbnailImage(item->GetCachedProgramThumb());
+ XFILE::CFile::Cache(item2.GetThumbnailImage(),newItem->GetCachedProgramThumb());
+ newItem->SetThumbnailImage(newItem->GetCachedProgramThumb());
}
}
- item->m_strPath.Replace("special://home/plugins/", "plugin://");
- item->m_strPath.Replace("\\", "/");
+ items.Add(newItem);
}
+
return true;
}
@@ -600,21 +579,23 @@ void CPluginDirectory::SetResolvedUrl(int handle, bool success, const CFileItem
SetEvent(dir->m_fetchComplete);
}
-void CPluginDirectory::SetContent(int handle, const CStdString &strContent)
+CStdString CPluginDirectory::GetSetting(int handle, const CStdString &strID)
{
if (handle < 0 || handle >= (int)globalHandles.size())
{
CLog::Log(LOGERROR, "%s called with an invalid handle.", __FUNCTION__);
- return;
+ return "";
}
CPluginDirectory *dir = globalHandles[handle];
- dir->m_listItems->SetContent(strContent);
+ if(dir->m_addon)
+ return dir->m_addon->GetSetting(strID);
+ else
+ return "";
}
-void CPluginDirectory::SetProperty(int handle, const CStdString &strProperty, const CStdString &strValue)
+void CPluginDirectory::SetSetting(int handle, const CStdString &strID, const CStdString &value)
{
- CSingleLock lock(m_handleLock);
if (handle < 0 || handle >= (int)globalHandles.size())
{
CLog::Log(LOGERROR, "%s called with an invalid handle.", __FUNCTION__);
@@ -622,37 +603,33 @@ void CPluginDirectory::SetProperty(int handle, const CStdString &strProperty, co
}
CPluginDirectory *dir = globalHandles[handle];
- dir->m_listItems->SetProperty(strProperty, strValue);
+ if(dir->m_addon)
+ dir->m_addon->UpdateSetting(strID, value);
}
-void CPluginDirectory::LoadPluginStrings(const CURL &url)
+void CPluginDirectory::SetContent(int handle, const CStdString &strContent)
{
- // Path where the plugin resides
- CStdString pathToPlugin = "special://home/plugins/";
- CUtil::AddFileToFolder(pathToPlugin, url.GetHostName(), pathToPlugin);
- CUtil::AddFileToFolder(pathToPlugin, url.GetFileName(), pathToPlugin);
-
- // Path where the language strings reside
- CStdString pathToLanguageFile = pathToPlugin;
- CStdString pathToFallbackLanguageFile = pathToPlugin;
- CUtil::AddFileToFolder(pathToLanguageFile, "resources", pathToLanguageFile);
- CUtil::AddFileToFolder(pathToFallbackLanguageFile, "resources", pathToFallbackLanguageFile);
- CUtil::AddFileToFolder(pathToLanguageFile, "language", pathToLanguageFile);
- CUtil::AddFileToFolder(pathToFallbackLanguageFile, "language", pathToFallbackLanguageFile);
- CUtil::AddFileToFolder(pathToLanguageFile, g_guiSettings.GetString("locale.language"), pathToLanguageFile);
- CUtil::AddFileToFolder(pathToFallbackLanguageFile, "english", pathToFallbackLanguageFile);
- CUtil::AddFileToFolder(pathToLanguageFile, "strings.xml", pathToLanguageFile);
- CUtil::AddFileToFolder(pathToFallbackLanguageFile, "strings.xml", pathToFallbackLanguageFile);
-
- // Load language strings temporarily
- g_localizeStringsTemp.Load(pathToLanguageFile, pathToFallbackLanguageFile);
+ if (handle < 0 || handle >= (int)globalHandles.size())
+ {
+ CLog::Log(LOGERROR, "%s called with an invalid handle.", __FUNCTION__);
+ return;
+ }
+
+ CPluginDirectory *dir = globalHandles[handle];
+ dir->m_listItems->SetContent(strContent);
}
-void CPluginDirectory::ClearPluginStrings()
+void CPluginDirectory::SetProperty(int handle, const CStdString &strProperty, const CStdString &strValue)
{
- // Unload temporary language strings
- g_localizeStringsTemp.Clear();
-}
+ CSingleLock lock(m_handleLock);
+ if (handle < 0 || handle >= (int)globalHandles.size())
+ {
+ CLog::Log(LOGERROR, "%s called with an invalid handle.", __FUNCTION__);
+ return;
+ }
+ CPluginDirectory *dir = globalHandles[handle];
+ dir->m_listItems->SetProperty(strProperty, strValue);
+}
diff --git a/xbmc/FileSystem/PluginDirectory.h b/xbmc/FileSystem/PluginDirectory.h
index 183bd4e43d..cd201c2ba4 100644
--- a/xbmc/FileSystem/PluginDirectory.h
+++ b/xbmc/FileSystem/PluginDirectory.h
@@ -28,6 +28,7 @@
#include <string>
#include <vector>
#include "../utils/CriticalSection.h"
+#include "../utils/IAddon.h"
class CURL;
class CFileItemList;
@@ -38,16 +39,14 @@ namespace XFILE
class CPluginDirectory : public IDirectory
{
public:
- CPluginDirectory(void);
+ CPluginDirectory(const CONTENT_TYPE &content);
~CPluginDirectory(void);
virtual bool GetDirectory(const CStdString& strPath, CFileItemList& items);
virtual bool IsAllowed(const CStdString &strFile) const { return true; };
virtual bool Exists(const char* strPath) { return true; }
static bool RunScriptWithParams(const CStdString& strPath);
- static bool HasPlugins(const CStdString &type);
- bool GetPluginsDirectory(const CStdString &type, CFileItemList &items);
- static void LoadPluginStrings(const CURL &url);
- static void ClearPluginStrings();
+ static bool HasPlugins(const CONTENT_TYPE &type);
+ bool GetPluginsDirectory(const CONTENT_TYPE &type, CFileItemList &items);
bool StartScript(const CStdString& strPath);
static bool GetPluginResult(const CStdString& strPath, CFileItem &resultItem);
@@ -56,11 +55,15 @@ public:
static bool AddItems(int handle, const CFileItemList *items, int totalItems);
static void EndOfDirectory(int handle, bool success, bool replaceListing, bool cacheToDisc);
static void AddSortMethod(int handle, SORT_METHOD sortMethod);
+ static CStdString GetSetting(int handle, const CStdString &key);
+ static void SetSetting(int handle, const CStdString &key, const CStdString &value);
static void SetContent(int handle, const CStdString &strContent);
static void SetProperty(int handle, const CStdString &strProperty, const CStdString &strValue);
static void SetResolvedUrl(int handle, bool success, const CFileItem* resultItem);
private:
+ ADDON::AddonPtr m_addon;
+ CONTENT_TYPE m_content;
bool WaitOnScriptResult(const CStdString &scriptPath, const CStdString &scriptName);
static std::vector<CPluginDirectory*> globalHandles;
diff --git a/xbmc/GUIDialogPluginSettings.cpp b/xbmc/GUIDialogAddonSettings.cpp
index 777939b047..7f0cebf04b 100644
--- a/xbmc/GUIDialogPluginSettings.cpp
+++ b/xbmc/GUIDialogAddonSettings.cpp
@@ -19,10 +19,12 @@
*
*/
-#include "GUIDialogPluginSettings.h"
+#include "GUIDialogAddonSettings.h"
#include "FileSystem/PluginDirectory.h"
+#include "utils/IAddon.h"
#include "GUIDialogNumeric.h"
#include "GUIDialogFileBrowser.h"
+#include "GUIDialogOK.h"
#include "GUIControlGroupList.h"
#include "Util.h"
#include "MediaManager.h"
@@ -32,18 +34,16 @@
#include "GUIImage.h"
#include "FileSystem/Directory.h"
#include "VideoInfoScanner.h"
-#include "ScraperSettings.h"
+#include "Scraper.h"
#include "GUIWindowManager.h"
#include "Application.h"
#include "GUIDialogKeyboard.h"
#include "FileItem.h"
#include "Settings.h"
-#include "ScriptSettings.h"
-#include "GUISettings.h"
-#include "LocalizeStrings.h"
using namespace std;
-using namespace XFILE;
+using namespace ADDON;
+using XFILE::CDirectory;
#define CONTROL_AREA 2
#define CONTROL_DEFAULT_BUTTON 3
@@ -57,14 +57,14 @@ using namespace XFILE;
#define CONTROL_HEADING_LABEL 20
#define CONTROL_START_CONTROL 100
-CGUIDialogPluginSettings::CGUIDialogPluginSettings()
- : CGUIDialogBoxBase(WINDOW_DIALOG_PLUGIN_SETTINGS, "DialogPluginSettings.xml")
+CGUIDialogAddonSettings::CGUIDialogAddonSettings()
+ : CGUIDialogBoxBase(WINDOW_DIALOG_ADDON_SETTINGS, "DialogAddonSettings.xml")
{}
-CGUIDialogPluginSettings::~CGUIDialogPluginSettings(void)
+CGUIDialogAddonSettings::~CGUIDialogAddonSettings(void)
{}
-bool CGUIDialogPluginSettings::OnMessage(CGUIMessage& message)
+bool CGUIDialogAddonSettings::OnMessage(CGUIMessage& message)
{
switch (message.GetMessage())
{
@@ -75,16 +75,19 @@ bool CGUIDialogPluginSettings::OnMessage(CGUIMessage& message)
if (iControl == ID_BUTTON_OK)
{
- m_bConfirmed = true;
- SaveSettings();
+ if (m_changed)
+ SaveSettings();
+ Close();
+ return true;
}
else if (iControl == ID_BUTTON_DEFAULT)
SetDefaults();
else
bCloseDialog = ShowVirtualKeyboard(iControl);
- if (iControl == ID_BUTTON_OK || iControl == ID_BUTTON_CANCEL || bCloseDialog)
+ if (iControl == ID_BUTTON_CANCEL || bCloseDialog)
{
+ m_changed = false;
Close();
return true;
}
@@ -94,108 +97,64 @@ bool CGUIDialogPluginSettings::OnMessage(CGUIMessage& message)
return CGUIDialogBoxBase::OnMessage(message);
}
-void CGUIDialogPluginSettings::OnInitWindow()
+void CGUIDialogAddonSettings::OnInitWindow()
{
FreeControls();
CreateControls();
CGUIDialogBoxBase::OnInitWindow();
- m_bConfirmed = false;
}
// \brief Show CGUIDialogOK dialog, then wait for user to dismiss it.
-bool CGUIDialogPluginSettings::ShowAndGetInput(CURL& url)
+bool CGUIDialogAddonSettings::ShowAndGetInput(const AddonPtr &addon)
{
- m_url = url;
-
- // Load language strings temporarily
- XFILE::CPluginDirectory::LoadPluginStrings(url);
-
- // Create the dialog
- CGUIDialogPluginSettings* pDialog = (CGUIDialogPluginSettings*) g_windowManager.GetWindow(WINDOW_DIALOG_PLUGIN_SETTINGS);
-
- pDialog->m_strHeading = m_url.GetFileName();
- CUtil::RemoveSlashAtEnd(pDialog->m_strHeading);
- pDialog->m_strHeading.Format("$LOCALIZE[1045] - %s", pDialog->m_strHeading.c_str());
-
- CPluginSettings settings;
- settings.Load(m_url);
- pDialog->m_settings = settings;
-
- pDialog->DoModal();
+ if (!addon)
+ return false;
+
+ bool changed(false);
+ if (addon->HasSettings())
+ {
+ // Create the dialog
+ CGUIDialogAddonSettings* pDialog = NULL;
+ pDialog = (CGUIDialogAddonSettings*) g_windowManager.GetWindow(WINDOW_DIALOG_ADDON_SETTINGS);
+ if (!pDialog)
+ return false;
+
+ // Set the heading
+ CStdString heading;
+ heading.Format("$LOCALIZE[10004] - %s", addon->Name().c_str()); // "Settings - AddonName"
+ pDialog->m_strHeading = heading;
+
+ if (addon->LoadSettings())
+ {
+ pDialog->m_changed = false;
+ pDialog->m_addon = addon;
+ pDialog->DoModal();
- if(pDialog->m_bConfirmed)
- {
- settings = pDialog->m_settings;
- settings.Save();
+ if (pDialog->m_changed)
+ {
+ changed = true;
+ addon->SaveSettings();
+ }
+ }
+ else
+ { // couldn't load settings, inform user
+ CGUIDialogOK::ShowAndGetInput(24000,0,24030,24031);
+ }
}
-
- return pDialog->m_bConfirmed;
-}
-
-// \brief Show CGUIDialogOK dialog, then wait for user to dismiss it.
-bool CGUIDialogPluginSettings::ShowAndGetInput(SScraperInfo& info)
-{
- // Create the dialog
- CGUIDialogPluginSettings* pDialog = (CGUIDialogPluginSettings*) g_windowManager.GetWindow(WINDOW_DIALOG_PLUGIN_SETTINGS);
-
- pDialog->m_settings = info.settings;
- pDialog->m_strHeading.Format("$LOCALIZE[20407] - %s", info.strTitle.c_str());
-
- pDialog->DoModal();
- if(pDialog->m_bConfirmed)
- info.settings.LoadUserXML(static_cast<CScraperSettings&>(pDialog->m_settings).GetSettings());
-
- return pDialog->m_bConfirmed;
-}
-
-// \brief Show CGUIDialogOK dialog, then wait for user to dismiss it.
-bool CGUIDialogPluginSettings::ShowAndGetInput(CStdString& path)
-{
- CUtil::RemoveSlashAtEnd(path);
- m_url = CURL(path);
-
- // Path where the language strings reside
- CStdString pathToLanguageFile = path;
- CStdString pathToFallbackLanguageFile = path;
- CUtil::AddFileToFolder(pathToLanguageFile, "resources", pathToLanguageFile);
- CUtil::AddFileToFolder(pathToFallbackLanguageFile, "resources", pathToFallbackLanguageFile);
- CUtil::AddFileToFolder(pathToLanguageFile, "language", pathToLanguageFile);
- CUtil::AddFileToFolder(pathToFallbackLanguageFile, "language", pathToFallbackLanguageFile);
- CUtil::AddFileToFolder(pathToLanguageFile, g_guiSettings.GetString("locale.language"), pathToLanguageFile);
- CUtil::AddFileToFolder(pathToFallbackLanguageFile, "english", pathToFallbackLanguageFile);
- CUtil::AddFileToFolder(pathToLanguageFile, "strings.xml", pathToLanguageFile);
- CUtil::AddFileToFolder(pathToFallbackLanguageFile, "strings.xml", pathToFallbackLanguageFile);
-
- // Load language strings temporarily
- g_localizeStringsTemp.Load(pathToLanguageFile, pathToFallbackLanguageFile);
-
- // Create the dialog
- CGUIDialogPluginSettings* pDialog = (CGUIDialogPluginSettings*) g_windowManager.GetWindow(WINDOW_DIALOG_PLUGIN_SETTINGS);
-
- pDialog->m_strHeading = CUtil::GetFileName(path);
- pDialog->m_strHeading.Format("$LOCALIZE[1049] - %s", pDialog->m_strHeading.c_str());
-
- CScriptSettings settings;
- settings.Load(path);
- pDialog->m_settings = settings;
-
- pDialog->DoModal();
-
- if(pDialog->m_bConfirmed)
- {
- settings = pDialog->m_settings;
- settings.Save();
+ else
+ { // addon does not support settings, inform user
+ CGUIDialogOK::ShowAndGetInput(24000,0,24030,0);
}
- return pDialog->m_bConfirmed;
+ return changed;
}
-bool CGUIDialogPluginSettings::ShowVirtualKeyboard(int iControl)
+bool CGUIDialogAddonSettings::ShowVirtualKeyboard(int iControl)
{
int controlId = CONTROL_START_CONTROL;
bool bCloseDialog = false;
- TiXmlElement *setting = m_settings.GetPluginRoot()->FirstChildElement("setting");
+ const TiXmlElement *setting = m_addon->GetSettingsXML()->FirstChildElement("setting");
while (setting)
{
if (controlId == iControl)
@@ -320,9 +279,7 @@ bool CGUIDialogPluginSettings::ShowVirtualKeyboard(int iControl)
if (setting->Attribute("default"))
{
CStdString action = setting->Attribute("default");
- CStdString url = m_url.Get();
- // replace $CWD with the url of plugin
- action.Replace("$CWD", url);
+ action.Replace("$CWD", m_addon->Path());
if (option)
bCloseDialog = (strcmpi(option, "close") == 0);
g_application.getApplicationMessenger().ExecBuiltIn(action);
@@ -340,11 +297,11 @@ bool CGUIDialogPluginSettings::ShowVirtualKeyboard(int iControl)
}
// Go over all the settings and set their values according to the values of the GUI components
-bool CGUIDialogPluginSettings::SaveSettings(void)
+bool CGUIDialogAddonSettings::SaveSettings(void)
{
// Retrieve all the values from the GUI components and put them in the model
int controlId = CONTROL_START_CONTROL;
- TiXmlElement *setting = m_settings.GetPluginRoot()->FirstChildElement("setting");
+ TiXmlElement *setting = m_addon->GetSettingsXML()->FirstChildElement("setting");
while (setting)
{
CStdString id;
@@ -378,7 +335,7 @@ bool CGUIDialogPluginSettings::SaveSettings(void)
default:
break;
}
- m_settings.Set(id, value);
+ m_addon->UpdateSetting(id, value, type);
}
setting = setting->NextSiblingElement("setting");
controlId++;
@@ -386,7 +343,7 @@ bool CGUIDialogPluginSettings::SaveSettings(void)
return true;
}
-void CGUIDialogPluginSettings::FreeControls()
+void CGUIDialogAddonSettings::FreeControls()
{
// clear the category group
CGUIControlGroupList *control = (CGUIControlGroupList *)GetControl(CONTROL_AREA);
@@ -397,7 +354,7 @@ void CGUIDialogPluginSettings::FreeControls()
}
}
-void CGUIDialogPluginSettings::CreateControls()
+void CGUIDialogAddonSettings::CreateControls()
{
CGUISpinControlEx *pOriginalSpin = (CGUISpinControlEx*)GetControl(CONTROL_DEFAULT_SPIN);
CGUIRadioButtonControl *pOriginalRadioButton = (CGUIRadioButtonControl *)GetControl(CONTROL_DEFAULT_RADIOBUTTON);
@@ -424,18 +381,11 @@ void CGUIDialogPluginSettings::CreateControls()
SET_CONTROL_LABEL(CONTROL_HEADING_LABEL, m_strHeading);
// Create our base path, used for type "fileenum" settings
- CStdString basepath;
- if (m_url.GetProtocol().Equals("plugin"))
- { // plugins need to create path
- basepath = CUtil::AddFileToFolder("special://home/plugins/", m_url.GetHostName());
- basepath = CUtil::AddFileToFolder(basepath, m_url.GetFileName());
- }
- else
- basepath = m_url.Get();
+ CStdString basepath(m_addon->Path());
CGUIControl* pControl = NULL;
int controlId = CONTROL_START_CONTROL;
- TiXmlElement *setting = m_settings.GetPluginRoot()->FirstChildElement("setting");
+ const TiXmlElement *setting = m_addon->GetSettingsXML()->FirstChildElement("setting");
while (setting)
{
const char *type = setting->Attribute("type");
@@ -451,7 +401,12 @@ void CGUIDialogPluginSettings::CreateControls()
entries = setting->Attribute("entries");
CStdString label;
if (setting->Attribute("label") && atoi(setting->Attribute("label")) > 0)
- label.Format("$LOCALIZE[%s]", setting->Attribute("label"));
+ {
+ if (m_addon->Parent())
+ label.Format("$ADDON[%s %s]", m_addon->Parent()->UUID().c_str(), setting->Attribute("label"));
+ else
+ label.Format("$ADDON[%s %s]", m_addon->UUID().c_str(), setting->Attribute("label"));
+ }
else
label = setting->Attribute("label");
@@ -474,8 +429,8 @@ void CGUIDialogPluginSettings::CreateControls()
((CGUIButtonControl *)pControl)->SetLabel(label);
if (id)
{
- m_buttonValues[id] = m_settings.Get(id);
- CStdString value=m_settings.Get(id);
+ CStdString value = m_addon->GetSetting(id);
+ m_buttonValues[id] = value;
// get any option to test for hidden
const char *option = setting->Attribute("option");
if (option && (strstr(option, "urlencoded")))
@@ -495,7 +450,7 @@ void CGUIDialogPluginSettings::CreateControls()
pControl = new CGUIRadioButtonControl(*pOriginalRadioButton);
if (!pControl) return;
((CGUIRadioButtonControl *)pControl)->SetLabel(label);
- ((CGUIRadioButtonControl *)pControl)->SetSelected(m_settings.Get(id) == "true");
+ ((CGUIRadioButtonControl *)pControl)->SetSelected(m_addon->GetSetting(id) == "true");
}
else if (strcmpi(type, "enum") == 0 || strcmpi(type, "labelenum") == 0)
{
@@ -523,7 +478,7 @@ void CGUIDialogPluginSettings::CreateControls()
iAdd = atoi(entryVec[i]);
if (!lvalues.IsEmpty())
{
- CStdString replace = g_localizeStringsTemp.Get(atoi(valuesVec[i]));
+ CStdString replace = m_addon->GetString(atoi(valuesVec[i]));
if (replace.IsEmpty())
replace = g_localizeStrings.Get(atoi(valuesVec[i]));
((CGUISpinControlEx *)pControl)->AddLabel(replace, iAdd);
@@ -533,10 +488,10 @@ void CGUIDialogPluginSettings::CreateControls()
}
if (strcmpi(type, "labelenum") == 0)
{ // need to run through all our settings and find the one that matches
- ((CGUISpinControlEx*) pControl)->SetValueFromLabel(m_settings.Get(id));
+ ((CGUISpinControlEx*) pControl)->SetValueFromLabel(m_addon->GetSetting(id));
}
else
- ((CGUISpinControlEx*) pControl)->SetValue(atoi(m_settings.Get(id)));
+ ((CGUISpinControlEx*) pControl)->SetValue(atoi(m_addon->GetSetting(id)));
}
else if (strcmpi(type, "fileenum") == 0)
@@ -564,7 +519,7 @@ void CGUIDialogPluginSettings::CreateControls()
if ((mask.Equals("/") && pItem->m_bIsFolder) || !pItem->m_bIsFolder)
{
((CGUISpinControlEx *)pControl)->AddLabel(pItem->GetLabel(), iItem);
- if (pItem->GetLabel().Equals(m_settings.Get(id)))
+ if (pItem->GetLabel().Equals(m_addon->GetSetting(id)))
((CGUISpinControlEx *)pControl)->SetValue(iItem);
iItem++;
}
@@ -597,10 +552,10 @@ void CGUIDialogPluginSettings::CreateControls()
}
// Go over all the settings and set their enabled condition according to the values of the enabled attribute
-void CGUIDialogPluginSettings::EnableControls()
+void CGUIDialogAddonSettings::EnableControls()
{
int controlId = CONTROL_START_CONTROL;
- TiXmlElement *setting = m_settings.GetPluginRoot()->FirstChildElement("setting");
+ const TiXmlElement *setting = m_addon->GetSettingsXML()->FirstChildElement("setting");
while (setting)
{
const CGUIControl* control = GetControl(controlId);
@@ -622,7 +577,7 @@ void CGUIDialogPluginSettings::EnableControls()
}
}
-bool CGUIDialogPluginSettings::GetCondition(const CStdString &condition, const int controlId)
+bool CGUIDialogAddonSettings::GetCondition(const CStdString &condition, const int controlId)
{
if (condition.IsEmpty()) return true;
@@ -693,7 +648,7 @@ bool CGUIDialogPluginSettings::GetCondition(const CStdString &condition, const i
return bCondition;
}
-bool CGUIDialogPluginSettings::TranslateSingleString(const CStdString &strCondition, vector<CStdString> &condVec)
+bool CGUIDialogAddonSettings::TranslateSingleString(const CStdString &strCondition, vector<CStdString> &condVec)
{
CStdString strTest = strCondition;
strTest.ToLower();
@@ -714,10 +669,10 @@ bool CGUIDialogPluginSettings::TranslateSingleString(const CStdString &strCondit
}
// Go over all the settings and set their default values
-void CGUIDialogPluginSettings::SetDefaults()
+void CGUIDialogAddonSettings::SetDefaults()
{
int controlId = CONTROL_START_CONTROL;
- TiXmlElement *setting = m_settings.GetPluginRoot()->FirstChildElement("setting");
+ const TiXmlElement *setting = m_addon->GetSettingsXML()->FirstChildElement("setting");
while (setting)
{
const CGUIControl* control = GetControl(controlId);
@@ -763,5 +718,3 @@ void CGUIDialogPluginSettings::SetDefaults()
EnableControls();
}
-CURL CGUIDialogPluginSettings::m_url;
-
diff --git a/xbmc/GUIDialogPluginSettings.h b/xbmc/GUIDialogAddonSettings.h
index 5a3253d0e8..917f3589ba 100644
--- a/xbmc/GUIDialogPluginSettings.h
+++ b/xbmc/GUIDialogAddonSettings.h
@@ -1,6 +1,4 @@
-#ifndef GUIDIALOG_PLUGIN_SETTINGS_
-#define GUIDIALOG_PLUGIN_SETTINGS_
-
+#pragma once
/*
* Copyright (C) 2005-2008 Team XBMC
* http://www.xbmc.org
@@ -23,19 +21,15 @@
*/
#include "GUIDialogBoxBase.h"
-#include "PluginSettings.h"
-
-struct SScraperInfo;
+#include "Addon.h"
-class CGUIDialogPluginSettings : public CGUIDialogBoxBase
+class CGUIDialogAddonSettings : public CGUIDialogBoxBase
{
public:
- CGUIDialogPluginSettings(void);
- virtual ~CGUIDialogPluginSettings(void);
+ CGUIDialogAddonSettings(void);
+ virtual ~CGUIDialogAddonSettings(void);
virtual bool OnMessage(CGUIMessage& message);
- static bool ShowAndGetInput(CURL& url);
- static bool ShowAndGetInput(SScraperInfo& info);
- static bool ShowAndGetInput(CStdString& path);
+ static bool ShowAndGetInput(const ADDON::AddonPtr &addon);
protected:
virtual void OnInitWindow();
@@ -49,12 +43,10 @@ private:
bool SaveSettings(void);
bool ShowVirtualKeyboard(int iControl);
- static CURL m_url;
bool TranslateSingleString(const CStdString &strCondition, std::vector<CStdString> &enableVec);
- CBasicSettings m_settings;
+ ADDON::AddonPtr m_addon;
CStdString m_strHeading;
std::map<CStdString,CStdString> m_buttonValues;
+ bool m_changed;
};
-#endif
-
diff --git a/xbmc/GUIDialogContentSettings.cpp b/xbmc/GUIDialogContentSettings.cpp
index d3009d609d..d46ed21113 100644
--- a/xbmc/GUIDialogContentSettings.cpp
+++ b/xbmc/GUIDialogContentSettings.cpp
@@ -20,31 +20,29 @@
*/
#include "GUIDialogContentSettings.h"
-#include "GUIDialogPluginSettings.h"
-#include "Util.h"
-#include "VideoDatabase.h"
-#include "VideoInfoScanner.h"
-#include "FileSystem/Directory.h"
-#include "FileSystem/MultiPathDirectory.h"
+#include "GUIDialogAddonSettings.h"
+#include "GUIDialogOK.h"
+#include "GUISettings.h"
#include "GUIWindowManager.h"
-#include "utils/ScraperParser.h"
+#include "utils/IAddon.h"
#include "FileItem.h"
+#include "VideoDatabase.h"
+#include "VideoInfoScanner.h"
#include "GUISettings.h"
-#include "LocalizeStrings.h"
-#include "LangCodeExpander.h"
#define CONTROL_CONTENT_TYPE 3
#define CONTROL_SCRAPER_LIST 4
#define CONTROL_SCRAPER_SETTINGS 6
#define CONTROL_START 30
-using namespace XFILE;
using namespace std;
+using namespace ADDON;
CGUIDialogContentSettings::CGUIDialogContentSettings(void)
: CGUIDialogSettings(WINDOW_DIALOG_CONTENT_SETTINGS, "DialogContentSettings.xml")
{
m_bNeedSave = false;
+ m_content = CONTENT_NONE;
m_vecItems = new CFileItemList;
}
@@ -65,313 +63,228 @@ bool CGUIDialogContentSettings::OnMessage(CGUIMessage &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);
+ CGUIMessage msg(GUI_MSG_ITEM_SELECTED,GetID(), CONTROL_CONTENT_TYPE);
g_windowManager.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.scraper"));
- CreateSettings();
- SetupPage();
- break;
- }
+ m_content = (CONTENT_TYPE) msg.GetParam1();
+ SetupPage();
}
if (iControl == CONTROL_SCRAPER_LIST)
{
- CGUIMessage msg(GUI_MSG_ITEM_SELECTED,GetID(),CONTROL_SCRAPER_LIST);
+ CGUIMessage msg(GUI_MSG_ITEM_SELECTED,GetID(), CONTROL_SCRAPER_LIST);
g_windowManager.SendMessage(msg);
int iSelected = msg.GetParam1();
+ AddonPtr last = m_scraper;
+ m_scraper = m_scrapers[m_content][iSelected];
+
+ if (!last && m_scraper)
+ SetupPage();
- m_info = m_scrapers[m_info.strContent][iSelected];
- FillListControl();
- SET_CONTROL_FOCUS(30,0);
+ m_bNeedSave = m_scraper != last;
+ CONTROL_ENABLE_ON_CONDITION(CONTROL_SCRAPER_SETTINGS, m_scraper->HasSettings());
+ SET_CONTROL_FOCUS(CONTROL_START,0);
}
- CStdString scraperPath = GetScraperDirectory(m_info);
if (iControl == CONTROL_SCRAPER_SETTINGS)
{
- if (!scraperPath.IsEmpty() && m_info.settings.LoadSettingsXML(scraperPath + m_info.strPath))
- {
- CGUIDialogPluginSettings::ShowAndGetInput(m_info);
- m_bNeedSave = true;
- return true;
- }
- return false;
+ m_bNeedSave = CGUIDialogAddonSettings::ShowAndGetInput(m_scraper);
+ return m_bNeedSave;
}
- CScraperParser parser;
- CStdString strPath;
- if (!m_info.strContent.IsEmpty())
- strPath=scraperPath;
- if (!strPath.IsEmpty() && parser.Load(strPath + m_info.strPath)
- && parser.HasFunction("GetSettings"))
- CONTROL_ENABLE(CONTROL_SCRAPER_SETTINGS);
- else
- CONTROL_DISABLE(CONTROL_SCRAPER_SETTINGS);
- break;
}
return CGUIDialogSettings::OnMessage(message);
}
void CGUIDialogContentSettings::OnWindowLoaded()
{
+ FillContentTypes();
CGUIDialogSettings::OnWindowLoaded();
+}
- CFileItemList items;
- CStdString baseDir = GetScraperDirectory(m_info);
- if (!baseDir.IsEmpty())
- CDirectory::GetDirectory(baseDir, items, ".xml", false);
-
- for (int i=0;i<items.Size();++i)
+void CGUIDialogContentSettings::SetupPage()
+{
+ if (m_content == CONTENT_NONE)
{
- CScraperParser parser;
- if (parser.Load(items[i]->m_strPath))
- {
- bool IsDefaultScraper = false;
-
- SScraperInfo info;
- info.strTitle = parser.GetName();
- info.strPath = CUtil::GetFileName(items[i]->m_strPath);
- info.strThumb = parser.GetThumb();
- info.strContent = parser.GetContent();
- info.strLanguage = parser.GetLanguage();
- info.settings = m_scraperSettings;
-
- if ( info.strPath == g_guiSettings.GetString("musiclibrary.scraper")
- || info.strPath == g_guiSettings.GetString("scrapers.moviedefault")
- || info.strPath == g_guiSettings.GetString("scrapers.tvshowdefault")
- || info.strPath == g_guiSettings.GetString("scrapers.musicvideodefault"))
- {
- IsDefaultScraper = true;
- }
-
- map<CStdString,vector<SScraperInfo> >::iterator iter=m_scrapers.find(info.strContent);
- if (iter != m_scrapers.end())
- {
- if (IsDefaultScraper)
- iter->second.insert(iter->second.begin(),info);
- else
- iter->second.push_back(info);
- }
-
- vector<SScraperInfo> vec;
- vec.push_back(info);
- m_scrapers.insert(make_pair(info.strContent,vec));
- }
+ m_bShowScanSettings = false;
+ SET_CONTROL_HIDDEN(CONTROL_SCRAPER_LIST);
+ CONTROL_DISABLE(CONTROL_SCRAPER_SETTINGS);
}
-
- // now select the correct scraper
- if (!m_info.strContent.IsEmpty())
+ else
{
- map<CStdString,vector<SScraperInfo> >::iterator iter = m_scrapers.find(m_info.strContent);
- if (iter != m_scrapers.end())
+ FillListControl();
+ SET_CONTROL_VISIBLE(CONTROL_SCRAPER_LIST);
+ if (m_scraper)
{
- for (vector<SScraperInfo>::iterator iter2 = iter->second.begin();iter2 != iter->second.end();++iter2)
- {
- if (iter2->strPath == m_info.strPath)
- {
- m_info = *iter2;
- break;
- }
- }
+ m_bShowScanSettings = true;
+ if (m_scraper->Supports(m_content) && m_scraper->HasSettings())
+ CONTROL_ENABLE(CONTROL_SCRAPER_SETTINGS);
}
+ else
+ CONTROL_DISABLE(CONTROL_SCRAPER_SETTINGS);
}
-}
-void CGUIDialogContentSettings::SetupPage()
-{
+ CreateSettings();
CGUIDialogSettings::SetupPage();
+ SET_CONTROL_VISIBLE(CONTROL_CONTENT_TYPE);
+}
- CGUIMessage msg(GUI_MSG_LABEL_RESET,GetID(),CONTROL_CONTENT_TYPE);
- g_windowManager.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_windowManager.SendMessage(msg2);
- }
-
- if (m_scrapers.find("movies") != m_scrapers.end())
+void CGUIDialogContentSettings::CreateSettings()
+{
+ // crappy setting dependencies part 1
+ m_settings.clear();
+ switch (m_content)
{
- msg2.SetLabel(g_localizeStrings.Get(20342));
- msg2.SetParam1(1);
- g_windowManager.SendMessage(msg2);
- if (m_info.strContent.Equals("movies"))
+ case CONTENT_TVSHOWS:
{
- SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,g_localizeStrings.Get(20342));
- CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 1);
+ AddBool(1,20345,&m_bRunScan, m_bShowScanSettings);
+ AddBool(2,20379,&m_bSingleItem, m_bShowScanSettings);
+ AddBool(3,20432,&m_bNoUpdate, m_bShowScanSettings);
}
- }
-
- if (m_scrapers.find("tvshows") != m_scrapers.end())
- {
- msg2.SetLabel(g_localizeStrings.Get(20343));
- msg2.SetParam1(2);
- g_windowManager.SendMessage(msg2);
- if (m_info.strContent.Equals("tvshows"))
+ break;
+ case CONTENT_MOVIES:
{
- CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 2);
+ AddBool(1,20345,&m_bRunScan, m_bShowScanSettings);
+ AddBool(2,20330,&m_bUseDirNames, m_bShowScanSettings);
+ AddBool(3,20346,&m_bScanRecursive, m_bShowScanSettings && ((m_bUseDirNames && !m_bSingleItem) || !m_bUseDirNames));
+ AddBool(4,20383,&m_bSingleItem, m_bShowScanSettings && (m_bUseDirNames && !m_bScanRecursive));
+ AddBool(5,20432,&m_bNoUpdate, m_bShowScanSettings);
}
- }
- if (m_scrapers.find("musicvideos") != m_scrapers.end())
- {
- msg2.SetLabel(g_localizeStrings.Get(20389));
- msg2.SetParam1(3);
- g_windowManager.SendMessage(msg2);
- if (m_info.strContent.Equals("musicvideos"))
+ break;
+ case CONTENT_MUSICVIDEOS:
{
- SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,g_localizeStrings.Get(20389));
- CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 3);
+ AddBool(1,20345,&m_bRunScan, m_bShowScanSettings);
+ AddBool(2,20346,&m_bScanRecursive, m_bShowScanSettings);
+ AddBool(3,20432,&m_bNoUpdate, m_bShowScanSettings);
}
- }
- if (m_scrapers.find("albums") != m_scrapers.end())
- {
- msg2.SetLabel(m_strContentType);
- msg2.SetParam1(4);
- g_windowManager.SendMessage(msg2);
- if (m_info.strContent.Equals("albums"))
+ break;
+ case CONTENT_ALBUMS:
{
- SET_CONTROL_LABEL(CONTROL_CONTENT_TYPE,m_strContentType);
- CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, 3);
+ AddBool(1,20345,&m_bRunScan, m_bShowScanSettings);
+ }
+ break;
+ case CONTENT_NONE:
+ default:
+ {
+ AddBool(1,20380,&m_bExclude, !m_bShowScanSettings);
}
}
- 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()
+void CGUIDialogContentSettings::OnSettingChanged(SettingInfo &setting)
{
- // clear out any old settings
- m_settings.clear();
+ CreateSettings();
- 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"))
+ // crappy setting dependencies part 2
+ if (setting.id == 2) // use dir names
{
- AddBool(1,20345,&m_bRunScan);
- AddBool(2,20379,&m_bSingleItem);
- AddBool(3,20432,&m_bUpdate);
+ m_bSingleItem = false;
+ UpdateSetting(3); // scan recursively
+ UpdateSetting(4); // single item
}
- if (m_info.strContent.Equals("musicvideos"))
+ else if (setting.id == 3)
{
- AddBool(1,20345,&m_bRunScan);
- AddBool(2,20346,&m_bScanRecursive);
- AddBool(3,20432,&m_bUpdate);
+ m_bSingleItem = false;
+ UpdateSetting(4);
}
- if (m_info.strContent.Equals("albums"))
+ else if (setting.id == 4)
{
- AddBool(1,20345,&m_bRunScan);
+ m_bScanRecursive = false;
+ UpdateSetting(3);
}
+
+ m_bNeedSave = true;
+}
+
+void CGUIDialogContentSettings::OnOkay()
+{ // watch for content change, but same scraper
+ if (m_content != m_origContent)
+ m_bNeedSave = true;
}
-void CGUIDialogContentSettings::OnSettingChanged(unsigned int num)
+void CGUIDialogContentSettings::OnCancel()
{
- // setting has changed - update anything that needs it
- if (num >= m_settings.size())
- return;
+ m_bNeedSave = false;
+}
- SettingInfo &setting = m_settings.at(num);
- OnSettingChanged(setting);
+void CGUIDialogContentSettings::OnInitWindow()
+{
+ m_bNeedSave = false;
+ CGUIDialogSettings::OnInitWindow();
}
-void CGUIDialogContentSettings::OnSettingChanged(SettingInfo &setting)
+void CGUIDialogContentSettings::FillContentTypes()
{
- // check and update anything that needs it
- if (setting.id == 1 || setting.id == 2)
+ CGUIMessage msg(GUI_MSG_LABEL_RESET,GetID(),CONTROL_CONTENT_TYPE);
+ g_windowManager.SendMessage(msg);
+
+ if (m_content == CONTENT_ALBUMS || m_content == CONTENT_ARTISTS)
{
- CreateSettings();
- UpdateSetting(1);
- UpdateSetting(2);
- UpdateSetting(3);
- UpdateSetting(4);
- UpdateSetting(5);
+ FillContentTypes(CONTENT_ALBUMS);
+ FillContentTypes(CONTENT_ARTISTS);
+ }
+ else
+ {
+ FillContentTypes(CONTENT_MOVIES);
+ FillContentTypes(CONTENT_TVSHOWS);
+ FillContentTypes(CONTENT_MUSICVIDEOS);
+
+ // add 'None' to spinner
+ CGUIMessage msg2(GUI_MSG_LABEL_ADD,GetID(),CONTROL_CONTENT_TYPE);
+ msg2.SetLabel(TranslateContent(CONTENT_NONE, true));
+ msg2.SetParam1((int) CONTENT_NONE);
+ g_windowManager.SendMessage(msg2);
}
- m_bNeedSave = true;
+ CONTROL_SELECT_ITEM(CONTROL_CONTENT_TYPE, (int) m_content);
}
-void CGUIDialogContentSettings::OnCancel()
+void CGUIDialogContentSettings::FillContentTypes(const CONTENT_TYPE &content)
{
- m_bNeedSave = false;
-}
+ // grab all scrapers which support this content-type
+ VECADDONS addons;
+ if (!CAddonMgr::Get()->GetAddons(ADDON_SCRAPER, addons, content))
+ return;
-void CGUIDialogContentSettings::OnInitWindow()
-{
- m_bNeedSave = false;
+ AddonPtr addon;
+ CStdString defaultUUID;
+ CAddonMgr::Get()->GetDefault(ADDON_SCRAPER, addon, content);
+ if (addon)
+ defaultUUID = addon->UUID();
- CGUIDialogSettings::OnInitWindow();
- SET_CONTROL_FOCUS(CONTROL_CONTENT_TYPE,0);
+ for (IVECADDONS it = addons.begin(); it != addons.end(); it++)
+ {
+ bool isDefault = ((*it)->UUID() == defaultUUID);
+ map<CONTENT_TYPE,VECADDONS>::iterator iter=m_scrapers.find(content);
+
+ AddonPtr scraper = (*it)->Clone((*it));
+
+ if (m_scraper && m_scraper->Parent() && m_scraper->Parent()->UUID() == (*it)->UUID())
+ { // don't overwrite preconfigured scraper
+ scraper = m_scraper;
+ }
+
+ if (iter != m_scrapers.end())
+ {
+ if (isDefault)
+ iter->second.insert(iter->second.begin(), scraper);
+ else
+ iter->second.push_back(scraper);
+ }
+ else
+ {
+ VECADDONS vec;
+ vec.push_back(scraper);
+ m_scrapers.insert(make_pair(content,vec));
+ }
+ }
+
+ // add CONTENT type to spinner
+ CGUIMessage msg(GUI_MSG_LABEL_ADD,GetID(),CONTROL_CONTENT_TYPE);
+ msg.SetLabel(TranslateContent(content, true));
+ msg.SetParam1((int) content);
+ g_windowManager.SendMessage(msg);
}
void CGUIDialogContentSettings::FillListControl()
@@ -381,25 +294,16 @@ void CGUIDialogContentSettings::FillListControl()
int iIndex=0;
int selectedIndex = 0;
m_vecItems->Clear();
- for (vector<SScraperInfo>::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;
-
- CStdString strLanguage;
-
- if (iter->strLanguage.Equals("multi"))
- strLanguage = g_localizeStrings.Get(21418);
- else
- g_LangCodeExpander.Lookup(strLanguage, iter->strLanguage);
-
- item->SetLabel(iter->strTitle + " (" + strLanguage + ")");
- CStdString baseDir = GetScraperDirectory(*iter);
- if (!baseDir.IsEmpty())
- item->SetThumbnailImage(baseDir + iter->strThumb);
+ if (m_scrapers.size() == 0)
+ return;
- if (iter->strPath.Equals(m_info.strPath))
+ for (IVECADDONS iter=m_scrapers.find(m_content)->second.begin();iter!=m_scrapers.find(m_content)->second.end();++iter)
+ {
+ CFileItemPtr item(new CFileItem((*iter)->Name()));
+ item->m_strPath = (*iter)->UUID();
+ item->SetThumbnailImage((*iter)->Icon());
+ if (m_scraper && (*iter)->UUID() == m_scraper->UUID())
{
item->Select(true);
selectedIndex = iIndex;
@@ -416,7 +320,7 @@ void CGUIDialogContentSettings::FillListControl()
CFileItemPtr CGUIDialogContentSettings::GetCurrentListItem(int offset)
{
int currentItem = -1;
- if( m_info.strContent.IsEmpty())
+ if(m_bExclude)
return CFileItemPtr();
for (int i=0;i<m_vecItems->Size();++i )
{
@@ -435,7 +339,7 @@ CFileItemPtr CGUIDialogContentSettings::GetCurrentListItem(int offset)
return m_vecItems->Get(item);
}
-bool CGUIDialogContentSettings::ShowForDirectory(const CStdString& strDirectory, SScraperInfo& scraper, VIDEO::SScanSettings& settings, bool& bRunScan)
+bool CGUIDialogContentSettings::ShowForDirectory(const CStdString& strDirectory, ADDON::ScraperPtr& scraper, VIDEO::SScanSettings& settings, bool& bRunScan)
{
CVideoDatabase database;
database.Open();
@@ -448,128 +352,91 @@ bool CGUIDialogContentSettings::ShowForDirectory(const CStdString& strDirectory,
return bResult;
}
-bool CGUIDialogContentSettings::Show(SScraperInfo& scraper, bool& bRunScan, int iLabel)
+bool CGUIDialogContentSettings::Show(ADDON::ScraperPtr& scraper, bool& bRunScan, CONTENT_TYPE musicContext/*=CONTENT_NONE*/)
{
VIDEO::SScanSettings dummy;
- dummy.recurse = -1;
- dummy.parent_name = false;
- dummy.parent_name_root = false;
- dummy.noupdate = false;
- return Show(scraper,dummy,bRunScan,iLabel);
+ return Show(scraper,dummy,bRunScan,musicContext);
}
-bool CGUIDialogContentSettings::Show(SScraperInfo& scraper, VIDEO::SScanSettings& settings, bool& bRunScan, int iLabel)
+bool CGUIDialogContentSettings::Show(ADDON::ScraperPtr& scraper, VIDEO::SScanSettings& settings, bool& bRunScan, CONTENT_TYPE musicContext/*=CONTENT_NONE*/)
{
CGUIDialogContentSettings *dialog = (CGUIDialogContentSettings *)g_windowManager.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;
+ if (musicContext != CONTENT_NONE)
+ {
+ dialog->m_content = musicContext;
+ }
+ if (scraper)
+ {
+ dialog->m_content = scraper->Content();
+ dialog->m_origContent = dialog->m_content;
+ dialog->m_scraper = scraper;
+ }
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_bExclude = settings.exclude;
dialog->m_bSingleItem = settings.parent_name_root;
+ dialog->m_bNoUpdate = settings.noupdate;
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"))
+ scraper = boost::dynamic_pointer_cast<CScraper>(dialog->m_scraper);
+ CONTENT_TYPE content = dialog->m_content;
+ if (!scraper || content == CONTENT_NONE)
{
- settings.parent_name = dialog->m_bSingleItem;
- settings.parent_name_root = dialog->m_bSingleItem;
- settings.recurse = 0;
-
- bRunScan = dialog->m_bRunScan;
+ scraper.reset();
+ bRunScan = false;
+ settings.exclude = dialog->m_bExclude;
}
- else if (scraper.strContent.Equals("movies"))
+ else
{
- if (dialog->m_bUseDirNames)
- {
- settings.parent_name = true;
- settings.parent_name_root = false;
- settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 1;
+ settings.exclude = false;
+ settings.noupdate = dialog->m_bNoUpdate;
+ bRunScan = dialog->m_bRunScan;
+ scraper->m_pathContent = content;
- if (dialog->m_bSingleItem)
+ if (content == CONTENT_TVSHOWS)
+ {
+ settings.parent_name = dialog->m_bSingleItem;
+ settings.parent_name_root = dialog->m_bSingleItem;
+ settings.recurse = 0;
+ }
+ else if (content == CONTENT_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_root = true;
- settings.recurse = 0;
+ settings.parent_name = false;
+ settings.parent_name_root = false;
+ settings.recurse = dialog->m_bScanRecursive ? INT_MAX : 0;
}
}
- else
+ else if (content == CONTENT_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("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.IsEmpty() || scraper.strContent.Equals("None") )
- {
- if (dialog->m_bExclude)
- scraper.strContent = "None";
- else
- scraper.strContent = "";
-
- bRunScan = false;
- }
-
- CStdString baseDir = GetScraperDirectory(scraper);
- if (!baseDir.IsEmpty() && (!scraper.settings.GetPluginRoot() || scraper.settings.GetSettings().IsEmpty()))
- { // load default scraper settings
- if (scraper.settings.LoadSettingsXML(baseDir + 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[strType].size();++i)
- {
- if (m_scrapers[strType][i].strPath.Equals(strDefault))
- {
- result = m_scrapers[strType][i];
- break;
- }
- }
-
- return result;
-}
-
-CStdString CGUIDialogContentSettings::GetScraperDirectory(const SScraperInfo &scraper)
-{
- CStdString dir = "video/";
- if (scraper.strContent.Equals("albums"))
- dir = "music/";
- else if (scraper.strContent.Equals("None"))
- return "";
- return "special://xbmc/system/scrapers/" + dir;
+ dialog->m_scraper.reset();
+ dialog->m_content = dialog->m_origContent = CONTENT_NONE;
+ return dialog->m_bNeedSave;
}
diff --git a/xbmc/GUIDialogContentSettings.h b/xbmc/GUIDialogContentSettings.h
index fc64cacc6c..22ff4d3fdd 100644
--- a/xbmc/GUIDialogContentSettings.h
+++ b/xbmc/GUIDialogContentSettings.h
@@ -22,7 +22,9 @@
*/
#include "GUIDialogSettings.h"
-#include "ScraperSettings.h"
+#include "Scraper.h"
+#include "utils/AddonManager.h"
+#include <vector>
namespace VIDEO
{
@@ -35,38 +37,41 @@ class CGUIDialogContentSettings : public CGUIDialogSettings
public:
CGUIDialogContentSettings(void);
virtual ~CGUIDialogContentSettings(void);
- virtual bool OnMessage(CGUIMessage &message);
+ virtual bool OnMessage(CGUIMessage& message);
- static bool Show(SScraperInfo& scraper, bool& bRunScan, int iLabel=-1);
- static bool Show(SScraperInfo& scraper, VIDEO::SScanSettings& settings, bool& bRunScan, int iLabel=-1);
- static bool ShowForDirectory(const CStdString& strDirectory, SScraperInfo& scraper, VIDEO::SScanSettings& settings, bool& bRunScan);
+ static bool Show(ADDON::ScraperPtr& scraper, bool& bRunScan, CONTENT_TYPE musicContext = CONTENT_NONE);
+ static bool Show(ADDON::ScraperPtr& scraper, VIDEO::SScanSettings& settings, bool& bRunScan, CONTENT_TYPE musicContext = CONTENT_NONE);
+ static bool ShowForDirectory(const CStdString& strDirectory, ADDON::ScraperPtr& scraper, VIDEO::SScanSettings& settings, bool& bRunScan);
virtual bool HasListItems() const { return true; };
virtual CFileItemPtr GetCurrentListItem(int offset = 0);
protected:
+ virtual void OnOkay();
virtual void OnCancel();
virtual void OnWindowLoaded();
virtual void OnInitWindow();
virtual void SetupPage();
virtual void CreateSettings();
+ void FillContentTypes();
+ void FillContentTypes(const CONTENT_TYPE& content);
+ void AddContentType(const CONTENT_TYPE& content);
void FillListControl();
- void OnSettingChanged(unsigned int setting);
- virtual void OnSettingChanged(SettingInfo &setting);
- SScraperInfo FindDefault(const CStdString& strType, const CStdString& strDefault);
- static CStdString GetScraperDirectory(const SScraperInfo& scraper);
+ virtual void OnSettingChanged(SettingInfo& setting);
bool m_bNeedSave;
+ bool m_bShowScanSettings;
bool m_bRunScan;
bool m_bScanRecursive;
bool m_bUseDirNames;
bool m_bSingleItem;
bool m_bExclude;
- bool m_bUpdate;
- std::map<CStdString,std::vector<SScraperInfo> > m_scrapers; // key = content type
+ bool m_bNoUpdate;
+ std::map<CONTENT_TYPE, ADDON::VECADDONS> m_scrapers;
CFileItemList* m_vecItems;
- SScraperInfo m_info;
- CScraperSettings m_scraperSettings; // needed so we have a basis
- CStdString m_strContentType; // used for artist/albums
+ CStdString m_strContentType;
+ ADDON::AddonPtr m_scraper;
+ CStdString m_defaultScraper;
+ CONTENT_TYPE m_content;
+ CONTENT_TYPE m_origContent;
};
-
diff --git a/xbmc/GUIDialogContextMenu.cpp b/xbmc/GUIDialogContextMenu.cpp
index b144d70484..54bc46b7ea 100644
--- a/xbmc/GUIDialogContextMenu.cpp
+++ b/xbmc/GUIDialogContextMenu.cpp
@@ -36,11 +36,13 @@
#include "MediaManager.h"
#include "GUIWindowManager.h"
#include "GUIDialogYesNo.h"
+#include "utils/AddonManager.h"
#include "FileItem.h"
#include "FileSystem/File.h"
#include "Picture.h"
#include "Settings.h"
#include "LocalizeStrings.h"
+#include "StringUtils.h"
#ifdef _WIN32
#include "WIN32Util.h"
@@ -289,11 +291,23 @@ void CGUIDialogContextMenu::GetContextButtons(const CStdString &type, const CFil
{
if (share)
{
- if (!share->m_ignore)
+ // Note. from now on, remove source & disable plugin should mean the same thing
+ //TODO might be smart to also combine editing source & plugin settings into one concept/dialog
+
+ CURL url(share->strPath);
+ bool isUUID = StringUtils::ValidateUUID(url.GetHostName());
+ if (!share->m_ignore && !isUUID)
buttons.Add(CONTEXT_BUTTON_EDIT_SOURCE, 1027); // Edit Source
+ else
+ {
+ ADDON::AddonPtr plugin;
+ if (ADDON::CAddonMgr::Get()->GetAddon(ADDON::ADDON_PLUGIN, url.GetHostName(), plugin))
+ if (plugin->HasSettings())
+ buttons.Add(CONTEXT_BUTTON_PLUGIN_SETTINGS, 1045); // Plugin Settings
+ }
buttons.Add(CONTEXT_BUTTON_SET_DEFAULT, 13335); // Set as Default
if (!share->m_ignore)
- buttons.Add(CONTEXT_BUTTON_REMOVE_SOURCE, 522); // Remove Source
+ buttons.Add(CONTEXT_BUTTON_REMOVE_SOURCE, 522); // Remove Source / disable plugin
buttons.Add(CONTEXT_BUTTON_SET_THUMB, 20019);
}
@@ -383,6 +397,7 @@ bool CGUIDialogContextMenu::OnContextButton(const CStdString &type, const CFileI
return CGUIDialogMediaSource::ShowAndEditMediaSource(type, *share);
case CONTEXT_BUTTON_REMOVE_SOURCE:
+ {
if (g_settings.m_iLastLoadedProfileIndex == 0)
{
if (!g_passwordManager.IsMasterLockUnlocked(true))
@@ -395,8 +410,14 @@ bool CGUIDialogContextMenu::OnContextButton(const CStdString &type, const CFileI
if (g_settings.m_vecProfiles[g_settings.m_iLastLoadedProfileIndex].canWriteSources() && !g_passwordManager.IsProfileLockUnlocked())
return false;
}
- // prompt user if they want to really delete the source
- if (CGUIDialogYesNo::ShowAndGetInput(751, 0, 750, 0))
+ // prompt user if they want to really delete the source/disable the plugin
+ bool yes(false);
+ bool plugin = item->IsPlugin();
+ if (plugin)
+ yes = CGUIDialogYesNo::ShowAndGetInput(24009, 24010, 24011, 0);
+ else
+ yes = CGUIDialogYesNo::ShowAndGetInput(751, 0, 750, 0);
+ if (yes)
{ // check default before we delete, as deletion will kill the share object
CStdString defaultSource(GetDefaultShareNameByType(type));
if (!defaultSource.IsEmpty())
@@ -404,13 +425,16 @@ bool CGUIDialogContextMenu::OnContextButton(const CStdString &type, const CFileI
if (share->strName.Equals(defaultSource))
ClearDefault(type);
}
-
- // delete this share
- g_settings.DeleteSource(type, share->strName, share->strPath);
- return true;
+ if (plugin)
+ {
+ CURL path(share->strPath);
+ ADDON::CAddonMgr::Get()->DisableAddon(path.GetHostName());
+ }
+ else
+ g_settings.DeleteSource(type, share->strName, share->strPath);
}
- break;
-
+ return true;
+ }
case CONTEXT_BUTTON_SET_DEFAULT:
if (g_settings.m_vecProfiles[g_settings.m_iLastLoadedProfileIndex].canWriteSources() && !g_passwordManager.IsProfileLockUnlocked())
return false;
diff --git a/xbmc/GUIDialogLockSettings.cpp b/xbmc/GUIDialogLockSettings.cpp
index ed1bee55a7..e52b5db882 100644
--- a/xbmc/GUIDialogLockSettings.cpp
+++ b/xbmc/GUIDialogLockSettings.cpp
@@ -116,6 +116,7 @@ void CGUIDialogLockSettings::CreateSettings()
AddBool(6,20041,&m_bLockPrograms);
AddBool(7,20042,&m_bLockFiles);
AddBool(8,20043,&m_bLockSettings);
+ AddBool(9,24090,&m_bLockAddOnManager);
EnableDetails(m_iLock != LOCK_MODE_EVERYONE);
}
}
@@ -236,10 +237,10 @@ bool CGUIDialogLockSettings::ShowAndGetUserAndPassword(CStdString& strUser, CStd
bool CGUIDialogLockSettings::ShowAndGetLock(LockType& iLockMode, CStdString& strPassword, int iHeader)
{
bool f;
- return ShowAndGetLock(iLockMode,strPassword,f,f,f,f,f,f,iHeader,false,false);
+ return ShowAndGetLock(iLockMode,strPassword,f,f,f,f,f,f,f,iHeader,false,false);
}
-bool CGUIDialogLockSettings::ShowAndGetLock(LockType& iLockMode, CStdString& strPassword, bool& bLockMusic, bool& bLockVideo, bool& bLockPictures, bool& bLockPrograms, bool& bLockFiles, bool& bLockSettings, int iButtonLabel, bool bConditional, bool bDetails)
+bool CGUIDialogLockSettings::ShowAndGetLock(LockType& iLockMode, CStdString& strPassword, bool& bLockMusic, bool& bLockVideo, bool& bLockPictures, bool& bLockPrograms, bool& bLockFiles, bool& bLockSettings, bool& bLockAddOnManager, int iButtonLabel, bool bConditional, bool bDetails)
{
CGUIDialogLockSettings *dialog = (CGUIDialogLockSettings *)g_windowManager.GetWindow(WINDOW_DIALOG_LOCK_SETTINGS);
if (!dialog) return false;
@@ -257,6 +258,7 @@ bool CGUIDialogLockSettings::ShowAndGetLock(LockType& iLockMode, CStdString& str
dialog->m_bLockPictures = bLockPictures;
dialog->m_bLockFiles = bLockFiles;
dialog->m_bLockSettings = bLockSettings;
+ dialog->m_bLockAddOnManager = bLockAddOnManager;
}
dialog->m_bDetails = bDetails;
dialog->DoModal();
@@ -279,6 +281,7 @@ bool CGUIDialogLockSettings::ShowAndGetLock(LockType& iLockMode, CStdString& str
bLockPictures = dialog->m_bLockPictures;
bLockFiles = dialog->m_bLockFiles;
bLockSettings = dialog->m_bLockSettings;
+ bLockAddOnManager = dialog->m_bLockAddOnManager;
}
return true;
}
diff --git a/xbmc/GUIDialogLockSettings.h b/xbmc/GUIDialogLockSettings.h
index cab22d8127..91432e16c9 100644
--- a/xbmc/GUIDialogLockSettings.h
+++ b/xbmc/GUIDialogLockSettings.h
@@ -31,7 +31,7 @@ public:
virtual ~CGUIDialogLockSettings(void);
virtual bool OnMessage(CGUIMessage &message);
static bool ShowAndGetLock(LockType& iLockMode, CStdString& strPassword, int iHeader=20091);
- static bool ShowAndGetLock(LockType& iLockMode, CStdString& strPassword, bool& bLockMusic, bool& bLockVideo, bool& bLockPictures, bool& bLockPrograms, bool& bLockFiles, bool& bLockSettings, int iButtonLabel=20091,bool bConditional=false, bool bDetails=true);
+ static bool ShowAndGetLock(LockType& iLockMode, CStdString& strPassword, bool& bLockMusic, bool& bLockVideo, bool& bLockPictures, bool& bLockPrograms, bool& bLockFiles, bool& bLockSettings, bool& bLockAddOnManager, int iButtonLabel=20091,bool bConditional=false, bool bDetails=true);
static bool ShowAndGetUserAndPassword(CStdString& strUser, CStdString& strPassword, const CStdString& strURL, bool *saveUserDetails);
protected:
virtual void OnCancel();
@@ -57,6 +57,7 @@ protected:
bool m_bLockFiles;
bool m_bLockSettings;
bool *m_saveUserDetails;
+ bool m_bLockAddOnManager;
};
diff --git a/xbmc/GUIDialogMediaSource.cpp b/xbmc/GUIDialogMediaSource.cpp
index 75bd7492ef..0f6ad08048 100644
--- a/xbmc/GUIDialogMediaSource.cpp
+++ b/xbmc/GUIDialogMediaSource.cpp
@@ -108,8 +108,6 @@ bool CGUIDialogMediaSource::OnMessage(CGUIMessage& message)
m_confirmed = false;
m_bRunScan = false;
m_bNameChanged=false;
- m_settings.parent_name = false;
- m_settings.recurse = 0;
UpdateButtons();
}
break;
@@ -166,7 +164,7 @@ bool CGUIDialogMediaSource::ShowAndAddMediaSource(const CStdString &type)
if (type == "video")
{
if (dialog->m_bRunScan)
- CGUIWindowVideoBase::OnScan(share.strPath,dialog->m_info,dialog->m_settings);
+ CGUIWindowVideoBase::OnScan(share.strPath,ADDON::ScraperPtr(),dialog->m_settings);
}
}
@@ -281,7 +279,7 @@ void CGUIDialogMediaSource::OnPathBrowse(int item)
extraShares.push_back(share1);
}
// add the plugins dir as needed
- if (CPluginDirectory::HasPlugins("music"))
+ if (ADDON::CAddonMgr::Get()->HasAddons(ADDON::ADDON_PLUGIN, CONTENT_ALBUMS))
{
share1.strPath = "plugin://music/";
share1.strName = g_localizeStrings.Get(1038); // Music Plugins
@@ -321,7 +319,7 @@ void CGUIDialogMediaSource::OnPathBrowse(int item)
extraShares.push_back(share1);
// add the plugins dir as needed
- if (CPluginDirectory::HasPlugins("video"))
+ if (ADDON::CAddonMgr::Get()->HasAddons(ADDON::ADDON_PLUGIN, CONTENT_MOVIES))
{
share1.strPath = "plugin://video/";
share1.strName = g_localizeStrings.Get(1037); // Video Plugins
@@ -352,7 +350,7 @@ void CGUIDialogMediaSource::OnPathBrowse(int item)
extraShares.push_back(share1);
// add the plugins dir as needed
- if (CPluginDirectory::HasPlugins("pictures"))
+ if (ADDON::CAddonMgr::Get()->HasAddons(ADDON::ADDON_PLUGIN, CONTENT_PICTURES))
{
share1.strPath = "plugin://pictures/";
share1.strName = g_localizeStrings.Get(1039); // Picture Plugins
@@ -361,7 +359,7 @@ void CGUIDialogMediaSource::OnPathBrowse(int item)
}
else if (m_type == "programs")
{
- if (CPluginDirectory::HasPlugins("programs"))
+ if (ADDON::CAddonMgr::Get()->HasAddons(ADDON::ADDON_PLUGIN, CONTENT_PROGRAMS))
{
CMediaSource share2;
share2.strPath = "plugin://programs/";
@@ -421,7 +419,7 @@ void CGUIDialogMediaSource::OnOK()
if (share.strPath.Left(9).Equals("plugin://"))
{
CStdString strPath=share.strPath;
- strPath.Replace("plugin://","special://home/plugins/");
+ strPath.Replace("plugin://","special://home/addons/plugins/");
CFileItem item(strPath,true);
item.SetCachedProgramThumb();
if (!item.HasThumbnail())
diff --git a/xbmc/GUIDialogMediaSource.h b/xbmc/GUIDialogMediaSource.h
index 84f7a62933..7c9082ba6e 100644
--- a/xbmc/GUIDialogMediaSource.h
+++ b/xbmc/GUIDialogMediaSource.h
@@ -61,7 +61,7 @@ protected:
CStdString m_name;
CFileItemList* m_paths;
bool m_confirmed;
- SScraperInfo m_info;
+ ADDON::ScraperPtr m_info;
bool m_bRunScan;
bool m_bNameChanged;
diff --git a/xbmc/GUIDialogMusicOSD.cpp b/xbmc/GUIDialogMusicOSD.cpp
index f1711ecc31..f64e65e144 100644
--- a/xbmc/GUIDialogMusicOSD.cpp
+++ b/xbmc/GUIDialogMusicOSD.cpp
@@ -30,6 +30,8 @@
#define CONTROL_LOCK_BUTTON 501
#define CONTROL_VIS_CHOOSER 503
+using ADDON::CVisualisation;
+
CGUIDialogMusicOSD::CGUIDialogMusicOSD(void)
: CGUIDialog(WINDOW_DIALOG_MUSIC_OSD, "MusicOSD.xml")
{
@@ -55,8 +57,7 @@ bool CGUIDialogMusicOSD::OnMessage(CGUIMessage &message)
if (msg.GetParam1() == 0)
g_guiSettings.SetString("musicplayer.visualisation", "None");
else
- g_guiSettings.SetString("musicplayer.visualisation",
- CVisualisation::GetCombinedName( strLabel ));
+ g_guiSettings.SetString("musicplayer.visualisation", strLabel);
// hide the control and reset focus
SET_CONTROL_HIDDEN(CONTROL_VIS_CHOOSER);
SET_CONTROL_FOCUS(CONTROL_VIS_BUTTON, 0);
diff --git a/xbmc/GUIDialogMusicOSD.h b/xbmc/GUIDialogMusicOSD.h
index b3654a20d2..a644684ea3 100644
--- a/xbmc/GUIDialogMusicOSD.h
+++ b/xbmc/GUIDialogMusicOSD.h
@@ -22,7 +22,11 @@
*/
#include "GUIDialog.h"
-#include "visualizations/Visualisation.h"
+
+namespace ADDON
+{
+ class CVisualisation;
+}
class CGUIDialogMusicOSD :
public CGUIDialog
@@ -36,5 +40,5 @@ public:
protected:
virtual bool OnMouseEvent(const CPoint &point, const CMouseEvent &event);
virtual void OnInitWindow();
- CVisualisation *m_pVisualisation;
+ ADDON::CVisualisation *m_pVisualisation;
};
diff --git a/xbmc/GUIDialogProfileSettings.cpp b/xbmc/GUIDialogProfileSettings.cpp
index 7a026397eb..f11582bd00 100644
--- a/xbmc/GUIDialogProfileSettings.cpp
+++ b/xbmc/GUIDialogProfileSettings.cpp
@@ -263,7 +263,7 @@ void CGUIDialogProfileSettings::OnSettingChanged(SettingInfo &setting)
if (g_settings.m_vecProfiles[0].getLockMode() == LOCK_MODE_EVERYONE)
return;
}
- if (CGUIDialogLockSettings::ShowAndGetLock(m_iLockMode,m_strLockCode,m_bLockMusic,m_bLockVideo,m_bLockPictures,m_bLockPrograms,m_bLockFiles,m_bLockSettings,m_bIsDefault?12360:20068,g_settings.m_vecProfiles[0].getLockMode() == LOCK_MODE_EVERYONE || m_bIsDefault))
+ if (CGUIDialogLockSettings::ShowAndGetLock(m_iLockMode,m_strLockCode,m_bLockMusic,m_bLockVideo,m_bLockPictures,m_bLockPrograms,m_bLockFiles,m_bLockSettings,m_bLockAddOnManager,m_bIsDefault?12360:20068,g_settings.m_vecProfiles[0].getLockMode() == LOCK_MODE_EVERYONE || m_bIsDefault))
m_bNeedSave = true;
}
else
@@ -300,6 +300,7 @@ bool CGUIDialogProfileSettings::ShowForProfile(unsigned int iProfile, bool bDeta
dialog->m_iDbMode = 2;
dialog->m_iLockMode = LOCK_MODE_EVERYONE;
dialog->m_iSourcesMode = 2;
+ dialog->m_bLockAddOnManager = true;
dialog->m_bLockSettings = true;
dialog->m_bLockMusic = false;
dialog->m_bLockVideo = false;
@@ -332,6 +333,7 @@ bool CGUIDialogProfileSettings::ShowForProfile(unsigned int iProfile, bool bDeta
dialog->m_bLockPrograms = g_settings.m_vecProfiles[iProfile].programsLocked();
dialog->m_bLockPictures = g_settings.m_vecProfiles[iProfile].picturesLocked();
dialog->m_bLockSettings = g_settings.m_vecProfiles[iProfile].settingsLocked();
+ dialog->m_bLockAddOnManager = g_settings.m_vecProfiles[iProfile].addonmanagerLocked();
dialog->m_bIsNewUser = false;
}
dialog->DoModal();
@@ -421,6 +423,7 @@ bool CGUIDialogProfileSettings::ShowForProfile(unsigned int iProfile, bool bDeta
g_settings.m_vecProfiles[iProfile].setMusicLocked(dialog->m_bLockMusic);
g_settings.m_vecProfiles[iProfile].setVideoLocked(dialog->m_bLockVideo);
g_settings.m_vecProfiles[iProfile].setSettingsLocked(dialog->m_bLockSettings);
+ g_settings.m_vecProfiles[iProfile].setAddonManagerLocked(dialog->m_bLockAddOnManager);
g_settings.m_vecProfiles[iProfile].setFilesLocked(dialog->m_bLockFiles);
g_settings.m_vecProfiles[iProfile].setPicturesLocked(dialog->m_bLockPictures);
g_settings.m_vecProfiles[iProfile].setProgramsLocked(dialog->m_bLockPrograms);
diff --git a/xbmc/GUIDialogProfileSettings.h b/xbmc/GUIDialogProfileSettings.h
index 48bfd9867e..470dabcab5 100644
--- a/xbmc/GUIDialogProfileSettings.h
+++ b/xbmc/GUIDialogProfileSettings.h
@@ -60,6 +60,7 @@ protected:
bool m_bLockFiles;
bool m_bLockPictures;
bool m_bLockPrograms;
+ bool m_bLockAddOnManager;
CStdString m_strDefaultImage;
};
diff --git a/xbmc/GUIDialogVideoScan.cpp b/xbmc/GUIDialogVideoScan.cpp
index 6b023050b3..5295d02333 100644
--- a/xbmc/GUIDialogVideoScan.cpp
+++ b/xbmc/GUIDialogVideoScan.cpp
@@ -115,7 +115,7 @@ void CGUIDialogVideoScan::OnSetTitle(const CStdString& strTitle)
m_strTitle = strTitle;
}
-void CGUIDialogVideoScan::StartScanning(const CStdString& strDirectory, const SScraperInfo& info, const SScanSettings& settings, bool bUpdateAll)
+void CGUIDialogVideoScan::StartScanning(const CStdString& strDirectory, const ADDON::ScraperPtr& info, const SScanSettings& settings, bool bUpdateAll)
{
m_ScanState = PREPARING;
diff --git a/xbmc/GUIDialogVideoScan.h b/xbmc/GUIDialogVideoScan.h
index b0102afaf0..2bd8f0b12c 100644
--- a/xbmc/GUIDialogVideoScan.h
+++ b/xbmc/GUIDialogVideoScan.h
@@ -33,7 +33,7 @@ public:
virtual bool OnMessage(CGUIMessage& message);
virtual void FrameMove();
- void StartScanning(const CStdString& strDirectory, const SScraperInfo& info, const VIDEO::SScanSettings& settings, bool bUpdateAll);
+ void StartScanning(const CStdString& strDirectory, const ADDON::ScraperPtr& info, const VIDEO::SScanSettings& settings, bool bUpdateAll);
bool IsScanning();
void StopScanning();
diff --git a/xbmc/GUIDialogVisualisationPresetList.cpp b/xbmc/GUIDialogVisualisationPresetList.cpp
index 7a870f33fa..5c0bb95800 100644
--- a/xbmc/GUIDialogVisualisationPresetList.cpp
+++ b/xbmc/GUIDialogVisualisationPresetList.cpp
@@ -20,9 +20,9 @@
*/
#include "GUIDialogVisualisationPresetList.h"
+#include "visualizations/Visualisation.h"
#include "GUIWindowManager.h"
#include "GUIListContainer.h"
-#include "GUISettings.h"
#include "GUIUserMessages.h"
#include "FileItem.h"
#include "LocalizeStrings.h"
@@ -31,6 +31,8 @@
#define CONTROL_PRESETS_LABEL 3
#define CONTROL_NONE_AVAILABLE 4
+using ADDON::CVisualisation;
+
CGUIDialogVisualisationPresetList::CGUIDialogVisualisationPresetList(void)
: CGUIDialog(WINDOW_DIALOG_VIS_PRESET_LIST, "VisualisationPresetList.xml")
{
@@ -57,8 +59,8 @@ bool CGUIDialogVisualisationPresetList::OnMessage(CGUIMessage &message)
if (pList)
{
int iItem = pList->GetSelectedItem();
- if (m_pVisualisation)
- m_pVisualisation->OnAction(CVisualisation::VIS_ACTION_LOAD_PRESET, (void *)&iItem);
+ if (m_viz)
+ m_viz->OnAction(VIS_ACTION_LOAD_PRESET, (void *)&iItem);
}
return true;
}
@@ -70,68 +72,76 @@ bool CGUIDialogVisualisationPresetList::OnMessage(CGUIMessage &message)
CGUIMessage msg(GUI_MSG_GET_VISUALISATION, 0, 0);
g_windowManager.SendMessage(msg);
- SetVisualisation((CVisualisation *)msg.GetPointer());
+ if (msg.GetPointer())
+ {
+ SetVisualisation((CVisualisation*)msg.GetPointer());
+ }
return true;
}
break;
case GUI_MSG_WINDOW_DEINIT:
case GUI_MSG_VISUALISATION_UNLOADING:
{
- m_pVisualisation = NULL;
+ m_viz = NULL;
CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), CONTROL_LIST);
OnMessage(msg);
- m_vecPresets->Clear();
+ Update();
}
break;
case GUI_MSG_VISUALISATION_LOADED:
{
if (message.GetPointer())
{
- SetVisualisation((CVisualisation *)message.GetPointer());
+ SetVisualisation((CVisualisation*)message.GetPointer());
}
}
}
return CGUIDialog::OnMessage(message);
}
+void CGUIDialogVisualisationPresetList::SetVisualisation(CVisualisation* vis)
+{
+ m_viz = NULL;
+ if (vis)
+ {
+ m_viz = vis;
+ Update();
+ }
+}
+
void CGUIDialogVisualisationPresetList::FrameMove()
{
- char **presets = NULL;
- int numPresets = 0;
- int currentPreset = 0;
- bool locked = false;
- if (m_pVisualisation)
- m_pVisualisation->GetPresets(&presets, &currentPreset, &numPresets, &locked);
- if (currentPreset != m_currentPreset)
- { // current preset changed...
- m_vecPresets->Get(m_currentPreset)->Select(false);
- m_currentPreset = currentPreset;
- m_vecPresets->Get(m_currentPreset)->Select(true);
+ //FIXME we shouldn't have to check preset each frame
+ // a viz callback could push GUI_MSG_VISUALISATION_UPDATED
+ if (m_viz)
+ {
+ unsigned preset = m_viz->GetPreset();
+ if (preset != m_currentPreset)
+ {
+ m_vecPresets->Get(m_currentPreset)->Select(false);
+ m_currentPreset = preset;
+ m_vecPresets->Get(m_currentPreset)->Select(true);
+ }
}
CGUIDialog::FrameMove();
}
-void CGUIDialogVisualisationPresetList::SetVisualisation(CVisualisation *pVisualisation)
+void CGUIDialogVisualisationPresetList::Update()
{
- m_pVisualisation = pVisualisation;
m_vecPresets->Clear();
- if (m_pVisualisation)
+ CStdString strHeading;
+ if (m_viz)
{
+ strHeading.Format(g_localizeStrings.Get(13407).c_str(), m_viz->Name().c_str());
+
//clear filelist
CGUIMessage msg(GUI_MSG_LABEL_RESET, GetID(), CONTROL_LIST);
OnMessage(msg);
- char **presets = NULL;
- int numPresets = 0;
- m_currentPreset = 0;
- bool locked = false;
- m_pVisualisation->GetPresets(&presets, &m_currentPreset, &numPresets, &locked);
- if (presets)
+ std::vector<CStdString> presets;
+ if (m_viz->GetPresetList(presets))
{
- //clear filelist
- CGUIMessage msg2(GUI_MSG_LABEL_RESET, GetID(), CONTROL_LIST);
- OnMessage(msg2);
- m_vecPresets->Clear();
- for (int i = 0; i < numPresets; i++)
+ m_currentPreset = m_viz->GetPreset();
+ for (unsigned i = 0; i < presets.size(); i++)
{
CFileItemPtr pItem(new CFileItem(presets[i]));
if (i == m_currentPreset)
@@ -144,16 +154,10 @@ void CGUIDialogVisualisationPresetList::SetVisualisation(CVisualisation *pVisual
OnMessage(msg);
}
}
- // update our settings label
- CStdString strVis = g_guiSettings.GetString("musicplayer.visualisation");
- if (strVis != "None" && strVis.size() > 4)
- { // make it look pretty
- strVis = strVis.Left(strVis.size() - 4);
- strVis[0] = toupper(strVis[0]);
- }
- CStdString strSettings;
- strSettings.Format(g_localizeStrings.Get(13407).c_str(), strVis.c_str());
- SET_CONTROL_LABEL(CONTROL_PRESETS_LABEL, strSettings);
+
+ // update our dialog's label
+ SET_CONTROL_LABEL(CONTROL_PRESETS_LABEL, strHeading);
+
// if there is no presets, add a label saying so
if (m_vecPresets->Size() == 0)
{
diff --git a/xbmc/GUIDialogVisualisationPresetList.h b/xbmc/GUIDialogVisualisationPresetList.h
index b50f06c1ef..e4f594f63e 100644
--- a/xbmc/GUIDialogVisualisationPresetList.h
+++ b/xbmc/GUIDialogVisualisationPresetList.h
@@ -22,8 +22,11 @@
*/
#include "GUIDialog.h"
-#include "visualizations/Visualisation.h"
+namespace ADDON
+{
+ class CVisualisation;
+}
class CFileItemList;
class CGUIDialogVisualisationPresetList :
@@ -36,8 +39,9 @@ public:
virtual void FrameMove();
protected:
- void SetVisualisation(CVisualisation *pVisualisation);
- CVisualisation *m_pVisualisation;
+ void SetVisualisation(ADDON::CVisualisation *addon);
+ void Update();
+ ADDON::CVisualisation* m_viz; //TODO get rid
CFileItemList* m_vecPresets;
- int m_currentPreset;
+ unsigned m_currentPreset;
};
diff --git a/xbmc/GUIDialogVisualisationSettings.cpp b/xbmc/GUIDialogVisualisationSettings.cpp
deleted file mode 100644
index 803b45d4d0..0000000000
--- a/xbmc/GUIDialogVisualisationSettings.cpp
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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 "GUIDialogVisualisationSettings.h"
-#include "GUIWindowManager.h"
-#include "GUIWindowSettingsCategory.h"
-#include "GUISpinControlEx.h"
-#include "GUIRadioButtonControl.h"
-#include "GUIControlGroupList.h"
-#include "GUIUserMessages.h"
-#include "utils/GUIInfoManager.h"
-#include "LocalizeStrings.h"
-
-#define CONTROL_SETTINGS_LABEL 2
-#define CONTROL_NONE_AVAILABLE 3
-#define CONTROL_GROUP_LIST 5
-#define CONTROL_DEFAULT_BUTTON 7
-#define CONTROL_DEFAULT_RADIOBUTTON 8
-#define CONTROL_DEFAULT_SPIN 9
-#define CONTROL_START 50
-#define CONTROL_PAGE 60
-
-CGUIDialogVisualisationSettings::CGUIDialogVisualisationSettings(void)
- : CGUIDialog(WINDOW_DIALOG_VIS_SETTINGS, "MusicOSDVisSettings.xml")
-{
- m_pOriginalSpin = NULL;
- m_pOriginalRadioButton = NULL;
- m_pOriginalSettingsButton = NULL;
- m_pVisualisation = NULL;
- m_pSettings = NULL;
-}
-
-CGUIDialogVisualisationSettings::~CGUIDialogVisualisationSettings(void)
-{
-}
-
-bool CGUIDialogVisualisationSettings::OnMessage(CGUIMessage &message)
-{
- switch (message.GetMessage())
- {
- case GUI_MSG_CLICKED:
- {
- unsigned int iControl = message.GetSenderId();
- if (iControl >= CONTROL_START && iControl < CONTROL_PAGE)
- OnClick(iControl);
- return true;
- }
- break;
- case GUI_MSG_WINDOW_DEINIT:
- case GUI_MSG_VISUALISATION_UNLOADING:
- {
- FreeControls();
- m_pVisualisation = NULL;
- m_pSettings = NULL;
- }
- break;
- case GUI_MSG_VISUALISATION_LOADED:
- {
- SetVisualisation((CVisualisation *)message.GetPointer());
- SetupPage();
- SET_CONTROL_FOCUS(CONTROL_START, 0);
- }
- }
- return CGUIDialog::OnMessage(message);
-}
-
-void CGUIDialogVisualisationSettings::SetupPage()
-{
- // cleanup first, if necessary
- FreeControls();
- m_pOriginalSpin = (CGUISpinControlEx*)GetControl(CONTROL_DEFAULT_SPIN);
- m_pOriginalRadioButton = (CGUIRadioButtonControl *)GetControl(CONTROL_DEFAULT_RADIOBUTTON);
- m_pOriginalSettingsButton = (CGUIButtonControl *)GetControl(CONTROL_DEFAULT_BUTTON);
- if (!m_pOriginalSpin || !m_pOriginalRadioButton || !m_pOriginalSettingsButton)
- return;
- m_pOriginalSpin->SetVisible(false);
- m_pOriginalRadioButton->SetVisible(false);
- m_pOriginalSettingsButton->SetVisible(false);
-
- // update our settings label
- CStdString strSettings;
- strSettings.Format("%s %s", g_infoManager.GetLabel(402).c_str(), g_localizeStrings.Get(5));
- SET_CONTROL_LABEL(CONTROL_SETTINGS_LABEL, strSettings);
-
- CGUIControlGroupList *group = (CGUIControlGroupList *)GetControl(CONTROL_GROUP_LIST);
- if (!group)
- return;
-
- if (!m_pSettings || !m_pSettings->size())
- { // no settings available
- SET_CONTROL_VISIBLE(CONTROL_NONE_AVAILABLE);
- return;
- }
- else
- {
- SET_CONTROL_HIDDEN(CONTROL_NONE_AVAILABLE);
- }
-
-
- // run through and create our controls
- for (unsigned int i = 0; i < m_pSettings->size(); i++)
- {
- VisSetting &setting = m_pSettings->at(i);
- AddSetting(setting, group->GetWidth(), CONTROL_START + i);
- }
- UpdateSettings();
-}
-
-
-void CGUIDialogVisualisationSettings::UpdateSettings()
-{
-}
-
-void CGUIDialogVisualisationSettings::OnClick(int iID)
-{
- if (!m_pSettings || !m_pVisualisation) return;
- unsigned int settingNum = iID - CONTROL_START;
- if (settingNum >= m_pSettings->size()) return;
- VisSetting &setting = m_pSettings->at(settingNum);
- if (setting.type == VisSetting::SPIN)
- {
- CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(iID);
- setting.current = pControl->GetValue();
- }
- else if (setting.type == VisSetting::CHECK)
- {
- CGUIRadioButtonControl *pControl = (CGUIRadioButtonControl *)GetControl(iID);
- setting.current = pControl->IsSelected() ? 1 : 0;
- }
- m_pVisualisation->UpdateSetting(settingNum, &m_pSettings);
- UpdateSettings();
-}
-
-void CGUIDialogVisualisationSettings::FreeControls()
-{
- // just clear our group list
- CGUIControlGroupList *group = (CGUIControlGroupList *)GetControl(CONTROL_GROUP_LIST);
- if (group)
- {
- group->FreeResources();
- group->ClearAll();
- }
-}
-
-void CGUIDialogVisualisationSettings::AddSetting(VisSetting &setting, float width, int iControlID)
-{
- CGUIControl *pControl = NULL;
- if (setting.type == VisSetting::CHECK)
- {
- pControl = new CGUIRadioButtonControl(*m_pOriginalRadioButton);
- if (!pControl) return ;
- ((CGUIRadioButtonControl *)pControl)->SetLabel(setting.name);
- pControl->SetWidth(width);
- ((CGUIRadioButtonControl *)pControl)->SetSelected(setting.current == 1);
- }
- else if (setting.type == VisSetting::SPIN && setting.entry.size() > 0)
- {
- pControl = new CGUISpinControlEx(*m_pOriginalSpin);
- if (!pControl) return ;
- pControl->SetWidth(width);
- ((CGUISpinControlEx *)pControl)->SetText(setting.name);
- pControl->SetWidth(width);
- for (unsigned int i = 0; i < setting.entry.size(); i++)
- ((CGUISpinControlEx *)pControl)->AddLabel(setting.entry[i], i);
- ((CGUISpinControlEx *)pControl)->SetValue(setting.current);
- }
- if (!pControl) return;
- pControl->SetID(iControlID);
- pControl->SetVisible(true);
- CGUIControlGroupList *group = (CGUIControlGroupList *)GetControl(CONTROL_GROUP_LIST);
- if (group)
- {
- pControl->AllocResources();
- group->AddControl(pControl);
- }
- else
- delete pControl;
-}
-
-void CGUIDialogVisualisationSettings::SetVisualisation(CVisualisation *pVisualisation)
-{
- m_pVisualisation = pVisualisation;
- if (m_pVisualisation)
- {
- m_pVisualisation->GetSettings(&m_pSettings);
- }
-}
-
-void CGUIDialogVisualisationSettings::OnInitWindow()
-{
- // set our visualisation
- CGUIMessage msg(GUI_MSG_GET_VISUALISATION, 0, 0);
- g_windowManager.SendMessage(msg);
- SetVisualisation((CVisualisation *)msg.GetPointer());
-
- SetupPage();
- // reset the default control
- m_lastControlID = CONTROL_START;
- CGUIDialog::OnInitWindow();
-}
-
diff --git a/xbmc/GUIDialogVisualisationSettings.h b/xbmc/GUIDialogVisualisationSettings.h
deleted file mode 100644
index 1fc6bc76a1..0000000000
--- a/xbmc/GUIDialogVisualisationSettings.h
+++ /dev/null
@@ -1,53 +0,0 @@
-#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 "visualizations/Visualisation.h"
-
-class CGUISpinControlEx;
-class CGUIRadioButtonControl;
-class CGUIButtonControl;
-
-class CGUIDialogVisualisationSettings :
- public CGUIDialog
-{
-public:
- CGUIDialogVisualisationSettings(void);
- virtual ~CGUIDialogVisualisationSettings(void);
- virtual bool OnMessage(CGUIMessage &message);
-protected:
- virtual void OnInitWindow();
- void SetVisualisation(CVisualisation *pVisualisation);
- virtual void SetupPage();
- void UpdateSettings();
- virtual void FreeControls();
- void OnClick(int iControl);
- void AddSetting(VisSetting &setting, float width, int iControlID);
-
- CGUISpinControlEx *m_pOriginalSpin;
- CGUIRadioButtonControl *m_pOriginalRadioButton;
- CGUIButtonControl *m_pOriginalSettingsButton;
-
- CVisualisation *m_pVisualisation;
- std::vector<VisSetting> *m_pSettings;
-};
diff --git a/xbmc/GUIMediaWindow.cpp b/xbmc/GUIMediaWindow.cpp
index 88fdf91daa..e4af255f56 100644
--- a/xbmc/GUIMediaWindow.cpp
+++ b/xbmc/GUIMediaWindow.cpp
@@ -23,6 +23,7 @@
#include "GUIUserMessages.h"
#include "Util.h"
#include "PlayListPlayer.h"
+#include "utils/AddonManager.h"
#include "FileSystem/ZipManager.h"
#include "FileSystem/PluginDirectory.h"
#include "FileSystem/MultiPathDirectory.h"
@@ -40,8 +41,8 @@
#include "GUISettings.h"
#include "GUIDialogSmartPlaylistEditor.h"
-#include "GUIDialogPluginSettings.h"
-#include "PluginSettings.h"
+#include "GUIDialogAddonSettings.h"
+#include "GUIDialogYesNo.h"
#include "GUIWindowManager.h"
#include "GUIDialogOK.h"
#include "PlayList.h"
@@ -64,6 +65,7 @@
#define CONTROL_LABELFILES 12
using namespace std;
+using namespace ADDON;
CGUIMediaWindow::CGUIMediaWindow(int id, const char *xmlFile)
: CGUIWindow(id, xmlFile)
@@ -1304,19 +1306,6 @@ void CGUIMediaWindow::GetContextButtons(int itemNumber, CContextButtons &buttons
buttons.Add((CONTEXT_BUTTON)i, item->GetProperty(label));
}
- if (item->IsPlugin() && item->m_bIsFolder)
- {
- if (CPluginSettings::SettingsExist(item->m_strPath))
- buttons.Add(CONTEXT_BUTTON_PLUGIN_SETTINGS, 1045);
- if (m_vecItems->m_strPath.Equals("plugin://music/") ||
- m_vecItems->m_strPath.Equals("plugin://video/") ||
- m_vecItems->m_strPath.Equals("plugin://pictures/") ||
- m_vecItems->m_strPath.Equals("plugin://programs/") )
- {
- buttons.Add(CONTEXT_BUTTON_DELETE_PLUGIN, 117);
- }
- }
-
if (item->GetPropertyBOOL("pluginreplacecontextitems"))
return;
@@ -1342,20 +1331,11 @@ bool CGUIMediaWindow::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
}
case CONTEXT_BUTTON_PLUGIN_SETTINGS:
{
- CURL url(m_vecItems->Get(itemNumber)->m_strPath);
- if(CGUIDialogPluginSettings::ShowAndGetInput(url))
- Update(m_vecItems->m_strPath);
- return true;
- }
- case CONTEXT_BUTTON_DELETE_PLUGIN:
- {
- CStdString path;
- CUtil::GetDirectory(m_vecItems->Get(itemNumber)->m_strPath,path);
- path.Replace("plugin://","special://home/plugins/");
- CFileItemPtr item2(new CFileItem(path,true));
- if (CFileUtils::DeleteItem(item2))
- Update(m_vecItems->m_strPath);
-
+ CURL plugin(m_vecItems->Get(itemNumber)->m_strPath);
+ ADDON::AddonPtr addon;
+ if (CAddonMgr::Get()->GetAddon(ADDON_PLUGIN, plugin.GetHostName(), addon))
+ if (CGUIDialogAddonSettings::ShowAndGetInput(addon))
+ Update(m_vecItems->m_strPath);
return true;
}
case CONTEXT_BUTTON_USER1:
diff --git a/xbmc/GUIPassword.cpp b/xbmc/GUIPassword.cpp
index a6152045e1..e4803bfb19 100644
--- a/xbmc/GUIPassword.cpp
+++ b/xbmc/GUIPassword.cpp
@@ -179,7 +179,7 @@ bool CGUIPassword::SetMasterLockMode(bool bDetails)
if (pDialog)
{
CProfile& profile=g_settings.m_vecProfiles.at(0);
- if (pDialog->ShowAndGetLock(profile._iLockMode,profile._strLockCode,profile._bLockMusic,profile._bLockVideo,profile._bLockPictures,profile._bLockPrograms,profile._bLockFiles,profile._bLockSettings,12360,true,bDetails))
+ if (pDialog->ShowAndGetLock(profile._iLockMode,profile._strLockCode,profile._bLockMusic,profile._bLockVideo,profile._bLockPictures,profile._bLockPrograms,profile._bLockFiles,profile._bLockSettings,profile._bLockAddonManager,12360,true,bDetails))
return true;
return false;
diff --git a/xbmc/GUISettings.cpp b/xbmc/GUISettings.cpp
index 8695be9b76..e67a71f486 100644
--- a/xbmc/GUISettings.cpp
+++ b/xbmc/GUISettings.cpp
@@ -253,8 +253,7 @@ void CGUISettings::Initialize()
AddString(wea, "weather.areacode2", 14020, "UKXX0085 - London, United Kingdom", BUTTON_CONTROL_STANDARD);
AddString(wea, "weather.areacode3", 14021, "JAXX0085 - Tokyo, Japan", BUTTON_CONTROL_STANDARD);
AddSeparator(wea, "weather.sep1");
- AddString(wea, "weather.plugin", 23000, "", SPIN_CONTROL_TEXT, true);
- AddString(wea, "weather.pluginsettings", 23001, "", BUTTON_CONTROL_STANDARD, true);
+ AddString(wea, "weather.plugin", 24027, "", SPIN_CONTROL_TEXT, true);
// My Music Settings
AddGroup(3, 2);
@@ -264,7 +263,6 @@ void CGUISettings::Initialize()
AddSeparator(ml,"musiclibrary.sep1");
AddBool(ml,"musiclibrary.downloadinfo", 20192, false);
AddString(ml, "musiclibrary.scraper", 20194, "allmusic.xml", SPIN_CONTROL_TEXT);
- AddString(ml, "musiclibrary.scrapersettings", 21417, "", BUTTON_CONTROL_STANDARD);
AddBool(ml, "musiclibrary.updateonstartup", 22000, false);
AddBool(NULL, "musiclibrary.backgroundupdate", 22001, false);
AddSeparator(ml,"musiclibrary.sep2");
@@ -1119,10 +1117,6 @@ void CGUISettings::LoadXML(TiXmlElement *pRootElement, bool hideSettings /* = fa
m_replayGain.iType = GetInt("musicplayer.replaygaintype");
m_replayGain.bAvoidClipping = GetBool("musicplayer.replaygainavoidclipping");
- // check if we load the right vis
- if(!CVisualisation::IsValidVisualisation(g_guiSettings.GetString("musicplayer.visualisation")))
- g_guiSettings.SetString("musicplayer.visualisation", DEFAULT_VISUALISATION);
-
#if defined(_LINUX) && !defined(__APPLE__)
CStdString timezone = GetString("locale.timezone");
if(timezone == "0" || timezone.IsEmpty())
diff --git a/xbmc/GUIViewState.cpp b/xbmc/GUIViewState.cpp
index 153b0bdad4..8ef944ef25 100644
--- a/xbmc/GUIViewState.cpp
+++ b/xbmc/GUIViewState.cpp
@@ -33,6 +33,7 @@
#include "ViewDatabase.h"
#include "AutoSwitch.h"
#include "GUIWindowManager.h"
+#include "utils/AddonManager.h"
#include "ViewState.h"
#include "GUISettings.h"
#include "Settings.h"
@@ -46,6 +47,9 @@ VECSOURCES CGUIViewState::m_sources;
CGUIViewState* CGUIViewState::GetViewState(int windowId, const CFileItemList& items)
{
+ // don't expect derived classes to clear the sources
+ m_sources.clear();
+
if (windowId == 0)
return GetViewState(g_windowManager.GetActiveWindow(),items);
@@ -120,11 +124,12 @@ CGUIViewState* CGUIViewState::GetViewState(int windowId, const CFileItemList& it
return new CGUIViewStateGeneral(items);
}
-CGUIViewState::CGUIViewState(const CFileItemList& items) : m_items(items)
+CGUIViewState::CGUIViewState(const CFileItemList& items, const CONTENT_TYPE& content/*=CONTENT_NONE*/) : m_items(items)
{
m_currentViewAsControl=0;
m_currentSortMethod=0;
m_sortOrder=SORT_ORDER_ASC;
+ m_content = content;
}
CGUIViewState::~CGUIViewState()
@@ -332,6 +337,29 @@ CStdString CGUIViewState::GetExtensions()
VECSOURCES& CGUIViewState::GetSources()
{
+ // more consolidation could happen here for all content types
+ // - playlists, autoconfig network shares, whatnot
+
+ if (m_content == CONTENT_NONE)
+ return m_sources;
+
+ ADDON::VECADDONS addons;
+ ADDON::CAddonMgr::Get()->GetAddons(ADDON::ADDON_PLUGIN, addons, m_content);
+
+ for (unsigned i=0; i<addons.size(); i++)
+ {
+ // format for sources's path is
+ // eg. pictures://UUID
+ CMediaSource plugin;
+ CURL path;
+ path.SetProtocol(ADDON::TranslateContent(m_content));
+ path.SetHostName(addons[i]->UUID());
+ plugin.strPath = path.Get();
+ plugin.strName = addons[i]->Name();
+ plugin.m_strThumbnailImage = addons[i]->Icon(); //FIXME cache by UUID
+ plugin.m_iDriveType = CMediaSource::SOURCE_TYPE_REMOTE;
+ m_sources.push_back(plugin);
+ }
return m_sources;
}
diff --git a/xbmc/GUIViewState.h b/xbmc/GUIViewState.h
index de5e431775..cb910bc505 100644
--- a/xbmc/GUIViewState.h
+++ b/xbmc/GUIViewState.h
@@ -25,6 +25,7 @@
#include "SortFileItem.h"
#include "GUIBaseContainer.h"
#include "MediaSource.h"
+#include "utils/IAddon.h"
class CViewState; // forward
class CFileItemList;
@@ -62,7 +63,7 @@ public:
virtual VECSOURCES& GetSources();
protected:
- CGUIViewState(const CFileItemList& items); // no direct object creation, use GetViewState()
+ CGUIViewState(const CFileItemList& items, const CONTENT_TYPE& content = CONTENT_NONE); // no direct object creation, use GetViewState()
virtual void SaveViewState()=0;
virtual void SaveViewToDb(const CStdString &path, int windowID, CViewState *viewState = NULL);
void LoadViewState(const CStdString &path, int windowID);
@@ -73,6 +74,7 @@ protected:
const CFileItemList& m_items;
static VECSOURCES m_sources;
+ CONTENT_TYPE m_content;
int m_currentViewAsControl;
diff --git a/xbmc/GUIViewStateMusic.cpp b/xbmc/GUIViewStateMusic.cpp
index 61b1403385..cad44107a3 100644
--- a/xbmc/GUIViewStateMusic.cpp
+++ b/xbmc/GUIViewStateMusic.cpp
@@ -32,9 +32,9 @@
#include "LocalizeStrings.h"
#include "utils/log.h"
+#include "FileSystem/Directory.h"
#include "FileSystem/MusicDatabaseDirectory.h"
#include "FileSystem/VideoDatabaseDirectory.h"
-#include "FileSystem/PluginDirectory.h"
#include "FileSystem/ShoutcastDirectory.h"
using namespace XFILE;
@@ -567,16 +567,6 @@ VECSOURCES& CGUIViewStateWindowMusicNav::GetSources()
m_sources.push_back(share);
}
- // plugins share
- if (CPluginDirectory::HasPlugins("music") && g_advancedSettings.m_bVirtualShares)
- {
- share.strName = g_localizeStrings.Get(1038);
- share.strPath = "plugin://music/";
- share.m_strThumbnailImage = CUtil::GetDefaultFolderThumb("DefaultMusicPlugins.png");
- share.m_ignore = true;
- m_sources.push_back(share);
- }
-
return CGUIViewStateWindowMusic::GetSources();
}
@@ -623,14 +613,7 @@ void CGUIViewStateWindowMusicSongs::SaveViewState()
VECSOURCES& CGUIViewStateWindowMusicSongs::GetSources()
{
- // plugins share
- if (CPluginDirectory::HasPlugins("music") && g_advancedSettings.m_bVirtualShares)
- {
- CMediaSource share;
- share.strName = g_localizeStrings.Get(1038);
- share.strPath = "plugin://music/";
- AddOrReplace(g_settings.m_musicSources,share);
- }
+ AddOrReplace(g_settings.m_musicSources, CGUIViewState::GetSources());
return g_settings.m_musicSources;
}
@@ -682,7 +665,8 @@ VECSOURCES& CGUIViewStateWindowMusicPlaylist::GetSources()
share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
m_sources.push_back(share);
- return CGUIViewStateWindowMusic::GetSources();
+ // CGUIViewState::GetSources would add music plugins
+ return m_sources;
}
CGUIViewStateMusicShoutcast::CGUIViewStateMusicShoutcast(const CFileItemList& items) : CGUIViewStateWindowMusic(items)
diff --git a/xbmc/GUIViewStateMusic.h b/xbmc/GUIViewStateMusic.h
index 1265389e81..086bef37ef 100644
--- a/xbmc/GUIViewStateMusic.h
+++ b/xbmc/GUIViewStateMusic.h
@@ -27,7 +27,7 @@
class CGUIViewStateWindowMusic : public CGUIViewState
{
public:
- CGUIViewStateWindowMusic(const CFileItemList& items) : CGUIViewState(items) {}
+ CGUIViewStateWindowMusic(const CFileItemList& items) : CGUIViewState(items, CONTENT_ALBUMS) {}
protected:
virtual int GetPlaylist();
virtual bool AutoPlayNextItem();
diff --git a/xbmc/GUIViewStatePictures.cpp b/xbmc/GUIViewStatePictures.cpp
index 4155f02708..05534f57e9 100644
--- a/xbmc/GUIViewStatePictures.cpp
+++ b/xbmc/GUIViewStatePictures.cpp
@@ -34,7 +34,7 @@
using namespace XFILE;
-CGUIViewStateWindowPictures::CGUIViewStateWindowPictures(const CFileItemList& items) : CGUIViewState(items)
+CGUIViewStateWindowPictures::CGUIViewStateWindowPictures(const CFileItemList& items) : CGUIViewState(items, CONTENT_PICTURES)
{
if (items.IsVirtualDirectoryRoot())
{
@@ -80,16 +80,7 @@ CStdString CGUIViewStateWindowPictures::GetExtensions()
VECSOURCES& CGUIViewStateWindowPictures::GetSources()
{
- // plugins share
- if (CPluginDirectory::HasPlugins("pictures") && g_advancedSettings.m_bVirtualShares)
- {
- CMediaSource share;
- share.strName = g_localizeStrings.Get(1039); // Picture Plugins
- share.strPath = "plugin://pictures/";
- share.m_strThumbnailImage = CUtil::GetDefaultFolderThumb("DefaultPicturePlugins.png");
- share.m_ignore = true;
- AddOrReplace(g_settings.m_pictureSources,share);
- }
+ AddOrReplace(g_settings.m_pictureSources, CGUIViewState::GetSources());
return g_settings.m_pictureSources;
}
diff --git a/xbmc/GUIViewStatePrograms.cpp b/xbmc/GUIViewStatePrograms.cpp
index 60e9a5512f..ea216ef2e6 100644
--- a/xbmc/GUIViewStatePrograms.cpp
+++ b/xbmc/GUIViewStatePrograms.cpp
@@ -33,7 +33,7 @@
using namespace XFILE;
-CGUIViewStateWindowPrograms::CGUIViewStateWindowPrograms(const CFileItemList& items) : CGUIViewState(items)
+CGUIViewStateWindowPrograms::CGUIViewStateWindowPrograms(const CFileItemList& items) : CGUIViewState(items, CONTENT_PROGRAMS)
{
if (g_guiSettings.GetBool("filelists.ignorethewhensorting"))
AddSortMethod(SORT_METHOD_LABEL_IGNORE_THE, 551, LABEL_MASKS("%K", "%I", "%L", "")); // Titel, Size | Foldername, empty
@@ -68,16 +68,7 @@ CStdString CGUIViewStateWindowPrograms::GetExtensions()
VECSOURCES& CGUIViewStateWindowPrograms::GetSources()
{
- // plugins share
- if (CPluginDirectory::HasPlugins("programs"))
- {
- CMediaSource share;
- share.strName = g_localizeStrings.Get(1043); // Program Plugins
- share.strPath = "plugin://programs/";
- share.m_strThumbnailImage = CUtil::GetDefaultFolderThumb("DefaultProgramPlugins.png");
- share.m_ignore= true;
- AddOrReplace(g_settings.m_programSources,share);
- }
+ AddOrReplace(g_settings.m_programSources,CGUIViewState::GetSources());
return g_settings.m_programSources;
}
diff --git a/xbmc/GUIViewStateScripts.cpp b/xbmc/GUIViewStateScripts.cpp
index 98dc7aee3e..50ba399b6a 100644
--- a/xbmc/GUIViewStateScripts.cpp
+++ b/xbmc/GUIViewStateScripts.cpp
@@ -62,24 +62,7 @@ VECSOURCES& CGUIViewStateWindowScripts::GetSources()
m_sources.clear();
CMediaSource share;
- if (g_settings.m_vecProfiles.size() > 1)
- {
- if (CDirectory::Exists("special://profile/scripts"))
- {
- CMediaSource share2;
- share2.strName = "Profile Scripts";
- share2.strPath = "special://profile/scripts";
- share2.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
- m_sources.push_back(share2);
- }
- share.strName = "Shared Scripts";
- }
- else
- share.strName = "Scripts";
-
- share.strPath = "special://home/scripts";
- if (!CDirectory::Exists(share.strPath))
- share.strPath = "special://xbmc/scripts";
+ share.strPath = "special://xbmc/scripts";
share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
m_sources.push_back(share);
diff --git a/xbmc/GUIViewStateVideo.cpp b/xbmc/GUIViewStateVideo.cpp
index b68087d4fc..d1d39e0946 100644
--- a/xbmc/GUIViewStateVideo.cpp
+++ b/xbmc/GUIViewStateVideo.cpp
@@ -87,15 +87,7 @@ void CGUIViewStateWindowVideoFiles::SaveViewState()
VECSOURCES& CGUIViewStateWindowVideoFiles::GetSources()
{
- // plugins share
- if (CPluginDirectory::HasPlugins("video") && g_advancedSettings.m_bVirtualShares)
- {
- CMediaSource share;
- share.strName = g_localizeStrings.Get(1037);
- share.strPath = "plugin://video/";
- share.m_ignore = true;
- AddOrReplace(g_settings.m_videoSources,share);
- }
+ AddOrReplace(g_settings.m_videoSources, CGUIViewState::GetSources());
return g_settings.m_videoSources;
}
@@ -395,15 +387,6 @@ VECSOURCES& CGUIViewStateWindowVideoNav::GetSources()
share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
m_sources.push_back(share);
- // plugins share
- if (CPluginDirectory::HasPlugins("video") && g_advancedSettings.m_bVirtualShares)
- {
- share.strName = g_localizeStrings.Get(1037);
- share.strPath = "plugin://video/";
- share.m_strThumbnailImage = CUtil::GetDefaultFolderThumb("DefaultVideoPlugins.png");
- m_sources.push_back(share);
- }
-
return CGUIViewStateWindowVideo::GetSources();
}
@@ -453,7 +436,8 @@ VECSOURCES& CGUIViewStateWindowVideoPlaylist::GetSources()
share.m_iDriveType = CMediaSource::SOURCE_TYPE_LOCAL;
m_sources.push_back(share);
- return CGUIViewStateWindowVideo::GetSources();
+ // no plugins in playlist window
+ return m_sources;
}
diff --git a/xbmc/GUIViewStateVideo.h b/xbmc/GUIViewStateVideo.h
index c1d339716f..e1f4d76b9a 100644
--- a/xbmc/GUIViewStateVideo.h
+++ b/xbmc/GUIViewStateVideo.h
@@ -27,7 +27,7 @@
class CGUIViewStateWindowVideo : public CGUIViewState
{
public:
- CGUIViewStateWindowVideo(const CFileItemList& items) : CGUIViewState(items) {}
+ CGUIViewStateWindowVideo(const CFileItemList& items) : CGUIViewState(items, CONTENT_MOVIES) {}
protected:
virtual CStdString GetLockType();
diff --git a/xbmc/GUIWindowAddonBrowser.cpp b/xbmc/GUIWindowAddonBrowser.cpp
new file mode 100644
index 0000000000..5deb3ee963
--- /dev/null
+++ b/xbmc/GUIWindowAddonBrowser.cpp
@@ -0,0 +1,254 @@
+/*
+ * Copyright (C) 2005-2010 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 "utils/AddonManager.h"
+#include "GUIWindowAddonBrowser.h"
+#include "GUISpinControlEx.h"
+#include "Settings.h"
+#include "GUIDialogContextMenu.h"
+#include "GUIDialogAddonSettings.h"
+#include "GUIDialogYesNo.h"
+#include "GUIDialogNumeric.h"
+#include "GUIDialogKeyboard.h"
+#include "GUIWindowManager.h"
+#include "Util.h"
+#include "URL.h"
+#include "utils/log.h"
+#include "FileItem.h"
+
+#define CONTROL_ADDONSLIST 2
+#define CONTROL_HEADING_LABEL 411
+
+using namespace ADDON;
+
+CGUIWindowAddonBrowser::CGUIWindowAddonBrowser(void)
+: CGUIWindow(WINDOW_ADDON_BROWSER, "AddonBrowser.xml")
+{
+ m_vecItems = new CFileItemList;
+}
+
+CGUIWindowAddonBrowser::~CGUIWindowAddonBrowser()
+{
+}
+
+bool CGUIWindowAddonBrowser::OnAction(const CAction &action)
+{
+ if (action.GetID() == ACTION_PREVIOUS_MENU)
+ {
+ g_windowManager.PreviousWindow();
+ return true;
+ }
+ else if (action.GetID() == ACTION_CONTEXT_MENU || action.GetID() == ACTION_MOUSE_RIGHT_CLICK)
+ {
+ int iItem = GetSelectedItem();
+ return OnContextMenu(iItem);
+ }
+ return CGUIWindow::OnAction(action);
+}
+
+bool CGUIWindowAddonBrowser::OnMessage(CGUIMessage& message)
+{
+ switch ( message.GetMessage() )
+ {
+ case GUI_MSG_WINDOW_DEINIT:
+ {
+ CGUIWindow::OnMessage(message);
+ ClearListItems();
+ return true;
+ }
+ break;
+
+ case GUI_MSG_CLICKED:
+ {
+ if (message.GetSenderId() == CONTROL_ADDONSLIST) // list control
+ {
+ int iItem = GetSelectedItem();
+ int iAction = message.GetParam1();
+ if (iItem < 0) break;
+ if (iAction == ACTION_SELECT_ITEM || iAction == ACTION_MOUSE_LEFT_CLICK)
+ {
+ OnClick(iItem);
+ return true;
+ }
+ if (iAction == ACTION_CONTEXT_MENU || iAction == ACTION_MOUSE_RIGHT_CLICK)
+ {
+ return OnContextMenu(iItem);
+ }
+ }
+ }
+ break;
+ }
+ return CGUIWindow::OnMessage(message);
+}
+
+void CGUIWindowAddonBrowser::ClearListItems()
+{
+ m_vecItems->Clear();
+}
+
+void CGUIWindowAddonBrowser::OnInitWindow()
+{
+ Update();
+ CGUIWindow::OnInitWindow();
+}
+
+int CGUIWindowAddonBrowser::GetSelectedItem()
+{
+ CGUIMessage msg(GUI_MSG_ITEM_SELECTED, GetID(), CONTROL_ADDONSLIST);
+ g_windowManager.SendMessage(msg);
+
+ return msg.GetParam1();
+}
+
+bool CGUIWindowAddonBrowser::SelectItem(int select)
+{
+ CGUIMessage msg(GUI_MSG_ITEM_SELECT, GetID(), CONTROL_ADDONSLIST, select);
+ return g_windowManager.SendMessage(msg);
+}
+
+void CGUIWindowAddonBrowser::OnSort()
+{
+ m_vecItems->Sort(SORT_METHOD_LABEL, SORT_ORDER_ASC);
+}
+
+void CGUIWindowAddonBrowser::Update()
+{
+ int selected = GetSelectedItem();
+ m_vecItems->Clear();
+
+ VECADDONS addons;
+ CAddonMgr::Get()->GetAllAddons(addons, false);
+
+ for (unsigned i=0; i < addons.size(); i++)
+ {
+ AddonPtr addon = addons[i];
+ CFileItemPtr pItem(new CFileItem(addon->UUID(), false));
+ pItem->SetLabel(addon->Name());
+ pItem->SetProperty("Addon.UUID", addon->UUID());
+ pItem->SetProperty("Addon.Type", TranslateType(addon->Type()));
+ pItem->SetProperty("Addon.Disabled", addon->Disabled());
+ pItem->SetProperty("Addon.Name", addon->Name());
+ pItem->SetProperty("Addon.Version", addon->Version().Print());
+ pItem->SetProperty("Addon.Summary", addon->Summary());
+ pItem->SetProperty("Addon.Description", addon->Description());
+ pItem->SetProperty("Addon.Creator", addon->Author());
+ pItem->SetProperty("Addon.Disclaimer", addon->Disclaimer());
+ pItem->SetProperty("Addon.Rating", addon->Stars());
+ pItem->SetThumbnailImage(addon->Icon());
+ m_vecItems->Add(pItem);
+ }
+
+ OnSort();
+ CGUIMessage msg(GUI_MSG_LABEL_BIND, GetID(), CONTROL_ADDONSLIST, 0, 0, m_vecItems);
+ OnMessage(msg);
+
+ if (selected != 0)
+ SelectItem(selected);
+}
+
+void CGUIWindowAddonBrowser::OnClick(int iItem)
+{
+ if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) return ;
+ CFileItemPtr pItem = (*m_vecItems)[iItem];
+ CStdString strPath = pItem->m_strPath;
+
+ // check if user is allowed to open this window
+ if (g_settings.m_vecProfiles[g_settings.m_iLastLoadedProfileIndex].addonmanagerLocked() && g_settings.m_vecProfiles[0].getLockMode() != LOCK_MODE_EVERYONE)
+ if (!g_passwordManager.IsMasterLockUnlocked(true))
+ return;
+
+ AddonPtr addon;
+ TYPE type = TranslateType(pItem->GetProperty("Addon.Type"));
+ if (CAddonMgr::Get()->GetAddon(type, pItem->GetProperty("Addon.UUID"), addon))
+ {
+ if (addon->Disabled())
+ {
+ CAddonMgr::Get()->EnableAddon(addon);
+ Update();
+
+ }
+ else
+ CGUIDialogAddonSettings::ShowAndGetInput(addon);
+ }
+}
+
+bool CGUIWindowAddonBrowser::OnContextMenu(int iItem)
+{
+ // check if user is allowed to open this window
+ if (g_settings.m_vecProfiles[g_settings.m_iLastLoadedProfileIndex].addonmanagerLocked() && g_settings.m_vecProfiles[0].getLockMode() != LOCK_MODE_EVERYONE)
+ if (!g_passwordManager.IsMasterLockUnlocked(true))
+ return false;
+
+ CGUIDialogContextMenu* pMenu = (CGUIDialogContextMenu*)g_windowManager.GetWindow(WINDOW_DIALOG_CONTEXT_MENU);
+ if (!pMenu)
+ return false;
+
+ pMenu->Initialize();
+ CFileItemPtr pItem = m_vecItems->Get(iItem);
+
+ TYPE type = TranslateType(pItem->GetProperty("Addon.Type"));
+ AddonPtr addon;
+ if (!CAddonMgr::Get()->GetAddon(type, pItem->GetProperty("Addon.UUID"), addon))
+ return false;
+
+ int iSettingsLabel = 24020;
+ int iDisableLabel = 24021;
+ int iEnableLabel = 24022;
+
+ int btn_Disable = -1;
+ int btn_Enable = -1;
+ int btn_Settings = -1;
+
+ if (addon->Disabled())
+ btn_Enable = pMenu->AddButton(iEnableLabel);
+ else
+ {
+ btn_Disable = pMenu->AddButton(iDisableLabel);
+ btn_Settings = pMenu->AddButton(iSettingsLabel);
+ }
+
+ pMenu->CenterWindow();
+ pMenu->DoModal();
+
+ int btnid = pMenu->GetButton();
+ if (btnid == -1)
+ return false;
+
+ if (btnid == btn_Settings)
+ {
+ CGUIDialogAddonSettings::ShowAndGetInput(addon);
+ return true;
+ }
+ else if (btnid == btn_Disable)
+ {
+ CAddonMgr::Get()->DisableAddon(addon);
+ Update();
+ return true;
+ }
+ else if (btnid == btn_Enable)
+ {
+ CAddonMgr::Get()->EnableAddon(addon);
+ Update();
+ return true;
+ }
+ return false;
+}
+
diff --git a/xbmc/visualizations/VisualisationFactory.h b/xbmc/GUIWindowAddonBrowser.h
index 36c16b8efb..47396ef270 100644
--- a/xbmc/visualizations/VisualisationFactory.h
+++ b/xbmc/GUIWindowAddonBrowser.h
@@ -1,6 +1,7 @@
#pragma once
+
/*
- * Copyright (C) 2005-2008 Team XBMC
+ * Copyright (C) 2005-2010 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
@@ -19,13 +20,33 @@
* http://www.gnu.org/copyleft/gpl.html
*
*/
-#include "Visualisation.h"
-class CVisualisationFactory
+#include "Addon.h"
+#include "GUIWindow.h"
+#include "GUIViewControl.h"
+
+class CFileItem;
+class CFileItemList;
+
+class CGUIWindowAddonBrowser :
+ public CGUIWindow
{
public:
- CVisualisationFactory();
- virtual ~CVisualisationFactory();
- CVisualisation* LoadVisualisation(const CStdString& strVisz) const;
- CVisualisation* LoadVisualisation(const CStdString& strVisz, const CStdString& strSubModule) const;
+ CGUIWindowAddonBrowser(void);
+ virtual ~CGUIWindowAddonBrowser(void);
+ virtual bool OnMessage(CGUIMessage& message);
+ virtual bool OnAction(const CAction &action);
+
+protected:
+ virtual void OnInitWindow();
+ int GetSelectedItem();
+ bool SelectItem(int select);
+ void OnClick(int iItem);
+ void OnSort();
+ void ClearListItems();
+ void Update();
+ bool OnContextMenu(int iItem);
+
+ CFileItemList* m_vecItems;
};
+
diff --git a/xbmc/GUIWindowMusicBase.cpp b/xbmc/GUIWindowMusicBase.cpp
index b67f4bbe30..c97a96779e 100644
--- a/xbmc/GUIWindowMusicBase.cpp
+++ b/xbmc/GUIWindowMusicBase.cpp
@@ -431,13 +431,8 @@ void CGUIWindowMusicBase::ShowArtistInfo(const CArtist& artist, const CStdString
return;
}
- // find album info
- SScraperInfo scraper;
- if (!m_musicdatabase.GetScraperForPath(path,scraper))
- return;
-
CMusicArtistInfo info;
- if (FindArtistInfo(artist.strArtist, info, scraper, bShowInfo ? (bRefresh ? SELECTION_FORCED : SELECTION_ALLOWED) : SELECTION_AUTO))
+ if (FindArtistInfo(artist.strArtist, info, bShowInfo ? (bRefresh ? SELECTION_FORCED : SELECTION_ALLOWED) : SELECTION_AUTO))
{
// download the album info
if ( info.Loaded() )
@@ -529,13 +524,8 @@ void CGUIWindowMusicBase::ShowAlbumInfo(const CAlbum& album, const CStdString& p
return;
}
- // find album info
- SScraperInfo scraper;
- if (!m_musicdatabase.GetScraperForPath(path,scraper))
- return;
-
CMusicAlbumInfo info;
- if (FindAlbumInfo(album.strAlbum, album.strArtist, info, scraper, bShowInfo ? (bRefresh ? SELECTION_FORCED : SELECTION_ALLOWED) : SELECTION_AUTO))
+ if (FindAlbumInfo(album.strAlbum, album.strArtist, info, bShowInfo ? (bRefresh ? SELECTION_FORCED : SELECTION_ALLOWED) : SELECTION_AUTO))
{
// download the album info
if ( info.Loaded() )
@@ -779,7 +769,7 @@ void CGUIWindowMusicBase::UpdateButtons()
CGUIMediaWindow::UpdateButtons();
}
-bool CGUIWindowMusicBase::FindAlbumInfo(const CStdString& strAlbum, const CStdString& strArtist, CMusicAlbumInfo& album, const SScraperInfo& info, ALLOW_SELECTION allowSelection)
+bool CGUIWindowMusicBase::FindAlbumInfo(const CStdString& strAlbum, const CStdString& strArtist, CMusicAlbumInfo& album, ALLOW_SELECTION allowSelection)
{
// show dialog box indicating we're searching the album
if (m_dlgProgress && allowSelection != SELECTION_AUTO)
@@ -830,7 +820,7 @@ bool CGUIWindowMusicBase::FindAlbumInfo(const CStdString& strAlbum, const CStdSt
return true;
}
-bool CGUIWindowMusicBase::FindArtistInfo(const CStdString& strArtist, CMusicArtistInfo& artist, const SScraperInfo& info, ALLOW_SELECTION allowSelection)
+bool CGUIWindowMusicBase::FindArtistInfo(const CStdString& strArtist, CMusicArtistInfo& artist, ALLOW_SELECTION allowSelection)
{
// show dialog box indicating we're searching the album
if (m_dlgProgress && allowSelection != SELECTION_AUTO)
diff --git a/xbmc/GUIWindowMusicBase.h b/xbmc/GUIWindowMusicBase.h
index dea204ce79..928dd2caf1 100644
--- a/xbmc/GUIWindowMusicBase.h
+++ b/xbmc/GUIWindowMusicBase.h
@@ -33,8 +33,6 @@
#include "PlayListPlayer.h"
#include "MusicInfoLoader.h"
-struct SScraperInfo;
-
/*!
\ingroup windows
\brief The base class for music windows
@@ -82,8 +80,8 @@ protected:
void OnInfoAll(int iItem, bool bCurrent=false);
virtual void OnQueueItem(int iItem);
enum ALLOW_SELECTION { SELECTION_ALLOWED = 0, SELECTION_AUTO, SELECTION_FORCED };
- bool FindAlbumInfo(const CStdString& strAlbum, const CStdString& strArtist, MUSIC_GRABBER::CMusicAlbumInfo& album, const SScraperInfo& info, ALLOW_SELECTION allowSelection);
- bool FindArtistInfo(const CStdString& strArtist, MUSIC_GRABBER::CMusicArtistInfo& artist, const SScraperInfo& info, ALLOW_SELECTION allowSelection);
+ bool FindAlbumInfo(const CStdString& strAlbum, const CStdString& strArtist, MUSIC_GRABBER::CMusicAlbumInfo& album, ALLOW_SELECTION allowSelection);
+ bool FindArtistInfo(const CStdString& strArtist, MUSIC_GRABBER::CMusicArtistInfo& artist, ALLOW_SELECTION allowSelection);
void ShowAlbumInfo(const CAlbum &album, const CStdString &strPath, bool bRefresh, bool bShowInfo = true);
void ShowArtistInfo(const CArtist &artist, const CStdString &strPath, bool bRefresh, bool bShowInfo = true);
diff --git a/xbmc/GUIWindowMusicNav.cpp b/xbmc/GUIWindowMusicNav.cpp
index bc76e8ae66..cb2a2aecd6 100644
--- a/xbmc/GUIWindowMusicNav.cpp
+++ b/xbmc/GUIWindowMusicNav.cpp
@@ -492,8 +492,8 @@ void CGUIWindowMusicNav::GetContextButtons(int itemNumber, CContextButtons &butt
m_vecItems->m_strPath.Equals("special://musicplaylists/");
CMusicDatabaseDirectory dir;
- SScraperInfo info;
- m_musicdatabase.GetScraperForPath(item->m_strPath,info);
+ ADDON::ScraperPtr info;
+ m_musicdatabase.GetScraperForPath(item->m_strPath, info);
// enable music info button on an album or on a song.
if (item->IsAudio() && !item->IsPlayList() && !item->IsSmartPlayList() &&
!item->IsLastFM() && !item->IsShoutCast() && !item->m_bIsFolder)
@@ -536,7 +536,7 @@ void CGUIWindowMusicNav::GetContextButtons(int itemNumber, CContextButtons &butt
// enable query all artist button only in album view
if (dir.IsArtistDir(item->m_strPath) && !dir.IsAllItem(item->m_strPath) &&
- item->m_bIsFolder && !item->IsVideoDb() && !info.strContent.IsEmpty())
+ item->m_bIsFolder && !item->IsVideoDb() && info->Supports(CONTENT_ALBUMS))
{
buttons.Add(CONTEXT_BUTTON_INFO_ALL, 21884);
}
@@ -640,7 +640,7 @@ bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
CGUIWindowVideoNav* pWindow = (CGUIWindowVideoNav*)g_windowManager.GetWindow(WINDOW_VIDEO_NAV);
if (pWindow)
{
- SScraperInfo info;
+ ADDON::ScraperPtr info;
pWindow->OnInfo(item.get(),info);
Update(m_vecItems->m_strPath);
}
@@ -728,7 +728,7 @@ bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
case CONTEXT_BUTTON_SET_CONTENT:
{
bool bScan=false;
- SScraperInfo info;
+ ADDON::ScraperPtr scraper;
CStdString path(item->m_strPath);
CQueryParams params;
CDirectoryNode::GetDatabaseInfo(item->m_strPath, params);
@@ -737,19 +737,24 @@ bool CGUIWindowMusicNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
else if (params.GetArtistId() != -1)
path.Format("musicdb://2/%i/",params.GetArtistId());
- if (!m_musicdatabase.GetScraperForPath(path,info))
- info.strContent = "albums";
+ if (!m_musicdatabase.GetScraperForPath(path,scraper))
+ {
+ ADDON::AddonPtr defaultScraper;
+ if (ADDON::CAddonMgr::Get()->GetDefault(ADDON::ADDON_SCRAPER, defaultScraper, CONTENT_ALBUMS))
+ {
+ scraper = boost::dynamic_pointer_cast<ADDON::CScraper>(defaultScraper->Clone(defaultScraper));
+ }
+ }
- int iLabel=132;
- // per genre or for all artists
+ CONTENT_TYPE context = CONTENT_ALBUMS;
if (m_vecItems->m_strPath.Left(12).Equals("musicdb://1/") || item->m_strPath.Left(12).Equals("musicdb://2/"))
{
- iLabel = 133;
+ context = CONTENT_ARTISTS;
}
- if (CGUIDialogContentSettings::Show(info, bScan,iLabel))
+ if (CGUIDialogContentSettings::Show(scraper, bScan, context))
{
- m_musicdatabase.SetScraperForPath(path,info);
+ m_musicdatabase.SetScraperForPath(path,scraper);
if (bScan)
OnInfoAll(itemNumber,true);
}
diff --git a/xbmc/GUIWindowScreensaver.cpp b/xbmc/GUIWindowScreensaver.cpp
index 1f7c369320..023eeeb927 100644
--- a/xbmc/GUIWindowScreensaver.cpp
+++ b/xbmc/GUIWindowScreensaver.cpp
@@ -21,9 +21,7 @@
#include "system.h"
#include "GUIWindowScreensaver.h"
-#ifdef HAS_SCREENSAVER
-#include "screensavers/ScreenSaverFactory.h"
-#endif
+#include "utils/AddonManager.h"
#include "Application.h"
#include "GUIPassword.h"
#include "GUISettings.h"
@@ -36,6 +34,7 @@ CGUIWindowScreensaver::CGUIWindowScreensaver(void)
{
#ifdef HAS_SCREENSAVER
m_pScreenSaver = NULL;
+ m_addon.reset();
#endif
}
@@ -62,7 +61,7 @@ void CGUIWindowScreensaver::Render()
}
catch (...)
{
- OutputDebugString("Screensaver Render - ohoh!\n");
+ CLog::Log(LOGERROR, "SCREENSAVER: - Exception in Render() - %s", m_addon->Name().c_str());
}
return ;
}
@@ -75,7 +74,7 @@ void CGUIWindowScreensaver::Render()
}
catch (...)
{
- OutputDebugString("Screensaver Start - ohoh!\n");
+ CLog::Log(LOGERROR, "SCREENSAVER: - Exception in Start() - %s", m_addon->Name().c_str());
}
return ;
}
@@ -107,10 +106,8 @@ bool CGUIWindowScreensaver::OnMessage(CGUIMessage& message)
#ifdef HAS_SCREENSAVER
if (m_pScreenSaver)
{
- OutputDebugString("ScreenSaver::Stop()\n");
+ CLog::Log(LOGDEBUG, "SCREENSAVER: - Stopping - %s", m_addon->Name().c_str());
m_pScreenSaver->Stop();
-
- OutputDebugString("delete ScreenSaver()\n");
delete m_pScreenSaver;
g_graphicsContext.ApplyStateBlock();
@@ -140,20 +137,23 @@ bool CGUIWindowScreensaver::OnMessage(CGUIMessage& message)
delete m_pScreenSaver;
g_graphicsContext.ApplyStateBlock();
}
- m_pScreenSaver = NULL;
m_bInitialized = false;
+ m_addon.reset();
// Setup new screensaver instance
- CScreenSaverFactory factory;
- CStdString strScr;
- OutputDebugString("Load Screensaver\n");
- strScr.Format("special://xbmc/screensavers/%s", g_guiSettings.GetString("screensaver.mode").c_str());
- m_pScreenSaver = factory.LoadScreenSaver(strScr.c_str());
+ ADDON::AddonPtr addon;
+ if (!ADDON::CAddonMgr::Get()->GetAddon(ADDON::ADDON_SCREENSAVER, g_guiSettings.GetString("screensaver.mode"), addon))
+ return false;
+ m_addon = boost::dynamic_pointer_cast<CScreenSaver>(addon);
+
+ if (!m_addon)
+ return false;
+
+ m_pScreenSaver = NULL; //TODO addonmanager loader /*factory.LoadScreenSaver(m_addon);*/
if (m_pScreenSaver)
{
- OutputDebugString("ScreenSaver::Create()\n");
g_graphicsContext.CaptureStateBlock();
- m_pScreenSaver->Create();
+ m_addon->Create();
}
#endif
// setup a z-buffer
diff --git a/xbmc/GUIWindowScreensaver.h b/xbmc/GUIWindowScreensaver.h
index 8f983db272..5a776e3c16 100644
--- a/xbmc/GUIWindowScreensaver.h
+++ b/xbmc/GUIWindowScreensaver.h
@@ -51,4 +51,5 @@ private:
#endif
bool m_bInitialized;
CCriticalSection m_critSection;
+ boost::shared_ptr<CScreenSaver> m_addon;
};
diff --git a/xbmc/GUIWindowScripts.cpp b/xbmc/GUIWindowScripts.cpp
index 41bb77801c..77a6062640 100644
--- a/xbmc/GUIWindowScripts.cpp
+++ b/xbmc/GUIWindowScripts.cpp
@@ -29,8 +29,8 @@
#include "GUIWindowManager.h"
#include "FileSystem/File.h"
#include "FileItem.h"
-#include "ScriptSettings.h"
-#include "GUIDialogPluginSettings.h"
+#include "utils/AddonManager.h"
+#include "GUIDialogAddonSettings.h"
#include "Settings.h"
#include "LocalizeStrings.h"
#if defined(__APPLE__)
@@ -74,7 +74,7 @@ bool CGUIWindowScripts::OnMessage(CGUIMessage& message)
case GUI_MSG_WINDOW_INIT:
{
if (m_vecItems->m_strPath == "?")
- m_vecItems->m_strPath = g_settings.GetScriptsFolder();
+ m_vecItems->m_strPath = "special://scripts/";
return CGUIMediaWindow::OnMessage(message);
}
break;
@@ -245,8 +245,14 @@ void CGUIWindowScripts::GetContextButtons(int itemNumber, CContextButtons &butto
{
CStdString path, filename;
CUtil::Split(item->m_strPath, path, filename);
- if (CScriptSettings::SettingsExist(path))
- buttons.Add(CONTEXT_BUTTON_SCRIPT_SETTINGS, 1049);
+ ADDON::AddonPtr script;
+ if (ADDON::CAddonMgr::Get()->GetAddon(ADDON::ADDON_SCRIPT, item->m_strPath, script))
+ {
+ if (script->HasSettings())
+ {
+ buttons.Add(CONTEXT_BUTTON_SCRIPT_SETTINGS, 1049);
+ }
+ }
}
buttons.Add(CONTEXT_BUTTON_INFO, 654);
@@ -264,8 +270,12 @@ bool CGUIWindowScripts::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
{
CStdString path, filename;
CUtil::Split(m_vecItems->Get(itemNumber)->m_strPath, path, filename);
- if(CGUIDialogPluginSettings::ShowAndGetInput(path))
- Update(m_vecItems->m_strPath);
+ ADDON::AddonPtr script;
+ if (ADDON::CAddonMgr::Get()->GetAddon(ADDON::ADDON_SCRIPT, m_vecItems->Get(itemNumber)->m_strPath, script))
+ {
+ if (CGUIDialogAddonSettings::ShowAndGetInput(script))
+ Update(m_vecItems->m_strPath);
+ }
return true;
}
else if (button == CONTEXT_BUTTON_DELETE)
diff --git a/xbmc/GUIWindowSettingsCategory.cpp b/xbmc/GUIWindowSettingsCategory.cpp
index 9be0de8509..40ecab546c 100644
--- a/xbmc/GUIWindowSettingsCategory.cpp
+++ b/xbmc/GUIWindowSettingsCategory.cpp
@@ -39,7 +39,6 @@
#ifdef HAS_LCD
#include "utils/LCDFactory.h"
#endif
-#include "visualizations/VisualisationFactory.h"
#include "PlayListPlayer.h"
#include "SkinInfo.h"
#include "GUIAudioManager.h"
@@ -51,11 +50,14 @@
#include "GUIDialogGamepad.h"
#include "GUIDialogNumeric.h"
#include "GUIDialogFileBrowser.h"
+#include "GUIDialogAddonSettings.h"
#include "GUIDialogContextMenu.h"
#include "GUIDialogKeyboard.h"
#include "GUIDialogYesNo.h"
#include "GUIDialogOK.h"
#include "GUIWindowPrograms.h"
+#include "visualizations/Visualisation.h"
+#include "AddonManager.h"
#include "MediaManager.h"
#include "utils/Network.h"
#include "GUIControlGroupList.h"
@@ -92,9 +94,6 @@
#include "cores/AudioRenderers/AudioRendererFactory.h"
#endif
#include <map>
-#include "ScraperSettings.h"
-#include "ScriptSettings.h"
-#include "GUIDialogPluginSettings.h"
#include "Settings.h"
#include "AdvancedSettings.h"
#include "MouseStat.h"
@@ -109,6 +108,7 @@
using namespace std;
using namespace XFILE;
+using namespace ADDON;
#define CONTROL_GROUP_BUTTONS 0
#define CONTROL_GROUP_SETTINGS 1
@@ -441,22 +441,22 @@ void CGUIWindowSettingsCategory::CreateSettings()
else if (strSetting.Equals("musiclibrary.scraper"))
{
CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID());
- FillInScrapers(pControl, g_guiSettings.GetString("musiclibrary.scraper"), "music");
+ FillInScrapers(pControl, g_guiSettings.GetString("musiclibrary.scraper"), CONTENT_ALBUMS);
}
else if (strSetting.Equals("scrapers.moviedefault"))
{
CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID());
- FillInScrapers(pControl, g_guiSettings.GetString("scrapers.moviedefault"), "movies");
+ FillInScrapers(pControl, g_guiSettings.GetString("scrapers.moviedefault"), CONTENT_MOVIES);
}
else if (strSetting.Equals("scrapers.tvshowdefault"))
{
CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID());
- FillInScrapers(pControl, g_guiSettings.GetString("scrapers.tvshowdefault"), "tvshows");
+ FillInScrapers(pControl, g_guiSettings.GetString("scrapers.tvshowdefault"), CONTENT_TVSHOWS);
}
else if (strSetting.Equals("scrapers.musicvideodefault"))
{
CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID());
- FillInScrapers(pControl, g_guiSettings.GetString("scrapers.musicvideodefault"), "musicvideos");
+ FillInScrapers(pControl, g_guiSettings.GetString("scrapers.musicvideodefault"), CONTENT_MUSICVIDEOS);
}
else if (strSetting.Equals("videooutput.aspect"))
{
@@ -672,10 +672,10 @@ void CGUIWindowSettingsCategory::CreateSettings()
pControl->AddLabel(g_localizeStrings.Get(13509), RESAMPLE_REALLYHIGH);
pControl->SetValue(pSettingInt->GetData());
}
- else if (strSetting.Equals("weather.plugin"))
+ else if (strSetting.Equals("weather.script"))
{
CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(GetSetting(pSetting->GetSetting())->GetID());
- FillInWeatherPlugins(pControl, g_guiSettings.GetString("weather.plugin"));
+ FillInWeatherScripts(pControl, g_guiSettings.GetString("weather.script"));
}
}
@@ -1021,13 +1021,13 @@ void CGUIWindowSettingsCategory::UpdateSettings()
CGUIButtonControl *pControl = (CGUIButtonControl *)GetControl(GetSetting(strSetting)->GetID());
pControl->SetLabel2(CWeather::GetAreaCity(pSetting->GetData()));
}
- else if (strSetting.Equals("weather.plugin"))
+ else if (strSetting.Equals("weather.script"))
{
CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID());
if (pControl->GetCurrentLabel().Equals(g_localizeStrings.Get(13611)))
- g_guiSettings.SetString("weather.plugin", "");
+ g_guiSettings.SetString("weather.script", "");
else
- g_guiSettings.SetString("weather.plugin", pControl->GetCurrentLabel());
+ g_guiSettings.SetString("weather.script", pControl->GetCurrentLabel());
}
else if (strSetting.Equals("musicfiles.trackformat"))
{
@@ -1063,16 +1063,6 @@ void CGUIWindowSettingsCategory::UpdateSettings()
CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
pControl->SetEnabled(XFILE::CFile::Exists(RSSEDITOR_PATH) && g_guiSettings.GetBool("lookandfeel.enablerssfeeds"));
}
- else if (strSetting.Equals("musiclibrary.scrapersettings"))
- {
- CScraperParser parser;
- bool enabled=false;
- if (parser.Load("special://xbmc/system/scrapers/music/"+g_guiSettings.GetString("musiclibrary.scraper")))
- enabled = parser.HasFunction("GetSettings");
-
- CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
- if (pControl) pControl->SetEnabled(enabled);
- }
else if (strSetting.Equals("videoplayer.synctype"))
{
CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
@@ -1098,12 +1088,12 @@ void CGUIWindowSettingsCategory::UpdateSettings()
pControl->SetEnabled(enabled);
}
}
- else if (strSetting.Equals("weather.pluginsettings"))
+ else if (strSetting.Equals("weather.scriptsettings"))
{
- // Create our base path
- CStdString basepath = "special://home/plugins/weather/" + g_guiSettings.GetString("weather.plugin");
- CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
- if (pControl) pControl->SetEnabled(!g_guiSettings.GetString("weather.plugin").IsEmpty() && CScriptSettings::SettingsExist(basepath));
+ //// Create our base path
+ //CStdString basepath = "special://home/plugins/weather/" + g_guiSettings.GetString("weather.plugin");
+ //CGUIControl *pControl = (CGUIControl *)GetControl(pSettingControl->GetID());
+ //if (pControl) pControl->SetEnabled(!g_guiSettings.GetString("weather.plugin").IsEmpty() && CScriptSettings::SettingsExist(basepath));
}
#if defined(_LINUX) && !defined(__APPLE__)
else if (strSetting.Equals("audiooutput.custompassthrough"))
@@ -1147,33 +1137,22 @@ void CGUIWindowSettingsCategory::OnClick(CBaseSettingControl *pSettingControl)
g_weatherManager.Refresh();
}
}
- else if (strSetting.Equals("weather.plugin"))
+ else if (strSetting.Equals("weather.script"))
{
g_weatherManager.Refresh();
}
- else if (strSetting.Equals("weather.pluginsettings"))
+ else if (strSetting.Equals("weather.scriptsettings"))
{
- // Create our base path
- CStdString basepath = "special://home/plugins/weather/" + g_guiSettings.GetString("weather.plugin");
- CGUIDialogPluginSettings::ShowAndGetInput(basepath);
- // TODO: maybe have ShowAndGetInput return a bool if settings changed, then only reset weather if true.
+ CStdString name = g_guiSettings.GetString("weather.script");
+ AddonPtr addon;
+ if (CAddonMgr::Get()->GetAddon(ADDON_PLUGIN, name, addon))
+ { // TODO: maybe have ShowAndGetInput return a bool if settings changed, then only reset weather if true.
+ CGUIDialogAddonSettings::ShowAndGetInput(addon);
+ }
g_weatherManager.Refresh();
}
else if (strSetting.Equals("lookandfeel.rssedit"))
CBuiltins::Execute("RunScript("RSSEDITOR_PATH")");
- else if (strSetting.Equals("musiclibrary.scrapersettings"))
- {
- CMusicDatabase database;
- database.Open();
- SScraperInfo info;
- database.GetScraperForPath("musicdb://",info);
-
- if (info.settings.LoadSettingsXML("special://xbmc/system/scrapers/music/" + info.strPath))
- CGUIDialogPluginSettings::ShowAndGetInput(info);
-
- database.SetScraperForPath("musicdb://",info);
- database.Close();
- }
// if OnClick() returns false, the setting hasn't changed or doesn't
// require immediate update
@@ -1218,7 +1197,7 @@ void CGUIWindowSettingsCategory::OnSettingChanged(CBaseSettingControl *pSettingC
if (pControl->GetValue() == 0)
pSettingString->SetData("None");
else
- pSettingString->SetData( CVisualisation::GetCombinedName( pControl->GetCurrentLabel() ) );
+ pSettingString->SetData(pControl->GetCurrentLabel());
}
else if (strSetting.Equals("debug.showloginfo"))
{
@@ -1248,22 +1227,22 @@ void CGUIWindowSettingsCategory::OnSettingChanged(CBaseSettingControl *pSettingC
else if (strSetting.Equals("musiclibrary.scraper"))
{
CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID());
- FillInScrapers(pControl, pControl->GetCurrentLabel(), "music");
+ FillInScrapers(pControl, pControl->GetCurrentLabel(), CONTENT_ALBUMS);
}
else if (strSetting.Equals("scrapers.moviedefault"))
{
CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID());
- FillInScrapers(pControl, pControl->GetCurrentLabel(), "movies");
+ FillInScrapers(pControl, pControl->GetCurrentLabel(), CONTENT_MOVIES); //TODO langify these
}
else if (strSetting.Equals("scrapers.tvshowdefault"))
{
CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID());
- FillInScrapers(pControl, pControl->GetCurrentLabel(), "tvshows");
+ FillInScrapers(pControl, pControl->GetCurrentLabel(), CONTENT_TVSHOWS);
}
else if (strSetting.Equals("scrapers.musicvideodefault"))
{
CGUISpinControlEx *pControl = (CGUISpinControlEx *)GetControl(pSettingControl->GetID());
- FillInScrapers(pControl, pControl->GetCurrentLabel(), "musicvideos");
+ FillInScrapers(pControl, pControl->GetCurrentLabel(), CONTENT_MUSICVIDEOS);
}
else if (strSetting.Equals("videolibrary.cleanup"))
{
@@ -1710,7 +1689,7 @@ void CGUIWindowSettingsCategory::OnSettingChanged(CBaseSettingControl *pSettingC
else if (iValue == 4)
strScreenSaver = "Fanart Slideshow"; //Fanart Slideshow
else
- strScreenSaver = pControl->GetCurrentLabel() + ".xbs";
+ strScreenSaver = pControl->GetCurrentLabel();
pSettingString->SetData(strScreenSaver);
}
else if (strSetting.Equals("screensaver.preview"))
@@ -2468,60 +2447,36 @@ void CGUIWindowSettingsCategory::FillInVisualisations(CSetting *pSetting, int iC
CGUIMessage msg(GUI_MSG_LABEL_RESET, iWinID, iControlID);
g_windowManager.SendMessage(msg);
}
+
vector<CStdString> vecVis;
- //find visz....
- CFileItemList items;
- CDirectory::GetDirectory("special://xbmc/visualisations/", items);
- if (!CSpecialProtocol::XBMCIsHome())
- CDirectory::GetDirectory("special://home/visualisations/", items);
+ VECADDONS addons;
- CVisualisationFactory visFactory;
- CStdString strExtension;
- for (int i = 0; i < items.Size(); ++i)
+ CAddonMgr::Get()->GetAddons(ADDON_VIZ, addons);
+ if (!addons.empty())
{
- CFileItemPtr pItem = items[i];
- if (!pItem->m_bIsFolder)
+ for (unsigned int i = 0; i < addons.size(); i++)
{
- const char *visPath = (const char*)pItem->m_strPath;
-
- CUtil::GetExtension(pItem->m_strPath, strExtension);
- if (strExtension == ".vis") // normal visualisation
+ const AddonPtr addon = addons.at(i);
+ boost::shared_ptr<CVisualisation> vis = boost::dynamic_pointer_cast<CVisualisation>(addon);
+ if (vis->HasSubModules())
{
- if(!CVisualisation::IsValidVisualisation(pItem->m_strPath))
+ vector<CStdString> modules;
+ if (!vis->GetSubModuleList(modules))
continue;
- CStdString strLabel = pItem->GetLabel();
- vecVis.push_back( CVisualisation::GetFriendlyName( strLabel ) );
- }
- else if ( strExtension == ".mvis" ) // multi visualisation with sub modules
- {
- CVisualisation* vis = visFactory.LoadVisualisation( visPath );
- if ( vis )
+ else
{
- map<string, string> subModules;
- map<string, string>::iterator iter;
- string moduleName;
- CStdString visName = pItem->GetLabel();
- visName = visName.Mid(0, visName.size() - 5);
-
- // get list of sub modules from the visualisation
- vis->GetSubModules( subModules );
-
- for ( iter=subModules.begin() ; iter!=subModules.end() ; iter++ )
- {
- // each pair of the map is of the format 'module name' => 'module path'
- moduleName = iter->first;
- vecVis.push_back( CVisualisation::GetFriendlyName( visName.c_str(), moduleName.c_str() ).c_str() );
- CLog::Log(LOGDEBUG, "Module %s for visualisation %s", moduleName.c_str(), visPath);
- }
- delete vis;
+ for (unsigned i=0; i<modules.size(); i++)
+ vecVis.push_back(CVisualisation::GetFriendlyName(addon->Name(), modules[i]));
}
}
+ else
+ vecVis.push_back(addon->Name());
}
}
CStdString strDefaultVis = pSettingString->GetData();
if (!strDefaultVis.Equals("None"))
- strDefaultVis = CVisualisation::GetFriendlyName( strDefaultVis );
+ strDefaultVis = strDefaultVis;
sort(vecVis.begin(), vecVis.end(), sortstringbyname());
@@ -2621,43 +2576,21 @@ void CGUIWindowSettingsCategory::FillInScreenSavers(CSetting *pSetting)
pControl->AddLabel(g_localizeStrings.Get(108), 3); // PictureSlideShow
pControl->AddLabel(g_localizeStrings.Get(20425), 4); // Fanart Slideshow
- //find screensavers ....
- CFileItemList items;
- CDirectory::GetDirectory( "special://xbmc/screensavers/", items);
- if (!CSpecialProtocol::XBMCIsHome())
- CDirectory::GetDirectory("special://home/screensavers/", items);
-
int iCurrentScr = -1;
vector<CStdString> vecScr;
- for (int i = 0; i < items.Size(); ++i)
+ VECADDONS addons;
+
+ CAddonMgr::Get()->GetAddons(ADDON_SCREENSAVER, addons);
+ if (!addons.empty())
{
- CFileItemPtr pItem = items[i];
- if (!pItem->m_bIsFolder)
+ for (unsigned int i = 0; i < addons.size(); i++)
{
- CStdString strExtension;
- CUtil::GetExtension(pItem->m_strPath, strExtension);
- if (strExtension == ".xbs")
- {
-#ifdef _LINUX
- void *handle = dlopen(_P(pItem->m_strPath).c_str(), RTLD_LAZY);
- if (!handle)
- {
- CLog::Log(LOGERROR, "FillInScreensavers: Unable to load %s, reason: %s", pItem->m_strPath.c_str(), dlerror());
- continue;
- }
- dlclose(handle);
-#endif
- CStdString strLabel = pItem->GetLabel();
- vecScr.push_back(strLabel.Mid(0, strLabel.size() - 4));
- }
+ const AddonPtr addon = addons.at(i);
+ vecScr.push_back(addon->Name());
}
}
CStdString strDefaultScr = pSettingString->GetData();
- CStdString strExtension;
- CUtil::GetExtension(strDefaultScr, strExtension);
- if (strExtension == ".xbs")
- strDefaultScr.Delete(strDefaultScr.size() - 4, 4);
sort(vecScr.begin(), vecScr.end(), sortstringbyname());
for (int i = 0; i < (int) vecScr.size(); ++i)
@@ -2973,58 +2906,52 @@ void CGUIWindowSettingsCategory::FillInSortMethods(CSetting *pSetting, int windo
delete state;
}
-void CGUIWindowSettingsCategory::FillInScrapers(CGUISpinControlEx *pControl, const CStdString& strSelected, const CStdString& strContent)
+void CGUIWindowSettingsCategory::FillInScrapers(CGUISpinControlEx *pControl, const CStdString& strSelected, const CONTENT_TYPE& content)
{
- CFileItemList items;
- if (strContent.Equals("music"))
- CDirectory::GetDirectory("special://xbmc/system/scrapers/music",items,".xml",false);
- else
- CDirectory::GetDirectory("special://xbmc/system/scrapers/video",items,".xml",false);
- int j=0;
- int k=0;
+ VECADDONS addons;
pControl->Clear();
- for ( int i=0;i<items.Size();++i)
- {
- if (items[i]->m_bIsFolder)
- continue;
-
- CScraperParser parser;
- if (parser.Load(items[i]->m_strPath))
- {
- if (parser.GetContent() != strContent && !strContent.Equals("music"))
- continue;
-
- if (parser.GetName().Equals(strSelected) || CUtil::GetFileName(items[i]->m_strPath).Equals(strSelected))
- {
- if (strContent.Equals("music")) // native strContent would be albums or artists but we're using the same scraper for both
- {
- if (g_guiSettings.GetString("musiclibrary.scraper") != strSelected)
- {
- g_guiSettings.SetString("musiclibrary.scraper", CUtil::GetFileName(items[i]->m_strPath));
-
- SScraperInfo info;
- CMusicDatabase database;
- info.strPath = g_guiSettings.GetString("musiclibrary.scraper");
- info.strContent = "albums";
- info.strTitle = parser.GetName();
+ if (content == CONTENT_ALBUMS || content == CONTENT_ALBUMS || content == CONTENT_ARTISTS)
+ CAddonMgr::Get()->GetAddons(ADDON_SCRAPER, addons, CONTENT_ALBUMS);
+ else if (content == CONTENT_MOVIES)
+ CAddonMgr::Get()->GetAddons(ADDON_SCRAPER, addons, CONTENT_MOVIES);
+ else if (content == CONTENT_TVSHOWS || content == CONTENT_EPISODES)
+ CAddonMgr::Get()->GetAddons(ADDON_SCRAPER, addons, CONTENT_TVSHOWS);
+ else if (content == CONTENT_MUSICVIDEOS)
+ CAddonMgr::Get()->GetAddons(ADDON_SCRAPER, addons, CONTENT_MUSICVIDEOS);
+ else if (content == CONTENT_PROGRAMS)
+ CAddonMgr::Get()->GetAddons(ADDON_SCRAPER, addons, CONTENT_PROGRAMS);
+
+ if (addons.empty())
+ {
+ pControl->AddLabel(g_localizeStrings.Get(231), 0); // "None"
+ pControl->SetValue(0);
+ return;
+ }
- database.Open();
- database.SetScraperForPath("musicdb://",info);
- database.Close();
- }
- }
- else if (strContent.Equals("movies"))
- g_guiSettings.SetString("scrapers.moviedefault", CUtil::GetFileName(items[i]->m_strPath));
- else if (strContent.Equals("tvshows"))
- g_guiSettings.SetString("scrapers.tvshowdefault", CUtil::GetFileName(items[i]->m_strPath));
- else if (strContent.Equals("musicvideos"))
- g_guiSettings.SetString("scrapers.musicvideodefault", CUtil::GetFileName(items[i]->m_strPath));
- k = j;
- }
- pControl->AddLabel(parser.GetName(),j++);
+ int j = 0;
+ int k = 0;
+ for (IVECADDONS it = addons.begin(); it != addons.end(); it++)
+ {
+ if ((*it)->Name().Equals(strSelected))
+ {
+ if (content == CONTENT_ALBUMS) // native strContent would be albums or artists but we're using the same scraper for both
+ g_guiSettings.SetString("musiclibrary.scraper", (*it)->Name());
+ else if (content == CONTENT_MOVIES)
+ g_guiSettings.SetString("scrapers.moviedefault", (*it)->Name());
+ else if (content == CONTENT_TVSHOWS)
+ g_guiSettings.SetString("scrapers.tvshowdefault", (*it)->Name());
+ else if (content == CONTENT_MUSICVIDEOS)
+ g_guiSettings.SetString("scrapers.musicvideodefault", (*it)->Name());
+ else if (content == CONTENT_PROGRAMS)
+ g_guiSettings.SetString("programfiles.defaultscraper", (*it)->Name());
+ k = j;
}
+ pControl->AddLabel((*it)->Name(),j++);
}
+ if (j == 0)
+ pControl->AddLabel(g_localizeStrings.Get(231), 0); // "None"
+
pControl->SetValue(k);
}
@@ -3150,33 +3077,31 @@ void CGUIWindowSettingsCategory::FillInAudioDevices(CSetting* pSetting, bool Pas
#endif
}
-void CGUIWindowSettingsCategory::FillInWeatherPlugins(CGUISpinControlEx *pControl, const CStdString& strSelected)
+void CGUIWindowSettingsCategory::FillInWeatherScripts(CGUISpinControlEx *pControl, const CStdString& strSelected)
{
+ VECADDONS addons;
int j=0;
int k=0;
pControl->Clear();
// add our disable option
pControl->AddLabel(g_localizeStrings.Get(13611), j++);
- CFileItemList items;
- if (CDirectory::GetDirectory("special://home/plugins/weather/", items, "/", false))
+ //find weather scripts....
+ CAddonMgr::Get()->GetAddons(ADDON_SCRIPT, addons);
+ if (!addons.empty())
{
- for (int i=0; i<items.Size(); ++i)
+ for (unsigned int i = 0; i < addons.size(); i++)
{
+ AddonPtr addon = addons.at(i);
// create the full path to the plugin
- CStdString plugin;
- CStdString pluginPath = items[i]->m_strPath;
- // remove slash at end so we can use the plugins folder as plugin name
- CUtil::RemoveSlashAtEnd(pluginPath);
- // add default.py to our plugin path to create the full path
- CUtil::AddFileToFolder(pluginPath, "default.py", plugin);
- if (XFILE::CFile::Exists(plugin))
+ CStdString strFileName = addon->Path() + addon->LibName();
+ if (XFILE::CFile::Exists(strFileName))
{
// is this the users choice
- if (CUtil::GetFileName(pluginPath).Equals(strSelected))
+ if (addon->Name().Equals(strSelected))
k = j;
// we want to use the plugins folder as name
- pControl->AddLabel(CUtil::GetFileName(pluginPath), j++);
+ pControl->AddLabel(addon->Name(), j++);
}
}
}
diff --git a/xbmc/GUIWindowSettingsCategory.h b/xbmc/GUIWindowSettingsCategory.h
index 701ed02d4e..178107abcc 100644
--- a/xbmc/GUIWindowSettingsCategory.h
+++ b/xbmc/GUIWindowSettingsCategory.h
@@ -25,6 +25,7 @@
#include "SettingsControls.h"
#include "GUISettings.h"
#include "utils/Stopwatch.h"
+#include "IAddon.h"
class CGUIWindowSettingsCategory :
public CGUIWindow
@@ -64,10 +65,10 @@ protected:
void FillInNetworkInterfaces(CSetting *pSetting);
void NetworkInterfaceChanged(void);
- void FillInScrapers(CGUISpinControlEx *pControl, const CStdString& strSelected, const CStdString& strContent);
+ void FillInScrapers(CGUISpinControlEx *pControl, const CStdString& strSelected, const CONTENT_TYPE& content);
void FillInAudioDevices(CSetting* pSetting, bool Passthrough = false);
- void FillInWeatherPlugins(CGUISpinControlEx *pControl, const CStdString& strSelected);
+ void FillInWeatherScripts(CGUISpinControlEx *pControl, const CStdString& strSelected);
virtual void SetupControls();
void CreateSettings();
diff --git a/xbmc/GUIWindowVideoBase.cpp b/xbmc/GUIWindowVideoBase.cpp
index bd10cea68b..8c14d00f65 100644
--- a/xbmc/GUIWindowVideoBase.cpp
+++ b/xbmc/GUIWindowVideoBase.cpp
@@ -25,6 +25,8 @@
#include "utils/IMDB.h"
#include "utils/RegExp.h"
#include "utils/GUIInfoManager.h"
+#include "utils/AddonManager.h"
+#include "utils/IAddon.h"
#include "GUIWindowVideoInfo.h"
#include "GUIWindowVideoNav.h"
#include "GUIDialogFileBrowser.h"
@@ -68,6 +70,7 @@ using namespace XFILE;
using namespace PLAYLIST;
using namespace VIDEODATABASEDIRECTORY;
using namespace VIDEO;
+using namespace ADDON;
#define CONTROL_BTNVIEWASICONS 2
#define CONTROL_BTNSORTBY 3
@@ -182,7 +185,6 @@ bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message)
}
else if (iAction == ACTION_SHOW_INFO)
{
- SScraperInfo info;
if (iItem < 0 || iItem >= m_vecItems->Size())
return false;
@@ -191,11 +193,8 @@ bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message)
if (item->m_strPath.Equals("add") || item->IsParentFolder())
return false;
- if (m_vecItems->IsPlugin() || m_vecItems->IsRSS())
- info.strContent = "plugin";
- else if(m_vecItems->IsLiveTV())
- info.strContent = "livetv";
- else
+ ADDON::ScraperPtr scraper;
+ if (!m_vecItems->IsPlugin() && !m_vecItems->IsRSS() && !m_vecItems->IsLiveTV())
{
CStdString strDir;
if (item->IsVideoDb() &&
@@ -209,9 +208,9 @@ bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message)
SScanSettings settings;
int iFound;
- m_database.GetScraperForPath(strDir, info, settings, iFound);
+ m_database.GetScraperForPath(strDir, scraper, settings, iFound);
- if (info.strContent.IsEmpty() &&
+ if (!scraper &&
!(m_database.HasMovieInfo(item->m_strPath) ||
m_database.HasTvShowInfo(strDir) ||
m_database.HasEpisodeInfo(item->m_strPath)))
@@ -223,16 +222,16 @@ bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message)
CStdString strOldPath = item->m_strPath;
item->m_strPath = strDir;
- OnAssignContent(iItem,1, info, settings);
+ OnAssignContent(iItem,1, scraper, settings);
item->m_strPath = strOldPath;
return true;
}
- if (info.strContent.Equals("tvshows") && iFound == 1 && !settings.parent_name_root) // dont lookup on root tvshow folder
+ if (scraper->Content() == CONTENT_TVSHOWS && iFound == 1 && !settings.parent_name_root) // dont lookup on root tvshow folder
return true;
}
- OnInfo(item.get(),info);
+ OnInfo(item.get(),scraper);
return true;
}
@@ -266,7 +265,7 @@ bool CGUIWindowVideoBase::OnMessage(CGUIMessage& message)
}
else if (iControl == CONTROL_IMDB)
{
- OnManualIMDB();
+ OnManualScrape();
}
}
break;
@@ -300,11 +299,14 @@ void CGUIWindowVideoBase::UpdateButtons()
CGUIMediaWindow::UpdateButtons();
}
-void CGUIWindowVideoBase::OnInfo(CFileItem* pItem, const SScraperInfo& info)
+void CGUIWindowVideoBase::OnInfo(CFileItem* pItem, const ADDON::ScraperPtr& scraper)
{
if (!pItem)
return;
+ if (!scraper)
+ return;
+
if (pItem->IsParentFolder() || pItem->m_bIsShareOrDrive || pItem->m_strPath.Equals("add"))
return;
@@ -320,7 +322,7 @@ void CGUIWindowVideoBase::OnInfo(CFileItem* pItem, const SScraperInfo& info)
}
else
{
- if (item.m_bIsFolder && !info.strContent.Equals("tvshows"))
+ if (item.m_bIsFolder && scraper->Content() != CONTENT_TVSHOWS)
{
CFileItemList items;
CDirectory::GetDirectory(item.m_strPath, items);
@@ -351,8 +353,8 @@ void CGUIWindowVideoBase::OnInfo(CFileItem* pItem, const SScraperInfo& info)
}
}
- bool modified = ShowIMDB(&item, info);
- if (modified && !info.strContent.Equals("plugin") && !info.strContent.Equals("livetv") &&
+ bool modified = ShowIMDB(&item, scraper);
+ if (modified && scraper->Content() != CONTENT_PLUGIN &&
(g_windowManager.GetActiveWindow() == WINDOW_VIDEO_FILES ||
g_windowManager.GetActiveWindow() == WINDOW_VIDEO_NAV)) // since we can be called from the music library we need this check
{
@@ -383,7 +385,7 @@ void CGUIWindowVideoBase::OnInfo(CFileItem* pItem, const SScraperInfo& info)
// and show the information.
// 6. Check for a refresh, and if so, go to 3.
-bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
+bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const ScraperPtr &info2)
{
/*
CLog::Log(LOGDEBUG,"CGUIWindowVideoBase::ShowIMDB");
@@ -399,7 +401,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
CVideoInfoScanner scanner;
scanner.m_IMDB.SetScraperInfo(info2);
- SScraperInfo info(info2); // use this as nfo might change it..
+ ScraperPtr info(info2); // use this as nfo might change it..
if (!pDlgProgress) return false;
if (!pDlgSelect) return false;
@@ -413,7 +415,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
movieDetails.Reset();
m_database.Open(); // since we can be called from the music library
- if (info.strContent.Equals("movies"))
+ if (info->Content() == CONTENT_MOVIES)
{
if (m_database.HasMovieInfo(item->m_strPath))
{
@@ -421,7 +423,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
m_database.GetMovieInfo(item->m_strPath, movieDetails);
}
}
- if (info.strContent.Equals("tvshows"))
+ if (info->Content() == CONTENT_TVSHOWS)
{
if (item->m_bIsFolder)
{
@@ -462,7 +464,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
}
}
}
- if (info.strContent.Equals("musicvideos"))
+ if (info->Content() == CONTENT_MUSICVIDEOS)
{
if (m_database.HasMusicVideoInfo(item->m_strPath))
{
@@ -470,13 +472,12 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
m_database.GetMusicVideoInfo(item->m_strPath, movieDetails);
}
}
- if (info.strContent.Equals("plugin")
- || info.strContent.Equals("livetv"))
+ if (info->Content() == CONTENT_PLUGIN)
{
if (!item->HasVideoInfoTag())
return false;
movieDetails = *item->GetVideoInfoTag();
- movieDetails.m_strIMDBNumber = "xx" + info.strContent; // disable refresh+get thumb button
+ movieDetails.m_strIMDBNumber = "xx" + ADDON::TranslateContent(info->Content()); // disable refresh+get thumb button
bHasInfo = true;
}
@@ -484,7 +485,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
m_database.Close();
if (bHasInfo)
{
- if (info.strContent.IsEmpty()) // disable refresh button
+ if (info->Content() == CONTENT_NONE) // disable refresh button
movieDetails.m_strIMDBNumber = "xx"+movieDetails.m_strIMDBNumber;
*item->GetVideoInfoTag() = movieDetails;
pDlgInfo->SetMovie(item);
@@ -510,21 +511,18 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
m_database.Open();
// 2. Look for a nfo File to get the search URL
SScanSettings settings;
- m_database.GetScraperForPath(item->m_strPath,info,settings);
+ ADDON::AddonPtr addon;
- if (!info.settings.GetPluginRoot() && info.settings.GetSettings().IsEmpty()) // check for settings, if they are around load defaults - to workaround the nastyness
+ if (!m_database.GetScraperForPath(item->m_strPath,info,settings))
{
- CScraperParser parser;
- CStdString strPath;
- if (!info.strContent.IsEmpty())
- strPath = "special://xbmc/system/scrapers/video/"+info.strPath;
- if (!strPath.IsEmpty() && parser.Load(strPath) && parser.HasFunction("GetSettings"))
- {
- info.settings.LoadSettingsXML("special://xbmc/system/scrapers/video/" + info.strPath);
- info.settings.SaveFromDefault();
- }
+ if (!ADDON::CAddonMgr::Get()->GetDefault(ADDON::ADDON_SCRAPER, addon, info->Content()))
+ return false;
}
+ info = boost::dynamic_pointer_cast<ADDON::CScraper>(addon);
+ if (!info)
+ return false;
+
bool ignoreNfo(false);
CNfoFile::NFOResult nfoResult = scanner.CheckForNFOFile(item,settings.parent_name_root,info,scrUrl);
if (nfoResult == CNfoFile::ERROR_NFO)
@@ -548,7 +546,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
// 4. if we don't have an url, or need to refresh the search
// then do the web search
IMDB_MOVIELIST movielist;
- if (info.strContent.Equals("tvshows") && !item->m_bIsFolder)
+ if (info->Content() == CONTENT_TVSHOWS && !item->m_bIsFolder)
hasDetails = true;
if (!hasDetails && (scrUrl.m_url.size() == 0 || needsRefresh))
@@ -556,7 +554,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
// 4a. show dialog that we're busy querying www.imdb.com
CStdString strHeading;
scanner.m_IMDB.SetScraperInfo(info);
- strHeading.Format(g_localizeStrings.Get(197),info.strTitle.c_str());
+ strHeading.Format(g_localizeStrings.Get(197),info->Name().c_str());
pDlgProgress->SetHeading(strHeading);
pDlgProgress->SetLine(0, movieName);
pDlgProgress->SetLine(1, "");
@@ -572,7 +570,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
if (movielist.size() > 0)
{
int iString = 196;
- if (info.strContent.Equals("tvshows"))
+ if (info->Content() == CONTENT_TVSHOWS)
iString = 20356;
pDlgSelect->SetHeading(iString);
pDlgSelect->Reset();
@@ -613,7 +611,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
// Prompt the user to input the movieName
int iString = 16009;
- if (info.strContent.Equals("tvshows"))
+ if (info->Content() == CONTENT_TVSHOWS)
iString = 20357;
if (!CGUIDialogKeyboard::ShowAndGetInput(movieName, g_localizeStrings.Get(iString), false))
{
@@ -647,14 +645,14 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
CUtil::GetDirectory(strPath,list.m_strPath);
int iString=198;
- if (info.strContent.Equals("tvshows"))
+ if (info->Content() == CONTENT_TVSHOWS)
{
if (item->m_bIsFolder)
iString = 20353;
else
iString = 20361;
}
- if (info.strContent.Equals("musicvideos"))
+ if (info->Content() == CONTENT_MUSICVIDEOS)
iString = 20394;
pDlgProgress->SetHeading(iString);
pDlgProgress->SetLine(0, movieName);
@@ -664,13 +662,13 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
pDlgProgress->Progress();
if (bHasInfo)
{
- if (info.strContent.Equals("movies"))
+ if (info->Content() == CONTENT_MOVIES)
m_database.DeleteMovie(item->m_strPath);
- if (info.strContent.Equals("tvshows") && !item->m_bIsFolder)
+ if (info->Content() == CONTENT_TVSHOWS && !item->m_bIsFolder)
m_database.DeleteEpisode(item->m_strPath,movieDetails.m_iDbId);
- if (info.strContent.Equals("musicvideos"))
+ if (info->Content() == CONTENT_MUSICVIDEOS)
m_database.DeleteMusicVideo(item->m_strPath);
- if (info.strContent.Equals("tvshows") && item->m_bIsFolder)
+ if (info->Content() == CONTENT_TVSHOWS && item->m_bIsFolder)
{
if (pDlgInfo->RefreshAll())
m_database.DeleteTvShow(item->m_strPath);
@@ -680,11 +678,11 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
}
if (scanner.RetrieveVideoInfo(list,settings.parent_name_root,info,!pDlgInfo->RefreshAll(),&scrUrl,pDlgProgress,ignoreNfo))
{
- if (info.strContent.Equals("movies"))
+ if (info->Content() == CONTENT_MOVIES)
m_database.GetMovieInfo(item->m_strPath,movieDetails);
- if (info.strContent.Equals("musicvideos"))
+ if (info->Content() == CONTENT_MUSICVIDEOS)
m_database.GetMusicVideoInfo(item->m_strPath,movieDetails);
- if (info.strContent.Equals("tvshows"))
+ if (info->Content() == CONTENT_TVSHOWS)
{
// update tvshow info to get updated episode numbers
if (item->m_bIsFolder)
@@ -694,7 +692,7 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
}
// set path hash
- if (info.strContent.Equals("movies") || info.strContent.Equals("musicvideos"))
+ if (info->Content() == CONTENT_MOVIES || info->Content() == CONTENT_MUSICVIDEOS)
{
CStdString hash, strParent;
CFileItemList items;
@@ -767,8 +765,11 @@ bool CGUIWindowVideoBase::ShowIMDB(CFileItem *item, const SScraperInfo& info2)
return listNeedsUpdating;
}
-void CGUIWindowVideoBase::OnManualIMDB()
+void CGUIWindowVideoBase::OnManualScrape()
{
+ // NOTE! this only works for movies
+ // previous OnManualIMDB only worked for IMDb, so not a regression!
+ // if we were tracking current content type this would work for all content
CStdString strInput;
if (!CGUIDialogKeyboard::ShowAndGetInput(strInput, g_localizeStrings.Get(16009), false))
return;
@@ -777,12 +778,21 @@ void CGUIWindowVideoBase::OnManualIMDB()
item.m_strPath = "special://temp/";
CFile::Delete(item.GetCachedVideoThumb().c_str());
- SScraperInfo info;
- info.strContent = "movies";
- info.strPath = "imdb.xml";
- info.strTitle = "IMDb";
+ ScraperPtr scraper;
+ m_database.Open();
+ if (!m_database.GetScraperForPath(m_vecItems->m_strPath, scraper))
+ {
+ AddonPtr addon;
+ if (CAddonMgr::Get()->GetDefault(ADDON_SCRAPER, addon, CONTENT_MOVIES))
+ {
+ scraper = boost::dynamic_pointer_cast<CScraper>(addon);
+ }
+ }
+
+ if (!scraper)
+ return;
- ShowIMDB(&item,info);
+ ShowIMDB(&item,scraper);
return;
}
@@ -1234,7 +1244,7 @@ bool CGUIWindowVideoBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
case CONTEXT_BUTTON_INFO:
{
- SScraperInfo info;
+ ADDON::ScraperPtr info;
VIDEO::SScanSettings settings;
GetScraperForItem(item.get(), info, settings);
@@ -1253,7 +1263,7 @@ bool CGUIWindowVideoBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
{
if( !item)
return false;
- SScraperInfo info;
+ ADDON::ScraperPtr info;
SScanSettings settings;
GetScraperForItem(item.get(), info, settings);
CStdString strPath = item->m_strPath;
@@ -1263,7 +1273,7 @@ bool CGUIWindowVideoBase::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
if (item->IsVideoDb())
strPath = item->GetVideoInfoTag()->m_strPath;
- if (info.strContent.IsEmpty())
+ if (info->Content() == CONTENT_NONE)
return false;
if (item->m_bIsFolder)
@@ -1926,19 +1936,19 @@ void CGUIWindowVideoBase::OnSearchItemFound(const CFileItem* pSelItem)
m_viewControl.SetFocused();
}
-int CGUIWindowVideoBase::GetScraperForItem(CFileItem *item, SScraperInfo &info, SScanSettings& settings)
+int CGUIWindowVideoBase::GetScraperForItem(CFileItem *item, ADDON::ScraperPtr &info, SScanSettings& settings)
{
if (!item)
return 0;
if (m_vecItems->IsPlugin() || m_vecItems->IsRSS())
{
- info.strContent = "plugin";
+ info.reset();
return 0;
}
else if(m_vecItems->IsLiveTV())
{
- info.strContent = "livetv";
+ info.reset();
return 0;
}
@@ -1951,7 +1961,7 @@ int CGUIWindowVideoBase::GetScraperForItem(CFileItem *item, SScraperInfo &info,
return found;
}
-void CGUIWindowVideoBase::OnScan(const CStdString& strPath, const SScraperInfo& info, const SScanSettings& settings)
+void CGUIWindowVideoBase::OnScan(const CStdString& strPath, const ScraperPtr& info, const SScanSettings& settings)
{
CGUIDialogVideoScan* pDialog = (CGUIDialogVideoScan*)g_windowManager.GetWindow(WINDOW_DIALOG_VIDEO_SCAN);
if (pDialog)
diff --git a/xbmc/GUIWindowVideoBase.h b/xbmc/GUIWindowVideoBase.h
index 506339c485..0ec7ec9b85 100644
--- a/xbmc/GUIWindowVideoBase.h
+++ b/xbmc/GUIWindowVideoBase.h
@@ -38,8 +38,8 @@ public:
int GetResumeItemOffset(const CFileItem *item);
void AddToDatabase(int iItem);
- static void OnScan(const CStdString& strPath, const SScraperInfo& info, const VIDEO::SScanSettings& settings);
- virtual void OnInfo(CFileItem* pItem, const SScraperInfo& info);
+ static void OnScan(const CStdString& strPath, const ADDON::ScraperPtr& info, const VIDEO::SScanSettings& settings);
+ virtual void OnInfo(CFileItem* pItem, const ADDON::ScraperPtr& scraper);
virtual void OnStreamDetails(const CStreamDetails &details, const CStdString &strFileName, long lFileId);
static void MarkWatched(const CFileItemPtr &pItem, bool mark);
static void UpdateVideoTitle(const CFileItem* pItem);
@@ -61,7 +61,7 @@ protected:
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, VIDEO::SScanSettings& settings) {};
+ virtual void OnAssignContent(int iItem, int iFound, ADDON::ScraperPtr& scraper, VIDEO::SScanSettings& settings) {};
virtual void OnUnAssignContent(int iItem) {};
virtual void OnQueueItem(int iItem);
virtual void OnDeleteItem(CFileItemPtr pItem);
@@ -76,9 +76,9 @@ protected:
virtual bool OnPlayMedia(int iItem);
void LoadPlayList(const CStdString& strPlayList, int iPlayList = PLAYLIST_VIDEO);
- bool ShowIMDB(CFileItem *item, const SScraperInfo& info);
+ bool ShowIMDB(CFileItem *item, const ADDON::ScraperPtr& content);
- void OnManualIMDB();
+ void OnManualScrape();
bool CheckMovie(const CStdString& strFileName);
void AddItemToPlayList(const CFileItemPtr &pItem, CFileItemList &queuedItems);
@@ -86,7 +86,7 @@ protected:
void OnSearch();
void OnSearchItemFound(const CFileItem* pSelItem);
- int GetScraperForItem(CFileItem *item, SScraperInfo &info, VIDEO::SScanSettings& settings);
+ int GetScraperForItem(CFileItem *item, ADDON::ScraperPtr &info, VIDEO::SScanSettings& settings);
CGUIDialogProgress* m_dlgProgress;
CVideoDatabase m_database;
diff --git a/xbmc/GUIWindowVideoFiles.cpp b/xbmc/GUIWindowVideoFiles.cpp
index 64341d7dcd..60c9828e8f 100644
--- a/xbmc/GUIWindowVideoFiles.cpp
+++ b/xbmc/GUIWindowVideoFiles.cpp
@@ -274,13 +274,13 @@ bool CGUIWindowVideoFiles::GetDirectory(const CStdString &strDirectory, CFileIte
if (!CGUIWindowVideoBase::GetDirectory(strDirectory, items))
return false;
- SScraperInfo info2;
+ ADDON::ScraperPtr info2;
m_stackingAvailable = true;
m_cleaningAvailable = true;
- if ((m_database.GetScraperForPath(strDirectory,info2) && info2.strContent.Equals("tvshows")) || items.IsTuxBox())
+ if ((m_database.GetScraperForPath(strDirectory,info2) && info2->Content() == CONTENT_TVSHOWS) || items.IsTuxBox())
{ // dont stack or clean strings in tv dirs
m_stackingAvailable = false;
m_cleaningAvailable = false;
@@ -288,8 +288,8 @@ bool CGUIWindowVideoFiles::GetDirectory(const CStdString &strDirectory, CFileIte
else if (!items.IsStack() && g_settings.m_iMyVideoStack != STACK_NONE)
items.Stack();
- if ((!info2.strContent.IsEmpty() && !info2.strContent.Equals("None")) && items.GetContent().IsEmpty())
- items.SetContent(info2.strContent.c_str());
+ if (info2 && info2->Content() != CONTENT_NONE)
+ items.SetContent(ADDON::TranslateContent(info2->Content()));
else
items.SetContent("files");
@@ -313,11 +313,6 @@ void CGUIWindowVideoFiles::OnPrepareFileItems(CFileItemList &items)
}
}
-bool CGUIWindowVideoFiles::OnClick(int iItem)
-{
- return CGUIWindowVideoBase::OnClick(iItem);
-}
-
bool CGUIWindowVideoFiles::OnPlayMedia(int iItem)
{
if ( iItem < 0 || iItem >= (int)m_vecItems->Size() ) return false;
@@ -385,8 +380,9 @@ bool CGUIWindowVideoFiles::OnUnAssignContent(int iItem, int label1, int label2,
{
if (!bCanceled)
{
- SScraperInfo info;
+ ADDON::ScraperPtr info;
SScanSettings settings;
+ settings.exclude = true;
m_database.SetScraperForPath(m_vecItems->Get(iItem)->m_strPath,info,settings);
}
}
@@ -394,42 +390,35 @@ bool CGUIWindowVideoFiles::OnUnAssignContent(int iItem, int label1, int label2,
return false;
}
-void CGUIWindowVideoFiles::OnAssignContent(int iItem, int iFound, SScraperInfo& info, SScanSettings& settings)
+void CGUIWindowVideoFiles::OnAssignContent(int iItem, int iFound, ADDON::ScraperPtr& info, SScanSettings& settings)
{
CFileItemPtr item = m_vecItems->Get(iItem);
bool bScan=false;
if (iFound == 0)
{
- m_database.GetScraperForPath(item->m_strPath,info, settings,iFound);
+ m_database.GetScraperForPath(item->m_strPath,info,settings,iFound);
}
- SScraperInfo info2 = info;
- SScanSettings settings2 = settings;
- if (CGUIDialogContentSettings::Show(info2, settings2, bScan))
+ if (CGUIDialogContentSettings::Show(info, settings, bScan))
{
- if((info2.strContent.IsEmpty() || info2.strContent.Equals("None")) &&
- (!info.strContent.IsEmpty() && !info.strContent.Equals("None")))
+ if(settings.exclude || !info)
{
OnUnAssignContent(iItem,20375,20340,20341);
}
- if (!info.strContent.IsEmpty() &&
- !info2.strContent.IsEmpty() &&
- !info.strContent.Equals("None") &&
- (info2.strContent != info.strContent ||
- !info.strPath.Equals(info2.strPath)))
+ else
{
if (OnUnAssignContent(iItem,20442,20443,20444))
bScan = true;
}
m_database.Open();
- m_database.SetScraperForPath(item->m_strPath,info2,settings2);
+ m_database.SetScraperForPath(item->m_strPath,info,settings);
m_database.Close();
- if (bScan)
+ if (!settings.exclude && bScan)
{
- GetScraperForItem(item.get(),info2,settings2);
- OnScan(item->m_strPath,info2,settings2);
+ GetScraperForItem(item.get(),info,settings);
+ OnScan(item->m_strPath,info,settings);
}
}
}
@@ -495,11 +484,11 @@ void CGUIWindowVideoFiles::GetContextButtons(int itemNumber, CContextButtons &bu
buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20333);
CVideoDatabase database;
database.Open();
- SScraperInfo info;
+ ADDON::ScraperPtr info;
if (item && database.GetScraperForPath(item->m_strPath,info))
{
- if (!info.strPath.IsEmpty() && !info.strContent.IsEmpty())
+ if (info->Content() != CONTENT_NONE)
if (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning()))
buttons.Add(CONTEXT_BUTTON_SCAN, 13349);
}
@@ -515,14 +504,15 @@ void CGUIWindowVideoFiles::GetContextButtons(int itemNumber, CContextButtons &bu
buttons.Add(CONTEXT_BUTTON_STOP_SCANNING, 13353);
if (g_settings.m_vecProfiles[g_settings.m_iLastLoadedProfileIndex].canWriteDatabases() || g_passwordManager.bMasterUser)
{
- SScraperInfo info;
+ ADDON::ScraperPtr info;
VIDEO::SScanSettings settings;
- int iFound = GetScraperForItem(item.get(), info, settings);
+ GetScraperForItem(item.get(), info, settings);
int infoString = 13346;
- if (info.strContent.Equals("tvshows"))
+
+ if (info && info->Content() == CONTENT_TVSHOWS)
infoString = item->m_bIsFolder ? 20351 : 20352;
- if (info.strContent.Equals("musicvideos"))
+ if (info && info->Content() == CONTENT_MUSICVIDEOS)
infoString = 20393;
if (item->m_bIsFolder && !item->IsParentFolder())
@@ -530,19 +520,22 @@ void CGUIWindowVideoFiles::GetContextButtons(int itemNumber, CContextButtons &bu
if (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning()))
if (!item->IsPlayList() && !item->IsLiveTV())
buttons.Add(CONTEXT_BUTTON_SET_CONTENT, 20333);
- if (iFound==0)
+ if (!info)
{ // scraper not set - allow movie information or set content
CStdString strPath(item->m_strPath);
CUtil::AddSlashAtEnd(strPath);
- if ((info.strContent.Equals("movies") && m_database.HasMovieInfo(strPath)) ||
- (info.strContent.Equals("tvshows") && m_database.HasTvShowInfo(strPath)))
+ if (m_database.HasMovieInfo(strPath) || m_database.HasTvShowInfo(strPath))
buttons.Add(CONTEXT_BUTTON_INFO, infoString);
}
else
{ // scraper found - allow movie information, scan for new content, or set different type of content
- if (!info.strContent.Equals("musicvideos"))
+ if (info->Content() == CONTENT_TVSHOWS)
+ infoString = item->m_bIsFolder ? 20351 : 20352;
+ if (info->Content() == CONTENT_MUSICVIDEOS)
+ infoString = 20393;
+ if (info->Content() != CONTENT_MUSICVIDEOS)
buttons.Add(CONTEXT_BUTTON_INFO, infoString);
- if (!info.strPath.IsEmpty() && !info.strContent.IsEmpty())
+ if (info->Content() != CONTENT_NONE)
if (!pScanDlg || (pScanDlg && !pScanDlg->IsScanning()))
buttons.Add(CONTEXT_BUTTON_SCAN, 13349);
}
@@ -550,11 +543,9 @@ void CGUIWindowVideoFiles::GetContextButtons(int itemNumber, CContextButtons &bu
else
{
// single file
- if ((info.strContent.Equals("movies") && (iFound > 0 ||
- m_database.HasMovieInfo(item->m_strPath))) ||
- m_database.HasEpisodeInfo(item->m_strPath) ||
- info.strContent.Equals("livetv") ||
- info.strContent.Equals("musicvideos"))
+ if ( (info && m_database.HasMovieInfo(item->m_strPath)) ||
+ m_database.HasEpisodeInfo(item->m_strPath) ||
+ (info && info->Content() == CONTENT_MUSICVIDEOS) )
{
buttons.Add(CONTEXT_BUTTON_INFO, infoString);
}
@@ -612,8 +603,11 @@ bool CGUIWindowVideoFiles::OnContextButton(int itemNumber, CONTEXT_BUTTON button
{
if (CGUIDialogContextMenu::OnContextButton("video", item, button))
{
- if (button == CONTEXT_BUTTON_REMOVE_SOURCE)
- OnUnAssignContent(itemNumber,20375,20340,20341);
+ //TODO should we search DB for entries from plugins?
+ if (button == CONTEXT_BUTTON_REMOVE_SOURCE && !item->IsPlugin())
+ {
+ OnUnAssignContent(itemNumber,20375,20340,20341);
+ }
Update("");
return true;
}
@@ -627,7 +621,7 @@ bool CGUIWindowVideoFiles::OnContextButton(int itemNumber, CONTEXT_BUTTON button
case CONTEXT_BUTTON_SET_CONTENT:
{
- SScraperInfo info;
+ ADDON::ScraperPtr info;
SScanSettings settings;
if (item->HasVideoInfoTag()) // files view shouldn't need this check I think?
m_database.GetScraperForPath(item->GetVideoInfoTag()->m_strPath, info, settings);
diff --git a/xbmc/GUIWindowVideoFiles.h b/xbmc/GUIWindowVideoFiles.h
index b99f24dedb..04b25b44b0 100644
--- a/xbmc/GUIWindowVideoFiles.h
+++ b/xbmc/GUIWindowVideoFiles.h
@@ -43,12 +43,11 @@ protected:
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, VIDEO::SScanSettings& settings);
+ virtual void OnAssignContent(int iItem, int iFound, ADDON::ScraperPtr& scraper, VIDEO::SScanSettings& settings);
virtual bool OnUnAssignContent(int iItem, int label1, int label2, int label3);
virtual void LoadPlayList(const CStdString& strFileName);
diff --git a/xbmc/GUIWindowVideoNav.cpp b/xbmc/GUIWindowVideoNav.cpp
index 2d12c486cf..f606cc5d48 100644
--- a/xbmc/GUIWindowVideoNav.cpp
+++ b/xbmc/GUIWindowVideoNav.cpp
@@ -36,6 +36,7 @@
#include "PlayListFactory.h"
#include "GUIDialogVideoScan.h"
#include "GUIDialogOK.h"
+#include "AddonManager.h"
#include "PartyModeManager.h"
#include "MusicDatabase.h"
#include "GUIWindowManager.h"
@@ -787,22 +788,19 @@ void CGUIWindowVideoNav::FrameMove()
CGUIWindowVideoBase::FrameMove();
}
-void CGUIWindowVideoNav::OnInfo(CFileItem* pItem, const SScraperInfo& info)
+void CGUIWindowVideoNav::OnInfo(CFileItem* pItem, ADDON::ScraperPtr& scraper)
{
- SScraperInfo info2(info);
m_database.Open(); // since we can be called from the music library without being inited
if (pItem->IsVideoDb())
- m_database.GetScraperForPath(pItem->GetVideoInfoTag()->m_strPath,info2);
- else if (m_vecItems->IsPlugin())
- info2.strContent = "plugin";
+ m_database.GetScraperForPath(pItem->GetVideoInfoTag()->m_strPath,scraper);
else
{
CStdString strPath,strFile;
CUtil::Split(pItem->m_strPath,strPath,strFile);
- m_database.GetScraperForPath(strPath,info2);
+ m_database.GetScraperForPath(strPath,scraper);
}
m_database.Close();
- CGUIWindowVideoBase::OnInfo(pItem,info2);
+ CGUIWindowVideoBase::OnInfo(pItem,scraper);
}
bool CGUIWindowVideoNav::CanDelete(const CStdString& strPath)
@@ -1056,13 +1054,13 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt
}
else
{
- SScraperInfo info;
+ ADDON::ScraperPtr info;
VIDEO::SScanSettings settings;
GetScraperForItem(item.get(), info, settings);
- if (info.strContent.Equals("tvshows"))
+ if (info && info->Content() == CONTENT_TVSHOWS)
buttons.Add(CONTEXT_BUTTON_INFO, item->m_bIsFolder ? 20351 : 20352);
- else if (info.strContent.Equals("musicvideos"))
+ else if (info && info->Content() == CONTENT_MUSICVIDEOS)
buttons.Add(CONTEXT_BUTTON_INFO,20393);
else if (!item->m_bIsFolder && !item->m_strPath.Left(19).Equals("newsmartplaylist://"))
buttons.Add(CONTEXT_BUTTON_INFO, 13346);
@@ -1107,7 +1105,7 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt
else
buttons.Add(CONTEXT_BUTTON_UPDATE_TVSHOW, 13349);
}
- if ((info.strContent.Equals("tvshows") && item->m_bIsFolder) ||
+ if ((info && info->Content() == CONTENT_TVSHOWS && item->m_bIsFolder) ||
(item->IsVideoDb() && item->HasVideoInfoTag() && !item->m_bIsFolder))
{
if (item->m_bIsFolder || item->GetVideoInfoTag()->m_playCount > 0)
@@ -1149,7 +1147,7 @@ void CGUIWindowVideoNav::GetContextButtons(int itemNumber, CContextButtons &butt
if (item->IsVideoDb() && item->HasVideoInfoTag() &&
(!item->m_bIsFolder || node == NODE_TYPE_TITLE_TVSHOWS))
{
- if (info.strContent.Equals("tvshows"))
+ if (info && info->Content() == CONTENT_TVSHOWS)
{
if(item->GetVideoInfoTag()->m_iBookmarkId != -1 &&
item->GetVideoInfoTag()->m_iBookmarkId != 0)
@@ -1442,9 +1440,8 @@ bool CGUIWindowVideoNav::OnContextButton(int itemNumber, CONTEXT_BUTTON button)
}
case CONTEXT_BUTTON_UPDATE_LIBRARY:
{
- SScraperInfo info;
VIDEO::SScanSettings settings;
- OnScan("",info,settings);
+ OnScan("",ADDON::ScraperPtr(),settings);
return true;
}
case CONTEXT_BUTTON_UNLINK_MOVIE:
diff --git a/xbmc/GUIWindowVideoNav.h b/xbmc/GUIWindowVideoNav.h
index fa77c07026..ee79241758 100644
--- a/xbmc/GUIWindowVideoNav.h
+++ b/xbmc/GUIWindowVideoNav.h
@@ -38,7 +38,7 @@ public:
virtual void FrameMove();
virtual void OnPrepareFileItems(CFileItemList &items);
- virtual void OnInfo(CFileItem* pItem, const SScraperInfo&info);
+ virtual void OnInfo(CFileItem* pItem, ADDON::ScraperPtr &info);
static bool CanDelete(const CStdString& strPath);
static bool DeleteItem(CFileItem* pItem, bool bUnavailable=false);
diff --git a/xbmc/GUIWindowVisualisation.cpp b/xbmc/GUIWindowVisualisation.cpp
index 6ebc6a2693..0c98eb5cc8 100644
--- a/xbmc/GUIWindowVisualisation.cpp
+++ b/xbmc/GUIWindowVisualisation.cpp
@@ -21,6 +21,7 @@
#include "GUIWindowVisualisation.h"
#include "GUIVisualisationControl.h"
+#include "visualizations/Visualisation.h"
#include "Application.h"
#include "GUIDialogMusicOSD.h"
#include "GUIUserMessages.h"
@@ -32,6 +33,7 @@
#include "AdvancedSettings.h"
using namespace MUSIC_INFO;
+using namespace ADDON;
#define TRANSISTION_COUNT 50 // 1 second
#define TRANSISTION_LENGTH 200 // 4 seconds
@@ -47,14 +49,21 @@ CGUIWindowVisualisation::CGUIWindowVisualisation(void)
m_bShowPreset = false;
}
-CGUIWindowVisualisation::~CGUIWindowVisualisation(void)
-{
-}
-
bool CGUIWindowVisualisation::OnAction(const CAction &action)
{
+ VIS_ACTION visAction = VIS_ACTION_NONE;
switch (action.GetID())
{
+ case ACTION_VIS_PRESET_NEXT:
+ visAction = VIS_ACTION_NEXT_PRESET; break;
+ case ACTION_VIS_PRESET_PREV:
+ visAction = VIS_ACTION_PREV_PRESET; break;
+ case ACTION_VIS_PRESET_RANDOM:
+ visAction = VIS_ACTION_RANDOM_PRESET; break;
+ case ACTION_VIS_RATE_PRESET_PLUS:
+ visAction = VIS_ACTION_RATE_PRESET_PLUS; break;
+ case ACTION_VIS_RATE_PRESET_MINUS:
+ visAction = VIS_ACTION_RATE_PRESET_MINUS; break;
case ACTION_SHOW_INFO:
{
if (!m_initTimer || g_settings.m_bMyMusicSongThumbInVis)
@@ -73,19 +82,6 @@ bool CGUIWindowVisualisation::OnAction(const CAction &action)
case ACTION_VIS_PRESET_LOCK:
{ // show the locked icon + fall through so that the vis handles the locking
- CGUIMessage msg(GUI_MSG_GET_VISUALISATION, 0, 0);
- g_windowManager.SendMessage(msg);
- if (msg.GetPointer())
- {
- CVisualisation *pVis = (CVisualisation *)msg.GetPointer();
- char** pPresets=NULL;
- int currpreset=0, numpresets=0;
- bool locked;
-
- pVis->GetPresets(&pPresets,&currpreset,&numpresets,&locked);
- if (numpresets == 1 || !pPresets)
- return true;
- }
if (!m_bShowPreset)
{
m_lockedTimer = START_FADE_LENGTH;
@@ -127,10 +123,10 @@ bool CGUIWindowVisualisation::OnAction(const CAction &action)
}
break;*/
}
- // default action is to send to the visualisation first
- CGUIVisualisationControl *pVisControl = (CGUIVisualisationControl *)GetControl(CONTROL_VIS);
- if (pVisControl && pVisControl->OnAction(action))
- return true;
+
+ if (visAction != VIS_ACTION_NONE && m_addon)
+ return m_addon->OnAction(visAction);
+
return CGUIWindow::OnAction(action);
}
@@ -138,30 +134,25 @@ bool CGUIWindowVisualisation::OnMessage(CGUIMessage& message)
{
switch ( message.GetMessage() )
{
- case GUI_MSG_PLAYBACK_STARTED:
- {
- CGUIVisualisationControl *pVisControl = (CGUIVisualisationControl *)GetControl(CONTROL_VIS);
- if (pVisControl)
- return pVisControl->OnMessage(message);
- }
- break;
case GUI_MSG_GET_VISUALISATION:
{
-// message.SetControlID(CONTROL_VIS);
- CGUIVisualisationControl *pVisControl = (CGUIVisualisationControl *)GetControl(CONTROL_VIS);
- if (pVisControl)
- message.SetPointer(pVisControl->GetVisualisation());
- return true;
+ if (m_addon)
+ message.SetPointer(m_addon.get());
+ return m_addon;
}
break;
case GUI_MSG_VISUALISATION_ACTION:
+ {
+ CAction action(message.GetParam1());
+ return OnAction(action);
+ }
+ case GUI_MSG_PLAYBACK_STARTED:
+ {
+ if (IsActive() && m_addon)
{
- // message.SetControlID(CONTROL_VIS);
- CGUIVisualisationControl *pVisControl = (CGUIVisualisationControl *)GetControl(CONTROL_VIS);
- if (pVisControl)
- return pVisControl->OnMessage(message);
+ m_addon->UpdateTrack();
}
- break;
+ }
case GUI_MSG_WINDOW_DEINIT:
{
if (IsActive()) // save any changed settings from the OSD
@@ -183,6 +174,12 @@ bool CGUIWindowVisualisation::OnMessage(CGUIMessage& message)
return true;
}
+ AddonPtr viz;
+ CAddonMgr::Get()->GetDefault(ADDON_VIZ, viz);
+ m_addon = boost::dynamic_pointer_cast<CVisualisation>(viz);
+ if (!m_addon)
+ return false;
+
// hide or show the preset button(s)
g_infoManager.SetShowCodec(m_bShowPreset);
g_infoManager.SetShowInfo(true); // always show the info initially.
@@ -205,6 +202,25 @@ bool CGUIWindowVisualisation::OnMessage(CGUIMessage& message)
return CGUIWindow::OnMessage(message);
}
+void CGUIWindowVisualisation::OnWindowLoaded()
+{
+ if (m_addon)
+ {
+ CGUIVisualisationControl *pVisControl = (CGUIVisualisationControl *)GetControl(CONTROL_VIS);
+ if (pVisControl)
+ pVisControl->LoadAddon(m_addon);
+ }
+}
+
+bool CGUIWindowVisualisation::UpdateTrack()
+{
+ if (m_addon)
+ {
+ return m_addon->UpdateTrack();
+ }
+ return false;
+}
+
bool CGUIWindowVisualisation::OnMouseEvent(const CPoint &point, const CMouseEvent &event)
{
if (event.m_id == ACTION_MOUSE_RIGHT_CLICK)
@@ -231,7 +247,7 @@ bool CGUIWindowVisualisation::OnMouseEvent(const CPoint &point, const CMouseEven
void CGUIWindowVisualisation::FrameMove()
{
- g_application.ResetScreenSaver();
+ g_application.ResetScreenSaver(); //why here?
// check for a tag change
const CMusicInfoTag* tag = g_infoManager.GetCurrentSongTag();
if (tag && *tag != m_tag)
diff --git a/xbmc/GUIWindowVisualisation.h b/xbmc/GUIWindowVisualisation.h
index a17f45e4e0..73cd5aa4fe 100644
--- a/xbmc/GUIWindowVisualisation.h
+++ b/xbmc/GUIWindowVisualisation.h
@@ -24,20 +24,27 @@
#include "GUIWindow.h"
#include "MusicInfoTag.h"
+namespace ADDON
+{
+ class CVisualisation;
+}
+
class CGUIWindowVisualisation :
public CGUIWindow
{
public:
CGUIWindowVisualisation(void);
- virtual ~CGUIWindowVisualisation(void);
virtual bool OnMessage(CGUIMessage& message);
+ virtual void OnWindowLoaded();
virtual bool OnAction(const CAction &action);
virtual void FrameMove();
protected:
+ bool UpdateTrack();
virtual bool OnMouseEvent(const CPoint &point, const CMouseEvent &event);
unsigned int m_initTimer;
unsigned int m_lockedTimer;
bool m_bShowPreset;
+ boost::shared_ptr<ADDON::CVisualisation> m_addon;
MUSIC_INFO::CMusicInfoTag m_tag; // current tag info, for finding when the info manager updates
};
diff --git a/xbmc/GUIWindowWeather.cpp b/xbmc/GUIWindowWeather.cpp
index 3825370992..a81033232d 100644
--- a/xbmc/GUIWindowWeather.cpp
+++ b/xbmc/GUIWindowWeather.cpp
@@ -30,6 +30,10 @@
#include "lib/libPython/XBPython.h"
#include "LangInfo.h"
#include "utils/log.h"
+#include "Settings.h"
+#include "utils/AddonManager.h"
+
+using namespace ADDON;
#define CONTROL_BTNREFRESH 2
#define CONTROL_SELECTLOCATION 3
@@ -56,7 +60,7 @@
#define LOCALIZED_TOKEN_FIRSTID 370
#define LOCALIZED_TOKEN_LASTID 395
-unsigned int timeToCallPlugin = 1000;
+unsigned int timeToCallScript = 1000;
/*
FIXME'S
>strings are not centered
@@ -99,9 +103,9 @@ bool CGUIWindowWeather::OnMessage(CGUIMessage& message)
}
else if (iControl == CONTROL_SELECTLOCATION)
{
- // stop the plugin timer here, so the user has a full second
- if (m_pluginTimer.IsRunning())
- m_pluginTimer.Stop();
+ // stop the script timer here, so the user has a full second
+ if (m_scriptTimer.IsRunning())
+ m_scriptTimer.Stop();
CGUIMessage msg(GUI_MSG_ITEM_SELECTED,GetID(),CONTROL_SELECTLOCATION);
g_windowManager.SendMessage(msg);
@@ -132,11 +136,11 @@ bool CGUIWindowWeather::OnMessage(CGUIMessage& message)
SetProperties();
if (g_windowManager.GetActiveWindow() == WINDOW_WEATHER)
{
- if (!g_guiSettings.GetString("weather.plugin").IsEmpty())
- m_pluginTimer.StartZero();
+ if (!g_guiSettings.GetString("weather.script").IsEmpty())
+ m_scriptTimer.StartZero();
}
else
- CallPlugin();
+ CallScript();
}
break;
}
@@ -234,11 +238,11 @@ void CGUIWindowWeather::FrameMove()
// update our controls
UpdateButtons();
- // call weather plugin
- if (m_pluginTimer.IsRunning() && m_pluginTimer.GetElapsedMilliseconds() > timeToCallPlugin)
+ // call weather script
+ if (m_scriptTimer.IsRunning() && m_scriptTimer.GetElapsedMilliseconds() > timeToCallScript)
{
- m_pluginTimer.Stop();
- CallPlugin();
+ m_scriptTimer.Stop();
+ CallScript();
}
CGUIWindow::FrameMove();
@@ -289,26 +293,30 @@ void CGUIWindowWeather::SetProperties()
}
}
-void CGUIWindowWeather::CallPlugin()
+void CGUIWindowWeather::CallScript()
{
#ifdef HAS_PYTHON
- if (!g_guiSettings.GetString("weather.plugin").IsEmpty())
+ if (!g_guiSettings.GetString("weather.script").IsEmpty())
{
- // create the full path to the plugin
- CStdString plugin = "special://home/plugins/weather/" + g_guiSettings.GetString("weather.plugin") + "/default.py";
+ AddonPtr addon;
+ if (!ADDON::CAddonMgr::Get()->GetAddon(ADDON_SCRIPT, g_guiSettings.GetString("weather.script"), addon))
+ return;
+
+ // create the full path to the script
+ CStdString script = addon->Path() + addon->LibName();
// initialize our sys.argv variables
unsigned int argc = 2;
char ** argv = new char*[argc];
- argv[0] = (char*)plugin.c_str();
+ argv[0] = (char*)script.c_str();
- // if plugin is running we wait for another timeout only when in weather window
+ // if script is running we wait for another timeout only when in weather window
if (g_windowManager.GetActiveWindow() == WINDOW_WEATHER)
{
int id = g_pythonParser.getScriptId(argv[0]);
if (id != -1 && g_pythonParser.isRunning(id))
{
- m_pluginTimer.StartZero();
+ m_scriptTimer.StartZero();
return;
}
}
@@ -319,10 +327,10 @@ void CGUIWindowWeather::CallPlugin()
const CStdString &areacode = CWeather::GetAreaCode(g_guiSettings.GetString(strSetting));
argv[1] = (char*)areacode.c_str();
- // call our plugin, passing the areacode
+ // call our script, passing the areacode
g_pythonParser.evalFile(argv[0], argc, (const char**)argv);
- CLog::Log(LOGDEBUG, "%s - Weather plugin called: %s (%s)", __FUNCTION__, argv[0], argv[1]);
+ CLog::Log(LOGDEBUG, "%s - Weather script called: %s (%s)", __FUNCTION__, argv[0], argv[1]);
}
#endif
}
diff --git a/xbmc/GUIWindowWeather.h b/xbmc/GUIWindowWeather.h
index e7752c4a91..acf83f24e6 100644
--- a/xbmc/GUIWindowWeather.h
+++ b/xbmc/GUIWindowWeather.h
@@ -39,10 +39,10 @@ protected:
void UpdateButtons();
void UpdateLocations();
void SetProperties();
- void CallPlugin();
+ void CallScript();
void Refresh();
unsigned int m_iCurWeather;
- CStopWatch m_pluginTimer;
+ CStopWatch m_scriptTimer;
};
diff --git a/xbmc/Makefile.in b/xbmc/Makefile.in
index e2bce3e1dd..2f491daf59 100644
--- a/xbmc/Makefile.in
+++ b/xbmc/Makefile.in
@@ -19,10 +19,12 @@ INCLUDES+=-I../lib/jsoncpp/jsoncpp/include
SRCS=Application.cpp \
CueDocument.cpp \
GUISettings.cpp \
+ GUIWindowAddonBrowser.cpp \
GUIWindowSettings.cpp \
GUIWindowSettingsCategory.cpp \
GUIWindowSettingsProfile.cpp \
GUIWindowSettingsScreenCalibration.cpp \
+ Scraper.cpp \
Settings.cpp \
SettingsControls.cpp \
GUIDialogMusicScan.cpp \
@@ -116,6 +118,7 @@ SRCS=Application.cpp \
Song.cpp \
VideoDatabase.cpp \
ViewDatabase.cpp \
+ GUIDialogAddonSettings.cpp \
GUIDialogAudioSubtitleSettings.cpp \
GUIDialogBoxBase.cpp \
GUIDialogButtonMenu.cpp \
@@ -143,7 +146,6 @@ SRCS=Application.cpp \
GUIDialogVideoBookmarks.cpp \
GUIDialogVideoSettings.cpp \
GUIDialogVisualisationPresetList.cpp \
- GUIDialogVisualisationSettings.cpp \
GUIDialogVolumeBar.cpp \
GUIDialogSlider.cpp \
GUIDialogYesNo.cpp \
@@ -187,10 +189,7 @@ SRCS=Application.cpp \
GUILargeTextureManager.cpp \
GUIDialogKaiToast.cpp \
KeyboardLayoutConfiguration.cpp \
- GUIDialogPluginSettings.cpp \
- PluginSettings.cpp \
GUIDialogAccessPoints.cpp \
- ScraperSettings.cpp \
Artist.cpp \
Album.cpp \
MediaSource.cpp \
@@ -205,7 +204,6 @@ SRCS=Application.cpp \
ZeroconfBrowser.cpp \
VideoReferenceClock.cpp \
DPMSSupport.cpp \
- ScriptSettings.cpp \
GUIWindowTestPatternGL.cpp \
RenderSystem.cpp \
RenderSystemGL.cpp \
diff --git a/xbmc/MediaSource.cpp b/xbmc/MediaSource.cpp
index 2638335a6a..0ee52124cc 100644
--- a/xbmc/MediaSource.cpp
+++ b/xbmc/MediaSource.cpp
@@ -91,6 +91,25 @@ bool CMediaSource::operator==(const CMediaSource &share) const
return true;
}
+void AddOrReplace(VECSOURCES& sources, const VECSOURCES& extras)
+{
+ unsigned int i;
+ for( i=0;i<extras.size();++i )
+ {
+ unsigned int j;
+ for ( j=0;j<sources.size();++j)
+ {
+ if (sources[j].strPath.Equals(extras[i].strPath))
+ {
+ sources[j] = extras[i];
+ break;
+ }
+ }
+ if (j == sources.size())
+ sources.push_back(extras[i]);
+ }
+}
+
void AddOrReplace(VECSOURCES& sources, const CMediaSource& source)
{
unsigned int i;
diff --git a/xbmc/MediaSource.h b/xbmc/MediaSource.h
index 567f1b8ed5..c595b3d3fd 100644
--- a/xbmc/MediaSource.h
+++ b/xbmc/MediaSource.h
@@ -114,4 +114,5 @@ typedef std::vector<CMediaSource> VECSOURCES;
*/
typedef std::vector<CMediaSource>::iterator IVECSOURCES;
+void AddOrReplace(VECSOURCES& sources, const VECSOURCES& extras);
void AddOrReplace(VECSOURCES& sources, const CMediaSource& source);
diff --git a/xbmc/MusicDatabase.cpp b/xbmc/MusicDatabase.cpp
index 37470cde8b..6b29e3b63d 100644
--- a/xbmc/MusicDatabase.cpp
+++ b/xbmc/MusicDatabase.cpp
@@ -30,7 +30,9 @@
#include "GUIDialogMusicScan.h"
#include "utils/GUIInfoManager.h"
#include "MusicInfoTag.h"
-#include "ScraperSettings.h"
+#include "AddonManager.h"
+#include "Scraper.h"
+#include "Addon.h"
#include "Util.h"
#include "Artist.h"
#include "Album.h"
@@ -59,6 +61,7 @@ using namespace std;
using namespace AUTOPTR;
using namespace XFILE;
using namespace MUSICDATABASEDIRECTORY;
+using ADDON::AddonPtr;
#define RECENTLY_PLAYED_LIMIT 25
#define MIN_FULL_SEARCH_LENGTH 3
@@ -4006,7 +4009,7 @@ bool CMusicDatabase::CommitTransaction()
return false;
}
-bool CMusicDatabase::SetScraperForPath(const CStdString& strPath, const SScraperInfo& info)
+bool CMusicDatabase::SetScraperForPath(const CStdString& strPath, const ADDON::ScraperPtr& scraper)
{
try
{
@@ -4018,7 +4021,8 @@ bool CMusicDatabase::SetScraperForPath(const CStdString& strPath, const SScraper
m_pDS->exec(strSQL.c_str());
// insert new settings
- strSQL = FormatSQL("insert into content (strPath, strScraperPath, strContent, strSettings) values ('%s','%s','%s','%s')",strPath.c_str(),info.strPath.c_str(),info.strContent.c_str(),info.settings.GetSettings().c_str());
+ strSQL = FormatSQL("insert into content (strPath, strScraperPath, strContent, strSettings) values ('%s','%s','%s','%s')",
+ strPath.c_str(), scraper->Parent()->UUID().c_str(), ADDON::TranslateContent(scraper->Content()).c_str(), scraper->GetSettings().c_str());
m_pDS->exec(strSQL.c_str());
return true;
@@ -4030,7 +4034,7 @@ bool CMusicDatabase::SetScraperForPath(const CStdString& strPath, const SScraper
return false;
}
-bool CMusicDatabase::GetScraperForPath(const CStdString& strPath, SScraperInfo& info)
+bool CMusicDatabase::GetScraperForPath(const CStdString& strPath, ADDON::ScraperPtr& info)
{
try
{
@@ -4071,41 +4075,51 @@ bool CMusicDatabase::GetScraperForPath(const CStdString& strPath, SScraperInfo&
}
if (!m_pDS->eof())
- {
- info.strContent = m_pDS->fv("content.strContent").get_asString();
- info.strPath = m_pDS->fv("content.strScraperPath").get_asString();
- info.settings.LoadUserXML(m_pDS->fv("content.strSettings").get_asString());
-
- CScraperParser parser;
- parser.Load("special://xbmc/system/scrapers/music/" + info.strPath);
- info.strTitle = parser.GetName();
- info.strDate = parser.GetDate();
- info.strFramework = parser.GetFramework();
- info.strLanguage = parser.GetLanguage();
+ { // try and ascertain scraper for this path
+ CONTENT_TYPE content = ADDON::TranslateContent(m_pDS->fv("content.strContent").get_asString());
+ CStdString scraperUUID = m_pDS->fv("content.strScraperPath").get_asString();
+
+ if (content != CONTENT_NONE)
+ { // content set, use pre configured or default scraper
+ ADDON::AddonPtr addon;
+ if (!scraperUUID.empty() && ADDON::CAddonMgr::Get()->GetAddon(ADDON::ADDON_SCRAPER, scraperUUID, addon) && addon)
+ {
+ info = boost::dynamic_pointer_cast<ADDON::CScraper>(addon->Clone(addon));
+ if (!info)
+ return false;
+ }
- }
- if (info.strPath.IsEmpty())
- { // no info available yet - check for a fallback
- if (!strPath.Equals("musicdb://")) // default fallback
- GetScraperForPath("musicdb://",info);
+ // store this path's settings
+ info->m_pathContent = content;
+ info->LoadUserXML(m_pDS->fv("content.strSettings").get_asString());
+ }
else
- { // none available yet (user wisely left defaults as is and didn't touch 'em)
- CScraperParser parser;
- if (parser.Load("special://xbmc/system/scrapers/music/" + g_guiSettings.GetString("musiclibrary.scraper")))
+ { // use default scraper for this content type
+ ADDON::AddonPtr defaultScraper;
+ if (ADDON::CAddonMgr::Get()->GetDefault(ADDON::ADDON_SCRAPER, defaultScraper, content))
{
- info.strPath = g_guiSettings.GetString("musiclibrary.scraper");
- info.strContent = "albums";
- info.strTitle = parser.GetName();
- info.strDate = parser.GetDate();
- info.strFramework = parser.GetFramework();
- info.strLanguage = parser.GetLanguage();
- info.settings.LoadSettingsXML("special://xbmc/system/scrapers/music/" + info.strPath);
- SetScraperForPath("musicdb://",info);
+ info = boost::dynamic_pointer_cast<ADDON::CScraper>(defaultScraper->Clone(defaultScraper));
+ if (info)
+ {
+ info->m_pathContent = content;
+ }
}
}
}
-
m_pDS->close();
+
+ if (!info)
+ { // use default music scraper instead
+ ADDON::AddonPtr addon;
+ if(ADDON::CAddonMgr::Get()->GetDefault(ADDON::ADDON_SCRAPER, addon, CONTENT_ALBUMS))
+ {
+ info = boost::dynamic_pointer_cast<ADDON::CScraper>(addon);
+ return (info);
+ }
+ else
+ return false;
+ }
+
return true;
}
catch (...)
diff --git a/xbmc/MusicDatabase.h b/xbmc/MusicDatabase.h
index 44ff9b4107..6c64821c91 100644
--- a/xbmc/MusicDatabase.h
+++ b/xbmc/MusicDatabase.h
@@ -25,8 +25,7 @@
#pragma once
#include "Database.h"
#include "Album.h"
-
-struct SScraperInfo;
+#include "Scraper.h"
class CArtist;
class CFileItem;
@@ -189,8 +188,8 @@ public:
int GetVariousArtistsAlbumsCount();
bool SetSongRating(const CStdString &filePath, char rating);
- bool SetScraperForPath(const CStdString& strPath, const SScraperInfo& info);
- bool GetScraperForPath(const CStdString& strPath, SScraperInfo& info);
+ bool SetScraperForPath(const CStdString& strPath, const ADDON::ScraperPtr& info);
+ bool GetScraperForPath(const CStdString& strPath, ADDON::ScraperPtr& info);
void ExportToXML(const CStdString &xmlFile, bool singleFiles = false, bool images=false, bool overwrite=false);
void ImportFromXML(const CStdString &xmlFile);
diff --git a/xbmc/MusicInfoScanner.cpp b/xbmc/MusicInfoScanner.cpp
index 13a9a751db..7898a10e2e 100644
--- a/xbmc/MusicInfoScanner.cpp
+++ b/xbmc/MusicInfoScanner.cpp
@@ -807,7 +807,7 @@ bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdS
return true;
// find album info
- SScraperInfo info;
+ ADDON::ScraperPtr info;
if (!m_musicDatabase.GetScraperForPath(strPath,info))
{
m_musicDatabase.Close();
@@ -831,7 +831,7 @@ bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdS
if (XFILE::CFile::Exists(strNfo))
{
CLog::Log(LOGDEBUG,"Found matching nfo file: %s", strNfo.c_str());
- result = nfoReader.Create(strNfo,"albums");
+ result = nfoReader.Create(strNfo, info);
if (result == CNfoFile::FULL_NFO)
{
CLog::Log(LOGDEBUG, "%s Got details from nfo", __FUNCTION__);
@@ -846,9 +846,9 @@ bool CMusicInfoScanner::DownloadAlbumInfo(const CStdString& strPath, const CStdS
{
CScraperUrl scrUrl(nfoReader.m_strImDbUrl);
CMusicAlbumInfo album("nfo",scrUrl);
- CLog::Log(LOGDEBUG,"-- nfo-scraper: %s",nfoReader.m_strScraper.c_str());
+ info = nfoReader.GetScraperInfo();
+ CLog::Log(LOGDEBUG,"-- nfo-scraper: %s",info->Name().c_str());
CLog::Log(LOGDEBUG,"-- nfo url: %s", scrUrl.m_url[0].m_url.c_str());
- info.strPath = nfoReader.m_strScraper;
scraper.SetScraperInfo(info);
scraper.GetAlbums().push_back(album);
}
@@ -1035,7 +1035,7 @@ bool CMusicInfoScanner::DownloadArtistInfo(const CStdString& strPath, const CStd
return true;
// find artist info
- SScraperInfo info;
+ ADDON::ScraperPtr info;
if (!m_musicDatabase.GetScraperForPath(strPath,info))
{
m_musicDatabase.Close();
@@ -1058,7 +1058,7 @@ bool CMusicInfoScanner::DownloadArtistInfo(const CStdString& strPath, const CStd
if (XFILE::CFile::Exists(strNfo))
{
CLog::Log(LOGDEBUG,"Found matching nfo file: %s", strNfo.c_str());
- result = nfoReader.Create(strNfo,"albums");
+ result = nfoReader.Create(strNfo, info);
if (result == CNfoFile::FULL_NFO)
{
CLog::Log(LOGDEBUG, "%s Got details from nfo", __FUNCTION__);
@@ -1073,9 +1073,9 @@ bool CMusicInfoScanner::DownloadArtistInfo(const CStdString& strPath, const CStd
{
CScraperUrl scrUrl(nfoReader.m_strImDbUrl);
CMusicArtistInfo artist("nfo",scrUrl);
- CLog::Log(LOGDEBUG,"-- nfo-scraper: %s",nfoReader.m_strScraper.c_str());
+ info = nfoReader.GetScraperInfo();
+ CLog::Log(LOGDEBUG,"-- nfo-scraper: %s",info->Name().c_str());
CLog::Log(LOGDEBUG,"-- nfo url: %s", scrUrl.m_url[0].m_url.c_str());
- info.strPath = nfoReader.m_strScraper;
scraper.SetScraperInfo(info);
scraper.GetArtists().push_back(artist);
}
diff --git a/xbmc/NfoFile.cpp b/xbmc/NfoFile.cpp
index 6395a60f69..a5f57bbd15 100644
--- a/xbmc/NfoFile.cpp
+++ b/xbmc/NfoFile.cpp
@@ -25,8 +25,10 @@
#include "NfoFile.h"
#include "VideoDatabase.h"
#include "utils/IMDB.h"
+#include "utils/AddonManager.h"
#include "FileSystem/File.h"
#include "FileSystem/Directory.h"
+#include "GUISettings.h"
#include "Util.h"
#include "FileItem.h"
#include "Album.h"
@@ -38,6 +40,8 @@
using namespace XFILE;
using namespace std;
+using namespace ADDON;
+
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
@@ -53,45 +57,39 @@ CNfoFile::~CNfoFile()
Close();
}
-CNfoFile::NFOResult CNfoFile::Create(const CStdString& strPath, const CStdString& strContent, int episode)
-{
- SScraperInfo info;
- info.strContent = strContent;
- return Create(strPath, info, episode);
-}
-
-CNfoFile::NFOResult CNfoFile::Create(const CStdString& strPath, SScraperInfo& info, int episode)
+CNfoFile::NFOResult CNfoFile::Create(const CStdString& strPath, ScraperPtr& info, int episode)
{
m_info = info; // assume we can use these settings
- m_strContent = info.strContent;
+ m_content = info->Content();
if (FAILED(Load(strPath)))
return NO_NFO;
CFileItemList items;
- CStdString strScraperBasePath, strDefault, strSelected;
bool bNfo=false;
- if (m_strContent.Equals("albums"))
+
+ AddonPtr addon;
+ ScraperPtr defaultScraper;
+ if (!CAddonMgr::Get()->GetDefault(ADDON_SCRAPER, addon, m_content))
+ return NO_NFO;
+ else
+ defaultScraper = boost::dynamic_pointer_cast<CScraper>(addon);
+
+ if (m_content == CONTENT_ALBUMS)
{
CAlbum album;
bNfo = GetDetails(album);
- CDirectory::GetDirectory("special://xbmc/system/scrapers/music/",items,".xml",false);
- strScraperBasePath = "special://xbmc/system/scrapers/music/";
- CUtil::AddFileToFolder(strScraperBasePath, g_guiSettings.GetString("musiclibrary.scraper"), strDefault);
}
- else if (m_strContent.Equals("artists"))
+ else if (m_content == CONTENT_ARTISTS)
{
CArtist artist;
bNfo = GetDetails(artist);
- CDirectory::GetDirectory("special://xbmc/system/scrapers/music/",items,".xml",false);
- strScraperBasePath = "special://xbmc/system/scrapers/music/";
- CUtil::AddFileToFolder(strScraperBasePath, g_guiSettings.GetString("musiclibrary.scraper"), strDefault);
}
- else if (m_strContent.Equals("tvshows") || m_strContent.Equals("movies") || m_strContent.Equals("musicvideos"))
+ else if (m_content == CONTENT_TVSHOWS || m_content == CONTENT_MOVIES || m_content == CONTENT_MUSICVIDEOS)
{
// first check if it's an XML file with the info we need
CVideoInfoTag details;
bNfo = GetDetails(details);
- if (episode > -1 && bNfo && m_strContent.Equals("tvshows"))
+ if (episode > -1 && bNfo && m_content == CONTENT_TVSHOWS)
{
int infos=0;
while (m_headofdoc && details.m_iEpisode != episode)
@@ -109,45 +107,36 @@ CNfoFile::NFOResult CNfoFile::Create(const CStdString& strPath, SScraperInfo& in
bNfo = GetDetails(details);
}
}
- CStdString strURL = details.m_strEpisodeGuide;
- strScraperBasePath = "special://xbmc/system/scrapers/video/";
- CDirectory::GetDirectory("special://xbmc/system/scrapers/video/",items,".xml",false);
-
- if (m_strContent.Equals("movies"))
- CUtil::AddFileToFolder(strScraperBasePath, g_guiSettings.GetString("scrapers.moviedefault"), strDefault);
- else if (m_strContent.Equals("tvshows"))
- CUtil::AddFileToFolder(strScraperBasePath, g_guiSettings.GetString("scrapers.tvshowdefault"), strDefault);
- else if (m_strContent.Equals("musicvideos"))
- CUtil::AddFileToFolder(strScraperBasePath, g_guiSettings.GetString("scrapers.musicvideodefault"), strDefault);
}
// Get Selected Scraper
CVideoDatabase database;
+ ADDON::ScraperPtr selected;
database.Open();
- database.GetScraperForPath(strPath,info);
+ database.GetScraperForPath(strPath,selected);
database.Close();
- CUtil::AddFileToFolder(strScraperBasePath, info.strPath, strSelected);
- vector<CStdString> vecScrapers;
+ vector<ScraperPtr> vecScrapers;
// add selected scraper
- vecScrapers.push_back(strSelected);
+ if (selected)
+ vecScrapers.push_back(selected);
- if (g_guiSettings.GetBool("scrapers.langfallback"))
+ /*if (g_guiSettings.GetBool("scrapers.langfallback"))
{
- for (int i=0;i<items.Size();++i)
+ for (unsigned i=0;i<addons.size();++i)
{
- if (!items[i]->m_bIsFolder)
- {
- // skip selected and default scraper
- if (items[i]->m_strPath.Equals(strSelected) || items[i]->m_strPath.Equals(strDefault))
- continue;
+ // skip selected and default scraper
+ if (addons[i]->UUID().Equals(selected->Parent()) || addons[i]->UUID().Equals(defaultScraper->UUID()))
+ continue;
+
+ (CScraperParser parser2;
+ parser2.Load(addons[i]);
+ CONTENT_TYPE content = parser2.GetContent();
- SScraperInfo info2;
- CScraperParser parser2;
- parser2.Load(items[i]->m_strPath);
- info2.strContent = parser2.GetContent();
- info2.strLanguage = parser2.GetLanguage();
+ // skip if scraper requires settings and there's nothing set yet
+ if (parser2.RequiresSettings() && info2.settings.GetSettings().IsEmpty())
+ continue;
// skip if scraper requires settings and there's nothing set yet
if (parser2.RequiresSettings() && info2.settings.GetSettings().IsEmpty())
@@ -157,16 +146,14 @@ CNfoFile::NFOResult CNfoFile::Create(const CStdString& strPath, SScraperInfo& in
if (info.strContent != info2.strContent && (info.strContent.Equals("movies") || info.strContent.Equals("tvshows") || info.strContent.Equals("musicvideos")))
continue;
- // add same language, multi-language and music scrapers
- if (info.strLanguage == info2.strLanguage || info2.strLanguage == "multi" || info.strContent.Equals("albums") || info.strContent.Equals("artists"))
- vecScrapers.push_back(items[i]->m_strPath);
- }
+ // add same language, multi-language and music scrapers
+ // TODO addons language handling
}
- }
+ }*/
// add default scraper
- if (find(vecScrapers.begin(),vecScrapers.end(),strDefault) == vecScrapers.end())
- vecScrapers.push_back(strDefault);
+ if ((selected && selected->Parent() != defaultScraper) || !selected)
+ vecScrapers.push_back(defaultScraper);
// search ..
int res = -1;
@@ -201,7 +188,7 @@ bool CNfoFile::DoScrape(CScraperParser& parser, const CScraperUrl* pURL, const C
parser.m_param[i] = strHTML[i];
}
- m_strImDbUrl = parser.Parse(strFunction, m_strScraper.CompareNoCase(m_info.strPath) == 0 ? &m_info.settings : 0);
+ m_strImDbUrl = parser.Parse(strFunction);
TiXmlDocument doc;
doc.Parse(m_strImDbUrl.c_str());
@@ -231,27 +218,25 @@ bool CNfoFile::DoScrape(CScraperParser& parser, const CScraperUrl* pURL, const C
return true;
}
-int CNfoFile::Scrape(const CStdString& strScraperPath, const CStdString& strURL /* = "" */)
+int CNfoFile::Scrape(const ScraperPtr& scraper, const CStdString& strURL /* = "" */)
{
- CScraperParser m_parser;
- if (!m_parser.Load(strScraperPath))
+ CScraperParser parser;
+ if (!parser.Load(scraper))
return 0;
- if (m_parser.GetContent() != m_strContent &&
- !(m_strContent.Equals("artists") && m_parser.GetContent().Equals("albums")))
+ if (scraper->Supports(m_content) &&
+ !(m_content == CONTENT_ARTISTS && scraper->Content() == CONTENT_ALBUMS))
// artists are scraped by album content scrapers
{
return 1;
}
- m_strScraper = CUtil::GetFileName(strScraperPath);
-
// init and clear cache
- m_parser.ClearCache();
+ parser.ClearCache();
if (strURL.IsEmpty())
{
- m_parser.m_param[0] = m_doc;
- m_strImDbUrl = m_parser.Parse("NfoScrape", m_strScraper.CompareNoCase(m_info.strPath) == 0 ? &m_info.settings : 0);
+ parser.m_param[0] = m_doc;
+ m_strImDbUrl = parser.Parse("NfoScrape");
TiXmlDocument doc;
doc.Parse(m_strImDbUrl.c_str());
if (doc.RootElement() && doc.RootElement()->FirstChildElement())
@@ -268,7 +253,7 @@ int CNfoFile::Scrape(const CStdString& strScraperPath, const CStdString& strURL
}
}
- if (!DoScrape(m_parser))
+ if (!DoScrape(parser))
return 2;
if (m_strImDbUrl.size() > 0)
@@ -278,8 +263,8 @@ int CNfoFile::Scrape(const CStdString& strScraperPath, const CStdString& strURL
}
else // we check to identify the episodeguide url
{
- 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?
+ parser.m_param[0] = strURL;
+ CStdString strEpGuide = parser.Parse("EpisodeGuideUrl"); // allow corrections?
if (strEpGuide.IsEmpty())
return 1;
return 0;
diff --git a/xbmc/NfoFile.h b/xbmc/NfoFile.h
index f3e3869fc5..d2413160ec 100644
--- a/xbmc/NfoFile.h
+++ b/xbmc/NfoFile.h
@@ -30,7 +30,7 @@
#endif // _MSC_VER > 1000
#include "tinyXML/tinyxml.h"
-#include "ScraperSettings.h"
+#include "Scraper.h"
#include "utils/CharsetConverter.h"
class CVideoInfoTag;
@@ -51,8 +51,7 @@ public:
ERROR_NFO = 4
};
- NFOResult Create(const CStdString&,const CStdString&, int episode=-1);
- NFOResult Create(const CStdString&,SScraperInfo&, int episode=-1);
+ NFOResult Create(const CStdString&, ADDON::ScraperPtr&, int episode=-1);
template<class T>
bool GetDetails(T& details,const char* document=NULL)
{
@@ -70,21 +69,20 @@ public:
return details.Load(doc.RootElement(),true);
}
- CStdString m_strScraper;
CStdString m_strImDbUrl;
CStdString m_strImDbNr;
void Close();
- void SetScraperInfo(const SScraperInfo& info) { m_info.Reset(); m_info = info; }
- const SScraperInfo& GetScraperInfo() const { return m_info; }
+ void SetScraperInfo(const ADDON::ScraperPtr& info) { m_info = info; }
+ const ADDON::ScraperPtr& GetScraperInfo() const { return m_info; }
private:
int Load(const CStdString&);
- int Scrape(const CStdString&, const CStdString& strURL="");
+ int Scrape(const ADDON::ScraperPtr& scraper, const CStdString& strURL="");
private:
char* m_doc;
char* m_headofdoc;
int m_size;
- SScraperInfo m_info;
- CStdString m_strContent;
+ ADDON::ScraperPtr m_info;
+ CONTENT_TYPE m_content;
bool DoScrape(CScraperParser& parser, const CScraperUrl* pURL=NULL, const CStdString& strFunction="NfoUrl");
};
diff --git a/xbmc/PluginSettings.cpp b/xbmc/PluginSettings.cpp
deleted file mode 100644
index e158bd14be..0000000000
--- a/xbmc/PluginSettings.cpp
+++ /dev/null
@@ -1,244 +0,0 @@
-/*
- * 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 "PluginSettings.h"
-#include "Util.h"
-#include "FileSystem/File.h"
-#include "FileSystem/Directory.h"
-#include "utils/log.h"
-
-CBasicSettings::CBasicSettings()
-{
-}
-
-CBasicSettings::~CBasicSettings()
-{
-}
-
-bool CBasicSettings::SaveFromDefault(void)
-{
- if (!GetPluginRoot()) //if scraper has no settings return false
- return false;
-
- TiXmlElement *setting = GetPluginRoot()->FirstChildElement("setting");
- while (setting)
- {
- CStdString id;
- if (setting->Attribute("id"))
- id = setting->Attribute("id");
- CStdString value;
- if (setting->Attribute("default"))
- value = setting->Attribute("default");
- Set(id,value);
- setting = setting->NextSiblingElement("setting");
- }
- return true;
-}
-
-void CBasicSettings::Clear()
-{
- m_pluginXmlDoc.Clear();
- m_userXmlDoc.Clear();
-}
-
-void CBasicSettings::Set(const CStdString& key, const CStdString& value)
-{
- if (key == "") return;
-
- // Try to find the setting and change its value
- if (!m_userXmlDoc.RootElement())
- {
- TiXmlElement node("settings");
- m_userXmlDoc.InsertEndChild(node);
- }
- TiXmlElement *setting = m_userXmlDoc.RootElement()->FirstChildElement("setting");
- while (setting)
- {
- const char *id = setting->Attribute("id");
- if (id && strcmpi(id, key) == 0)
- {
- setting->SetAttribute("value", value.c_str());
- return;
- }
-
- setting = setting->NextSiblingElement("setting");
- }
-
- // Setting not found, add it
- TiXmlElement nodeSetting("setting");
- nodeSetting.SetAttribute("id", key.c_str());
- nodeSetting.SetAttribute("value", value.c_str());
- m_userXmlDoc.RootElement()->InsertEndChild(nodeSetting);
-}
-
-CStdString CBasicSettings::Get(const CStdString& key) const
-{
- if (m_userXmlDoc.RootElement())
- {
- // Try to find the setting and return its value
- const TiXmlElement *setting = m_userXmlDoc.RootElement()->FirstChildElement("setting");
- while (setting)
- {
- const char *id = setting->Attribute("id");
- if (id && strcmpi(id, key) == 0)
- return setting->Attribute("value");
-
- setting = setting->NextSiblingElement("setting");
- }
- }
-
- if (m_pluginXmlDoc.RootElement())
- {
- // Try to find the setting in the plugin and return its default value
- const TiXmlElement* setting = m_pluginXmlDoc.RootElement()->FirstChildElement("setting");
- while (setting)
- {
- const char *id = setting->Attribute("id");
- if (id && strcmpi(id, key) == 0 && setting->Attribute("default"))
- return setting->Attribute("default");
-
- setting = setting->NextSiblingElement("setting");
- }
- }
-
- // Otherwise return empty string
- return "";
-}
-
-CPluginSettings::CPluginSettings()
-{
-}
-
-CPluginSettings::~CPluginSettings()
-{
-}
-
-bool CPluginSettings::Load(const CURL& url)
-{
- m_url = url;
-
- // create the users filepath
- m_userFileName.Format("special://profile/plugin_data/%s/%s", url.GetHostName().c_str(), url.GetFileName().c_str());
- CUtil::RemoveSlashAtEnd(m_userFileName);
- CUtil::AddFileToFolder(m_userFileName, "settings.xml", m_userFileName);
-
- // Create our final path
- CStdString pluginFileName = "special://home/plugins/";
-
- CUtil::AddFileToFolder(pluginFileName, url.GetHostName(), pluginFileName);
- CUtil::AddFileToFolder(pluginFileName, url.GetFileName(), pluginFileName);
-
- CUtil::AddFileToFolder(pluginFileName, "resources", pluginFileName);
- CUtil::AddFileToFolder(pluginFileName, "settings.xml", pluginFileName);
-
- if (!m_pluginXmlDoc.LoadFile(pluginFileName))
- {
- CLog::Log(LOGERROR, "Unable to load: %s, Line %d\n%s", pluginFileName.c_str(), m_pluginXmlDoc.ErrorRow(), m_pluginXmlDoc.ErrorDesc());
- return false;
- }
-
- // Make sure that the plugin XML has the settings element
- TiXmlElement *setting = m_pluginXmlDoc.RootElement();
- if (!setting || strcmpi(setting->Value(), "settings") != 0)
- {
- CLog::Log(LOGERROR, "Error loading Settings %s: cannot find root element 'settings'", pluginFileName.c_str());
- return false;
- }
-
- // Load the user saved settings. If it does not exist, create it
- if (!m_userXmlDoc.LoadFile(m_userFileName))
- {
- TiXmlDocument doc;
- TiXmlDeclaration decl("1.0", "UTF-8", "yes");
- doc.InsertEndChild(decl);
-
- TiXmlElement xmlRootElement("settings");
- doc.InsertEndChild(xmlRootElement);
-
- m_userXmlDoc = doc;
-
- // Don't worry about the actual settings, they will be set when the user clicks "Ok"
- // in the settings dialog
- }
-
- return true;
-}
-
-bool CPluginSettings::Save(void)
-{
- // break down the path into directories
- CStdString strRoot, strType, strPlugin;
- CUtil::GetDirectory(m_userFileName, strPlugin);
- CUtil::RemoveSlashAtEnd(strPlugin);
- CUtil::GetDirectory(strPlugin, strType);
- CUtil::RemoveSlashAtEnd(strType);
- CUtil::GetDirectory(strType, strRoot);
- CUtil::RemoveSlashAtEnd(strRoot);
-
- // create the individual folders
- if (!XFILE::CDirectory::Exists(strRoot))
- XFILE::CDirectory::Create(strRoot);
- if (!XFILE::CDirectory::Exists(strType))
- XFILE::CDirectory::Create(strType);
- if (!XFILE::CDirectory::Exists(strPlugin))
- XFILE::CDirectory::Create(strPlugin);
-
- return m_userXmlDoc.SaveFile(m_userFileName);
-}
-
-TiXmlElement* CBasicSettings::GetPluginRoot()
-{
- return m_pluginXmlDoc.RootElement();
-}
-
-bool CPluginSettings::SettingsExist(const CStdString& strPath)
-{
- CURL url(strPath);
- CStdString pluginFileName = "special://home/plugins/";
-
- // Create our final path
- CUtil::AddFileToFolder(pluginFileName, url.GetHostName(), pluginFileName);
- CUtil::AddFileToFolder(pluginFileName, url.GetFileName(), pluginFileName);
-
- CUtil::AddFileToFolder(pluginFileName, "resources", pluginFileName);
- CUtil::AddFileToFolder(pluginFileName, "settings.xml", pluginFileName);
-
- // Load the settings file to verify it's valid
- TiXmlDocument xmlDoc;
- if (!xmlDoc.LoadFile(pluginFileName))
- return false;
-
- // Make sure that the plugin XML has the settings element
- TiXmlElement *setting = xmlDoc.RootElement();
- if (!setting || strcmpi(setting->Value(), "settings") != 0)
- return false;
-
- return true;
-}
-
-CPluginSettings& CPluginSettings::operator=(const CBasicSettings& settings)
-{
- *((CBasicSettings*)this) = settings;
-
- return *this;
-}
-
-CPluginSettings g_currentPluginSettings;
diff --git a/xbmc/PluginSettings.h b/xbmc/PluginSettings.h
deleted file mode 100644
index 53d6226b8a..0000000000
--- a/xbmc/PluginSettings.h
+++ /dev/null
@@ -1,65 +0,0 @@
-#ifndef PLUGINSETTINGS_H_
-#define PLUGINSETTINGS_H_
-/*
- * 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 "tinyXML/tinyxml.h"
-#include "URL.h"
-
-class CBasicSettings
-{
-public:
- CBasicSettings();
- virtual ~CBasicSettings();
-
- bool SaveFromDefault(void);
- virtual bool Load(const CURL& url) { return false; }
- virtual bool Save(void) { return false; }
- void Clear();
-
- void Set(const CStdString& key, const CStdString& value);
- CStdString Get(const CStdString& key) const;
-
- TiXmlElement* GetPluginRoot();
-protected:
- TiXmlDocument m_userXmlDoc;
- TiXmlDocument m_pluginXmlDoc;
-};
-
-class CPluginSettings : public CBasicSettings
-{
-public:
- CPluginSettings();
- virtual ~CPluginSettings();
- bool Load(const CURL& url);
- bool Save(void);
- static bool SettingsExist(const CStdString &strPath);
-
- CPluginSettings& operator =(const CBasicSettings&);
-private:
- CStdString m_id;
- CURL m_url;
- CStdString m_userFileName;
-};
-
-extern CPluginSettings g_currentPluginSettings;
-
-#endif
diff --git a/xbmc/PowerManager.cpp b/xbmc/PowerManager.cpp
index 09700883d8..4d62b6037d 100644
--- a/xbmc/PowerManager.cpp
+++ b/xbmc/PowerManager.cpp
@@ -47,11 +47,11 @@ extern HWND g_hWnd;
#ifdef HAS_LIRC
#include "common/LIRC.h"
#endif
-#ifdef HAS_IRSERVERSUITE
- #include "common/IRServerSuite/IRServerSuite.h"
+#ifdef HAS_IRSERVERSUITE
+ #include "common/IRServerSuite/IRServerSuite.h"
#endif
-using namespace ANNOUNCEMENT;
+using namespace ANNOUNCEMENT;
CPowerManager g_powerManager;
diff --git a/xbmc/Profile.cpp b/xbmc/Profile.cpp
index 49e77bc712..ef9f42963f 100644
--- a/xbmc/Profile.cpp
+++ b/xbmc/Profile.cpp
@@ -29,12 +29,14 @@ CProfile::CProfile(void)
_bCanWrite = true;
_bSources = true;
_bCanWriteSources = true;
+ _bAddons = true;
_bLockPrograms = false;
_bLockPictures = false;
_bLockFiles = false;
_bLockVideo = false;
_bLockMusic = false;
_bLockSettings = false;
+ _bLockAddonManager = false;
_iLockMode = LOCK_MODE_EVERYONE;
}
diff --git a/xbmc/Profile.h b/xbmc/Profile.h
index 9b277ab51c..68a93e755b 100644
--- a/xbmc/Profile.h
+++ b/xbmc/Profile.h
@@ -42,7 +42,9 @@ public:
bool canWriteDatabases() const { return _bCanWrite; }
bool hasSources() const { return _bSources; }
bool canWriteSources() const { return _bCanWriteSources; }
+ bool hasAddons() const { return _bAddons; }
bool settingsLocked() const { return _bLockSettings; }
+ bool addonmanagerLocked() const { return _bLockAddonManager; }
bool musicLocked() const { return _bLockMusic; }
bool videoLocked() const { return _bLockVideo; }
bool picturesLocked() const { return _bLockPictures; }
@@ -61,6 +63,7 @@ public:
void setSources(bool bHas) { _bSources = bHas; }
void setWriteSources(bool bCan) { _bCanWriteSources = bCan; }
+ void setAddonManagerLocked(bool bLocked) { _bLockAddonManager = bLocked; }
void setSettingsLocked(bool bLocked) { _bLockSettings = bLocked; }
void setFilesLocked(bool bLocked) { _bLockFiles = bLocked; }
void setMusicLocked(bool bLocked) { _bLockMusic = bLocked; }
@@ -76,10 +79,12 @@ public:
bool _bCanWrite;
bool _bSources;
bool _bCanWriteSources;
+ bool _bAddons;
// lock stuff
LockType _iLockMode;
CStdString _strLockCode;
+ bool _bLockAddonManager;
bool _bLockSettings;
bool _bLockMusic;
bool _bLockVideo;
diff --git a/xbmc/ScraperSettings.cpp b/xbmc/Scraper.cpp
index 630b5406d1..d6163f4ec2 100644
--- a/xbmc/ScraperSettings.cpp
+++ b/xbmc/Scraper.cpp
@@ -1,47 +1,72 @@
/*
- * 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
- *
- */
-
+* 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 "Scraper.h"
#include "XMLUtils.h"
-#include "ScraperSettings.h"
#include "FileSystem/File.h"
#include "FileSystem/Directory.h"
#include "FileSystem/FileCurl.h"
-#include "utils/CharsetConverter.h"
+#include "utils/AddonManager.h"
#include "utils/ScraperParser.h"
#include "utils/ScraperUrl.h"
+#include "utils/CharsetConverter.h"
#include "utils/log.h"
#include <sstream>
-using namespace std;
+using std::vector;
+using std::stringstream;
+
+namespace ADDON
+{
+
+class CAddon;
+
+AddonPtr CScraper::Clone(const AddonPtr &self) const
+{
+ return AddonPtr(new CScraper(*this, self));
+}
+
+CScraper::CScraper(const CScraper &rhs, const AddonPtr &self)
+ : CAddon(rhs, self)
+{
+}
-CScraperSettings::CScraperSettings()
+bool CScraper::LoadSettings()
{
+ //TODO if cloned settings don't exist, load master settings and copy
+ if (!Parent())
+ return CAddon::LoadUserSettings();
+ else
+ return LoadSettingsXML();
}
-CScraperSettings::~CScraperSettings()
+bool CScraper::HasSettings()
{
+ if (!m_userXmlDoc.RootElement())
+ return LoadSettingsXML();
+
+ return true;
}
-bool CScraperSettings::Load(const CStdString& strSettings, const CStdString& strSaved)
+bool CScraper::Load(const CStdString& strSettings, const CStdString& strSaved)
{
if (!LoadSettingsXML(strSettings))
return false;
@@ -51,7 +76,7 @@ bool CScraperSettings::Load(const CStdString& strSettings, const CStdString& str
return true;
}
-bool CScraperSettings::LoadUserXML(const CStdString& strSaved)
+bool CScraper::LoadUserXML(const CStdString& strSaved)
{
m_userXmlDoc.Clear();
m_userXmlDoc.Parse(strSaved.c_str());
@@ -59,18 +84,24 @@ bool CScraperSettings::LoadUserXML(const CStdString& strSaved)
return m_userXmlDoc.RootElement()?true:false;
}
-bool CScraperSettings::LoadSettingsXML(const CStdString& strScraper, const CStdString& strFunction, const CScraperUrl* url)
+bool CScraper::LoadSettingsXML(const CStdString& strFunction, const CScraperUrl* url)
{
- CScraperParser parser;
+ CStdString uuid = UUID();
+ if (Parent())
+ { // called from DialogContentSettings. We are working with the cloned scraper settings
+ uuid = Parent()->UUID();
+ }
+
// load our scraper xml
- if (!parser.Load(strScraper))
+ CScraperParser parser;
+ if (!parser.Load(uuid))
return false;
if (!parser.HasFunction(strFunction))
return false;
if (!url && strFunction.Equals("GetSettings")) // entry point
- m_pluginXmlDoc.Clear();
+ m_addonXmlDoc.Clear();
vector<CStdString> strHTML;
if (url)
@@ -110,17 +141,22 @@ bool CScraperSettings::LoadSettingsXML(const CStdString& strScraper, const CStdS
}
// check our document
- if (!m_pluginXmlDoc.RootElement())
+ if (!m_addonXmlDoc.RootElement())
{
TiXmlElement xmlRootElement("settings");
- m_pluginXmlDoc.InsertEndChild(xmlRootElement);
+ m_addonXmlDoc.InsertEndChild(xmlRootElement);
}
// loop over all tags and append any setting tags
TiXmlElement* pElement = doc.RootElement()->FirstChildElement("setting");
+ if (pElement)
+ m_hasSettings = true;
+ else
+ m_hasSettings = false;
+
while (pElement)
{
- m_pluginXmlDoc.RootElement()->InsertEndChild(*pElement);
+ m_addonXmlDoc.RootElement()->InsertEndChild(*pElement);
pElement = pElement->NextSiblingElement("setting");
}
@@ -133,16 +169,16 @@ bool CScraperSettings::LoadSettingsXML(const CStdString& strScraper, const CStdS
if (szFunction)
{
CScraperUrl scrURL(xurl);
- if (!LoadSettingsXML(strScraper,szFunction,&scrURL))
+ if (!LoadSettingsXML(szFunction,&scrURL))
return false;
}
xurl = xurl->NextSiblingElement("url");
}
- return m_pluginXmlDoc.RootElement()?true:false;
+ return m_addonXmlDoc.RootElement()?true:false;
}
-CStdString CScraperSettings::GetSettings() const
+CStdString CScraper::GetSettings() const
{
stringstream stream;
if (m_userXmlDoc.RootElement())
@@ -151,3 +187,5 @@ CStdString CScraperSettings::GetSettings() const
return stream.str();
}
+}; /* namespace ADDON */
+
diff --git a/xbmc/Scraper.h b/xbmc/Scraper.h
new file mode 100644
index 0000000000..8a811c7034
--- /dev/null
+++ b/xbmc/Scraper.h
@@ -0,0 +1,58 @@
+#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 "utils/Addon.h"
+#include "utils/ScraperUrl.h"
+
+namespace ADDON
+{
+ class CScraper;
+ typedef boost::shared_ptr<CScraper> ScraperPtr;
+
+ class CScraper : public CAddon
+ {
+ public:
+ CScraper(const AddonProps &props) : CAddon(props) { }
+ virtual ~CScraper() {}
+ virtual AddonPtr Clone(const AddonPtr &self) const;
+
+ // from CAddon
+ virtual bool HasSettings();
+ virtual bool LoadSettings();
+
+ // scraper specialization
+ bool LoadUserXML(const CStdString& strXML);
+ bool LoadSettingsXML(const CStdString& strFunction="GetSettings", const CScraperUrl* url=NULL);
+ bool Load(const CStdString& strSettings, const CStdString& strSaved);
+ CStdString GetSettings() const;
+ CStdString m_strLanguage;
+ CONTENT_TYPE Content() const { return m_pathContent; }
+ const CStdString Framework() const { return m_framework; }
+ CONTENT_TYPE m_pathContent;
+
+ private:
+ CScraper(const CScraper&, const AddonPtr&);
+ bool m_hasSettings;
+ CStdString m_framework;
+ };
+
+}; /* namespace ADDON */
+
diff --git a/xbmc/ScraperSettings.h b/xbmc/ScraperSettings.h
deleted file mode 100644
index be8d7441d3..0000000000
--- a/xbmc/ScraperSettings.h
+++ /dev/null
@@ -1,62 +0,0 @@
-#ifndef SCRAPERSETTINGS_H_
-#define SCRAPERSETTINGS_H_
-/*
- * 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 "PluginSettings.h"
-#include "StdString.h"
-
-class CScraperUrl;
-
-class CScraperSettings : public CBasicSettings
-{
-public:
- CScraperSettings();
- virtual ~CScraperSettings();
- bool LoadUserXML(const CStdString& strXML);
- bool LoadSettingsXML(const CStdString& strScraper, const CStdString& strFunction="GetSettings", const CScraperUrl* url=NULL);
- bool Load(const CStdString& strSettings, const CStdString& strSaved);
- CStdString GetSettings() const;
-};
-
-struct SScraperInfo
-{
- CStdString strTitle;
- CStdString strPath;
- CStdString strThumb;
- CStdString strContent;
- CStdString strLanguage;
- CStdString strFramework;
- CStdString strDate;
- CScraperSettings settings;
- void Reset()
- {
- strTitle.clear();
- strPath.clear();
- strThumb.clear();
- strContent.clear();
- strLanguage.clear();
- settings.Clear();
- }
-};
-
-#endif
-
diff --git a/xbmc/ScriptSettings.cpp b/xbmc/ScriptSettings.cpp
deleted file mode 100644
index a7a106fc3f..0000000000
--- a/xbmc/ScriptSettings.cpp
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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 "ScriptSettings.h"
-#include "Util.h"
-#include "FileSystem/Directory.h"
-#include "utils/log.h"
-#ifdef _WIN32
-#include "PlatformDefs.h" //for strcasecmp
-#endif
-
-CScriptSettings::CScriptSettings()
-{
-}
-
-CScriptSettings::~CScriptSettings()
-{
-}
-
-bool CScriptSettings::Load(const CStdString& strPath)
-{
- m_scriptPath = strPath;
-
- // create the users filepath
- CUtil::RemoveSlashAtEnd(m_scriptPath);
- m_userFileName.Format("special://profile/script_data/%s", CUtil::GetFileName(m_scriptPath));
- CUtil::AddFileToFolder(m_userFileName, "settings.xml", m_userFileName);
-
- // Create our final settings path
- CStdString scriptFileName;
- CUtil::AddFileToFolder(m_scriptPath, "resources", scriptFileName);
- CUtil::AddFileToFolder(scriptFileName, "settings.xml", scriptFileName);
-
- if (!m_pluginXmlDoc.LoadFile(scriptFileName))
- {
- CLog::Log(LOGERROR, "Unable to load: %s, Line %d\n%s", scriptFileName.c_str(), m_pluginXmlDoc.ErrorRow(), m_pluginXmlDoc.ErrorDesc());
- return false;
- }
-
- // Make sure that the script XML has the settings element
- TiXmlElement *setting = m_pluginXmlDoc.RootElement();
- if (!setting || strcasecmp(setting->Value(), "settings") != 0)
- {
- CLog::Log(LOGERROR, "Error loading Settings %s: cannot find root element 'settings'", scriptFileName.c_str());
- return false;
- }
-
- // Load the user saved settings. If it does not exist, create it
- if (!m_userXmlDoc.LoadFile(m_userFileName))
- {
- TiXmlDocument doc;
- TiXmlDeclaration decl("1.0", "UTF-8", "yes");
- doc.InsertEndChild(decl);
-
- TiXmlElement xmlRootElement("settings");
- doc.InsertEndChild(xmlRootElement);
-
- m_userXmlDoc = doc;
-
- // Don't worry about the actual settings, they will be set when the user clicks "Ok"
- // in the settings dialog
- }
-
- return true;
-}
-
-bool CScriptSettings::Save(void)
-{
- // break down the path into directories
- CStdString strRoot, strType, strScript;
- CUtil::GetDirectory(m_userFileName, strScript);
- CUtil::RemoveSlashAtEnd(strScript);
- CUtil::GetDirectory(strScript, strType);
- CUtil::RemoveSlashAtEnd(strType);
- CUtil::GetDirectory(strType, strRoot);
- CUtil::RemoveSlashAtEnd(strRoot);
-
- // create the individual folders
- if (!XFILE::CDirectory::Exists(strRoot))
- XFILE::CDirectory::Create(strRoot);
- if (!XFILE::CDirectory::Exists(strType))
- XFILE::CDirectory::Create(strType);
- if (!XFILE::CDirectory::Exists(strScript))
- XFILE::CDirectory::Create(strScript);
-
- return m_userXmlDoc.SaveFile(m_userFileName);
-}
-
-bool CScriptSettings::SettingsExist(const CStdString& strPath)
-{
- CStdString scriptFileName = strPath;
- CUtil::RemoveSlashAtEnd(scriptFileName);
-
- CUtil::AddFileToFolder(scriptFileName, "resources", scriptFileName);
- CUtil::AddFileToFolder(scriptFileName, "settings.xml", scriptFileName);
-
- // Load the settings file to verify it's valid
- TiXmlDocument xmlDoc;
- if (!xmlDoc.LoadFile(scriptFileName))
- return false;
-
- // Make sure that the script XML has the settings element
- TiXmlElement *setting = xmlDoc.RootElement();
- if (!setting || strcasecmp(setting->Value(), "settings") != 0)
- return false;
-
- return true;
-}
-
-CScriptSettings& CScriptSettings::operator=(const CBasicSettings& settings)
-{
- *((CBasicSettings*)this) = settings;
-
- return *this;
-}
-
diff --git a/xbmc/Settings.cpp b/xbmc/Settings.cpp
index ec96d8d91b..6ed75b4649 100644
--- a/xbmc/Settings.cpp
+++ b/xbmc/Settings.cpp
@@ -33,6 +33,8 @@
#include "ButtonTranslator.h"
#include "XMLUtils.h"
#include "utils/PasswordManager.h"
+#include "utils/RegExp.h"
+#include "GUIPassword.h"
#include "GUIAudioManager.h"
#include "AudioContext.h"
#include "utils/GUIInfoManager.h"
@@ -1063,6 +1065,10 @@ bool CSettings::LoadProfiles(const CStdString& strSettingsFile)
profile.setWriteSources(bHas);
bHas = false;
+ XMLUtils::GetBoolean(pProfile, "lockaddonmanager", bHas);
+ profile.setAddonManagerLocked(bHas);
+
+ bHas = false;
XMLUtils::GetBoolean(pProfile, "locksettings", bHas);
profile.setSettingsLocked(bHas);
@@ -1139,6 +1145,7 @@ bool CSettings::SaveProfiles(const CStdString& strSettingsFile) const
XMLUtils::SetBoolean(pNode,"lockpictures",m_vecProfiles[iProfile].picturesLocked());
XMLUtils::SetBoolean(pNode,"lockprograms",m_vecProfiles[iProfile].programsLocked());
XMLUtils::SetBoolean(pNode,"locksettings",m_vecProfiles[iProfile].settingsLocked());
+ XMLUtils::SetBoolean(pNode,"lockaddonmanager",m_vecProfiles[iProfile].addonmanagerLocked());
XMLUtils::SetBoolean(pNode,"lockfiles",m_vecProfiles[iProfile].filesLocked());
}
@@ -1952,6 +1959,7 @@ void CSettings::CreateProfileFolders()
CDirectory::Create(CUtil::AddFileToFolder(GetMusicThumbFolder(), strHex));
CDirectory::Create(CUtil::AddFileToFolder(GetVideoThumbFolder(), strHex));
}
+ CDirectory::Create("special://profile/addon_data");
CDirectory::Create("special://profile/keymaps");
- CDirectory::Create("special://profile/visualisations");
}
+
diff --git a/xbmc/StringUtils.cpp b/xbmc/StringUtils.cpp
index 34b32993f3..e82c80dfde 100644
--- a/xbmc/StringUtils.cpp
+++ b/xbmc/StringUtils.cpp
@@ -31,14 +31,18 @@
#include "StringUtils.h"
+#include "utils/RegExp.h"
#include <math.h>
#include <sstream>
using namespace std;
+const char* ADDON_GUID_RE = "^(\\{){0,1}[0-9a-fA-F]{8}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{4}\\-[0-9a-fA-F]{12}(\\}){0,1}$";
+
/* empty string for use in returns by ref */
const CStdString StringUtils::EmptyString = "";
+CStdString StringUtils::m_lastUUID = "";
void StringUtils::JoinString(const CStdStringArray &strings, const CStdString& delimiter, CStdString& result)
{
@@ -383,3 +387,58 @@ void StringUtils::WordToDigits(CStdString &word)
}
}
+CStdString StringUtils::CreateUUID()
+{
+ /* This function generate a DCE 1.1, ISO/IEC 11578:1996 and IETF RFC-4122
+ * Version 4 conform local unique UUID based upon random number generation.
+ */
+ char UuidStrTmp[40];
+ char *pUuidStr = UuidStrTmp;
+ int i;
+
+ /* generate hash from last generated UUID string */
+ unsigned seed = 0;
+ for (unsigned i = 0; i < m_lastUUID.length(); i++) {
+ seed = 31*seed + m_lastUUID[i];
+ }
+
+ /* use hash as the seed for rand()*/
+ srand(seed);
+
+ /*Data1 - 8 characters.*/
+ for(i = 0; i < 8; i++, pUuidStr++)
+ ((*pUuidStr = (rand() % 16)) < 10) ? *pUuidStr += 48 : *pUuidStr += 55;
+
+ /*Data2 - 4 characters.*/
+ *pUuidStr++ = '-';
+ for(i = 0; i < 4; i++, pUuidStr++)
+ ((*pUuidStr = (rand() % 16)) < 10) ? *pUuidStr += 48 : *pUuidStr += 55;
+
+ /*Data3 - 4 characters.*/
+ *pUuidStr++ = '-';
+ for(i = 0; i < 4; i++, pUuidStr++)
+ ((*pUuidStr = (rand() % 16)) < 10) ? *pUuidStr += 48 : *pUuidStr += 55;
+
+ /*Data4 - 4 characters.*/
+ *pUuidStr++ = '-';
+ for(i = 0; i < 4; i++, pUuidStr++)
+ ((*pUuidStr = (rand() % 16)) < 10) ? *pUuidStr += 48 : *pUuidStr += 55;
+
+ /*Data5 - 12 characters.*/
+ *pUuidStr++ = '-';
+ for(i = 0; i < 12; i++, pUuidStr++)
+ ((*pUuidStr = (rand() % 16)) < 10) ? *pUuidStr += 48 : *pUuidStr += 55;
+
+ *pUuidStr = '\0';
+
+ m_lastUUID = UuidStrTmp;
+ return UuidStrTmp;
+}
+
+bool StringUtils::ValidateUUID(const CStdString &uuid)
+{
+ CRegExp guidRE;
+ guidRE.RegComp(ADDON_GUID_RE);
+ return (guidRE.RegFind(uuid.c_str()) == 0);
+}
+
diff --git a/xbmc/StringUtils.h b/xbmc/StringUtils.h
index a59cf337f1..7afebe2626 100644
--- a/xbmc/StringUtils.h
+++ b/xbmc/StringUtils.h
@@ -54,6 +54,10 @@ public:
static int FindEndBracket(const CStdString &str, char opener, char closer, int startPos = 0);
static int DateStringToYYYYMMDD(const CStdString &dateString);
static void WordToDigits(CStdString &word);
+ static CStdString CreateUUID();
+ static bool ValidateUUID(const CStdString &uuid); // NB only validates syntax
+private:
+ static CStdString m_lastUUID;
};
#endif
diff --git a/xbmc/URL.cpp b/xbmc/URL.cpp
index 24722328e8..ba07315239 100644
--- a/xbmc/URL.cpp
+++ b/xbmc/URL.cpp
@@ -26,12 +26,14 @@
#include "FileSystem/File.h"
#include "FileItem.h"
#include "FileSystem/StackDirectory.h"
+#include "utils/Addon.h"
#ifndef _LINUX
#include <sys\types.h>
#include <sys\stat.h>
#endif
using namespace std;
+using namespace ADDON;
CStdString URLEncodeInline(const CStdString& strData)
{
@@ -188,7 +190,7 @@ void CURL::Parse(const CStdString& strURL1)
else
if(strProtocol2.Equals("http")
|| strProtocol2.Equals("https")
- || strProtocol2.Equals("plugin")
+ || TranslateContent(m_strProtocol) != CONTENT_NONE // plugin paths
|| strProtocol2.Equals("hdhomerun")
|| strProtocol2.Equals("rtsp")
|| strProtocol2.Equals("zip"))
diff --git a/xbmc/Util.cpp b/xbmc/Util.cpp
index e643f4742e..af0a6b16fb 100644
--- a/xbmc/Util.cpp
+++ b/xbmc/Util.cpp
@@ -745,7 +745,7 @@ bool CUtil::HasSlashAtEnd(const CStdString& strFile)
bool CUtil::IsRemote(const CStdString& strFile)
{
- if (IsCDDA(strFile) || IsISO9660(strFile) || IsPlugin(strFile))
+ if (IsCDDA(strFile) || IsISO9660(strFile))
return false;
if (IsSpecial(strFile))
@@ -986,7 +986,7 @@ bool CUtil::IsSpecial(const CStdString& strFile)
bool CUtil::IsPlugin(const CStdString& strFile)
{
CURL url(strFile);
- return url.GetProtocol().Equals("plugin") && !url.GetFileName().IsEmpty();
+ return !url.GetProtocol().IsEmpty() && StringUtils::ValidateUUID(url.GetHostName());
}
bool CUtil::IsPluginRoot(const CStdString& strFile)
diff --git a/xbmc/VideoDatabase.cpp b/xbmc/VideoDatabase.cpp
index 43c429a2a3..abbeb9667e 100644
--- a/xbmc/VideoDatabase.cpp
+++ b/xbmc/VideoDatabase.cpp
@@ -22,6 +22,7 @@
#include "VideoDatabase.h"
#include "GUIWindowVideoBase.h"
#include "utils/RegExp.h"
+#include "utils/AddonManager.h"
#include "utils/GUIInfoManager.h"
#include "Util.h"
#include "XMLUtils.h"
@@ -48,6 +49,7 @@ using namespace std;
using namespace dbiplus;
using namespace XFILE;
using namespace VIDEO;
+using namespace ADDON;
#define VIDEO_DATABASE_VIEW_TVSHOW "SELECT tvshow.*,path.strPath AS strPath," \
"counts.totalcount AS totalCount,counts.watchedcount AS watchedCount," \
@@ -3199,7 +3201,7 @@ void CVideoDatabase::RemoveContentForPath(const CStdString& strPath, CGUIDialogP
progress->Close();
}
-void CVideoDatabase::SetScraperForPath(const CStdString& filePath, const SScraperInfo& info, const VIDEO::SScanSettings& settings)
+void CVideoDatabase::SetScraperForPath(const CStdString& filePath, const ScraperPtr& scraper, const VIDEO::SScanSettings& settings)
{
// if we have a multipath, set scraper for all contained paths too
if(CUtil::IsMultiPath(filePath))
@@ -3208,7 +3210,7 @@ void CVideoDatabase::SetScraperForPath(const CStdString& filePath, const SScrape
CMultiPathDirectory::GetPaths(filePath, paths);
for(unsigned i=0;i<paths.size();i++)
- SetScraperForPath(paths[i],info,settings);
+ SetScraperForPath(paths[i],scraper,settings);
}
try
@@ -3223,7 +3225,20 @@ void CVideoDatabase::SetScraperForPath(const CStdString& filePath, const SScrape
}
// Update
- CStdString strSQL=FormatSQL("update path set strContent='%s',strScraper='%s', scanRecursive=%i, useFolderNames=%i, strSettings='%s', noUpdate=%i where idPath=%i", info.strContent.c_str(), info.strPath.c_str(),settings.recurse,settings.parent_name,info.settings.GetSettings().c_str(),settings.noupdate, idPath);
+ CStdString strSQL;
+ if (settings.exclude)
+ { //NB See note in ::GetScraperForPath about strContent=='none'
+ strSQL=FormatSQL("update path set strContent='none', strScraper='', scanRecursive=0, useFolderNames=0, strSettings='', noUpdate=0 where idPath=%i", idPath);
+ }
+ else if(!scraper)
+ { // catch clearing content, but not excluding
+ strSQL=FormatSQL("update path set strContent='', strScraper='', scanRecursive=0, useFolderNames=0, strSettings='', noUpdate=0 where idPath=%i", idPath);
+ }
+ else
+ {
+ CStdString content = TranslateContent(scraper->Content());
+ strSQL=FormatSQL("update path set strContent='%s', strScraper='%s', scanRecursive=%i, useFolderNames=%i, strSettings='%s', noUpdate=%i where idPath=%i", content.c_str(), scraper->UUID().c_str(),settings.recurse,settings.parent_name,scraper->GetSettings().c_str(),settings.noupdate, idPath);
+ }
m_pDS->exec(strSQL.c_str());
}
catch (...)
@@ -5498,29 +5513,28 @@ int CVideoDatabase::GetMusicVideoCount(const CStdString& strWhere)
return 0;
}
-bool CVideoDatabase::GetScraperForPath(const CStdString& strPath, SScraperInfo& info)
+bool CVideoDatabase::GetScraperForPath( const CStdString& strPath, ScraperPtr& scraper )
{
int iDummy;
- return GetScraperForPath(strPath, info, iDummy);
+ return GetScraperForPath(strPath, scraper, iDummy);
}
-bool CVideoDatabase::GetScraperForPath(const CStdString& strPath, SScraperInfo& info, int& iFound)
+bool CVideoDatabase::GetScraperForPath(const CStdString& strPath, ScraperPtr& scraper, int& iFound)
{
SScanSettings settings;
- return GetScraperForPath(strPath, info, settings, iFound);
+ return GetScraperForPath(strPath, scraper, settings, iFound);
}
-bool CVideoDatabase::GetScraperForPath(const CStdString& strPath, SScraperInfo& info, SScanSettings& settings)
+bool CVideoDatabase::GetScraperForPath(const CStdString& strPath, ScraperPtr& scraper, SScanSettings& settings)
{
int iDummy;
- return GetScraperForPath(strPath, info, settings, iDummy);
+ return GetScraperForPath(strPath, scraper, settings, iDummy);
}
-bool CVideoDatabase::GetScraperForPath(const CStdString& strPath, SScraperInfo& info, SScanSettings& settings, int& iFound)
+bool CVideoDatabase::GetScraperForPath(const CStdString& strPath, ScraperPtr& scraper, SScanSettings& settings, int& iFound)
{
try
{
- info.Reset();
if (strPath.IsEmpty()) return false;
if (NULL == m_pDB.get()) return false;
if (NULL == m_pDS.get()) return false;
@@ -5542,59 +5556,100 @@ bool CVideoDatabase::GetScraperForPath(const CStdString& strPath, SScraperInfo&
iFound = 1;
if (!m_pDS->eof())
- {
- info.strContent = m_pDS->fv("path.strContent").get_asString();
- info.strPath = m_pDS->fv("path.strScraper").get_asString();
- info.settings.LoadUserXML(m_pDS->fv("path.strSettings").get_asString());
-
- CScraperParser parser;
- parser.Load("special://xbmc/system/scrapers/video/" + info.strPath);
- info.strLanguage = parser.GetLanguage();
- info.strTitle = parser.GetName();
- info.strDate = parser.GetDate();
- info.strFramework = parser.GetFramework();
-
- settings.parent_name = m_pDS->fv("path.useFolderNames").get_asBool();
- settings.recurse = m_pDS->fv("path.scanRecursive").get_asInt();
- settings.noupdate = m_pDS->fv("path.noUpdate").get_asBool();
- }
- if (info.strContent.IsEmpty())
- {
- CStdString strParent;
-
- while (CUtil::GetParentPath(strPath1, strParent))
+ { //!!!
+ //FIXME confusion arises here as VIDEODB_CONTENT_NONE has no relation to strContent == 'none'.
+ // Here, we are referring to paths which are explicitly excluded from scraping, by
+ // having settings.exclude == true
+ //!!
+ CStdString strcontent = m_pDS->fv("path.strContent").get_asString();
+ strcontent.ToLower();
+ if (strcontent.Equals("none"))
{
- iFound++;
+ settings.exclude = true;
+ scraper.reset();
+ m_pDS->close();
+ return false;
+ }
- CStdString strSQL=FormatSQL("select path.strContent,path.strScraper,path.scanRecursive,path.useFolderNames,path.strSettings,path.noUpdate from path where strPath like '%s'",strParent.c_str());
- m_pDS->query(strSQL.c_str());
- if (!m_pDS->eof())
- {
- info.strContent = m_pDS->fv("path.strContent").get_asString();
- info.strPath = m_pDS->fv("path.strScraper").get_asString();
- info.settings.LoadUserXML(m_pDS->fv("path.strSettings").get_asString());
+ // path is not excluded, find out if content is set
+ // then try and ascertain scraper for this path
+ CONTENT_TYPE content = TranslateContent(strcontent);
+ CStdString scraperUUID = m_pDS->fv("path.strScraper").get_asString();
- CScraperParser parser;
- parser.Load("special://xbmc/system/scrapers/video/" + info.strPath);
- info.strLanguage = parser.GetLanguage();
- info.strTitle = parser.GetName();
- info.strDate = parser.GetDate();
- info.strFramework = parser.GetFramework();
+ if (content != CONTENT_NONE)
+ { // content set, use pre configured or default scraper
+ AddonPtr addon;
+ if (!scraperUUID.empty() &&
+ CAddonMgr::Get()->GetAddon(ADDON::ADDON_SCRAPER, scraperUUID, addon))
+ {
+ scraper = boost::dynamic_pointer_cast<CScraper>(addon->Clone(addon));
+ if (!scraper)
+ return false;
+ // store this path's content & settings
+ scraper->m_pathContent = content;
+ scraper->LoadUserXML(m_pDS->fv("path.strSettings").get_asString());
settings.parent_name = m_pDS->fv("path.useFolderNames").get_asBool();
settings.recurse = m_pDS->fv("path.scanRecursive").get_asInt();
settings.noupdate = m_pDS->fv("path.noUpdate").get_asBool();
-
- if (!info.strContent.IsEmpty())
- break;
}
+ else
+ { // use default scraper for this content type
+ if (CAddonMgr::Get()->GetDefault(ADDON::ADDON_SCRAPER, addon, content))
+ {
+ scraper = boost::dynamic_pointer_cast<CScraper>(addon->Clone(addon));
+ if (scraper)
+ {
+ scraper->m_pathContent = content;
+ settings.parent_name = m_pDS->fv("path.useFolderNames").get_asBool();
+ settings.recurse = m_pDS->fv("path.scanRecursive").get_asInt();
+ settings.noupdate = m_pDS->fv("path.noUpdate").get_asBool();
+ }
+ }
+ }
+ }
+ else
+ { // no content set for this path (ie path.strContent == '')
+ // we must drill up until a scraper is configured
+ CStdString strParent;
+ while (CUtil::GetParentPath(strPath1, strParent))
+ {
+ iFound++;
- strPath1 = strParent;
+ CStdString strSQL=FormatSQL("select path.strContent,path.strScraper,path.scanRecursive,path.useFolderNames,path.strSettings,path.noUpdate from path where strPath like '%s'",strParent.c_str());
+ m_pDS->query(strSQL.c_str());
+ if (!m_pDS->eof())
+ {
+ AddonPtr defaultScraper;
+ if (!CAddonMgr::Get()->GetAddon(ADDON::ADDON_SCRAPER, m_pDS->fv("path.strScraper").get_asString(), defaultScraper))
+ {
+ strPath1 = strParent;
+ continue;
+ }
+
+ scraper = boost::dynamic_pointer_cast<CScraper>(defaultScraper->Clone(defaultScraper));
+ content = TranslateContent(m_pDS->fv("path.strContent").get_asString());
+ scraper->m_pathContent = content;
+ scraper->LoadUserXML(m_pDS->fv("path.strSettings").get_asString());
+ settings.parent_name = m_pDS->fv("path.useFolderNames").get_asBool();
+ settings.recurse = m_pDS->fv("path.scanRecursive").get_asInt();
+ settings.noupdate = m_pDS->fv("path.noUpdate").get_asBool();
+ settings.exclude = false;
+
+ //TODO fix CONTENT_NONE storage in db, per discussion
+ if (!content == CONTENT_NONE)
+ break;
+ }
+ strPath1 = strParent;
+ }
}
}
m_pDS->close();
- if (info.strContent.Equals("tvshows"))
+ if (!scraper)
+ return false;
+
+ if (scraper->Content() == CONTENT_TVSHOWS)
{
settings.recurse = 0;
if(settings.parent_name) // single show
@@ -5608,13 +5663,13 @@ bool CVideoDatabase::GetScraperForPath(const CStdString& strPath, SScraperInfo&
return iFound <= 3;
}
}
- else if (info.strContent.Equals("movies"))
+ else if (scraper->Content() == CONTENT_MOVIES)
{
settings.recurse = settings.recurse - (iFound-1);
settings.parent_name_root = settings.parent_name && (!settings.recurse || iFound > 1);
return settings.recurse >= 0;
}
- else if (info.strContent.Equals("musicvideos"))
+ else if (scraper->Content() == CONTENT_MUSICVIDEOS)
{
settings.recurse = settings.recurse - (iFound-1);
settings.parent_name_root = settings.parent_name && (!settings.recurse || iFound > 1);
@@ -5623,11 +5678,6 @@ bool CVideoDatabase::GetScraperForPath(const CStdString& strPath, SScraperInfo&
else
{
iFound = 0;
- // this is setup so set content dialog will show correct defaults
- settings.recurse = -1;
- settings.parent_name = false;
- settings.parent_name_root = false;
- settings.noupdate = false;
return false;
}
}
@@ -7384,7 +7434,7 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f
TiXmlNode *pPaths = pMain->InsertEndChild(xmlPathElement);
for( map<CStdString,SScanSettings>::iterator iter=paths.begin();iter != paths.end();++iter)
{
- SScraperInfo info;
+ ScraperPtr info;
int iFound=0;
if (GetScraperForPath(iter->first,info,iFound) && iFound == 1)
{
@@ -7393,8 +7443,8 @@ void CVideoDatabase::ExportToXML(const CStdString &path, bool singleFiles /* = f
XMLUtils::SetString(pPath,"url",iter->first);
XMLUtils::SetInt(pPath,"scanrecursive",iter->second.recurse);
XMLUtils::SetBoolean(pPath,"usefoldernames",iter->second.parent_name);
- XMLUtils::SetString(pPath,"content",info.strContent);
- XMLUtils::SetString(pPath,"scraperpath",info.strPath);
+ XMLUtils::SetString(pPath,"content", TranslateContent(info->Content()));
+ XMLUtils::SetString(pPath,"scraperpath",info->UUID());
}
}
xmlDoc.SaveFile(xmlFile);
@@ -7523,7 +7573,7 @@ void CVideoDatabase::ImportFromXML(const CStdString &path)
{
info.Load(movie);
CFileItem item(info);
- scanner.AddMovie(&item,"movies",info);
+ scanner.AddMovie(&item,CONTENT_MOVIES,info);
SetPlayCount(item, info.m_playCount, info.m_lastPlayed);
CStdString file(GetSafeFile(moviesDir, info.m_strTitle));
CFile::Cache(file + ".tbn", item.GetCachedVideoThumb());
@@ -7536,7 +7586,7 @@ void CVideoDatabase::ImportFromXML(const CStdString &path)
{
info.Load(movie);
CFileItem item(info);
- scanner.AddMovie(&item,"musicvideos",info);
+ scanner.AddMovie(&item,CONTENT_MUSICVIDEOS,info);
SetPlayCount(item, info.m_playCount, info.m_lastPlayed);
CStdString file(GetSafeFile(musicvideosDir, info.m_strArtist + "." + info.m_strTitle));
CFile::Cache(file + ".tbn", item.GetCachedVideoThumb());
@@ -7550,7 +7600,7 @@ void CVideoDatabase::ImportFromXML(const CStdString &path)
CUtil::AddSlashAtEnd(info.m_strPath);
DeleteTvShow(info.m_strPath);
CFileItem item(info);
- int showID = scanner.AddMovie(&item,"tvshows",info);
+ int showID = scanner.AddMovie(&item,CONTENT_TVSHOWS,info);
current++;
CStdString showDir(GetSafeFile(tvshowsDir, info.m_strTitle));
CFile::Cache(CUtil::AddFileToFolder(showDir, "folder.jpg"), item.GetCachedVideoThumb());
@@ -7565,7 +7615,7 @@ void CVideoDatabase::ImportFromXML(const CStdString &path)
CVideoInfoTag info;
info.Load(episode);
CFileItem item(info);
- scanner.AddMovie(&item,"tvshows",info,showID);
+ scanner.AddMovie(&item,CONTENT_TVSHOWS,info,showID);
SetPlayCount(item, info.m_playCount, info.m_lastPlayed);
CStdString file;
file.Format("s%02ie%02i.tbn", info.m_iSeason, info.m_iEpisode);
@@ -7584,13 +7634,29 @@ void CVideoDatabase::ImportFromXML(const CStdString &path)
{
CStdString strPath;
XMLUtils::GetString(path,"url",strPath);
- SScraperInfo info;
- SScanSettings settings;
- XMLUtils::GetString(path,"content",info.strContent);
- XMLUtils::GetString(path,"scraperpath",info.strPath);
- XMLUtils::GetInt(path,"scanrecursive",settings.recurse);
- XMLUtils::GetBoolean(path,"usefoldernames",settings.parent_name);
- SetScraperForPath(strPath,info,settings);
+ CStdString content;
+
+ if (XMLUtils::GetString(path,"content", content))
+ { // check the scraper exists, if so store the path
+ AddonPtr addon;
+ CStdString uuid;
+
+ if (!XMLUtils::GetString(path,"scraperuuid",uuid))
+ { // support pre addons exports
+ XMLUtils::GetString(path, "scraperpath", uuid);
+ uuid = CUtil::GetFileName(uuid);
+ }
+
+ if (CAddonMgr::Get()->GetAddon(ADDON::ADDON_SCRAPER, uuid, addon))
+ {
+ SScanSettings settings;
+ ScraperPtr scraper = boost::dynamic_pointer_cast<CScraper>(addon);
+ scraper->m_pathContent = TranslateContent(content);
+ XMLUtils::GetInt(path,"scanrecursive",settings.recurse);
+ XMLUtils::GetBoolean(path,"usefoldernames",settings.parent_name);
+ SetScraperForPath(strPath,scraper,settings);
+ }
+ }
path = path->NextSiblingElement();
}
}
@@ -7711,14 +7777,16 @@ void CVideoDatabase::SplitPath(const CStdString& strFileNameAndPath, CStdString&
void CVideoDatabase::InvalidatePathHash(const CStdString& strPath)
{
- SScraperInfo info;
+ ScraperPtr info;
SScanSettings settings;
int iFound;
GetScraperForPath(strPath,info,settings,iFound);
SetPathHash(strPath,"");
- if (info.strContent.Equals("tvshows") || (info.strContent.Equals("movies") && iFound != 1)) // if we scan by folder name we need to invalidate parent as well
+ if (!info)
+ return;
+ if (info->Content() == CONTENT_TVSHOWS || (info->Content() == CONTENT_MOVIES && iFound != 1)) // if we scan by folder name we need to invalidate parent as well
{
- if (info.strContent.Equals("tvshows") || settings.parent_name_root)
+ if (info->Content() == CONTENT_TVSHOWS || settings.parent_name_root)
{
CStdString strParent;
CUtil::GetParentPath(strPath,strParent);
diff --git a/xbmc/VideoDatabase.h b/xbmc/VideoDatabase.h
index 724518e949..614508f3f0 100644
--- a/xbmc/VideoDatabase.h
+++ b/xbmc/VideoDatabase.h
@@ -21,12 +21,12 @@
*/
#include "Database.h"
#include "VideoInfoTag.h"
+#include "Scraper.h"
#include "Bookmark.h"
#include <memory>
#include <set>
-struct SScraperInfo;
class CFileItem;
class CFileItemList;
class CVideoSettings;
@@ -389,11 +389,12 @@ public:
void DeleteBookMarkForEpisode(const CVideoInfoTag& tag);
// scraper settings
- void SetScraperForPath(const CStdString& filePath, const SScraperInfo& info, const VIDEO::SScanSettings& settings);
- bool GetScraperForPath(const CStdString& strPath, SScraperInfo& info);
- bool GetScraperForPath(const CStdString& strPath, SScraperInfo& info, int& iFound);
- bool GetScraperForPath(const CStdString& strPath, SScraperInfo& info, VIDEO::SScanSettings& settings);
- bool GetScraperForPath(const CStdString& strPath, SScraperInfo& info, VIDEO::SScanSettings& settings, int& iFound);
+ void SetScraperForPath(const CStdString& filePath, const ADDON::ScraperPtr& info, const VIDEO::SScanSettings& settings);
+ bool GetScraperForPath(const CStdString& strPath, ADDON::ScraperPtr& scraper);
+ bool GetScraperForPath(const CStdString& strPath, ADDON::ScraperPtr& scraper, int& iFound);
+ bool GetScraperForPath(const CStdString& strPath, ADDON::ScraperPtr& scraper, VIDEO::SScanSettings& settings);
+ bool GetScraperForPath(const CStdString& strPath, ADDON::ScraperPtr& scraper, VIDEO::SScanSettings& settings, int& iFound);
+ CONTENT_TYPE GetContentForPath(const CStdString& strPath);
// scanning hashes and paths scanned
bool SetPathHash(const CStdString &path, const CStdString &hash);
diff --git a/xbmc/VideoInfoScanner.cpp b/xbmc/VideoInfoScanner.cpp
index 06c62ed2bb..8353288db3 100644
--- a/xbmc/VideoInfoScanner.cpp
+++ b/xbmc/VideoInfoScanner.cpp
@@ -21,6 +21,7 @@
#include "FileItem.h"
#include "VideoInfoScanner.h"
+#include "AddonManager.h"
#include "FileSystem/DirectoryCache.h"
#include "Util.h"
#include "NfoFile.h"
@@ -44,6 +45,7 @@
using namespace std;
using namespace XFILE;
+using namespace ADDON;
namespace VIDEO
{
@@ -135,7 +137,7 @@ namespace VIDEO
}
}
- void CVideoInfoScanner::Start(const CStdString& strDirectory, const SScraperInfo& info, const SScanSettings& settings, bool bUpdateAll)
+ void CVideoInfoScanner::Start(const CStdString& strDirectory, const ScraperPtr& info, const SScanSettings& settings, bool bUpdateAll)
{
m_strStartDir = strDirectory;
m_bUpdateAll = bUpdateAll;
@@ -200,12 +202,19 @@ namespace VIDEO
CFileItemList items;
int iFound;
bool bSkip=false;
- m_database.GetScraperForPath(strDirectory,m_info,settings, iFound);
- if (m_info.strContent.IsEmpty() || m_info.strContent.Equals("None"))
+ // first time m_info is set
+
+ if (!m_database.GetScraperForPath(strDirectory,m_info,settings, iFound))
+ {
+ m_info.reset();
+ return false;
+ }
+
+ if (m_info->Content() == CONTENT_NONE)
bSkip = true;
CStdString hash, dbHash;
- if (m_info.strContent.Equals("movies") && !settings.noupdate)
+ if (m_info->Content() == CONTENT_MOVIES && !settings.noupdate)
{
if (m_pObserver)
m_pObserver->OnStateChanged(FETCHING_MOVIE_INFO);
@@ -237,7 +246,7 @@ namespace VIDEO
bSkip = true;
}
}
- else if (m_info.strContent.Equals("tvshows") && !settings.noupdate)
+ else if (m_info->Content() == CONTENT_TVSHOWS && !settings.noupdate)
{
if (m_pObserver)
m_pObserver->OnStateChanged(FETCHING_TVSHOW_INFO);
@@ -265,7 +274,7 @@ namespace VIDEO
CUtil::GetParentPath(item->m_strPath,items.m_strPath);
}
}
- else if (m_info.strContent.Equals("musicvideos") && !settings.noupdate)
+ else if (m_info->Content() == CONTENT_MUSICVIDEOS && !settings.noupdate)
{
if (m_pObserver)
m_pObserver->OnStateChanged(FETCHING_MUSICVIDEO_INFO);
@@ -297,27 +306,13 @@ namespace VIDEO
}
}
- CLog::Log(LOGDEBUG,"Hash[%s,%s]:DB=[%s],Computed=[%s]",
- m_info.strContent.c_str(),strDirectory.c_str(),dbHash.c_str(),hash.c_str());
-
- if (!m_info.settings.GetPluginRoot() && m_info.settings.GetSettings().IsEmpty()) // check for settings, if they are around load defaults - to workaround the nastyness
- {
- CScraperParser parser;
- CStdString strPath;
- if (!m_info.strContent.IsEmpty())
- strPath = "special://xbmc/system/scrapers/video/" + m_info.strPath;
- if (!strPath.IsEmpty() && parser.Load(strPath) && parser.HasFunction("GetSettings"))
- {
- if (m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/video/" + m_info.strPath))
- m_info.settings.SaveFromDefault();
- }
- }
+ CLog::Log(LOGDEBUG,"Hash[%s,%s]:DB=[%s],Computed=[%s]", TranslateContent(m_info->Content()).c_str(),strDirectory.c_str(),dbHash.c_str(),hash.c_str());
if (!bSkip)
{
if (RetrieveVideoInfo(items,settings.parent_name_root,m_info))
{
- if (!m_bStop && (m_info.strContent.Equals("movies") || m_info.strContent.Equals("musicvideos")))
+ if (!m_bStop && (m_info->Content() == CONTENT_MOVIES || m_info->Content() == CONTENT_MUSICVIDEOS))
{
m_database.SetPathHash(strDirectory, hash);
m_pathsToClean.push_back(m_database.GetPathId(strDirectory));
@@ -335,7 +330,7 @@ namespace VIDEO
CLog::Log(LOGDEBUG, "%s - Finished dir: %s", __FUNCTION__, strDirectory.c_str());
// exclude folders that match our exclude regexps
- CStdStringArray regexps = m_info.strContent.Equals("tvshows") ? g_advancedSettings.m_tvshowExcludeFromScanRegExps
+ CStdStringArray regexps = m_info->Content() == CONTENT_TVSHOWS ? g_advancedSettings.m_tvshowExcludeFromScanRegExps
: g_advancedSettings.m_moviesExcludeFromScanRegExps;
for (int i = 0; i < items.Size(); ++i)
@@ -346,7 +341,7 @@ namespace VIDEO
break;
// if we have a directory item (non-playlist) we then recurse into that folder
- if (pItem->m_bIsFolder && !pItem->GetLabel().Equals("sample") && !pItem->GetLabel().Equals("subs") && !pItem->IsParentFolder() && !pItem->IsPlayList() && settings.recurse > 0 && !m_info.strContent.Equals("tvshows")) // do not recurse for tv shows - we have already looked recursively for episodes
+ if (pItem->m_bIsFolder && !pItem->GetLabel().Equals("sample") && !pItem->GetLabel().Equals("subs") && !pItem->IsParentFolder() && !pItem->IsPlayList() && settings.recurse > 0 && m_info->Content() != CONTENT_TVSHOWS) // do not recurse for tv shows - we have already looked recursively for episodes
{
CStdString strPath=pItem->m_strPath;
@@ -371,9 +366,9 @@ namespace VIDEO
return !m_bStop;
}
- bool CVideoInfoScanner::RetrieveVideoInfo(CFileItemList& items, bool bDirNames, const SScraperInfo& info, bool bRefresh, CScraperUrl* pURL, CGUIDialogProgress* pDlgProgress, bool ignoreNfo)
+ bool CVideoInfoScanner::RetrieveVideoInfo(CFileItemList& items, bool bDirNames, const ScraperPtr& scraper, bool bRefresh, CScraperUrl* pURL, CGUIDialogProgress* pDlgProgress, bool ignoreNfo)
{
- m_IMDB.SetScraperInfo(info);
+ m_IMDB.SetScraperInfo(scraper);
if (pDlgProgress)
{
@@ -406,41 +401,23 @@ namespace VIDEO
CFileItemPtr pItem = items[i];
// we do this since we may have a override per dir
- SScraperInfo info2;
+ ScraperPtr info2;
if (pItem->m_bIsFolder)
m_database.GetScraperForPath(pItem->m_strPath,info2);
else
m_database.GetScraperForPath(items.m_strPath,info2);
- if (info2.strContent.Equals("None")) // skip
+ if (!info2 || info2->Content() == CONTENT_NONE) // skip
continue;
- if (!info2.settings.GetPluginRoot() && info2.settings.GetSettings().IsEmpty()) // check for settings, if they are around load defaults - to workaround the nastyness
- {
- CScraperParser parser;
- if (parser.Load("special://xbmc/system/scrapers/video/"+info2.strPath) && parser.HasFunction("GetSettings"))
- {
- if (info2.settings.LoadSettingsXML("special://xbmc/system/scrapers/video/" + info2.strPath))
- info2.settings.SaveFromDefault();
- else if (!DownloadFailed(pDlgProgress))
- return false;
- else
- continue;
- }
- }
-
- // we might override scraper
- if (info2.strContent == info.strContent)
- info2.strPath = info.strPath;
-
m_IMDB.SetScraperInfo(info2);
// Discard all exclude files defined by regExExclude
- if (CUtil::ExcludeFileOrFolder(pItem->m_strPath, info.strContent.Equals("tvshows") ? g_advancedSettings.m_tvshowExcludeFromScanRegExps
+ if (CUtil::ExcludeFileOrFolder(pItem->m_strPath, scraper->Content() == CONTENT_TVSHOWS ? g_advancedSettings.m_tvshowExcludeFromScanRegExps
: g_advancedSettings.m_moviesExcludeFromScanRegExps))
continue;
- if (info2.strContent.Equals("movies") || info2.strContent.Equals("musicvideos"))
+ if (info2->Content() == CONTENT_MOVIES || info2->Content() == CONTENT_MUSICVIDEOS)
{
if (m_pObserver)
{
@@ -450,7 +427,7 @@ namespace VIDEO
}
}
- if (info2.strContent.Equals("tvshows"))
+ if (info2->Content() == CONTENT_TVSHOWS)
{
if (pItem->m_bIsFolder)
idTvShow = m_database.GetTvShowId(pItem->m_strPath);
@@ -514,21 +491,21 @@ namespace VIDEO
}
}
- if (!pItem->m_bIsFolder || info2.strContent.Equals("tvshows"))
+ if (!pItem->m_bIsFolder || info2->Content() == CONTENT_TVSHOWS)
{
- if ((pItem->IsVideo() && !pItem->IsNFO() && !pItem->IsPlayList()) || info2.strContent.Equals("tvshows") )
+ if ((pItem->IsVideo() && !pItem->IsNFO() && !pItem->IsPlayList()) || info2->Content() == CONTENT_TVSHOWS )
{
if (pDlgProgress)
{
int iString=198;
- if (info2.strContent.Equals("tvshows"))
+ if (info2->Content() == CONTENT_TVSHOWS)
{
if (pItem->m_bIsFolder)
iString = 20353;
else
iString = 20361;
}
- if (info2.strContent.Equals("musicvideos"))
+ if (info2->Content() == CONTENT_MUSICVIDEOS)
iString = 20394;
pDlgProgress->SetHeading(iString);
pDlgProgress->SetLine(0, pItem->GetLabel());
@@ -548,8 +525,8 @@ namespace VIDEO
m_database.Close();
return false;
}
- if ((info2.strContent.Equals("movies") && m_database.HasMovieInfo(pItem->m_strPath)) ||
- (info2.strContent.Equals("musicvideos") && m_database.HasMusicVideoInfo(pItem->m_strPath)))
+ if ((info2->Content() == CONTENT_MOVIES && m_database.HasMovieInfo(pItem->m_strPath)) ||
+ (info2->Content() == CONTENT_MUSICVIDEOS && m_database.HasMusicVideoInfo(pItem->m_strPath)))
continue;
CNfoFile::NFOResult result=CNfoFile::NO_NFO;
@@ -559,13 +536,19 @@ namespace VIDEO
result = CheckForNFOFile(pItem.get(),bDirNames,info2,scrUrl);
if (result == CNfoFile::ERROR_NFO)
continue;
- if (info2.strContent.Equals("tvshows") && result != CNfoFile::NO_NFO)
- {
- SScraperInfo info3(info2);
+ if (info2->Content() == CONTENT_TVSHOWS && result != CNfoFile::NO_NFO)
+ { //FIXME this comment doesn't match second comment
+ // check for preconfigured scraper; if found, overwrite with interpreted scraper but keep current scan settings
+ ScraperPtr temp;
SScanSettings settings;
- m_database.GetScraperForPath(pItem->m_strPath,info3,settings);
- info3.strPath = info2.strPath;
- m_database.SetScraperForPath(pItem->m_strPath,info3,settings);
+ if (m_database.GetScraperForPath(pItem->m_strPath,temp,settings))
+ {
+ if (temp->Parent())
+ { // as we are working with a new clone, default scraper settings are saved
+ temp = boost::dynamic_pointer_cast<CScraper>(temp->Parent());
+ m_database.SetScraperForPath(pItem->m_strPath,temp,settings);
+ }
+ }
}
if (result == CNfoFile::FULL_NFO)
{
@@ -574,10 +557,10 @@ namespace VIDEO
if (m_pObserver)
m_pObserver->OnSetTitle(pItem->GetVideoInfoTag()->m_strTitle);
- long lResult = AddMovieAndGetThumb(pItem.get(), info2.strContent, *pItem->GetVideoInfoTag(), -1, bDirNames, bRefresh, pDlgProgress);
- if (bRefresh && info.strContent.Equals("tvshows") && g_guiSettings.GetBool("videolibrary.seasonthumbs"))
+ long lResult = AddMovieAndGetThumb(pItem.get(), info2->Content(), *pItem->GetVideoInfoTag(), -1, bDirNames, bRefresh, pDlgProgress);
+ if (bRefresh && scraper->Content() == CONTENT_TVSHOWS && g_guiSettings.GetBool("videolibrary.seasonthumbs"))
FetchSeasonThumbs(lResult);
- if (!bRefresh && info2.strContent.Equals("tvshows"))
+ if (!bRefresh && info2->Content() == CONTENT_TVSHOWS)
i--;
Return = true;
continue;
@@ -609,18 +592,17 @@ namespace VIDEO
if (m_pObserver && !url.strTitle.IsEmpty())
m_pObserver->OnSetTitle(url.strTitle);
long lResult=1;
-
- // force thumb and fanart
- bool bForce(false);
+ // force thumb and fanart
+ bool bForce(false);
if (result==CNfoFile::NO_NFO || result==CNfoFile::ERROR_NFO)
bForce = true;
if (pDlgProgress)
- lResult=GetIMDBDetails(pItem.get(), url, info2, bDirNames && info2.strContent.Equals("movies"), pDlgProgress, result == CNfoFile::COMBINED_NFO, bForce);
+ lResult=GetIMDBDetails(pItem.get(), url, info2, bDirNames && info2->Content() == CONTENT_MOVIES, pDlgProgress, result == CNfoFile::COMBINED_NFO, bForce);
else
- lResult=GetIMDBDetails(pItem.get(), url, info2, bDirNames && info2.strContent.Equals("movies"), NULL, result == CNfoFile::COMBINED_NFO, bForce);
+ lResult=GetIMDBDetails(pItem.get(), url, info2, bDirNames && info2->Content() == CONTENT_MOVIES, NULL, result == CNfoFile::COMBINED_NFO, bForce);
- if (info2.strContent.Equals("tvshows"))
+ if (info2->Content() == CONTENT_TVSHOWS)
{
if (!bRefresh)
{
@@ -682,7 +664,7 @@ namespace VIDEO
CFileItemList items;
CLog::Log(LOGDEBUG, "%s - processing dir: %s", __FUNCTION__, strPath.c_str());
CDirectory::GetDirectory(strPath, items, g_settings.m_videoExtensions, true);
- if (m_info.strContent.Equals("movies"))
+ if (m_info->Content() == CONTENT_MOVIES)
items.Stack();
for (int i=0; i<items.Size(); ++i)
@@ -976,7 +958,7 @@ namespace VIDEO
return bMatched;
}
- long CVideoInfoScanner::AddMovie(CFileItem *pItem, const CStdString &content, CVideoInfoTag &movieDetails, int idShow)
+ long CVideoInfoScanner::AddMovie(CFileItem *pItem, const CONTENT_TYPE &content, CVideoInfoTag &movieDetails, int idShow)
{
// ensure our database is open (this can get called via other classes)
if (!m_database.Open())
@@ -984,10 +966,11 @@ namespace VIDEO
CLog::Log(LOGERROR, "%s - failed to open database", __FUNCTION__);
return -1;
}
- CLog::Log(LOGDEBUG,"Adding new item to %s:%s", content.c_str(), pItem->m_strPath.c_str());
+ CLog::Log(LOGDEBUG,"Adding new item to %s:%s", TranslateContent(content).c_str(), pItem->m_strPath.c_str());
long lResult=-1;
+
// add to all movies in the stacked set
- if (content.Equals("movies"))
+ if (content == CONTENT_MOVIES)
{
// find local trailer first
CStdString strTrailer = pItem->FindTrailer();
@@ -1014,7 +997,7 @@ namespace VIDEO
}
}
}
- else if (content.Equals("tvshows"))
+ else if (content == CONTENT_TVSHOWS)
{
if (pItem->m_bIsFolder)
{
@@ -1037,14 +1020,14 @@ namespace VIDEO
}
}
}
- else if (content.Equals("musicvideos"))
+ else if (content == CONTENT_MUSICVIDEOS)
{
m_database.SetDetailsForMusicVideo(pItem->m_strPath, movieDetails);
}
return lResult;
}
- long CVideoInfoScanner::AddMovieAndGetThumb(CFileItem *pItem, const CStdString &content, CVideoInfoTag &movieDetails, int idShow, bool bApplyToDir, bool bRefresh, CGUIDialogProgress* pDialog /* == NULL */)
+ long CVideoInfoScanner::AddMovieAndGetThumb(CFileItem *pItem, const CONTENT_TYPE &content, CVideoInfoTag &movieDetails, int idShow, bool bApplyToDir, bool bRefresh, CGUIDialogProgress* pDialog /* == NULL */)
{
long lResult = AddMovie(pItem, content, movieDetails, idShow);
// get & save fanart image
@@ -1066,7 +1049,7 @@ namespace VIDEO
}
CStdString strThumb = pItem->GetCachedVideoThumb();
- if (content.Equals("tvshows") && !pItem->m_bIsFolder && CFile::Exists(strThumb))
+ if (content == CONTENT_TVSHOWS && !pItem->m_bIsFolder && CFile::Exists(strThumb))
{
movieDetails.m_strFileNameAndPath = pItem->m_strPath;
CFileItem item(movieDetails);
@@ -1180,7 +1163,7 @@ namespace VIDEO
// handle .nfo files
CScraperUrl scrUrl;
- SScraperInfo info(m_IMDB.GetScraperInfo());
+ ScraperPtr info(m_IMDB.GetScraperInfo());
item.GetVideoInfoTag()->m_iEpisode = file->iEpisode;
CNfoFile::NFOResult result = CheckForNFOFile(&item,false,info,scrUrl);
if (result == CNfoFile::FULL_NFO)
@@ -1192,7 +1175,7 @@ namespace VIDEO
strTitle.Format("%s - %ix%i - %s",strShowTitle.c_str(),episodeDetails.m_iSeason,episodeDetails.m_iEpisode,episodeDetails.m_strTitle.c_str());
m_pObserver->OnSetTitle(strTitle);
}
- AddMovieAndGetThumb(&item,"tvshows",episodeDetails,idShow);
+ AddMovieAndGetThumb(&item,CONTENT_TVSHOWS,episodeDetails,idShow);
continue;
}
@@ -1241,7 +1224,7 @@ namespace VIDEO
}
CFileItem item;
item.m_strPath = file->strPath;
- AddMovieAndGetThumb(&item,"tvshows",episodeDetails,idShow);
+ AddMovieAndGetThumb(&item,CONTENT_TVSHOWS,episodeDetails,idShow);
}
}
if (g_guiSettings.GetBool("videolibrary.seasonthumbs"))
@@ -1358,10 +1341,10 @@ namespace VIDEO
return nfoFile;
}
- long CVideoInfoScanner::GetIMDBDetails(CFileItem *pItem, CScraperUrl &url, const SScraperInfo& info, bool bUseDirNames, CGUIDialogProgress* pDialog /* = NULL */, bool bCombined, bool bRefresh)
+ long CVideoInfoScanner::GetIMDBDetails(CFileItem *pItem, CScraperUrl &url, const ScraperPtr& scraper, bool bUseDirNames, CGUIDialogProgress* pDialog /* = NULL */, bool bCombined, bool bRefresh)
{
CVideoInfoTag movieDetails;
- m_IMDB.SetScraperInfo(info);
+ m_IMDB.SetScraperInfo(scraper);
movieDetails.m_strFileNameAndPath = pItem->m_strPath;
if ( m_IMDB.GetDetails(url, movieDetails, pDialog) )
@@ -1378,7 +1361,7 @@ namespace VIDEO
pDialog->Progress();
}
- return AddMovieAndGetThumb(pItem, info.strContent, movieDetails, -1, bUseDirNames, bRefresh);
+ return AddMovieAndGetThumb(pItem, scraper->Content(), movieDetails, -1, bUseDirNames, bRefresh);
}
return -1;
}
@@ -1489,12 +1472,13 @@ namespace VIDEO
}
}
- CNfoFile::NFOResult CVideoInfoScanner::CheckForNFOFile(CFileItem* pItem, bool bGrabAny, SScraperInfo& info, CScraperUrl& scrUrl)
+ CNfoFile::NFOResult CVideoInfoScanner::CheckForNFOFile(CFileItem* pItem, bool bGrabAny, ScraperPtr& info, CScraperUrl& scrUrl)
{
CStdString strNfoFile;
- if (info.strContent.Equals("movies") || info.strContent.Equals("musicvideos") || (info.strContent.Equals("tvshows") && !pItem->m_bIsFolder))
+ if (info->Content() == CONTENT_MOVIES || info->Content() == CONTENT_MUSICVIDEOS
+ || (info->Content() == CONTENT_TVSHOWS && !pItem->m_bIsFolder))
strNfoFile = GetnfoFile(pItem,bGrabAny);
- if (info.strContent.Equals("tvshows") && pItem->m_bIsFolder)
+ if (info->Content() == CONTENT_TVSHOWS && pItem->m_bIsFolder)
CUtil::AddFileToFolder(pItem->m_strPath,"tvshow.nfo",strNfoFile);
CNfoFile::NFOResult result=CNfoFile::NO_NFO;
@@ -1520,19 +1504,20 @@ namespace VIDEO
CLog::Log(LOGDEBUG,"Found matching %s NFO file: %s", type.c_str(), strNfoFile.c_str());
if (result == CNfoFile::FULL_NFO)
{
- if (info.strContent.Equals("tvshows"))
- info.strPath = m_nfoReader.m_strScraper;
+ if (info->Content() == CONTENT_TVSHOWS)
+ info = m_nfoReader.GetScraperInfo();
}
else if (result != CNfoFile::NO_NFO)
{
CScraperUrl url(m_nfoReader.m_strImDbUrl);
scrUrl = url;
- CLog::Log(LOGDEBUG, "scraper: Fetching url '%s' using %s scraper (file: '%s', content: '%s', language: '%s', date: '%s', framework: '%s')",
- scrUrl.m_url[0].m_url.c_str(), info.strTitle.c_str(), info.strPath.c_str(), info.strContent.c_str(), info.strLanguage.c_str(), info.strDate.c_str(), info.strFramework.c_str());
+ ScraperPtr info(m_nfoReader.GetScraperInfo());
+ CLog::Log(LOGDEBUG, "scraper: Fetching url '%s' using %s scraper (content: '%s')",
+ scrUrl.m_url[0].m_url.c_str(), info->Name().c_str(), TranslateContent(info->Content()).c_str());
scrUrl.strId = m_nfoReader.m_strImDbNr;
- info.strPath = m_nfoReader.m_strScraper;
+ info = m_nfoReader.GetScraperInfo();
if (result == CNfoFile::COMBINED_NFO)
m_nfoReader.GetDetails(*pItem->GetVideoInfoTag());
}
diff --git a/xbmc/VideoInfoScanner.h b/xbmc/VideoInfoScanner.h
index 78fca539ff..f6b6ca340d 100644
--- a/xbmc/VideoInfoScanner.h
+++ b/xbmc/VideoInfoScanner.h
@@ -21,7 +21,7 @@
*/
#include "utils/Thread.h"
#include "VideoDatabase.h"
-#include "ScraperSettings.h"
+#include "Scraper.h"
#include "NfoFile.h"
#include "IMDB.h"
#include "DateTime.h"
@@ -32,10 +32,12 @@ namespace VIDEO
{
typedef struct SScanSettings
{
+ SScanSettings() { parent_name = parent_name_root = noupdate = exclude = false; recurse = -1;}
bool parent_name; /* use the parent dirname as name of lookup */
bool parent_name_root; /* use the name of directory where scan started as name for files in that dir */
int recurse; /* recurse into sub folders (indicate levels) */
bool noupdate; /* exclude from update library function */
+ bool exclude; /* exclude this path from scraping */
} SScanSettings;
typedef struct SEpisode
@@ -68,7 +70,7 @@ namespace VIDEO
public:
CVideoInfoScanner();
virtual ~CVideoInfoScanner();
- void Start(const CStdString& strDirectory, const SScraperInfo& info, const SScanSettings& settings, bool bUpdateAll);
+ void Start(const CStdString& strDirectory, const ADDON::ScraperPtr& info, const SScanSettings& settings, bool bUpdateAll);
bool IsScanning();
void Stop();
void SetObserver(IVideoInfoScannerObserver* pObserver);
@@ -76,16 +78,16 @@ namespace VIDEO
void EnumerateSeriesFolder(CFileItem* item, EPISODES& episodeList);
bool ProcessItemNormal(CFileItemPtr item, EPISODES& episodeList, CStdString regexp);
bool ProcessItemByDate(CFileItemPtr item, EPISODES& eipsodeList, CStdString regexp);
- long AddMovie(CFileItem *pItem, const CStdString &content, CVideoInfoTag &movieDetails, int idShow = -1);
- long AddMovieAndGetThumb(CFileItem *pItem, const CStdString &content, CVideoInfoTag &movieDetails, int idShow, bool bApplyToDir=false, bool bRefresh=false, CGUIDialogProgress* pDialog = NULL);
+ long AddMovie(CFileItem *pItem, const CONTENT_TYPE &content, CVideoInfoTag &movieDetails, int idShow = -1);
+ long AddMovieAndGetThumb(CFileItem *pItem, const CONTENT_TYPE &content, CVideoInfoTag &movieDetails, int idShow, bool bApplyToDir=false, bool bRefresh=false, CGUIDialogProgress* pDialog = NULL);
bool OnProcessSeriesFolder(IMDB_EPISODELIST& episodes, EPISODES& files, int idShow, const CStdString& strShowTitle, CGUIDialogProgress* pDlgProgress = NULL);
static CStdString GetnfoFile(CFileItem *item, bool bGrabAny=false);
- long GetIMDBDetails(CFileItem *pItem, CScraperUrl &url, const SScraperInfo& info, bool bUseDirNames=false, CGUIDialogProgress* pDialog=NULL, bool bCombined=false, bool bRefresh=false);
- bool RetrieveVideoInfo(CFileItemList& items, bool bDirNames, const SScraperInfo& info, bool bRefresh=false, CScraperUrl *pURL=NULL, CGUIDialogProgress* pDlgProgress = NULL, bool ignoreNfo=false);
+ long GetIMDBDetails(CFileItem *pItem, CScraperUrl &url, const ADDON::ScraperPtr &scraper, bool bUseDirNames=false, CGUIDialogProgress* pDialog=NULL, bool bCombined=false, bool bRefresh=false);
+ bool RetrieveVideoInfo(CFileItemList& items, bool bDirNames, const ADDON::ScraperPtr &info, bool bRefresh=false, CScraperUrl *pURL=NULL, CGUIDialogProgress* pDlgProgress = NULL, bool ignoreNfo=false);
static void ApplyIMDBThumbToFolder(const CStdString &folder, const CStdString &imdbThumb);
static int GetPathHash(const CFileItemList &items, CStdString &hash);
static bool DownloadFailed(CGUIDialogProgress* pDlgProgress);
- CNfoFile::NFOResult CheckForNFOFile(CFileItem* pItem, bool bGrabAny, SScraperInfo& info, CScraperUrl& scrUrl);
+ CNfoFile::NFOResult CheckForNFOFile(CFileItem* pItem, bool bGrabAny, ADDON::ScraperPtr& scraper, CScraperUrl& scrUrl);
CIMDB m_IMDB;
/*! \brief Fetch thumbs for seasons for a given show
Fetches and caches local season thumbs of the form season##.tbn and season-all.tbn for the current show,
@@ -114,7 +116,7 @@ namespace VIDEO
bool m_bClean;
CStdString m_strStartDir;
CVideoDatabase m_database;
- SScraperInfo m_info;
+ ADDON::ScraperPtr m_info;
std::map<CStdString,SScanSettings> m_pathsToScan;
std::set<CStdString> m_pathsToCount;
std::vector<int> m_pathsToClean;
diff --git a/xbmc/addons/include/NOTE b/xbmc/addons/include/NOTE
new file mode 100644
index 0000000000..a38d4328c3
--- /dev/null
+++ b/xbmc/addons/include/NOTE
@@ -0,0 +1,9 @@
+NOTE:
+
+This directory contains independent Headers to build Add-on's
+without the whole XBMC source tree. The Add-on itself can add
+this headers to his source tree without dependencies to any
+XBMC related classes or functions.
+
+Also this headers are never changed without a API Version
+change.
diff --git a/xbmc/addons/include/xbmc_addon_cpp_dll.h b/xbmc/addons/include/xbmc_addon_cpp_dll.h
new file mode 100644
index 0000000000..a193a76c9e
--- /dev/null
+++ b/xbmc/addons/include/xbmc_addon_cpp_dll.h
@@ -0,0 +1,171 @@
+#ifndef __XBMC_ADDON_CPP_H__
+#define __XBMC_ADDON_CPP_H__
+
+#include "xbmc_addon_dll.h"
+
+#include <vector>
+#include <string.h>
+#include <stdlib.h>
+
+class DllSetting
+{
+public:
+ enum SETTING_TYPE { NONE=0, CHECK, SPIN };
+
+ DllSetting(SETTING_TYPE t, const char *n, const char *l)
+ {
+ id = NULL;
+ label = NULL;
+ if (n)
+ {
+ id = new char[strlen(n)+1];
+ strcpy(id, n);
+ }
+ if (l)
+ {
+ label = new char[strlen(l)+1];
+ strcpy(label, l);
+ }
+ current = 0;
+ type = t;
+ }
+
+ DllSetting(const DllSetting &rhs) // copy constructor
+ {
+ id = NULL;
+ label = NULL;
+ if (rhs.id)
+ {
+ id = new char[strlen(rhs.id)+1];
+ strcpy(id, rhs.id);
+ }
+ if (rhs.label)
+ {
+ label = new char[strlen(rhs.label)+1];
+ strcpy(label, rhs.label);
+ }
+ current = rhs.current;
+ type = rhs.type;
+ for (unsigned int i = 0; i < rhs.entry.size(); i++)
+ {
+ char *lab = new char[strlen(rhs.entry[i]) + 1];
+ strcpy(lab, rhs.entry[i]);
+ entry.push_back(lab);
+ }
+ }
+
+ ~DllSetting()
+ {
+ delete[] id;
+ delete[] label;
+ for (unsigned int i=0; i < entry.size(); i++)
+ delete[] entry[i];
+ }
+
+ void AddEntry(const char *label)
+ {
+ if (!label || type != SPIN) return;
+ char *lab = new char[strlen(label) + 1];
+ strcpy(lab, label);
+ entry.push_back(lab);
+ }
+
+ // data members
+ SETTING_TYPE type;
+ char* id;
+ char* label;
+ int current;
+ std::vector<const char *> entry;
+};
+
+class DllUtils
+{
+public:
+
+ static unsigned int VecToStruct(std::vector<DllSetting> &vecSet, StructSetting*** sSet)
+ {
+ *sSet = NULL;
+ if(vecSet.size() == 0)
+ return 0;
+
+ unsigned int uiElements=0;
+
+ *sSet = (StructSetting**)malloc(vecSet.size()*sizeof(StructSetting*));
+ for(unsigned int i=0;i<vecSet.size();i++)
+ {
+ (*sSet)[i] = NULL;
+ (*sSet)[i] = (StructSetting*)malloc(sizeof(StructSetting));
+ (*sSet)[i]->id = NULL;
+ (*sSet)[i]->label = NULL;
+ uiElements++;
+
+ if (vecSet[i].id && vecSet[i].label)
+ {
+ (*sSet)[i]->id = strdup(vecSet[i].id);
+ (*sSet)[i]->label = strdup(vecSet[i].label);
+ (*sSet)[i]->type = vecSet[i].type;
+ (*sSet)[i]->current = vecSet[i].current;
+ (*sSet)[i]->entry_elements = 0;
+ (*sSet)[i]->entry = NULL;
+ if(vecSet[i].type == DllSetting::SPIN && vecSet[i].entry.size() > 0)
+ {
+ (*sSet)[i]->entry = (char**)malloc(vecSet[i].entry.size()*sizeof(char**));
+ for(unsigned int j=0;j<vecSet[i].entry.size();j++)
+ {
+ if(strlen(vecSet[i].entry[j]) > 0)
+ {
+ (*sSet)[i]->entry[j] = strdup(vecSet[i].entry[j]);
+ (*sSet)[i]->entry_elements++;
+ }
+ }
+ }
+ }
+ }
+ return uiElements;
+ }
+
+ static void StructToVec(unsigned int iElements, StructSetting*** sSet, std::vector<DllSetting> *vecSet)
+ {
+ if(iElements == 0)
+ return;
+
+ vecSet->clear();
+ for(unsigned int i=0;i<iElements;i++)
+ {
+ DllSetting vSet((DllSetting::SETTING_TYPE)(*sSet)[i]->type, (*sSet)[i]->id, (*sSet)[i]->label);
+ if((*sSet)[i]->type == DllSetting::SPIN)
+ {
+ for(unsigned int j=0;j<(*sSet)[i]->entry_elements;j++)
+ {
+ vSet.AddEntry((*sSet)[i]->entry[j]);
+ }
+ }
+ vSet.current = (*sSet)[i]->current;
+ vecSet->push_back(vSet);
+ }
+ }
+
+ static void FreeStruct(unsigned int iElements, StructSetting*** sSet)
+ {
+ if(iElements == 0)
+ return;
+
+ for(unsigned int i=0;i<iElements;i++)
+ {
+ if((*sSet)[i]->type == DllSetting::SPIN)
+ {
+ for(unsigned int j=0;j<(*sSet)[i]->entry_elements;j++)
+ {
+ free((*sSet)[i]->entry[j]);
+ }
+ free((*sSet)[i]->entry);
+ }
+ free((*sSet)[i]->id);
+ free((*sSet)[i]->label);
+ free((*sSet)[i]);
+ }
+ free(*sSet);
+ }
+};
+
+#endif
diff --git a/xbmc/addons/include/xbmc_addon_dll.h b/xbmc/addons/include/xbmc_addon_dll.h
new file mode 100644
index 0000000000..b973b21154
--- /dev/null
+++ b/xbmc/addons/include/xbmc_addon_dll.h
@@ -0,0 +1,46 @@
+#ifndef __XBMC_ADDON_H__
+#define __XBMC_ADDON_H__
+
+#ifdef _WIN32
+#include <windows.h>
+#else
+#ifndef __cdecl
+#define __cdecl
+#endif
+#ifndef __declspec
+#define __declspec(X)
+#endif
+#endif
+
+extern "C"
+{
+ enum ADDON_STATUS
+ {
+ STATUS_OK,
+ STATUS_LOST_CONNECTION,
+ STATUS_NEED_RESTART,
+ STATUS_NEED_SETTINGS,
+ STATUS_UNKNOWN
+ };
+
+ typedef struct
+ {
+ int type;
+ char* id;
+ char* label;
+ int current;
+ char** entry;
+ unsigned int entry_elements;
+ } StructSetting;
+
+ ADDON_STATUS __declspec(dllexport) Create(void *callbacks, void* props);
+ void __declspec(dllexport) Destroy();
+ ADDON_STATUS __declspec(dllexport) GetStatus();
+ bool __declspec(dllexport) HasSettings();
+ unsigned int __declspec(dllexport) GetSettings(StructSetting ***sSet);
+ ADDON_STATUS __declspec(dllexport) SetSetting(const char *settingName, const void *settingValue);
+ void __declspec(dllexport) Remove();
+ void __declspec(dllexport) FreeSettings();
+};
+
+#endif
diff --git a/xbmc/addons/include/xbmc_scr_dll.h b/xbmc/addons/include/xbmc_scr_dll.h
new file mode 100644
index 0000000000..554c42e977
--- /dev/null
+++ b/xbmc/addons/include/xbmc_scr_dll.h
@@ -0,0 +1,26 @@
+#ifndef __XBMC_SCR_H__
+#define __XBMC_SCR_H__
+
+#include "xbmc_addon_dll.h"
+#include "xbmc_scr_types.h"
+
+extern "C"
+{
+
+ // Functions that your visualisation must implement
+ void Start();
+ void Render();
+ void Stop();
+ void GetInfo(SCR_INFO* pInfo);
+
+ // function to export the above structure to XBMC
+ void __declspec(dllexport) get_addon(struct ScreenSaver* pScr)
+ {
+ pScr->Start = Start;
+ pScr->Render = Render;
+ pScr->Stop = Stop;
+ pScr->GetInfo = GetInfo;
+ };
+};
+
+#endif
diff --git a/xbmc/screensavers/ScreenSaverFactory.h b/xbmc/addons/include/xbmc_scr_types.h
index 81fc4ea1f9..e1d0bbac51 100644
--- a/xbmc/screensavers/ScreenSaverFactory.h
+++ b/xbmc/addons/include/xbmc_scr_types.h
@@ -1,6 +1,6 @@
#pragma once
/*
- * Copyright (C) 2005-2008 Team XBMC
+ * Copyright (C) 2005-2009 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
@@ -19,12 +19,35 @@
* http://www.gnu.org/copyleft/gpl.html
*
*/
-#include "ScreenSaver.h"
-class CScreenSaverFactory
+#ifndef __SCREENSAVER_TYPES_H__
+#define __SCREENSAVER_TYPES_H__
+
+extern "C"
{
-public:
- CScreenSaverFactory();
- virtual ~CScreenSaverFactory();
- CScreenSaver* LoadScreenSaver(const CStdString& strScr) const;
-};
+ struct SCR_INFO
+ {
+ int dummy;
+ };
+
+ struct SCR_PROPS
+ {
+ void *device;
+ int x;
+ int y;
+ int width;
+ int height;
+ float pixelRatio;
+ char *name;
+ };
+
+ struct ScreenSaver
+ {
+ void (__cdecl* Start) ();
+ void (__cdecl* Render) ();
+ void (__cdecl* Stop) ();
+ void (__cdecl* GetInfo)(SCR_INFO *info);
+ };
+}
+
+#endif // __SCREENSAVER_TYPES_H__
diff --git a/xbmc/addons/include/xbmc_vis_dll.h b/xbmc/addons/include/xbmc_vis_dll.h
new file mode 100644
index 0000000000..60aef0bab1
--- /dev/null
+++ b/xbmc/addons/include/xbmc_vis_dll.h
@@ -0,0 +1,37 @@
+#ifndef __XBMC_VIS_H__
+#define __XBMC_VIS_H__
+
+#include "xbmc_addon_dll.h"
+#include "xbmc_vis_types.h"
+
+extern "C"
+{
+ // Functions that your visualisation must implement
+ void Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, const char* szSongName);
+ void AudioData(const short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength);
+ void Render();
+ void Stop();
+ bool OnAction(long action, const void *param);
+ void GetInfo(VIS_INFO* pInfo);
+ unsigned int GetPresets(char ***presets);
+ unsigned GetPreset();
+ unsigned int GetSubModules(char ***presets);
+ bool IsLocked();
+
+ // function to export the above structure to XBMC
+ void __declspec(dllexport) get_addon(struct Visualisation* pVisz)
+ {
+ pVisz->Start = Start;
+ pVisz->AudioData = AudioData;
+ pVisz->Render = Render;
+ pVisz->Stop = Stop;
+ pVisz->OnAction = OnAction;
+ pVisz->GetInfo = GetInfo;
+ pVisz->GetPresets = GetPresets;
+ pVisz->GetPreset = GetPreset;
+ pVisz->GetSubModules = GetSubModules;
+ pVisz->IsLocked = IsLocked;
+ };
+};
+
+#endif
diff --git a/xbmc/addons/include/xbmc_vis_types.h b/xbmc/addons/include/xbmc_vis_types.h
new file mode 100644
index 0000000000..3c6f904d8c
--- /dev/null
+++ b/xbmc/addons/include/xbmc_vis_types.h
@@ -0,0 +1,113 @@
+/*
+ * 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
+ *
+ */
+
+/*
+ Common data structures shared between XBMC and XBMC's visualisations
+ */
+
+#ifndef __VISUALISATION_TYPES_H__
+#define __VISUALISATION_TYPES_H__
+#include <cstddef>
+
+extern "C"
+{
+ struct VIS_INFO
+ {
+ int bWantsFreq;
+ int iSyncDelay;
+ };
+
+ struct VIS_PROPS
+ {
+ void *device;
+ int x;
+ int y;
+ int width;
+ int height;
+ float pixelRatio;
+ const char *name;
+ const char *presets;
+ const char *profile;
+ const char *submodule;
+ };
+
+ enum VIS_ACTION
+ {
+ VIS_ACTION_NONE = 0,
+ VIS_ACTION_NEXT_PRESET,
+ VIS_ACTION_PREV_PRESET,
+ VIS_ACTION_LOAD_PRESET,
+ VIS_ACTION_RANDOM_PRESET,
+ VIS_ACTION_LOCK_PRESET,
+ VIS_ACTION_RATE_PRESET_PLUS,
+ VIS_ACTION_RATE_PRESET_MINUS,
+ VIS_ACTION_UPDATE_ALBUMART,
+ VIS_ACTION_UPDATE_TRACK
+ };
+
+ class VisTrack
+ {
+ public:
+ VisTrack()
+ {
+ title = artist = album = albumArtist = NULL;
+ genre = comment = lyrics = reserved1 = reserved2 = NULL;
+ trackNumber = discNumber = duration = year = 0;
+ rating = 0;
+ reserved3 = reserved4 = 0;
+ }
+
+ const char *title;
+ const char *artist;
+ const char *album;
+ const char *albumArtist;
+ const char *genre;
+ const char *comment;
+ const char *lyrics;
+ const char *reserved1;
+ const char *reserved2;
+
+ int trackNumber;
+ int discNumber;
+ int duration;
+ int year;
+ char rating;
+ int reserved3;
+ int reserved4;
+ };
+
+ struct Visualisation
+ {
+ void (__cdecl* Start)(int iChannels, int iSamplesPerSec, int iBitsPerSample, const char* szSongName);
+ void (__cdecl* AudioData)(const short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength);
+ void (__cdecl* Render) ();
+ void (__cdecl* Stop)();
+ void (__cdecl* GetInfo)(VIS_INFO *info);
+ bool (__cdecl* OnAction)(long flags, const void *param);
+ int (__cdecl* HasPresets)();
+ unsigned int (__cdecl *GetPresets)(char ***presets);
+ unsigned int (__cdecl *GetPreset)();
+ unsigned int (__cdecl *GetSubModules)(char ***modules);
+ bool (__cdecl* IsLocked)();
+ };
+}
+
+#endif //__VISUALISATION_TYPES_H__
diff --git a/xbmc/karaoke/karaokewindowbackground.cpp b/xbmc/karaoke/karaokewindowbackground.cpp
index 376059a245..49c598f837 100644
--- a/xbmc/karaoke/karaokewindowbackground.cpp
+++ b/xbmc/karaoke/karaokewindowbackground.cpp
@@ -115,7 +115,7 @@ bool CKaraokeWindowBackground::OnMessage(CGUIMessage & message)
case GUI_MSG_GET_VISUALISATION:
if ( m_currentMode == BACKGROUND_VISUALISATION )
- message.SetPointer( m_VisControl->GetVisualisation() );
+ return m_VisControl->OnMessage(message);
break;
case GUI_MSG_VISUALISATION_ACTION:
diff --git a/xbmc/lib/libPython/xbmcmodule/PythonSettings.cpp b/xbmc/lib/libPython/xbmcmodule/PythonSettings.cpp
index 770283d417..e3ff82a31e 100644
--- a/xbmc/lib/libPython/xbmcmodule/PythonSettings.cpp
+++ b/xbmc/lib/libPython/xbmcmodule/PythonSettings.cpp
@@ -21,7 +21,8 @@
#include "PythonSettings.h"
#include "pyutil.h"
-#include "GUIDialogPluginSettings.h"
+#include "AddonManager.h"
+#include "GUIDialogAddonSettings.h"
#ifndef __GNUC__
#pragma code_seg("PY_TEXT")
@@ -34,6 +35,9 @@
extern "C" {
#endif
+using ADDON::AddonPtr;
+using ADDON::CAddonMgr;
+
namespace PYXBMC
{
PyObject* Settings_New(PyTypeObject *type, PyObject *args, PyObject *kwds)
@@ -43,8 +47,8 @@ namespace PYXBMC
self = (Settings*)type->tp_alloc(type, 0);
if (!self) return NULL;
- static const char *keywords[] = { "path", NULL };
- char *cScriptPath = NULL;
+ static const char *keywords[] = { "uuid", NULL };
+ char *cScriptUUID = NULL;
// parse arguments
if (!PyArg_ParseTupleAndKeywords(
@@ -52,33 +56,35 @@ namespace PYXBMC
kwds,
(char*)"s",
(char**)keywords,
- &cScriptPath
+ &cScriptUUID
))
{
Py_DECREF(self);
return NULL;
};
- if (!CScriptSettings::SettingsExist(cScriptPath))
+ AddonPtr addon;
+ if (CAddonMgr::Get()->GetAddon(ADDON::ADDON_SCRIPT, CStdString(cScriptUUID), addon))
+ {
+ PyErr_SetString(PyExc_Exception, "Could not get AddonPtr!");
+ return NULL;
+ }
+
+ self->pAddon = addon.get();
+ if (!self->pAddon->HasSettings())
{
PyErr_SetString(PyExc_Exception, "No settings.xml file could be found!");
return NULL;
}
- self->pSettings = new CScriptSettings();
- self->pSettings->Clear();
- self->pSettings->Load(cScriptPath);
+ self->pAddon->LoadSettings();
return (PyObject*)self;
}
void Settings_Dealloc(Settings* self)
{
- if (self->pSettings)
- {
- self->pSettings->Clear();
- delete self->pSettings;
- }
+ //TODO is there anything that should be freed here, other than the AddonPtr?
self->ob_type->tp_free((PyObject*)self);
}
@@ -107,7 +113,7 @@ namespace PYXBMC
return NULL;
};
- return Py_BuildValue((char*)"s", self->pSettings->Get(id).c_str());
+ return Py_BuildValue((char*)"s", self->pAddon->GetSetting(id).c_str());
}
PyDoc_STRVAR(setSetting__doc__,
@@ -146,8 +152,8 @@ namespace PYXBMC
return NULL;
}
- self->pSettings->Set(id, value);
- self->pSettings->Save();
+ self->pAddon->UpdateSetting(id, "", value);
+ self->pAddon->SaveSettings();
Py_INCREF(Py_None);
return Py_None;
@@ -162,11 +168,11 @@ namespace PYXBMC
PyObject* Settings_OpenSettings(Settings *self, PyObject *args, PyObject *kwds)
{
// show settings dialog
- CStdString path = self->pSettings->getPath();
- CGUIDialogPluginSettings::ShowAndGetInput(path);
+ AddonPtr addon(self->pAddon);
+ CGUIDialogAddonSettings::ShowAndGetInput(addon);
// reload settings
- self->pSettings->Load(path);
+ self->pAddon->LoadSettings();
Py_INCREF(Py_None);
return Py_None;
@@ -179,20 +185,21 @@ namespace PYXBMC
{NULL, NULL, 0, NULL}
};
+ //FIXME!! incomplete docs
PyDoc_STRVAR(settings__doc__,
"Settings class.\n"
"\n"
- "Settings(path) -- Creates a new Settings class.\n"
+ "Settings(uuid) -- Creates a new Settings class.\n"
"\n"
- "path : string - path to script. (eg special://home/scripts/Apple Movie Trailers)\n"
+ "uuid : string - UUID of this script.\n"
"\n"
- "*Note, settings folder structure is eg(resources/settings.xml)\n"
+ "*Note, settings folder structure must match (resources/settings.xml)\n"
"\n"
" You can use the above as keywords for arguments and skip certain optional arguments.\n"
" Once you use a keyword, all following arguments require the keyword.\n"
"\n"
"example:\n"
- " - self.Settings = xbmc.Settings(path=os.getcwd())\n");
+ " - self.Settings = xbmc.Settings(uuid=os.uuid())\n");
// Restore code and data sections to normal.
#ifndef __GNUC__
diff --git a/xbmc/lib/libPython/xbmcmodule/PythonSettings.h b/xbmc/lib/libPython/xbmcmodule/PythonSettings.h
index 10302b73c3..72f5cdcb00 100644
--- a/xbmc/lib/libPython/xbmcmodule/PythonSettings.h
+++ b/xbmc/lib/libPython/xbmcmodule/PythonSettings.h
@@ -37,7 +37,8 @@
#else
#include "lib/libPython/Python/Include/Python.h"
#endif
-#include "ScriptSettings.h"
+
+#include "utils/IAddon.h"
#ifdef __cplusplus
extern "C" {
@@ -47,7 +48,7 @@ namespace PYXBMC
{
typedef struct {
PyObject_HEAD
- CScriptSettings* pSettings;
+ ADDON::IAddon* pAddon;
} Settings;
extern PyTypeObject Settings_Type;
diff --git a/xbmc/lib/libPython/xbmcmodule/xbmcplugin.cpp b/xbmc/lib/libPython/xbmcmodule/xbmcplugin.cpp
index 1fc5cf7191..76ebac2e00 100644
--- a/xbmc/lib/libPython/xbmcmodule/xbmcplugin.cpp
+++ b/xbmc/lib/libPython/xbmcmodule/xbmcplugin.cpp
@@ -21,15 +21,14 @@
#include "FileSystem/PluginDirectory.h"
#include "listitem.h"
-#include "PluginSettings.h"
#include "FileItem.h"
-#include "GUIDialogPluginSettings.h"
// include for constants
#include "pyutil.h"
using namespace std;
using namespace XFILE;
+using namespace ADDON;
#ifndef __GNUC__
#pragma code_seg("PY_TEXT")
@@ -292,55 +291,61 @@ namespace PYXBMC
}
PyDoc_STRVAR(getSetting__doc__,
- "getSetting(id) -- Returns the value of a setting as a string.\n"
+ "getSetting(handle, id) -- Returns the value of a setting as a string.\n"
"\n"
+ "handle : integer - handle the plugin was started with.\n"
"id : string - id of the setting that the module needs to access.\n"
"\n"
"*Note, You can use the above as a keyword.\n"
"\n"
"example:\n"
- " - apikey = xbmcplugin.getSetting('apikey')\n");
+ " - apikey = xbmcplugin.getSetting(int(sys.argv[1]), 'apikey')\n");
PyObject* XBMCPLUGIN_GetSetting(PyObject *self, PyObject *args, PyObject *kwds)
{
- static const char *keywords[] = { "id", NULL };
+ static const char *keywords[] = { "handle", "id", NULL };
+ int handle = -1;
char *id;
if (!PyArg_ParseTupleAndKeywords(
args,
kwds,
- (char*)"s",
+ (char*)"is",
(char**)keywords,
+ &handle,
&id
))
{
return NULL;
};
- return Py_BuildValue((char*)"s", g_currentPluginSettings.Get(id).c_str());
+ return Py_BuildValue((char*)"s", XFILE::CPluginDirectory::GetSetting(handle, id).c_str());
}
PyDoc_STRVAR(setSetting__doc__,
- "setSetting(id, value) -- Sets a plugin setting for the current running plugin.\n"
+ "setSetting(handle, id, value) -- Sets a plugin setting for the current running plugin.\n"
"\n"
+ "handle : integer - handle the plugin was started with.\n"
"id : string - id of the setting that the module needs to access.\n"
"value : string or unicode - value of the setting.\n"
"\n"
"*Note, You can use the above as keywords for arguments.\n"
"\n"
"example:\n"
- " - xbmcplugin.setSetting(id='username', value='teamxbmc')\n");
+ " - xbmcplugin.setSetting(int(sys.argv[1]), id='username', value='teamxbmc')\n");
PyObject* XBMCPLUGIN_SetSetting(PyObject *self, PyObject *args, PyObject *kwds)
{
- static const char *keywords[] = { "id", "value", NULL };
+ static const char *keywords[] = { "handle", "id", "value" };
+ int handle = -1;
char *id;
PyObject *pValue = NULL;
if (!PyArg_ParseTupleAndKeywords(
args,
kwds,
- (char*)"sO",
+ (char*)"isO",
(char**)keywords,
+ &handle,
&id,
&pValue
))
@@ -350,13 +355,9 @@ namespace PYXBMC
CStdString value;
if (!id || !PyXBMCGetUnicodeString(value, pValue, 1))
- {
- PyErr_SetString(PyExc_ValueError, "Invalid id or value!");
return NULL;
- }
- g_currentPluginSettings.Set(id, value);
- g_currentPluginSettings.Save();
+ XFILE::CPluginDirectory::SetSetting(handle, id, value);
Py_INCREF(Py_None);
return Py_None;
@@ -449,7 +450,7 @@ namespace PYXBMC
"*Note, You can use the above as keywords for arguments.\n"
"\n"
"example:\n"
- " - xbmcplugin.setPluginFanart(int(sys.argv[1]), 'special://home/plugins/video/Apple movie trailers II/fanart.png', color2='0xFFFF3300')\n");
+ " - xbmcplugin.setPluginFanart(int(sys.argv[1]), 'special://home/addons/plugins/video/Apple movie trailers II/fanart.png', color2='0xFFFF3300')\n");
PyObject* XBMCPLUGIN_SetPluginFanart(PyTypeObject *type, PyObject *args, PyObject *kwds)
{
@@ -533,61 +534,6 @@ namespace PYXBMC
return Py_None;
}
- PyDoc_STRVAR(openSettings__doc__,
- "openSettings(url[, reload]) -- Opens this plugins settings.\n"
- "\n"
- "url : string or unicode - url of plugin. (plugin://pictures/picasa/)\n"
- "reload : [opt] bool - reload language strings and settings (default=True)\n"
- "\n"
- "*Note, You can use the above as keywords for arguments and skip certain optional arguments.\n"
- " Once you use a keyword, all following arguments require the keyword.\n"
- " reload is only necessary if calling openSettings() from the plugin.\n"
- "\n"
- "example:\n"
- " - xbmcplugin.openSettings(url=sys.argv[0])\n");
-
- PyObject* XBMCPLUGIN_OpenSettings(PyTypeObject *type, PyObject *args, PyObject *kwds)
- {
- static const char *keywords[] = { "url", "reload", NULL };
- PyObject *pUrl = NULL;
- char bReload = true;
- // parse arguments to constructor
- if (!PyArg_ParseTupleAndKeywords(
- args,
- kwds,
- (char*)"O|b",
- (char**)keywords,
- &pUrl,
- &bReload
- ))
- {
- return NULL;
- };
-
- CStdString url;
- if (!pUrl || (pUrl && !PyXBMCGetUnicodeString(url, pUrl, 1)))
- return NULL;
-
- if (!CPluginSettings::SettingsExist(url))
- {
- PyErr_SetString(PyExc_Exception, "No settings.xml file could be found!");
- return NULL;
- }
-
- CURL cUrl(url);
- CGUIDialogPluginSettings::ShowAndGetInput(cUrl);
-
- // reload plugin settings & strings
- if (bReload)
- {
- g_currentPluginSettings.Load(cUrl);
- XFILE::CPluginDirectory::LoadPluginStrings(cUrl);
- }
-
- Py_INCREF(Py_None);
- return Py_None;
- }
-
// define c functions to be used in python here
PyMethodDef pluginMethods[] = {
{(char*)"addDirectoryItem", (PyCFunction)XBMCPLUGIN_AddDirectoryItem, METH_VARARGS|METH_KEYWORDS, addDirectoryItem__doc__},
@@ -601,7 +547,6 @@ namespace PYXBMC
{(char*)"setPluginCategory", (PyCFunction)XBMCPLUGIN_SetPluginCategory, METH_VARARGS|METH_KEYWORDS, setPluginCategory__doc__},
{(char*)"setPluginFanart", (PyCFunction)XBMCPLUGIN_SetPluginFanart, METH_VARARGS|METH_KEYWORDS, setPluginFanart__doc__},
{(char*)"setProperty", (PyCFunction)XBMCPLUGIN_SetProperty, METH_VARARGS|METH_KEYWORDS, setProperty__doc__},
- {(char*)"openSettings", (PyCFunction)XBMCPLUGIN_OpenSettings, METH_VARARGS|METH_KEYWORDS, openSettings__doc__},
{NULL, NULL, 0, NULL}
};
diff --git a/xbmc/lib/libhttpapi/XBMChttp.cpp b/xbmc/lib/libhttpapi/XBMChttp.cpp
index b8a10b9abe..cd0db87b4c 100644
--- a/xbmc/lib/libhttpapi/XBMChttp.cpp
+++ b/xbmc/lib/libhttpapi/XBMChttp.cpp
@@ -28,6 +28,7 @@
#include "Picture.h"
#include "MusicInfoTagLoaderFactory.h"
#include "utils/MusicInfoScraper.h"
+#include "utils/AddonManager.h"
#include "MusicDatabase.h"
#include "GUIUserMessages.h"
#include "GUIWindowSlideShow.h"
@@ -61,6 +62,7 @@ using namespace MUSIC_GRABBER;
using namespace XFILE;
using namespace PLAYLIST;
using namespace MUSIC_INFO;
+using namespace ADDON;
#define XML_MAX_INNERTEXT_SIZE 256
#define MAX_PARAS 20
@@ -2250,9 +2252,14 @@ int CXbmcHttp::xbmcLookupAlbum(int numParas, CStdString paras[])
CStdString albums="", album, artist="", tmp;
double relevance;
bool rel = false;
- SScraperInfo info;
- info.strContent = "albums";
- info.strPath = g_guiSettings.GetString("musiclibrary.defaultscraper");
+ AddonPtr addon;
+ if (!CAddonMgr::Get()->GetDefault(ADDON_SCRAPER, addon, CONTENT_ALBUMS))
+ return -1;
+ ScraperPtr info = boost::dynamic_pointer_cast<CScraper>(addon);
+ if (!info)
+ return -1;
+ info->m_pathContent = CONTENT_ALBUMS;
+
CMusicInfoScraper scraper(info);
if (numParas<1)
@@ -2318,7 +2325,7 @@ int CXbmcHttp::xbmcChooseAlbum(int numParas, CStdString paras[])
{
CMusicAlbumInfo musicInfo;//("", "") ;
XFILE::CFileCurl http;
- SScraperInfo info; // TODO - WTF is this code supposed to do?
+ ScraperPtr info; // TODO - WTF is this code supposed to do?
if (musicInfo.Load(http,info))
{
if (musicInfo.GetAlbum().thumbURL.m_url.size() > 0)
diff --git a/xbmc/screensavers/DllScreenSaver.h b/xbmc/screensavers/DllScreenSaver.h
index c481b916fe..4512a5f361 100644
--- a/xbmc/screensavers/DllScreenSaver.h
+++ b/xbmc/screensavers/DllScreenSaver.h
@@ -19,38 +19,12 @@
* http://www.gnu.org/copyleft/gpl.html
*
*/
-#include "DynamicDll.h"
-struct SCR_INFO
-{
- int dummy;
-};
+#include "../DllAddon.h"
+#include "../addons/include/xbmc_scr_types.h"
-struct ScreenSaver
+class DllScreenSaver : public DllAddon<ScreenSaver, SCR_PROPS>
{
-public:
-#ifdef HAS_DX
- void (__cdecl* Create)(LPDIRECT3DDEVICE9 pd3dDevice, int iWidth, int iHeight, const char* szScreensaver, float pixelRatio);
-#else
- void (__cdecl* Create)(void* pd3dDevice, int iWidth, int iHeight, const char* szScreensaver, float pixelRatio);
-#endif
- void (__cdecl* Start) ();
- void (__cdecl* Render) ();
- void (__cdecl* Stop) ();
- void (__cdecl* GetInfo)(SCR_INFO *info);
+ // this is populated via Macro calls in DllAddon.h
};
-class DllScreensaverInterface
-{
-public:
- void GetModule(struct ScreenSaver* pScr);
-};
-
-class DllScreensaver : public DllDynamic, DllScreensaverInterface
-{
- DECLARE_DLL_WRAPPER_TEMPLATE(DllScreensaver)
- DEFINE_METHOD1(void, GetModule, (struct ScreenSaver* p1))
- BEGIN_METHOD_RESOLVE()
- RESOLVE_METHOD_RENAME(get_module,GetModule)
- END_METHOD_RESOLVE()
-};
diff --git a/xbmc/screensavers/Makefile.in b/xbmc/screensavers/Makefile.in
index 232772c506..664041556b 100644
--- a/xbmc/screensavers/Makefile.in
+++ b/xbmc/screensavers/Makefile.in
@@ -8,7 +8,7 @@ ifeq ($(findstring osx,$(ARCH)), osx)
CXXFLAGS+=-isysroot /Developer/SDKs/MacOSX10.4u.sdk -mmacosx-version-min=10.4
endif
-SRCS=ScreenSaver.cpp ScreenSaverFactory.cpp
+SRCS=ScreenSaver.cpp
LIB=screensaver.a
include ../../Makefile.include
diff --git a/xbmc/screensavers/ScreenSaver.cpp b/xbmc/screensavers/ScreenSaver.cpp
index aae316e8e1..3bcb73c814 100644
--- a/xbmc/screensavers/ScreenSaver.cpp
+++ b/xbmc/screensavers/ScreenSaver.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2008 Team XBMC
+ * Copyright (C) 2005-2009 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
@@ -18,68 +18,29 @@
* http://www.gnu.org/copyleft/gpl.html
*
*/
-// Screensaver.cpp: implementation of the CScreenSaver class.
-//
-//////////////////////////////////////////////////////////////////////
-
#include "ScreenSaver.h"
-#include "Settings.h"
-#include "WindowingFactory.h"
-
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
-
-CScreenSaver::CScreenSaver(struct ScreenSaver* pScr, DllScreensaver* pDll, const CStdString& strScreenSaverName)
- : m_pScr(pScr)
- , m_pDll(pDll)
- , m_strScreenSaverName(strScreenSaverName)
-{}
-
-CScreenSaver::~CScreenSaver()
-{
-}
-
-void CScreenSaver::Create()
-{
- // pass it the screen width,height
- // and the name of the screensaver
- int iWidth = g_graphicsContext.GetWidth();
- int iHeight = g_graphicsContext.GetHeight();
-
- char szTmp[129];
- sprintf(szTmp, "scr create:%ix%i %s\n", iWidth, iHeight, m_strScreenSaverName.c_str());
- OutputDebugString(szTmp);
-
- float pixelRatio = g_settings.m_ResInfo[g_graphicsContext.GetVideoResolution()].fPixelRatio;
-#ifdef HAS_DX
- m_pScr->Create(g_Windowing.Get3DDevice(), iWidth, iHeight, m_strScreenSaverName.c_str(), pixelRatio);
-#else
- m_pScr->Create(0, iWidth, iHeight, m_strScreenSaverName.c_str(), pixelRatio);
-#endif
-}
void CScreenSaver::Start()
{
// notify screen saver that they should start
- m_pScr->Start();
+ if (Initialized()) m_pStruct->Start();
}
void CScreenSaver::Render()
{
// ask screensaver to render itself
- m_pScr->Render();
+ if (Initialized()) m_pStruct->Render();
}
void CScreenSaver::Stop()
{
// ask screensaver to cleanup
- m_pScr->Stop();
+ if (Initialized()) m_pStruct->Stop();
}
void CScreenSaver::GetInfo(SCR_INFO *info)
{
// get info from screensaver
- m_pScr->GetInfo(info);
+ if (Initialized()) m_pStruct->GetInfo(info);
}
diff --git a/xbmc/screensavers/ScreenSaver.h b/xbmc/screensavers/ScreenSaver.h
index 615a1a8b17..e0b939395c 100644
--- a/xbmc/screensavers/ScreenSaver.h
+++ b/xbmc/screensavers/ScreenSaver.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2008 Team XBMC
+ * Copyright (C) 2005-2009 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
@@ -18,46 +18,21 @@
* http://www.gnu.org/copyleft/gpl.html
*
*/
-// Screensaver.h: interface for the CScreensaver class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_ScreenSaver_H__99B9A52D_ED09_4540_A887_162A68217A31__INCLUDED_)
-#define AFX_ScreenSaver_H__99B9A52D_ED09_4540_A887_162A68217A31__INCLUDED_
-
-#if _MSC_VER > 1000
#pragma once
-#endif // _MSC_VER > 1000
+#include "AddonDll.h"
#include "DllScreenSaver.h"
-#ifdef __cplusplus
-extern "C"
-{
-}
-#endif
-
-#include <memory>
-
-class CScreenSaver
+class CScreenSaver : public ADDON::CAddonDll<DllScreenSaver, ScreenSaver, SCR_PROPS>
{
public:
- CScreenSaver(struct ScreenSaver* pScr, DllScreensaver* pDll, const CStdString& strScreenSaverName);
- ~CScreenSaver();
+ CScreenSaver(const ADDON::AddonProps& props) : ADDON::CAddonDll<DllScreenSaver, ScreenSaver, SCR_PROPS>(props) {};
+ virtual ~CScreenSaver() {}
// Things that MUST be supplied by the child classes
- void Create();
void Start();
void Render();
void Stop();
void GetInfo(SCR_INFO *info);
-
-protected:
- std::auto_ptr<struct ScreenSaver> m_pScr;
- std::auto_ptr<DllScreensaver> m_pDll;
- CStdString m_strScreenSaverName;
};
-
-#endif // !defined(AFX_ScreenSaver_H__99B9A52D_ED09_4540_A887_162A68217A31__INCLUDED_)
-
diff --git a/xbmc/screensavers/ScreenSaverFactory.cpp b/xbmc/screensavers/ScreenSaverFactory.cpp
deleted file mode 100644
index b718c149ff..0000000000
--- a/xbmc/screensavers/ScreenSaverFactory.cpp
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * 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 "ScreenSaverFactory.h"
-#include "Util.h"
-
-
-CScreenSaverFactory::CScreenSaverFactory()
-{}
-CScreenSaverFactory::~CScreenSaverFactory()
-{}
-
-extern "C" void __declspec(dllexport) get_module(struct ScreenSaver* pScr);
-
-CScreenSaver* CScreenSaverFactory::LoadScreenSaver(const CStdString& strScr) const
-{
- // strip of the path & extension to get the name of the visualisation
- CStdString strName = CUtil::GetFileName(strScr);
- strName = strName.Left(strName.size() - 4);
-
- // load visualisation
- DllScreensaver* pDll = new DllScreensaver;
- pDll->SetFile(strScr);
- pDll->EnableDelayedUnload(false);
- if (!pDll->Load())
- {
- delete pDll;
- return NULL;
- }
-
- struct ScreenSaver* pScr = (struct ScreenSaver*)malloc(sizeof(struct ScreenSaver));
- ZeroMemory(pScr, sizeof(struct ScreenSaver));
- pDll->GetModule(pScr);
-
- // and pass it to a new instance of CScreenSaver() which will handle the screensaver
- return new CScreenSaver(pScr, pDll, strName);
-}
diff --git a/xbmc/screensavers/xbmc_scr.h b/xbmc/screensavers/xbmc_scr.h
deleted file mode 100644
index 19aae64a74..0000000000
--- a/xbmc/screensavers/xbmc_scr.h
+++ /dev/null
@@ -1,58 +0,0 @@
-#ifndef __XBMC_SCR_H__
-#define __XBMC_SCR_H__
-
-#ifndef _LINUX
-#include <xtl.h>
-#else
-#define __cdecl
-#define __declspec(x)
-#endif
-
-extern "C"
-{
-
-struct SCR_INFO
-{
- int dummy;
-};
-
- // Functions that your visualisation must implement
-#ifndef _LINUX
- void Create(LPDIRECT3DDEVICE8 pd3dDevice, int iWidth, int iHeight, const char* szScreensaver, float fPixelRatio);
-#else
- void Create(void* pd3dDevice, int iWidth, int iHeight, const char* szScreensaver, float fPixelRatio);
-#endif
- void Start();
- void Render();
- void Stop();
- void GetInfo(SCR_INFO* pInfo)
- {
- }
-
-
- // Structure to transfer the above functions to XBMC
- struct ScreenSaver
- {
-#ifndef _LINUX
- void (__cdecl* Create)(LPDIRECT3DDEVICE8 pd3dDevice, int iWidth, int iHeight, const char* szScreensaver, float pixelRatio);
-#else
- void (__cdecl* Create)(void* pd3dDevice, int iWidth, int iHeight, const char* szScreensaver, float pixelRatio);
-#endif
- void (__cdecl* Start) ();
- void (__cdecl* Render) ();
- void (__cdecl* Stop) ();
- void (__cdecl* GetInfo)(SCR_INFO *info);
- };
-
- // function to export the above structure to XBMC
- void __declspec(dllexport) get_module(struct ScreenSaver* pScr)
- {
- pScr->Create = Create;
- pScr->Start = Start;
- pScr->Render = Render;
- pScr->Stop = Stop;
- pScr->GetInfo = GetInfo;
- };
-};
-
-#endif
diff --git a/xbmc/utils/Addon.cpp b/xbmc/utils/Addon.cpp
new file mode 100644
index 0000000000..e71215208a
--- /dev/null
+++ b/xbmc/utils/Addon.cpp
@@ -0,0 +1,537 @@
+/*
+ * 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
+ *
+ */
+
+#include "Addon.h"
+#include "AddonManager.h"
+#include "Settings.h"
+#include "GUISettings.h"
+#include "StringUtils.h"
+#include "FileSystem/Directory.h"
+#include "log.h"
+#include <string.h>
+
+using XFILE::CDirectory;
+
+namespace ADDON
+{
+
+/**
+ * helper functions
+ *
+ */
+
+const CStdString TranslateContent(const CONTENT_TYPE &type, bool pretty/*=false*/)
+{
+ switch (type)
+ {
+ case CONTENT_ALBUMS:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(132);
+ return "albums";
+ }
+ case CONTENT_ARTISTS:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(133);
+ return "artists";
+ }
+ case CONTENT_MOVIES:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(20342);
+ return "movies";
+ }
+ case CONTENT_TVSHOWS:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(20343);
+ return "tvshows";
+ }
+ case CONTENT_MUSICVIDEOS:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(20389);
+ return "musicvideos";
+ }
+ case CONTENT_EPISODES:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(20360);
+ return "episodes";
+ }
+ case CONTENT_PROGRAMS:
+ {
+ return "programs";
+ }
+ case CONTENT_NONE:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(231);
+ return "";
+ }
+ default:
+ {
+ return "";
+ }
+ }
+}
+
+const CONTENT_TYPE TranslateContent(const CStdString &string)
+{
+ if (string.Equals("albums")) return CONTENT_ALBUMS;
+ else if (string.Equals("artists")) return CONTENT_ARTISTS;
+ else if (string.Equals("movies")) return CONTENT_MOVIES;
+ else if (string.Equals("tvshows")) return CONTENT_TVSHOWS;
+ else if (string.Equals("episodes")) return CONTENT_EPISODES;
+ else if (string.Equals("musicvideos")) return CONTENT_MUSICVIDEOS;
+ else if (string.Equals("plugin")) return CONTENT_PLUGIN;
+ else if (string.Equals("programs")) return CONTENT_PROGRAMS;
+ else return CONTENT_NONE;
+}
+
+const CStdString TranslateType(const ADDON::TYPE &type, bool pretty/*=false*/)
+{
+ switch (type)
+ {
+ case ADDON::ADDON_SCRAPER:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(24007);
+ return "scraper";
+ }
+ case ADDON::ADDON_SCRAPER_LIBRARY:
+ {
+ return "scraper-library";
+ }
+ case ADDON::ADDON_SCREENSAVER:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(24008);
+ return "screensaver";
+ }
+ case ADDON::ADDON_VIZ:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(24010);
+ return "visualization";
+ }
+ case ADDON::ADDON_VIZ_LIBRARY:
+ {
+ return "visualization-library";
+ }
+ case ADDON::ADDON_PLUGIN:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(24005);
+ return "plugin";
+ }
+ case ADDON::ADDON_SCRIPT:
+ {
+ if (pretty)
+ return g_localizeStrings.Get(24009);
+ return "script";
+ }
+ default:
+ {
+ return "";
+ }
+ }
+}
+
+const ADDON::TYPE TranslateType(const CStdString &string)
+{
+ if (string.Equals("pvrclient")) return ADDON_PVRDLL;
+ else if (string.Equals("scraper")) return ADDON_SCRAPER;
+ else if (string.Equals("scraper-library")) return ADDON_SCRAPER_LIBRARY;
+ else if (string.Equals("screensaver")) return ADDON_SCREENSAVER;
+ else if (string.Equals("visualization")) return ADDON_VIZ;
+ else if (string.Equals("visualization-library")) return ADDON_VIZ_LIBRARY;
+ else if (string.Equals("plugin")) return ADDON_PLUGIN;
+ else if (string.Equals("script")) return ADDON_SCRIPT;
+ else return ADDON_UNKNOWN;
+}
+
+/**
+ * AddonVersion
+ *
+ */
+
+bool AddonVersion::operator==(const AddonVersion &rhs) const
+{
+ return str.Equals(rhs.str);
+}
+
+bool AddonVersion::operator!=(const AddonVersion &rhs) const
+{
+ return !(*this == rhs);
+}
+
+bool AddonVersion::operator>(const AddonVersion &rhs) const
+{
+ return (strverscmp(str.c_str(), rhs.str.c_str()) > 0);
+}
+
+bool AddonVersion::operator>=(const AddonVersion &rhs) const
+{
+ return (*this == rhs) || (*this > rhs);
+}
+
+bool AddonVersion::operator<(const AddonVersion &rhs) const
+{
+ return (strverscmp(str.c_str(), rhs.str.c_str()) < 0);
+}
+
+bool AddonVersion::operator<=(const AddonVersion &rhs) const
+{
+ return (*this == rhs) || !(*this > rhs);
+}
+
+CStdString AddonVersion::Print() const
+{
+ CStdString out;
+ out.Format("%s %s", g_localizeStrings.Get(24051), str); // "Version: <str>"
+ return CStdString(out);
+}
+
+/**
+ * CAddon
+ *
+ */
+
+CAddon::CAddon(const AddonProps &props)
+ : m_props(props)
+ , m_parent(AddonPtr())
+{
+ if (props.libname.empty()) BuildLibName();
+ else m_strLibName = props.libname;
+ m_strProfile = GetProfilePath();
+ m_userSettingsPath = GetUserSettingsPath();
+ m_disabled = true;
+}
+
+CAddon::CAddon(const CAddon &rhs, const AddonPtr &parent)
+ : m_props(rhs.Props())
+ , m_parent(parent)
+{
+ m_props.uuid = StringUtils::CreateUUID();
+ m_userXmlDoc = rhs.m_userXmlDoc;
+ m_strProfile = GetProfilePath();
+ m_userSettingsPath = GetUserSettingsPath();
+ m_strLibName = rhs.LibName();
+ m_disabled = false;
+}
+
+AddonPtr CAddon::Clone(const AddonPtr &self) const
+{
+ return AddonPtr(new CAddon(*this, self));
+}
+
+const AddonVersion CAddon::Version()
+{
+ return m_props.version;
+}
+
+//TODO platform/path crap should be negotiated between the addon and
+// the handler for it's type
+void CAddon::BuildLibName()
+{
+ m_strLibName = "default";
+ CStdString ext;
+ switch (m_props.type)
+ {
+ case ADDON_SCRAPER:
+ case ADDON_SCRAPER_LIBRARY:
+ ext = ADDON_SCRAPER_EXT;
+ break;
+ case ADDON_SCREENSAVER:
+ ext = ADDON_SCREENSAVER_EXT;
+ break;
+ case ADDON_VIZ:
+ ext = ADDON_VIS_EXT;
+ break;
+ case ADDON_PLUGIN:
+ ext = ADDON_PYTHON_EXT;
+ break;
+ default:
+ m_strLibName.clear();
+ return;
+ }
+ // extensions are returned as *.ext
+ // so remove the asterisk
+ ext.erase(0,1);
+ m_strLibName.append(ext);
+}
+
+/**
+ * Language File Handling
+ */
+bool CAddon::LoadStrings()
+{
+ if (!HasSettings())
+ return false;
+
+ // Path where the language strings reside
+ CStdString pathToLanguageFile = m_props.path;
+ CStdString pathToFallbackLanguageFile = m_props.path;
+ CUtil::AddFileToFolder(pathToLanguageFile, "resources", pathToLanguageFile);
+ CUtil::AddFileToFolder(pathToFallbackLanguageFile, "resources", pathToFallbackLanguageFile);
+ CUtil::AddFileToFolder(pathToLanguageFile, "language", pathToLanguageFile);
+ CUtil::AddFileToFolder(pathToFallbackLanguageFile, "language", pathToFallbackLanguageFile);
+ CUtil::AddFileToFolder(pathToLanguageFile, g_guiSettings.GetString("locale.language"), pathToLanguageFile);
+ CUtil::AddFileToFolder(pathToFallbackLanguageFile, "english", pathToFallbackLanguageFile);
+ CUtil::AddFileToFolder(pathToLanguageFile, "strings.xml", pathToLanguageFile);
+ CUtil::AddFileToFolder(pathToFallbackLanguageFile, "strings.xml", pathToFallbackLanguageFile);
+
+ // Load language strings temporarily
+ return m_strings.Load(pathToLanguageFile, pathToFallbackLanguageFile);
+}
+
+void CAddon::ClearStrings()
+{
+ // Unload temporary language strings
+ m_strings.Clear();
+}
+
+CStdString CAddon::GetString(uint32_t id) const
+{
+ return m_strings.Get(id);
+}
+
+/**
+ * Settings Handling
+ */
+bool CAddon::HasSettings()
+{
+ CStdString addonFileName = m_props.path;
+ CUtil::AddFileToFolder(addonFileName, "resources", addonFileName);
+ CUtil::AddFileToFolder(addonFileName, "settings.xml", addonFileName);
+
+ // Load the settings file to verify it's valid
+ TiXmlDocument xmlDoc;
+ if (!xmlDoc.LoadFile(addonFileName))
+ return false;
+
+ // Make sure that the addon XML has the settings element
+ TiXmlElement *setting = xmlDoc.RootElement();
+ if (!setting || strcmpi(setting->Value(), "settings") != 0)
+ return false;
+
+ return true;
+}
+
+bool CAddon::LoadSettings()
+{
+ CStdString addonFileName = m_props.path;
+ CUtil::AddFileToFolder(addonFileName, "resources", addonFileName);
+ CUtil::AddFileToFolder(addonFileName, "settings.xml", addonFileName);
+
+ if (!m_addonXmlDoc.LoadFile(addonFileName))
+ {
+ CLog::Log(LOGERROR, "Unable to load: %s, Line %d\n%s", addonFileName.c_str(), m_addonXmlDoc.ErrorRow(), m_addonXmlDoc.ErrorDesc());
+ return false;
+ }
+
+ // Make sure that the addon XML has the settings element
+ TiXmlElement *setting = m_addonXmlDoc.RootElement();
+ if (!setting || strcmpi(setting->Value(), "settings") != 0)
+ {
+ CLog::Log(LOGERROR, "Error loading Settings %s: cannot find root element 'settings'", addonFileName.c_str());
+ return false;
+ }
+ return LoadUserSettings();
+}
+
+bool CAddon::LoadUserSettings()
+{
+ // Load the user saved settings. If it does not exist, create it
+ if (!m_userXmlDoc.LoadFile(m_userSettingsPath))
+ {
+ TiXmlDocument doc;
+ TiXmlDeclaration decl("1.0", "UTF-8", "yes");
+ doc.InsertEndChild(decl);
+
+ TiXmlElement xmlRootElement("settings");
+ doc.InsertEndChild(xmlRootElement);
+
+ m_userXmlDoc = doc;
+ }
+ return true;
+}
+
+void CAddon::SaveSettings(void)
+{
+ // break down the path into directories
+ CStdString strRoot, strAddon;
+ CUtil::GetDirectory(m_userSettingsPath, strAddon);
+ CUtil::RemoveSlashAtEnd(strAddon);
+ CUtil::GetDirectory(strAddon, strRoot);
+ CUtil::RemoveSlashAtEnd(strRoot);
+
+ // create the individual folders
+ if (!CDirectory::Exists(strRoot))
+ CDirectory::Create(strRoot);
+ if (!CDirectory::Exists(strAddon))
+ CDirectory::Create(strAddon);
+
+ m_userXmlDoc.SaveFile(m_userSettingsPath);
+}
+
+void CAddon::SaveFromDefault()
+{
+ if (!GetSettingsXML())
+ { // no settings found
+ return;
+ }
+
+ const TiXmlElement *setting = GetSettingsXML()->FirstChildElement("setting");
+ while (setting)
+ {
+ CStdString id;
+ if (setting->Attribute("id"))
+ id = setting->Attribute("id");
+ CStdString type;
+ if (setting->Attribute("type"))
+ type = setting->Attribute("type");
+ CStdString value;
+ if (setting->Attribute("default"))
+ value = setting->Attribute("default");
+ UpdateSetting(id, type, value);
+ setting = setting->NextSiblingElement("setting");
+ }
+
+ // now save to file
+ SaveSettings();
+}
+
+CStdString CAddon::GetSetting(const CStdString& key) const
+{
+ if (m_userXmlDoc.RootElement())
+ {
+ // Try to find the setting and return its value
+ const TiXmlElement *setting = m_userXmlDoc.RootElement()->FirstChildElement("setting");
+ while (setting)
+ {
+ const char *id = setting->Attribute("id");
+ if (id && strcmpi(id, key) == 0)
+ return setting->Attribute("value");
+
+ setting = setting->NextSiblingElement("setting");
+ }
+ }
+
+ if (m_addonXmlDoc.RootElement())
+ {
+ // Try to find the setting in the addon and return its default value
+ const TiXmlElement* setting = m_addonXmlDoc.RootElement()->FirstChildElement("setting");
+ while (setting)
+ {
+ const char *id = setting->Attribute("id");
+ if (id && strcmpi(id, key) == 0 && setting->Attribute("default"))
+ return setting->Attribute("default");
+
+ setting = setting->NextSiblingElement("setting");
+ }
+ }
+
+ // Otherwise return empty string
+ return "";
+}
+
+void CAddon::UpdateSetting(const CStdString& key, const CStdString& value, const CStdString& type/* = "" */)
+{
+ if (key.empty()) return;
+
+ // Try to find the setting and change its value
+ if (!m_userXmlDoc.RootElement())
+ {
+ TiXmlElement node("settings");
+ m_userXmlDoc.InsertEndChild(node);
+ }
+ TiXmlElement *setting = m_userXmlDoc.RootElement()->FirstChildElement("setting");
+ while (setting)
+ {
+ const char *id = setting->Attribute("id");
+ const char *storedtype = setting->Attribute("type");
+ if (id && strcmpi(id, key) == 0)
+ {
+ if (!type.empty() && storedtype && strcmpi(storedtype, type) != 0)
+ setting->SetAttribute("type", type.c_str());
+
+ setting->SetAttribute("value", value.c_str());
+ return;
+ }
+ setting = setting->NextSiblingElement("setting");
+ }
+
+ // Setting not found, add it
+ TiXmlElement nodeSetting("setting");
+ nodeSetting.SetAttribute("id", std::string(key.c_str())); //FIXME otherwise attribute value isn't updated
+ if (!type.empty())
+ nodeSetting.SetAttribute("type", std::string(type.c_str()));
+ else
+ nodeSetting.SetAttribute("type", "text");
+ nodeSetting.SetAttribute("value", std::string(value.c_str()));
+ m_userXmlDoc.RootElement()->InsertEndChild(nodeSetting);
+}
+
+TiXmlElement* CAddon::GetSettingsXML()
+{
+ return m_addonXmlDoc.RootElement();
+}
+
+CStdString CAddon::GetProfilePath()
+{
+ CStdString profile;
+ profile.Format("special://profile/addon_data/%s/", UUID().c_str());
+ return profile;
+}
+
+CStdString CAddon::GetUserSettingsPath()
+{
+ CStdString path;
+ CUtil::AddFileToFolder(Profile(), "settings.xml", path);
+ return path;
+}
+
+/**
+ * CAddonLibrary
+ *
+ */
+
+CAddonLibrary::CAddonLibrary(const AddonProps& props)
+ : CAddon(props)
+ , m_addonType(SetAddonType())
+{
+}
+
+TYPE CAddonLibrary::SetAddonType()
+{
+ if (Type() == ADDON_SCRAPER_LIBRARY)
+ return ADDON_SCRAPER;
+ else if (Type() == ADDON_VIZ_LIBRARY)
+ return ADDON_VIZ;
+ else
+ return ADDON_UNKNOWN;
+}
+
+} /* namespace ADDON */
+
diff --git a/xbmc/utils/Addon.h b/xbmc/utils/Addon.h
new file mode 100644
index 0000000000..b599f6dae2
--- /dev/null
+++ b/xbmc/utils/Addon.h
@@ -0,0 +1,176 @@
+#pragma once
+/*
+ * 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
+ *
+ */
+
+#include "IAddon.h"
+#include "tinyXML/tinyxml.h"
+#include "Util.h"
+#include "URL.h"
+#include "LocalizeStrings.h"
+#include <ostream>
+
+class CURL;
+class TiXmlElement;
+
+namespace ADDON
+{
+
+// utils
+const CStdString TranslateContent(const CONTENT_TYPE &content, bool pretty=false);
+const CONTENT_TYPE TranslateContent(const CStdString &string);
+const CStdString TranslateType(const TYPE &type, bool pretty=false);
+const TYPE TranslateType(const CStdString &string);
+
+struct AddonVersion
+{
+public:
+ AddonVersion(const CStdString &str) : str(str) {}
+ bool operator==(const AddonVersion &rhs) const;
+ bool operator!=(const AddonVersion &rhs) const;
+ bool operator>(const AddonVersion &rhs) const;
+ bool operator>=(const AddonVersion &rhs) const;
+ bool operator<(const AddonVersion &rhs) const;
+ bool operator<=(const AddonVersion &rhs) const;
+ CStdString Print() const;
+ const CStdString str;
+};
+
+struct AddonProps
+{
+public:
+ AddonProps(CStdString &uuid, TYPE type, CStdString &versionstr)
+ : uuid(uuid)
+ , type(type)
+ , version(versionstr)
+ {}
+
+ AddonProps(const AddonPtr &addon)
+ : uuid(addon->UUID())
+ , type(addon->Type())
+ , version(addon->Version())
+ { if(addon->Parent()) parent = addon->Parent()->UUID(); }
+
+ bool operator=(const AddonProps &rhs)
+ { return (*this).uuid == rhs.uuid
+ && (*this).type == rhs.type
+ && (*this).version == rhs.version; }
+ CStdString uuid;
+ TYPE type;
+ AddonVersion version;
+ CStdString name;
+ CStdString parent;
+ CStdString license;
+ CStdString summary;
+ CStdString description;
+ CStdString path;
+ CStdString libname;
+ CStdString author;
+ CStdString source;
+ CStdString icon;
+ CStdString disclaimer;
+ std::set<CONTENT_TYPE> contents;
+ int stars;
+};
+typedef std::vector<struct AddonProps> VECADDONPROPS;
+
+class CAddon : public IAddon
+{
+public:
+ CAddon(const AddonProps &addonprops);
+ virtual ~CAddon() {}
+ virtual AddonPtr Clone(const AddonPtr& parent) const;
+
+ // settings & language
+ virtual bool HasSettings();
+ virtual bool LoadSettings();
+ virtual void SaveSettings();
+ virtual void SaveFromDefault();
+ virtual void UpdateSetting(const CStdString& key, const CStdString& value, const CStdString &type = "");
+ virtual CStdString GetSetting(const CStdString& key) const;
+ TiXmlElement* GetSettingsXML();
+ virtual CStdString GetString(uint32_t id) const;
+
+ // properties
+ const TYPE Type() const { return m_props.type; }
+ AddonProps Props() const { return m_props; }
+ const CStdString UUID() const { return m_props.uuid; }
+ const AddonPtr Parent() const { return m_parent; }
+ const CStdString Name() const { return m_props.name; }
+ bool Disabled() const { return m_disabled; }
+ const AddonVersion Version();
+ const CStdString Summary() const { return m_props.summary; }
+ const CStdString Description() const { return m_props.description; }
+ const CStdString Path() const { return m_props.path; }
+ const CStdString Profile() const { return m_strProfile; }
+ const CStdString LibName() const { return m_props.libname; }
+ const CStdString Author() const { return m_props.author; }
+ const CStdString Icon() const { return m_props.icon; }
+ const int Stars() const { return m_props.stars; }
+ const CStdString Disclaimer() const { return m_props.disclaimer; }
+ bool Supports(const CONTENT_TYPE &content) const { return (m_props.contents.count(content) == 1); }
+ ADDONDEPS GetDeps() { return m_dependencies; }
+
+protected:
+ CAddon(const CAddon&); // protected as all copying is handled by Clone()
+ CAddon(const CAddon&, const AddonPtr&);
+ bool LoadUserSettings();
+ TiXmlDocument m_addonXmlDoc;
+ TiXmlDocument m_userXmlDoc;
+ CStdString m_userSettingsPath;
+
+private:
+ friend class AddonMgr;
+ AddonProps m_props;
+ const AddonPtr m_parent;
+ CStdString GetProfilePath();
+ CStdString GetUserSettingsPath();
+
+ virtual bool IsAddonLibrary() { return false; }
+
+ void Enable() { LoadStrings(); m_disabled = false; }
+ void Disable() { m_disabled = true; ClearStrings();}
+
+ virtual bool LoadStrings();
+ virtual void ClearStrings();
+
+ void SetDeps(ADDONDEPS& deps) { m_dependencies = deps; }
+ ADDONDEPS m_dependencies;
+
+ void BuildLibName();
+ CStdString m_strProfile;
+ CStdString m_strLibName;
+ bool m_disabled;
+ CLocalizeStrings m_strings;
+};
+
+class CAddonLibrary : public CAddon
+{
+public:
+ CAddonLibrary(const AddonProps &props);
+
+private:
+ virtual bool IsAddonLibrary() { return true; }
+ TYPE SetAddonType();
+ const TYPE m_addonType; // addon type this library enhances
+};
+
+}; /* namespace ADDON */
+
diff --git a/xbmc/utils/AddonDll.h b/xbmc/utils/AddonDll.h
new file mode 100644
index 0000000000..69c9197c24
--- /dev/null
+++ b/xbmc/utils/AddonDll.h
@@ -0,0 +1,399 @@
+#pragma once
+/*
+ * 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
+ *
+ */
+#include "Addon.h"
+#include "../DllAddon.h"
+#include "AddonManager.h"
+#include "GUIDialogSettings.h"
+#include "Util.h"
+#include "FileSystem/File.h"
+#include "FileSystem/SpecialProtocol.h"
+#include "FileSystem/Directory.h"
+#include "log.h"
+
+using namespace XFILE;
+
+namespace ADDON
+{
+ template<class TheDll, typename TheStruct, typename TheProps>
+ class CAddonDll : public CAddon
+ {
+ public:
+ CAddonDll(const AddonProps &props);
+ virtual ~CAddonDll();
+ AddonPtr Clone() const;
+ virtual ADDON_STATUS GetStatus();
+ virtual void Remove();
+
+ // addon settings
+ virtual bool HasSettings();
+ virtual bool LoadSettings();
+ virtual void SaveSettings();
+ virtual void SaveFromDefault();
+ virtual CStdString GetSetting(const CStdString& key);
+
+ bool Create();
+ void Destroy();
+
+ protected:
+ bool LoadDll();
+ void HandleException(std::exception &e, const char* context);
+ bool Initialized() { return m_initialized; }
+ TheStruct* m_pStruct;
+ TheProps* m_pInfo;
+
+ private:
+ TheDll* m_pDll;
+ bool m_initialized;
+
+ virtual ADDON_STATUS TransferSettings();
+ TiXmlElement MakeSetting(DllSetting& setting) const;
+
+ static void AddOnStatusCallback(void *userData, const ADDON_STATUS status, const char* msg);
+ static bool AddOnGetSetting(void *userData, const char *settingName, void *settingValue);
+ static void AddOnOpenSettings(const char *url, bool bReload);
+ static void AddOnOpenOwnSettings(void *userData, bool bReload);
+ static const char* AddOnGetAddonDirectory(void *userData);
+ static const char* AddOnGetUserDirectory(void *userData);
+ };
+
+template<class TheDll, typename TheStruct, typename TheProps>
+CAddonDll<TheDll, TheStruct, TheProps>::CAddonDll(const AddonProps &props)
+ : CAddon(props)
+{
+ m_pStruct = NULL;
+ m_initialized = false;
+ m_pDll = NULL;
+ m_pInfo = NULL;
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+CAddonDll<TheDll, TheStruct, TheProps>::~CAddonDll()
+{
+ if (m_initialized)
+ Destroy();
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+AddonPtr CAddonDll<TheDll, TheStruct, TheProps>::Clone() const
+{
+ return AddonPtr(new CAddonDll<TheDll, TheStruct, TheProps>(*this));
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+bool CAddonDll<TheDll, TheStruct, TheProps>::LoadDll()
+{
+ CStdString strFileName;
+ if (!Parent())
+ {
+ strFileName = Path() + LibName();
+ }
+ else
+ { //FIXME hack to load same Dll twice
+ CStdString extension = CUtil::GetExtension(LibName());
+ strFileName = "special://temp/" + LibName();
+ CUtil::RemoveExtension(strFileName);
+ strFileName += "-" + UUID() + extension;
+
+ if (!CFile::Exists(strFileName))
+ CFile::Cache(Path() + LibName(), strFileName);
+
+ CLog::Log(LOGNOTICE, "ADDON: Loaded virtual child addon %s", strFileName.c_str());
+ }
+
+ /* Load the Dll */
+ m_pDll = new TheDll;
+ m_pDll->SetFile(strFileName);
+ m_pDll->EnableDelayedUnload(false);
+ if (!m_pDll->Load())
+ {
+ delete m_pDll;
+ m_pDll = NULL;
+ new CAddonStatusHandler(this, STATUS_UNKNOWN, "Can't load Dll", false);
+ return false;
+ }
+ m_pStruct = (TheStruct*)malloc(sizeof(TheStruct));
+ ZeroMemory(m_pStruct, sizeof(TheStruct));
+ m_pDll->GetAddon(m_pStruct);
+ return (m_pStruct != NULL);
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+bool CAddonDll<TheDll, TheStruct, TheProps>::Create()
+{
+ CLog::Log(LOGDEBUG, "ADDON: Dll Initializing - %s", Name().c_str());
+ m_initialized = false;
+
+ if (!LoadDll())
+ return false;
+
+ try
+ {
+ ADDON_STATUS status = m_pDll->Create(NULL, m_pInfo);
+ if (status != STATUS_OK)
+ throw status;
+ m_initialized = true;
+ }
+ catch (std::exception &e)
+ {
+ HandleException(e, "m_pDll->Create");
+ }
+ catch (ADDON_STATUS status)
+ {
+ if (status == STATUS_NEED_SETTINGS)
+ { // catch request for settings in initalization
+ if (TransferSettings() == STATUS_OK)
+ m_initialized = true;
+ else
+ new CAddonStatusHandler(this, status, "", false);
+ }
+ else
+ { // Addon failed initialization
+ CLog::Log(LOGERROR, "ADDON: Dll %s - Client returned bad status (%i) from Create and is not usable", Name().c_str(), status);
+ new CAddonStatusHandler(this, status, "", false);
+ }
+ }
+
+ return m_initialized;
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+void CAddonDll<TheDll, TheStruct, TheProps>::Destroy()
+{
+ delete m_pStruct;
+ m_pStruct = NULL;
+ delete m_pDll;
+ m_pDll = NULL;
+ m_initialized = false;
+ CLog::Log(LOGINFO, "ADDON: Dll Destroyed - %s", Name().c_str());
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+void CAddonDll<TheDll, TheStruct, TheProps>::Remove()
+{
+ /* Unload library file */
+ try
+ {
+ m_pDll->Unload();
+ }
+ catch (std::exception &e)
+ {
+ HandleException(e, "m_pDll->Unload");
+ }
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+ADDON_STATUS CAddonDll<TheDll, TheStruct, TheProps>::GetStatus()
+{
+ try
+ {
+ return m_pDll->GetStatus();
+ }
+ catch (std::exception &e)
+ {
+ HandleException(e, "m_pDll->GetStatus()");
+ }
+ return STATUS_UNKNOWN;
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+bool CAddonDll<TheDll, TheStruct, TheProps>::HasSettings()
+{
+ if (!LoadDll())
+ return false;
+
+ try
+ {
+ return m_pDll->HasSettings();
+ }
+ catch (std::exception &e)
+ {
+ HandleException(e, "m_pDll->HasSettings()");
+ return false;
+ }
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+bool CAddonDll<TheDll, TheStruct, TheProps>::LoadSettings()
+{
+ if (!LoadDll())
+ return false;
+
+ StructSetting** sSet;
+ std::vector<DllSetting> vSet;
+ unsigned entries = 0;
+ try
+ {
+ entries = m_pDll->GetSettings(&sSet);
+ DllUtils::StructToVec(entries, &sSet, &vSet);
+ m_pDll->FreeSettings();
+ }
+ catch (std::exception &e)
+ {
+ HandleException(e, "m_pDll->GetSettings()");
+ return false;
+ }
+
+ if (vSet.size())
+ {
+ // regenerate XML doc
+ m_addonXmlDoc.Clear();
+ TiXmlElement node("settings");
+ m_addonXmlDoc.InsertEndChild(node);
+
+ for (unsigned i=0; i < entries; i++)
+ {
+ DllSetting& setting = vSet[i];
+ m_addonXmlDoc.RootElement()->InsertEndChild(MakeSetting(setting));
+ }
+ }
+ else
+ return CAddon::LoadSettings();
+
+ return CAddon::LoadUserSettings();
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+TiXmlElement CAddonDll<TheDll, TheStruct, TheProps>::MakeSetting(DllSetting& setting) const
+{
+ TiXmlElement node("setting");
+
+ switch (setting.type)
+ {
+ case DllSetting::CHECK:
+ {
+ node.SetAttribute("id", setting.id);
+ node.SetAttribute("type", "bool");
+ node.SetAttribute("label", setting.label);
+ break;
+ }
+ case DllSetting::SPIN:
+ {
+ node.SetAttribute("id", setting.id);
+ node.SetAttribute("type", "enum");
+ node.SetAttribute("label", setting.label);
+ CStdString values;
+ for (unsigned int i = 0; i < setting.entry.size(); i++)
+ {
+ values.append(setting.entry[i]);
+ values.append("|");
+ }
+ node.SetAttribute("values", values.c_str());
+ break;
+ }
+ default:
+ break;
+ }
+
+ return node;
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+void CAddonDll<TheDll, TheStruct, TheProps>::SaveSettings()
+{
+ // must save first, as TransferSettings() reloads saved settings!
+ CAddon::SaveSettings();
+ TransferSettings();
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+void CAddonDll<TheDll, TheStruct, TheProps>::SaveFromDefault()
+{
+ CAddon::SaveFromDefault();
+ TransferSettings();
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+CStdString CAddonDll<TheDll, TheStruct, TheProps>::GetSetting(const CStdString& key)
+{
+ return CAddon::GetSetting(key);
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+ADDON_STATUS CAddonDll<TheDll, TheStruct, TheProps>::TransferSettings()
+{
+ bool restart = false;
+ ADDON_STATUS reportStatus = STATUS_OK;
+
+ CLog::Log(LOGDEBUG, "Calling TransferSettings for: %s", Name().c_str());
+
+ LoadUserSettings();
+
+ TiXmlElement *setting = m_userXmlDoc.RootElement()->FirstChildElement("setting");
+ while (setting)
+ {
+ ADDON_STATUS status = STATUS_OK;
+ const char *id = setting->Attribute("id");
+ const char *type = setting->Attribute("type");
+
+ if (type)
+ {
+ if (strcmpi(type, "text") == 0 || strcmpi(type, "ipaddress") == 0 ||
+ strcmpi(type, "folder") == 0 || strcmpi(type, "action") == 0 ||
+ strcmpi(type, "music") == 0 || strcmpi(type, "pictures") == 0 ||
+ strcmpi(type, "folder") == 0 || strcmpi(type, "programs") == 0 ||
+ strcmpi(type, "files") == 0 || strcmpi(type, "fileenum") == 0)
+ {
+ status = m_pDll->SetSetting(id, (const char*) GetSetting(id).c_str());
+ }
+ else if (strcmpi(type, "integer") == 0 || strcmpi(type, "enum") == 0 ||
+ strcmpi(type, "labelenum") == 0)
+ {
+ int tmp = atoi(GetSetting(id));
+ status = m_pDll->SetSetting(id, (int*) &tmp);
+ }
+ else if (strcmpi(type, "bool") == 0)
+ {
+ bool tmp = (GetSetting(id) == "true") ? true : false;
+ status = m_pDll->SetSetting(id, (bool*) &tmp);
+ }
+ else
+ {
+ CLog::Log(LOGERROR, "Unknown setting type '%s' for %s", type, Name().c_str());
+ }
+
+ if (status == STATUS_NEED_RESTART)
+ restart = true;
+ else if (status != STATUS_OK)
+ reportStatus = status;
+ }
+ setting = setting->NextSiblingElement("setting");
+ }
+
+ if (restart || reportStatus != STATUS_OK)
+ {
+ //FIXME
+ //new CAddonStatusHandler(this, restart ? STATUS_NEED_RESTART : reportStatus, "", true);
+ }
+
+ return STATUS_OK;
+}
+
+template<class TheDll, typename TheStruct, typename TheProps>
+void CAddonDll<TheDll, TheStruct, TheProps>::HandleException(std::exception &e, const char* context)
+{
+ m_initialized = false;
+ m_pDll->Unload();
+ CLog::Log(LOGERROR, "ADDON: Dll %s, throws an exception '%s' during %s. Contact developer '%s' with bug reports", Name().c_str(), e.what(), context, Author().c_str());
+}
+
+}; /* namespace ADDON */
+
diff --git a/xbmc/utils/AddonManager.cpp b/xbmc/utils/AddonManager.cpp
new file mode 100644
index 0000000000..0af7c9e6b0
--- /dev/null
+++ b/xbmc/utils/AddonManager.cpp
@@ -0,0 +1,1198 @@
+/*
+ * 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
+ *
+ */
+#include "AddonManager.h"
+#include "Addon.h"
+#include "Application.h"
+#include "utils/log.h"
+#include "StringUtils.h"
+#include "RegExp.h"
+#include "XMLUtils.h"
+#include "GUIDialogYesNo.h"
+#include "GUIDialogOK.h"
+#include "GUIDialogAddonSettings.h"
+#include "GUIWindowManager.h"
+#include "FileItem.h"
+#include "Settings.h"
+#include "GUISettings.h"
+#include "SingleLock.h"
+#include "DownloadQueueManager.h"
+
+#ifdef HAS_VISUALISATION
+#include "../visualizations/DllVisualisation.h"
+#include "../visualizations/Visualisation.h"
+#endif
+#ifdef HAS_PVRCLIENTS
+#include "../pvrclients/DllPVRClient.h"
+#include "../pvrclients/PVRClient.h"
+#endif
+#ifdef HAS_SCREENSAVER
+#include "../screensavers/DllScreenSaver.h"
+#include "../screensavers/ScreenSaver.h"
+#endif
+//#ifdef HAS_SCRAPERS
+#include "../Scraper.h"
+//#endif
+
+
+namespace ADDON
+{
+
+/**********************************************************
+ * CAddonStatusHandler - AddOn Status Report Class
+ *
+ * Used to informate the user about occurred errors and
+ * changes inside Add-on's, and ask him what to do.
+ *
+ */
+
+CCriticalSection CAddonStatusHandler::m_critSection;
+
+CAddonStatusHandler::CAddonStatusHandler(IAddon* addon, ADDON_STATUS status, CStdString message, bool sameThread)
+ : m_addon(addon)
+{
+ if (m_addon == NULL)
+ return;
+
+ CLog::Log(LOGINFO, "Called Add-on status handler for '%u' of clientName:%s, clientGUID:%s (same Thread=%s)", status, m_addon->Name().c_str(), m_addon->UUID().c_str(), sameThread ? "yes" : "no");
+
+ m_status = status;
+ m_message = message;
+
+ if (sameThread)
+ {
+ Process();
+ }
+ else
+ {
+ CStdString ThreadName;
+ ThreadName.Format("Addon Status: %s", m_addon->Name().c_str());
+
+ Create(true, THREAD_MINSTACKSIZE);
+ SetName(ThreadName.c_str());
+ SetPriority(-15);
+ }
+}
+
+CAddonStatusHandler::~CAddonStatusHandler()
+{
+ StopThread();
+}
+
+void CAddonStatusHandler::OnStartup()
+{
+}
+
+void CAddonStatusHandler::OnExit()
+{
+}
+
+void CAddonStatusHandler::Process()
+{
+ CSingleLock lock(m_critSection);
+
+ CStdString heading;
+ heading.Format("%s: %s", TranslateType(m_addon->Type(), true).c_str(), m_addon->Name().c_str());
+
+ /* AddOn lost connection to his backend (for ones that use Network) */
+ if (m_status == STATUS_LOST_CONNECTION)
+ {
+ CGUIDialogYesNo* pDialog = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
+ if (!pDialog) return;
+
+ pDialog->SetHeading(heading);
+ pDialog->SetLine(1, 24070);
+ pDialog->SetLine(2, 24073);
+
+ //send message and wait for user input
+ ThreadMessage tMsg = {TMSG_DIALOG_DOMODAL, WINDOW_DIALOG_YES_NO, g_windowManager.GetActiveWindow()};
+ g_application.getApplicationMessenger().SendMessage(tMsg, true);
+
+ if (pDialog->IsConfirmed())
+ CAddonMgr::Get()->GetCallbackForType(m_addon->Type())->RequestRestart(m_addon, false);
+ }
+ /* Request to restart the AddOn and data structures need updated */
+ else if (m_status == STATUS_NEED_RESTART)
+ {
+ CGUIDialogOK* pDialog = (CGUIDialogOK*)g_windowManager.GetWindow(WINDOW_DIALOG_OK);
+ if (!pDialog) return;
+
+ pDialog->SetHeading(heading);
+ pDialog->SetLine(1, 24074);
+
+ //send message and wait for user input
+ ThreadMessage tMsg = {TMSG_DIALOG_DOMODAL, WINDOW_DIALOG_OK, g_windowManager.GetActiveWindow()};
+ g_application.getApplicationMessenger().SendMessage(tMsg, true);
+
+ CAddonMgr::Get()->GetCallbackForType(m_addon->Type())->RequestRestart(m_addon, true);
+ }
+ /* Some required settings are missing/invalid */
+ else if (m_status == STATUS_NEED_SETTINGS)
+ {
+ CGUIDialogYesNo* pDialogYesNo = (CGUIDialogYesNo*)g_windowManager.GetWindow(WINDOW_DIALOG_YES_NO);
+ if (!pDialogYesNo) return;
+
+ pDialogYesNo->SetHeading(heading);
+ pDialogYesNo->SetLine(1, 24070);
+ pDialogYesNo->SetLine(2, 24072);
+ pDialogYesNo->SetLine(3, m_message);
+
+ //send message and wait for user input
+ ThreadMessage tMsg = {TMSG_DIALOG_DOMODAL, WINDOW_DIALOG_YES_NO, g_windowManager.GetActiveWindow()};
+ g_application.getApplicationMessenger().SendMessage(tMsg, true);
+
+ if (!pDialogYesNo->IsConfirmed()) return;
+
+ if (!m_addon->HasSettings())
+ return;
+
+ const AddonPtr addon(m_addon);
+ if (CGUIDialogAddonSettings::ShowAndGetInput(addon))
+ {
+ //todo doesn't dialogaddonsettings save these automatically? should do
+ m_addon->SaveSettings();
+ CAddonMgr::Get()->GetCallbackForType(m_addon->Type())->RequestRestart(m_addon, true);
+ }
+ else
+ m_addon->LoadSettings();
+ }
+ /* A unknown event has occurred */
+ else if (m_status == STATUS_UNKNOWN)
+ {
+ CGUIDialogOK* pDialog = (CGUIDialogOK*)g_windowManager.GetWindow(WINDOW_DIALOG_OK);
+ if (!pDialog) return;
+
+ pDialog->SetHeading(heading);
+ pDialog->SetLine(1, 24070);
+ pDialog->SetLine(2, 24071);
+ pDialog->SetLine(3, m_message);
+
+ //send message and wait for user input
+ ThreadMessage tMsg = {TMSG_DIALOG_DOMODAL, WINDOW_DIALOG_OK, g_windowManager.GetActiveWindow()};
+ g_application.getApplicationMessenger().SendMessage(tMsg, true);
+ }
+}
+
+
+/**********************************************************
+ * CAddonMgr
+ *
+ */
+
+CAddonMgr* CAddonMgr::m_pInstance = NULL;
+std::map<TYPE, IAddonMgrCallback*> CAddonMgr::m_managers;
+
+CAddonMgr::CAddonMgr()
+{
+}
+
+CAddonMgr::~CAddonMgr()
+{
+}
+
+CAddonMgr* CAddonMgr::Get()
+{
+ if (!m_pInstance)
+ {
+ m_pInstance = new CAddonMgr();
+ }
+ return m_pInstance;
+}
+
+IAddonMgrCallback* CAddonMgr::GetCallbackForType(TYPE type)
+{
+ if (m_managers.find(type) == m_managers.end())
+ return NULL;
+ else
+ return m_managers[type];
+}
+
+bool CAddonMgr::RegisterAddonMgrCallback(const TYPE type, IAddonMgrCallback* cb)
+{
+ if (cb == NULL)
+ return false;
+
+ m_managers.erase(type);
+ m_managers[type] = cb;
+
+ return true;
+}
+
+void CAddonMgr::UnregisterAddonMgrCallback(TYPE type)
+{
+ m_managers.erase(type);
+}
+
+bool CAddonMgr::HasAddons(const TYPE &type, const CONTENT_TYPE &content/*= CONTENT_NONE*/)
+{
+ if (content == CONTENT_NONE)
+ return (m_addons.find(type) != m_addons.end());
+
+ VECADDONS addons;
+ return GetAddons(type, addons, content, true);
+}
+
+void CAddonMgr::UpdateRepos()
+{
+ m_downloads.push_back(g_DownloadManager.RequestFile(ADDON_XBMC_REPO_URL, this));
+}
+
+bool CAddonMgr::ParseRepoXML(const CStdString &path)
+{
+ //TODO
+ //check file exists, for each addoninfo, create an AddonProps struct, store in m_remoteAddons
+ return false;
+}
+
+void CAddonMgr::OnFileComplete(TICKET aTicket, CStdString& aFilePath, INT aByteRxCount, Result aResult)
+{
+ for (unsigned i=0; i < m_downloads.size(); i++)
+ {
+ if (m_downloads[i].wQueueId == aTicket.wQueueId
+ && m_downloads[i].dwItemId == aTicket.dwItemId)
+ {
+ CLog::Log(LOGINFO, "ADDONS: Downloaded addons.xml");
+ ParseRepoXML(aFilePath);
+ }
+ }
+}
+
+bool CAddonMgr::GetAllAddons(VECADDONS &addons, bool enabledOnly/*= true*/)
+{
+ VECADDONS temp;
+ if (CAddonMgr::Get()->GetAddons(ADDON_PLUGIN, temp, CONTENT_NONE, enabledOnly))
+ addons.insert(addons.end(), temp.begin(), temp.end());
+ if (CAddonMgr::Get()->GetAddons(ADDON_SCRAPER, temp, CONTENT_NONE, enabledOnly))
+ addons.insert(addons.end(), temp.begin(), temp.end());
+ if (CAddonMgr::Get()->GetAddons(ADDON_SCREENSAVER, temp, CONTENT_NONE, enabledOnly))
+ addons.insert(addons.end(), temp.begin(), temp.end());
+ if (CAddonMgr::Get()->GetAddons(ADDON_SCRIPT, temp, CONTENT_NONE, enabledOnly))
+ addons.insert(addons.end(), temp.begin(), temp.end());
+ if (CAddonMgr::Get()->GetAddons(ADDON_VIZ, temp, CONTENT_NONE, enabledOnly))
+ addons.insert(addons.end(), temp.begin(), temp.end());
+ return !addons.empty();
+}
+
+bool CAddonMgr::GetAddons(const TYPE &type, VECADDONS &addons, const CONTENT_TYPE &content/*= CONTENT_NONE*/, bool enabledOnly/*= true*/)
+{
+ // recheck addons.xml & each addontype's directories no more than once every ADDON_DIRSCAN_FREQ seconds
+ CDateTimeSpan span;
+ span.SetDateTimeSpan(0, 0, 0, ADDON_DIRSCAN_FREQ);
+ if(!m_lastDirScan[type].IsValid() || (m_lastDirScan[type] + span) < CDateTime::GetCurrentDateTime())
+ {
+ m_lastDirScan[type] = CDateTime::GetCurrentDateTime();
+ LoadAddonsXML(type);
+ }
+
+ addons.clear();
+ if (m_addons.find(type) != m_addons.end())
+ {
+ IVECADDONS itr = m_addons[type].begin();
+ while (itr != m_addons[type].end())
+ { // filter out what we're not looking for
+ if ((enabledOnly && (*itr)->Disabled())
+ || (content != CONTENT_NONE && !(*itr)->Supports(content)))
+ {
+ ++itr;
+ continue;
+ }
+ addons.push_back(*itr);
+ ++itr;
+ }
+ }
+ return !addons.empty();
+}
+
+bool CAddonMgr::GetAddon(const TYPE &type, const CStdString &str, AddonPtr &addon)
+{
+ CDateTimeSpan span;
+ span.SetDateTimeSpan(0, 0, 0, ADDON_DIRSCAN_FREQ);
+ if(!m_lastDirScan[type].IsValid() || (m_lastDirScan[type] + span) < CDateTime::GetCurrentDateTime())
+ {
+ m_lastDirScan[type] = CDateTime::GetCurrentDateTime();
+ LoadAddonsXML(type);
+ }
+
+ if (m_addons.find(type) == m_addons.end())
+ return false;
+
+ bool isUUID = StringUtils::ValidateUUID(str);
+
+ VECADDONS &addons = m_addons[type];
+ IVECADDONS adnItr = addons.begin();
+ while (adnItr != addons.end())
+ {
+ //FIXME scrapers were previously registered by filename
+ if ( (isUUID && (*adnItr)->UUID() == str)
+ || (!isUUID && (*adnItr)->Name() == str)
+ || (type == ADDON_SCRAPER && (*adnItr)->LibName() == str))
+ {
+ addon = (*adnItr);
+ return true;
+ }
+ adnItr++;
+ }
+
+ return false;
+}
+
+//TODO handle all 'default' cases here, not just scrapers & vizs
+bool CAddonMgr::GetDefault(const TYPE &type, AddonPtr &addon, const CONTENT_TYPE &content)
+{
+ if (type != ADDON_SCRAPER && type != ADDON_VIZ)
+ return false;
+
+ CStdString setting;
+ if (type == ADDON_VIZ)
+ setting = g_guiSettings.GetString("musicplayer.visualisation");
+ else
+ {
+ switch (content)
+ {
+ case CONTENT_MOVIES:
+ {
+ setting = g_guiSettings.GetString("scrapers.moviedefault");
+ break;
+ }
+ case CONTENT_TVSHOWS:
+ {
+ setting = g_guiSettings.GetString("scrapers.tvshowdefault");
+ break;
+ }
+ case CONTENT_MUSICVIDEOS:
+ {
+ setting = g_guiSettings.GetString("scrapers.musicvideodefault");
+ break;
+ }
+ case CONTENT_ALBUMS:
+ case CONTENT_ARTISTS:
+ {
+ setting = g_guiSettings.GetString("musiclibrary.scraper");
+ break;
+ }
+ default:
+ return false;
+ }
+ }
+ return GetAddon(type, setting, addon);
+}
+
+CStdString CAddonMgr::GetString(const CStdString &uuid, const int number)
+{
+ AddonPtr addon = m_uuidMap[uuid];
+ if (addon)
+ return addon->GetString(number);
+
+ return "";
+}
+
+bool CAddonMgr::EnableAddon(const CStdString &uuid)
+{
+ AddonPtr addon = m_uuidMap[uuid];
+ if (!addon)
+ {
+ CLog::Log(LOGINFO,"ADDON: Couldn't find Add-on to Enable: %s", uuid.c_str());
+ return false;
+ }
+
+ return EnableAddon(addon);
+}
+
+bool CAddonMgr::EnableAddon(AddonPtr &addon)
+{
+ CUtil::CreateDirectoryEx(addon->Profile());
+ addon->Enable();
+ CLog::Log(LOGINFO,"ADDON: Enabled %s: %s : %s", TranslateType(addon->Type()).c_str(), addon->Name().c_str(), addon->Version().Print().c_str());
+ SaveAddonsXML(addon->Type());
+ return true;
+}
+
+bool CAddonMgr::DisableAddon(const CStdString &uuid)
+{
+ AddonPtr addon = m_uuidMap[uuid];
+ if (!addon)
+ return false;
+ return DisableAddon(addon);
+}
+
+bool CAddonMgr::DisableAddon(AddonPtr &addon)
+{
+ const TYPE type = addon->Type();
+
+ if (m_addons.find(type) == m_addons.end())
+ return false;
+
+ for (IVECADDONS itr = m_addons[type].begin(); itr != m_addons[type].end(); itr++)
+ {
+ if (addon == (*itr))
+ {
+ addon->Disable();
+
+ if (addon->Parent())
+ { // we can delete this cloned addon
+ m_addons[type].erase(itr);
+ }
+
+ CLog::Log(LOGINFO,"ADDON: Disabled %s: %s", TranslateType(addon->Type()).c_str(), addon->Name().c_str());
+ SaveAddonsXML(type);
+ return true;
+ }
+ }
+ CLog::Log(LOGINFO,"ADDON: Couldn't find Add-on to Disable: %s", addon->Name().c_str());
+ return false;
+}
+
+bool CAddonMgr::LoadAddonsXML(const TYPE &type)
+{
+ VECADDONPROPS props;
+ if (!LoadAddonsXML(type, props))
+ return false;
+
+ // refresh addon dirs if neccesary/forced
+ FindAddons(type);
+
+ // now enable accordingly
+ VECADDONPROPS::const_iterator itr = props.begin();
+ while (itr != props.end())
+ {
+ AddonPtr addon;
+ if (itr->parent.empty() && GetAddon(type, itr->uuid, addon))
+ {
+ EnableAddon(addon);
+ }
+ else if (GetAddon(type, itr->parent, addon))
+ { // multiple addon configurations
+ AddonPtr clone = addon->Clone(addon);
+ if (clone)
+ {
+ m_addons[type].push_back(clone);
+ }
+ }
+ else
+ { // addon not found
+ CLog::Log(LOGERROR, "ADDON: Couldn't find %s requested. Name: %s", TranslateType(type).c_str(), itr->name.c_str());
+ //TODO we should really add but mark unavailable, to prompt user
+ }
+ ++itr;
+ }
+ return true;
+}
+
+bool CAddonMgr::GetAddonProps(const TYPE &type, VECADDONPROPS &props)
+{
+ props.clear();
+ VECADDONS addons;
+ bool found = GetAddons(type, addons);
+ if (found)
+ {
+ IVECADDONS itr = addons.begin();
+ while (itr != addons.end())
+ {
+ AddonProps addon(*itr);
+ props.push_back(addon);
+ ++itr;
+ }
+ }
+ return found;
+}
+
+void CAddonMgr::FindAddons(const TYPE &type)
+{
+ // parse the user & system dirs for addons of the requested type
+ CFileItemList items;
+ bool isHome = CSpecialProtocol::XBMCIsHome();
+
+ // store any addons with unresolved deps, then recheck at the end
+ VECADDONS unresolved;
+
+ switch (type)
+ {
+ case ADDON_VIZ:
+ { //TODO fix mvis handling
+ if (!isHome)
+ CDirectory::GetDirectory("special://home/addons/visualizations", items, ADDON_VIS_EXT, false);
+ CDirectory::GetDirectory("special://xbmc/addons/visualizations", items, ADDON_VIS_EXT, false);
+ break;
+ }
+ case ADDON_SCREENSAVER:
+ {
+ if (!isHome)
+ CDirectory::GetDirectory("special://home/addons/screensavers", items, ADDON_SCREENSAVER_EXT, false);
+ CDirectory::GetDirectory("special://xbmc/addons/screensavers", items, ADDON_SCREENSAVER_EXT, false);
+ break;
+ }
+ case ADDON_SCRAPER:
+ {
+ if (!isHome)
+ CDirectory::GetDirectory("special://home/addons/scrapers", items, ADDON_SCRAPER_EXT, false);
+ CDirectory::GetDirectory("special://xbmc/addons/scrapers", items, ADDON_SCRAPER_EXT, false);
+ break;
+ }
+ case ADDON_SCRAPER_LIBRARY:
+ {
+ if (!isHome)
+ CDirectory::GetDirectory("special://home/addons/libraries/scrapers", items, ADDON_SCRAPER_EXT, false);
+ CDirectory::GetDirectory("special://xbmc/addons/libraries/scrapers", items, ADDON_SCRAPER_EXT, false);
+ break;
+ }
+ case ADDON_SCRIPT:
+ {
+ if (!isHome)
+ CDirectory::GetDirectory("special://home/addons/scripts", items, ADDON_PYTHON_EXT, false);
+ CDirectory::GetDirectory("special://xbmc/addons/scripts", items, ADDON_PYTHON_EXT, false);
+ break;
+ }
+ case ADDON_PLUGIN:
+ {
+ if (!isHome)
+ CDirectory::GetDirectory("special://home/addons/plugins", items, ADDON_PYTHON_EXT, false);
+ CDirectory::GetDirectory("special://xbmc/addons/plugins", items, ADDON_PYTHON_EXT, false);
+ break;
+ }
+ default:
+ return;
+ }
+
+ //FIXME this only checks library dependencies - multiple addon type deps
+ //need a more sophisticated approach
+ if (type == ADDON_SCRAPER)
+ FindAddons(ADDON_SCRAPER_LIBRARY);
+ else if (type == ADDON_VIZ)
+ FindAddons(ADDON_VIZ_LIBRARY);
+
+ // for all folders found
+ for (int i = 0; i < items.Size(); ++i)
+ {
+ CFileItemPtr item = items[i];
+
+ // read description.xml and populate the addon
+ AddonPtr addon;
+ if (!AddonFromInfoXML(type, item->m_strPath, addon))
+ {
+ CLog::Log(LOGDEBUG, "ADDON: Error reading %sdescription.xml, bypassing package", item->m_strPath.c_str());
+ continue;
+ }
+
+ // check for/cache icon thumbnail
+ //TODO cache one thumb per addon uuid instead
+ CFileItem item2(addon->Path());
+ CUtil::AddFileToFolder(addon->Path(), addon->LibName(), item2.m_strPath);
+ item2.m_bIsFolder = false;
+ item2.SetCachedProgramThumb();
+ if (!item2.HasThumbnail())
+ item2.SetUserProgramThumb();
+ if (!item2.HasThumbnail())
+ item2.SetThumbnailImage(addon->Icon());
+ if (item2.HasThumbnail())
+ {
+ XFILE::CFile::Cache(item2.GetThumbnailImage(),item->GetCachedProgramThumb());
+ }
+
+ if (!DependenciesMet(addon))
+ {
+ unresolved.push_back(addon);
+ continue;
+ }
+ else
+ { // everything ok, add to available addons if new
+ if (UpdateIfKnown(addon))
+ continue;
+ else
+ {
+ assert(addon->Type() == type);
+ m_addons[type].push_back(addon);
+ m_uuidMap.insert(std::make_pair(addon->UUID(), addon));
+ }
+ }
+ }
+
+ for (unsigned i = 0; i < unresolved.size(); i++)
+ {
+ AddonPtr& addon = unresolved[i];
+ if (DependenciesMet(addon))
+ {
+ if (!UpdateIfKnown(addon))
+ {
+ m_addons[type].push_back(addon);
+ m_uuidMap.insert(std::make_pair(addon->UUID(), addon));
+ }
+ }
+ }
+ CLog::Log(LOGINFO, "ADDON: Found %"PRIuS" addons of type %s", m_addons[type].size(), TranslateType(type).c_str());
+}
+
+bool CAddonMgr::UpdateIfKnown(AddonPtr &addon)
+{
+ if (m_addons.find(addon->Type()) != m_addons.end())
+ {
+ for (unsigned i = 0; i < m_addons[addon->Type()].size(); i++)
+ {
+ if (m_addons[addon->Type()][i]->UUID() == addon->UUID())
+ {
+ //TODO inform any manager first, and request removal
+ //TODO choose most recent version if varying
+ m_addons[addon->Type()][i] = addon;
+ CStdString uuid = addon->UUID();
+ m_uuidMap.erase(uuid);
+ m_uuidMap.insert(std::make_pair(addon->UUID(), addon));
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool CAddonMgr::DependenciesMet(AddonPtr &addon)
+{
+ // As remote repos are not functioning,
+ // this will fail if a dependency is not found locally
+ if (!addon)
+ return false;
+
+ ADDONDEPS deps = addon->GetDeps();
+ ADDONDEPS::iterator itr = deps.begin();
+ while (itr != deps.end())
+ {
+ CStdString uuid;
+ uuid = (*itr).first;
+ AddonVersion min = (*itr).second.first;
+ AddonVersion max = (*itr).second.second;
+ if (m_uuidMap.count(uuid))
+ {
+ AddonPtr dep = m_uuidMap[uuid];
+ // we're guaranteed to have at least max OR min here
+ if (!min.str.IsEmpty() && !max.str.IsEmpty())
+ return (dep->Version() >= min && dep->Version() <= max);
+ else if (!min.str.IsEmpty())
+ return (dep->Version() >= min);
+ else
+ return (dep->Version() <= max);
+ }
+ for (unsigned i=0; i < m_remoteAddons.size(); i++)
+ {
+ if (m_remoteAddons[i].uuid == uuid)
+ {
+ if(m_remoteAddons[i].version >= min && m_remoteAddons[i].version <= max)
+ {
+ //TODO line up download
+ return false;
+ }
+ }
+ }
+ itr++;
+ }
+ return deps.empty();
+}
+
+bool CAddonMgr::AddonFromInfoXML(const TYPE &reqType, const CStdString &path, AddonPtr &addon)
+{
+ // First check that we can load description.xml
+ CStdString strPath(path);
+ CUtil::AddFileToFolder(strPath, ADDON_METAFILE, strPath);
+
+ TiXmlDocument xmlDoc;
+ if (!xmlDoc.LoadFile(strPath))
+ {
+ CLog::Log(LOGERROR, "Unable to load: %s, Line %d\n%s", strPath.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
+ return false;
+ }
+
+ TiXmlElement *element = xmlDoc.RootElement();
+ if (!element || strcmpi(element->Value(), "addoninfo") != 0)
+ {
+ CLog::Log(LOGERROR, "ADDON: Error loading %s: cannot find <addon> root element", strPath.c_str());
+ return false;
+ }
+
+ /* Steps required to meet package requirements
+ * 1. uuid exists and is valid
+ * 2. type exists and is valid
+ * 3. version exists
+ * 4. a license is specified
+ * 5. operating system matches ours
+ * 6. summary exists
+ * 7. for scrapers & plugins, support at least one type of content
+ *
+ * NOTE: addon dependencies are handled in ::FindAddons()
+ */
+
+ /* Read uuid */
+ CStdString uuid;
+ element = xmlDoc.RootElement()->FirstChildElement("uuid");
+ if (!element)
+ {
+ CLog::Log(LOGERROR, "ADDON: %s does not contain the <uuid> element, ignoring", strPath.c_str());
+ return false;
+ }
+ uuid = element->GetText();
+
+ /* Validate type */
+ element = xmlDoc.RootElement()->FirstChildElement("type");
+ TYPE type = TranslateType(element->GetText());
+ if (type != reqType)
+ {
+ CLog::Log(LOGERROR, "ADDON: %s has invalid type identifier: '%d'", strPath.c_str(), type);
+ return false;
+ }
+
+ /* Validate uuid */
+ if (!StringUtils::ValidateUUID(uuid))
+ {
+ CLog::Log(LOGERROR, "ADDON: %s has invalid <uuid> element, ignoring", strPath.c_str());
+ return false;
+ }
+
+ /* Retrieve Name */
+ CStdString name;
+ element = NULL;
+ element = xmlDoc.RootElement()->FirstChildElement("title");
+ if (!element)
+ {
+ CLog::Log(LOGERROR, "ADDON: %s missing <title> element, ignoring", strPath.c_str());
+ return false;
+ }
+ name = element->GetText();
+
+ /* Retrieve version */
+ CStdString version;
+ element = NULL;
+ element = xmlDoc.RootElement()->FirstChildElement("version");
+ if (!element)
+ {
+ CLog::Log(LOGERROR, "ADDON: %s missing <version> element, ignoring", strPath.c_str());
+ return false;
+ }
+ /* Validate version */
+ version = element->GetText();
+ CRegExp versionRE;
+ versionRE.RegComp(ADDON_VERSION_RE.c_str());
+ if (versionRE.RegFind(version.c_str()) != 0)
+ {
+ CLog::Log(LOGERROR, "ADDON: %s has invalid <version> element, ignoring", strPath.c_str());
+ return false;
+ }
+
+ /* Path, UUID & Version are valid */
+ AddonProps addonProps(uuid, type, version);
+ addonProps.name = name;
+ addonProps.path = path;
+ addonProps.icon = CUtil::AddFileToFolder(path, "default.tbn");
+
+ /* Retrieve license */
+ element = NULL;
+ element = xmlDoc.RootElement()->FirstChildElement("license");
+/* if (!element)
+ {
+ CLog::Log(LOGERROR, "ADDON: %s missing <license> element, ignoring", strPath.c_str());
+ return false;
+ }
+ addonProps.license = element->GetText();*/
+
+ /* Retrieve platforms which this addon supports */
+ CStdString platform;
+ element = NULL;
+ element = xmlDoc.RootElement()->FirstChildElement("platforms")->FirstChildElement("platform");
+ if (!element)
+ {
+ CLog::Log(LOGERROR, "ADDON: %s missing <platforms> element, ignoring", strPath.c_str());
+ return false;
+ }
+
+ bool all(false);
+ std::set<CStdString> platforms;
+ do
+ {
+ CStdString platform = element->GetText();
+ if (platform == "all")
+ {
+ all = true;
+ break;
+ }
+ platforms.insert(platform);
+ element = element->NextSiblingElement("platform");
+ } while (element != NULL);
+
+ if (!all)
+ {
+#if defined(_LINUX) && !defined(__APPLE__)
+ if (!platforms.count("linux"))
+ {
+ CLog::Log(LOGNOTICE, "ADDON: %s is not supported under Linux, ignoring", strPath.c_str());
+ return false;
+ }
+#elif defined(_WIN32)
+ if (!platforms.count("windows"))
+ {
+ CLog::Log(LOGNOTICE, "ADDON: %s is not supported under Windows, ignoring", strPath.c_str());
+ return false;
+ }
+#elif defined(__APPLE__)
+ if (!platforms.count("osx"))
+ {
+ CLog::Log(LOGNOTICE, "ADDON: %s is not supported under OSX, ignoring", strPath.c_str());
+ return false;
+ }
+#elif defined(_XBOX)
+ if (!platforms.count("xbox"))
+ {
+ CLog::Log(LOGNOTICE, "ADDON: %s is not supported under XBOX, ignoring", strPath.c_str());
+ return false;
+ }
+#endif
+ }
+
+ /* Retrieve summary */
+ CStdString summary;
+ element = NULL;
+ element = xmlDoc.RootElement()->FirstChildElement("summary");
+ if (!element)
+ {
+ CLog::Log(LOGERROR, "ADDON: %s missing <summary> element, ignoring", strPath.c_str());
+ return false;
+ }
+ addonProps.summary = element->GetText();
+
+ if (addonProps.type == ADDON_SCRAPER || addonProps.type == ADDON_PLUGIN)
+ {
+ /* Retrieve content types that this addon supports */
+ CStdString platform;
+ element = NULL;
+ if (xmlDoc.RootElement()->FirstChildElement("supportedcontent"))
+ {
+ element = xmlDoc.RootElement()->FirstChildElement("supportedcontent")->FirstChildElement("content");
+ }
+ if (!element)
+ {
+ CLog::Log(LOGERROR, "ADDON: %s missing <supportedcontent> element, ignoring", strPath.c_str());
+ return false;
+ }
+
+ std::set<CONTENT_TYPE> contents;
+ do
+ {
+ CONTENT_TYPE content = TranslateContent(element->GetText());
+ if (content != CONTENT_NONE)
+ {
+ contents.insert(content);
+ }
+ element = element->NextSiblingElement("content");
+ } while (element != NULL);
+
+ if (contents.empty())
+ {
+ CLog::Log(LOGERROR, "ADDON: %s %s supports no available content-types, ignoring", TranslateType(addonProps.type).c_str(), addonProps.name.c_str());
+ return false;
+ }
+ else
+ {
+ addonProps.contents = contents;
+ }
+ }
+
+ /*** Beginning of optional fields ***/
+ /* Retrieve description */
+ element = NULL;
+ element = xmlDoc.RootElement()->FirstChildElement("description");
+ if (element)
+ addonProps.description = element->GetText();
+
+ /* Retrieve author */
+ element = NULL;
+ element = xmlDoc.RootElement()->FirstChildElement("author");
+ if (element)
+ addonProps.author = element->GetText();
+
+ /* Retrieve disclaimer */
+ element = NULL;
+ element = xmlDoc.RootElement()->FirstChildElement("disclaimer");
+ if (element)
+ addonProps.disclaimer = element->GetText();
+
+ /* Retrieve library file name */
+ // will be replaced with default library name if unspecified
+ element = NULL;
+ element = xmlDoc.RootElement()->FirstChildElement("library");
+ if (element)
+ addonProps.libname = element->GetText();
+
+ //TODO move this to addon specific class, if it's needed at all..
+#ifdef _WIN32
+ /* Retrieve WIN32 library file name in case it is present
+ * This is required for no overwrite to the fixed WIN32 add-on's
+ * during compile time
+ */
+ element = NULL;
+ element = xmlDoc.RootElement()->FirstChildElement("librarywin32");
+ if (element) // If it is found overwrite standard library name
+ addonProps.libname = element->GetText();
+#endif
+
+ /* Retrieve dependencies that this addon requires */
+ std::map<CStdString, std::pair<const AddonVersion, const AddonVersion> > deps;
+ element = NULL;
+ element = xmlDoc.RootElement()->FirstChildElement("dependencies");
+ if (element)
+ {
+ element = element->FirstChildElement("dependency");
+ if (!element)
+ CLog::Log(LOGDEBUG, "ADDON: %s missing at least one <dependency> element, will ignore this dependency", strPath.c_str());
+ else
+ {
+ do
+ {
+ CStdString min = element->Attribute("minversion");
+ CStdString max = element->Attribute("maxversion");
+ CStdString uuid = element->GetText();
+ if (!uuid || (!min && ! max))
+ {
+ CLog::Log(LOGDEBUG, "ADDON: %s malformed <dependency> element, will ignore this dependency", strPath.c_str());
+ continue;
+ }
+ deps.insert(std::make_pair(uuid, std::make_pair(AddonVersion(min), AddonVersion(max))));
+ element = element->NextSiblingElement("dependency");
+ } while (element != NULL);
+ }
+ }
+
+ /*** end of optional fields ***/
+
+ /* Create an addon object and store in a shared_ptr */
+ addon.reset();
+ switch (type)
+ {
+ case ADDON_PLUGIN:
+ case ADDON_SCRIPT:
+ {
+ AddonPtr temp(new CAddon(addonProps));
+ addon = temp;
+ break;
+ }
+ case ADDON_SCRAPER:
+ {
+ AddonPtr temp(new CScraper(addonProps));
+ addon = temp;
+ break;
+ }
+ case ADDON_VIZ:
+ {
+ AddonPtr temp(new CVisualisation(addonProps));
+ addon = temp;
+ break;
+ }
+ case ADDON_SCREENSAVER:
+ {
+ AddonPtr temp(new CScreenSaver(addonProps));
+ addon = temp;
+ break;
+ }
+ case ADDON_SCRAPER_LIBRARY:
+ case ADDON_VIZ_LIBRARY:
+ {
+ AddonPtr temp(new CAddonLibrary(addonProps));
+ addon = temp;
+ break;
+ }
+ default:
+ return false;
+ }
+
+ addon->SetDeps(deps);
+ return true;
+}
+
+CStdString CAddonMgr::GetAddonsXMLFile() const
+{
+ CStdString folder;
+ if (g_settings.m_vecProfiles[g_settings.m_iLastLoadedProfileIndex].hasAddons())
+ CUtil::AddFileToFolder(g_settings.GetProfileUserDataFolder(),"addons.xml",folder);
+ else
+ CUtil::AddFileToFolder(g_settings.GetUserDataFolder(),"addons.xml",folder);
+
+ return folder;
+}
+
+bool CAddonMgr::SaveAddonsXML(const TYPE &type)
+{
+ VECADDONPROPS props;
+ GetAddonProps(type, props);
+
+ // TODO: Should we be specifying utf8 here??
+ TiXmlDocument doc;
+ if (!doc.LoadFile(GetAddonsXMLFile()))
+ doc.ClearError();
+
+ // either point to existing addons node, or create one
+ TiXmlNode *pRoot = NULL;
+ pRoot = doc.FirstChildElement("addons");
+ if (!pRoot)
+ {
+ TiXmlElement xmlRootElement("addons");
+ pRoot = doc.InsertEndChild(xmlRootElement);
+ if (!pRoot)
+ return false;
+ }
+
+ // ok, now run through and save the modified addons section
+ SetAddons(pRoot, type, props);
+
+ return doc.SaveFile(GetAddonsXMLFile());
+}
+
+bool CAddonMgr::SetAddons(TiXmlNode *root, const TYPE &type, const VECADDONPROPS &addons)
+{
+ CStdString strType;
+ strType = TranslateType(type);
+
+ if (strType.IsEmpty())
+ return false;
+
+ TiXmlElement sectionElement(strType);
+ TiXmlNode *sectionNode = root->FirstChild(strType);
+
+ if (sectionNode)
+ { // must delete the original section before regenerating
+ root->RemoveChild(sectionNode);
+ }
+ if (!addons.empty())
+ { // only recreate the sectionNode if there's addons of this type enabled
+ sectionNode = root->InsertEndChild(sectionElement);
+
+ VECADDONPROPS::const_iterator itr = addons.begin();
+ while (itr != addons.end())
+ {
+ TiXmlElement element("addon");
+ XMLUtils::SetString(&element, "uuid", itr->uuid);
+ if (!itr->parent.IsEmpty())
+ XMLUtils::SetString(&element, "parentuuid", itr->parent);
+ sectionNode->InsertEndChild(element);
+ ++itr;
+ }
+ }
+ return true;
+}
+
+bool CAddonMgr::LoadAddonsXML(const TYPE &type, VECADDONPROPS &addons)
+{
+ CStdString strXMLFile;
+ TiXmlDocument xmlDoc;
+ TiXmlElement *pRootElement = NULL;
+ strXMLFile = GetAddonsXMLFile();
+ CLog::Log(LOGNOTICE, "ADDONS: Attempting to parse %s", strXMLFile.c_str());
+ if ( xmlDoc.LoadFile( strXMLFile ) )
+ {
+ pRootElement = xmlDoc.RootElement();
+ CStdString strValue;
+ if (pRootElement)
+ strValue = pRootElement->Value();
+ if ( strValue != "addons")
+ {
+ CLog::Log(LOGERROR, "ADDONS: %s does not contain <addons> element", strXMLFile.c_str());
+ return false;
+ }
+ }
+ else if (CFile::Exists(strXMLFile))
+ {
+ CLog::Log(LOGERROR, "ADDONS: Error loading %s: Line %d, %s", strXMLFile.c_str(), xmlDoc.ErrorRow(), xmlDoc.ErrorDesc());
+ return false;
+ }
+ else
+ {
+ CLog::Log(LOGINFO, "ADDONS: No addons.xml found");
+ return true; // no addons enabled for this profile yet
+ }
+
+ if (pRootElement)
+ { // parse addons...
+ GetAddons(pRootElement, type, addons);
+ return true;
+ }
+
+ return false;
+}
+
+void CAddonMgr::GetAddons(const TiXmlElement* pRootElement, const TYPE &type, VECADDONPROPS &addons)
+{
+ CStdString strTagName;
+ strTagName = TranslateType(type);
+
+ const TiXmlNode *pChild = pRootElement->FirstChild(strTagName.c_str());
+ if (pChild)
+ {
+ pChild = pChild->FirstChild();
+ while (pChild > 0)
+ {
+ CStdString strValue = pChild->Value();
+ if (strValue == "addon")
+ {
+ GetAddon(type, pChild, addons);
+ }
+ pChild = pChild->NextSibling();
+ }
+ }
+ else
+ {
+ CLog::Log(LOGDEBUG, "ADDONS: <%s> tag is missing or addons.xml is malformed", strTagName.c_str());
+ }
+}
+
+bool CAddonMgr::GetAddon(const TYPE &type, const TiXmlNode *node, VECADDONPROPS &addons)
+{
+ // uuid
+ const TiXmlNode *pNodePath = node->FirstChild("uuid");
+ CStdString uuid;
+ if (pNodePath && pNodePath->FirstChild())
+ {
+ uuid = pNodePath->FirstChild()->Value();
+ }
+ else
+ return false;
+
+ // this AddonProps doesn't need a valid version
+ CStdString version;
+ AddonProps props(uuid, type, version);
+
+ // name if present
+ const TiXmlNode *pNodeName = node->FirstChild("name");
+ CStdString strName;
+ if (pNodeName && pNodeName->FirstChild())
+ {
+ props.name = pNodeName->FirstChild()->Value();
+ }
+
+ // parent uuid if present
+ const TiXmlNode *pNodeChildGUID = node->FirstChild("parentuuid");
+ if (pNodeChildGUID && pNodeChildGUID->FirstChild())
+ {
+ props.parent = pNodeChildGUID->FirstChild()->Value();
+ }
+
+ // get custom thumbnail
+ const TiXmlNode *pThumbnailNode = node->FirstChild("thumbnail");
+ if (pThumbnailNode && pThumbnailNode->FirstChild())
+ {
+ props.icon = pThumbnailNode->FirstChild()->Value();
+ }
+
+ addons.insert(addons.end(), props);
+ return true;
+}
+
+} /* namespace ADDON */
+
diff --git a/xbmc/utils/AddonManager.h b/xbmc/utils/AddonManager.h
new file mode 100644
index 0000000000..ee546f9798
--- /dev/null
+++ b/xbmc/utils/AddonManager.h
@@ -0,0 +1,151 @@
+#pragma once
+/*
+ * 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
+ *
+ */
+#include "Addon.h"
+#include "../addons/include/xbmc_addon_dll.h"
+#include "tinyXML/tinyxml.h"
+#include "Thread.h"
+#include "StdString.h"
+#include "DateTime.h"
+#include "DownloadQueue.h"
+#include <vector>
+#include <map>
+
+class CCriticalSection;
+
+namespace ADDON
+{
+ typedef std::vector<AddonPtr> VECADDONS;
+ typedef std::vector<AddonPtr>::iterator IVECADDONS;
+ typedef std::map<TYPE, VECADDONS> MAPADDONS;
+
+ const int ADDON_DIRSCAN_FREQ = 300;
+ const CStdString ADDON_XBMC_REPO_URL = "http://mirrors.xbmc.org/addons/addons.xml";
+ const CStdString ADDON_METAFILE = "description.xml";
+ const CStdString ADDON_VIS_EXT = "*.vis";
+ const CStdString ADDON_PYTHON_EXT = "*.py";
+ const CStdString ADDON_SCRAPER_EXT = "*.xml";
+ const CStdString ADDON_SCREENSAVER_EXT = "*.xbs";
+ const CStdString ADDON_DSP_AUDIO_EXT = "*.adsp";
+ const CStdString ADDON_VERSION_RE = "(?<Major>\\d*)\\.?(?<Minor>\\d*)?\\.?(?<Build>\\d*)?\\.?(?<Revision>\\d*)?";
+
+ /**
+ * Class - IAddonCallback
+ * This callback should be inherited by any class which manages
+ * specific addon types. Could be mostly used for Dll addon types to handle
+ * cleanup before restart/removal
+ */
+ class IAddonMgrCallback
+ {
+ public:
+ virtual bool RequestRestart(const IAddon* addon, bool datachanged)=0;
+ virtual bool RequestRemoval(const IAddon* addon)=0;
+ };
+
+ /**
+ * Class - CAddonStatusHandler
+ * Used to informate the user about occurred errors and
+ * changes inside Add-on's, and ask him what to do.
+ * It can executed in the same thread as the calling
+ * function or in a seperate thread.
+ */
+ class CAddonStatusHandler : private CThread
+ {
+ public:
+ CAddonStatusHandler(IAddon* const addon, ADDON_STATUS status, CStdString message, bool sameThread = true);
+ ~CAddonStatusHandler();
+
+ /* Thread handling */
+ virtual void Process();
+ virtual void OnStartup();
+ virtual void OnExit();
+
+ private:
+ static CCriticalSection m_critSection;
+ IAddon* m_addon;
+ ADDON_STATUS m_status;
+ CStdString m_message;
+ };
+
+ /**
+ * Class - CAddonMgr
+ * Holds references to all addons, enabled or
+ * otherwise. Services the generic callbacks available
+ * to all addon variants.
+ */
+ class CAddonMgr : public IDownloadQueueObserver
+ {
+ public:
+ static CAddonMgr* Get();
+ virtual ~CAddonMgr();
+
+ IAddonMgrCallback* GetCallbackForType(TYPE type);
+ bool RegisterAddonMgrCallback(TYPE type, IAddonMgrCallback* cb);
+ void UnregisterAddonMgrCallback(TYPE type);
+
+ /* Addon access */
+ bool GetDefault(const TYPE &type, AddonPtr &addon, const CONTENT_TYPE &content = CONTENT_NONE);
+ bool GetAddon(const TYPE &type, const CStdString &str, AddonPtr &addon);
+ bool HasAddons(const TYPE &type, const CONTENT_TYPE &content = CONTENT_NONE);
+ bool GetAddons(const TYPE &type, VECADDONS &addons, const CONTENT_TYPE &content = CONTENT_NONE, bool enabled = true);
+ bool GetAllAddons(VECADDONS &addons, bool enabledOnly = true);
+ CStdString GetString(const CStdString &uuid, const int number);
+
+ /* Addon operations */
+ bool EnableAddon(AddonPtr &addon);
+ bool EnableAddon(const CStdString &uuid);
+ bool DisableAddon(AddonPtr &addon);
+ bool DisableAddon(const CStdString &uuid);
+ bool Clone(const AddonPtr& parent, AddonPtr& child);
+
+ private:
+ /* Addon Repositories */
+ virtual void OnFileComplete(TICKET aTicket, CStdString& aFilePath, INT aByteRxCount, Result aResult);
+ std::vector<TICKET> m_downloads;
+ VECADDONPROPS m_remoteAddons;
+ void UpdateRepos();
+ bool ParseRepoXML(const CStdString &path);
+
+ void FindAddons(const TYPE &type);
+ bool LoadAddonsXML(const TYPE &type);
+ bool SaveAddonsXML(const TYPE &type);
+ bool AddonFromInfoXML(const TYPE &reqType, const CStdString &path, AddonPtr &addon);
+ bool DependenciesMet(AddonPtr &addon);
+ bool UpdateIfKnown(AddonPtr &addon);
+
+ /* addons.xml */
+ CStdString GetAddonsXMLFile() const;
+ bool GetAddonProps(const TYPE &type, VECADDONPROPS &addons);
+ bool LoadAddonsXML(const TYPE& type, VECADDONPROPS& addons);
+ bool SaveAddonsXML(const TYPE& type, const VECADDONPROPS &addons);
+ bool SetAddons(TiXmlNode *root, const TYPE &type, const VECADDONPROPS &addons);
+ void GetAddons(const TiXmlElement* pRootElement, const TYPE &type, VECADDONPROPS &addons);
+ bool GetAddon(const TYPE &type, const TiXmlNode *node, VECADDONPROPS &addon);
+
+ CAddonMgr();
+ static CAddonMgr* m_pInstance;
+ static std::map<TYPE, IAddonMgrCallback*> m_managers;
+ MAPADDONS m_addons;
+ std::map<TYPE, CDateTime> m_lastDirScan;
+ std::map<CStdString, AddonPtr> m_uuidMap;
+ };
+
+}; /* namespace ADDON */
diff --git a/xbmc/utils/Builtins.cpp b/xbmc/utils/Builtins.cpp
index c2f3efc715..ba6e49b74b 100644
--- a/xbmc/utils/Builtins.cpp
+++ b/xbmc/utils/Builtins.cpp
@@ -37,6 +37,7 @@
#include "GUIUserMessages.h"
#include "GUIWindowLoginScreen.h"
#include "GUIWindowVideoBase.h"
+#include "Addon.h" // for TranslateType, TranslateContent
#include "LastFmManager.h"
#include "LCD.h"
#include "log.h"
@@ -927,30 +928,43 @@ int CBuiltins::Execute(const CStdString& execString)
}
else if (execute.Equals("skin.setfile"))
{
+ // Note. can only browse one addon type from here
+ // if browsing for addons, required param[1] is addontype string, with optional param[2]
+ // as contenttype string see IAddon.h & ADDON::TranslateXX
CStdString strMask = (params.size() > 1) ? params[1] : "";
- if (strMask.Find(".py") > -1)
+ strMask.ToLower();
+ ADDON::TYPE type;
+ if ((type = ADDON::TranslateType(strMask)) != ADDON::ADDON_UNKNOWN)
{
- CMediaSource source;
- source.strPath = "special://home/scripts/";
- source.strName = g_localizeStrings.Get(247);
- localShares.push_back(source);
+ CURL url;
+ url.SetProtocol("addons");
+ url.SetHostName(strMask);
+ localShares.clear();
+ CStdString content = (params.size() > 2) ? params[2] : "";
+ content.ToLower();
+ url.SetPassword(content);
+ CStdString replace;
+ if (CGUIDialogFileBrowser::ShowAndGetFile(url.Get(), "", TranslateType(type, true), replace, true, true))
+ g_settings.SetSkinString(string, replace);
}
-
- if (params.size() > 2)
+ else
{
- value = params[2];
- CUtil::AddSlashAtEnd(value);
- bool bIsSource;
- if (CUtil::GetMatchingSource(value,localShares,bIsSource) < 0) // path is outside shares - add it as a separate one
+ if (params.size() > 2)
{
- CMediaSource share;
- share.strName = g_localizeStrings.Get(13278);
- share.strPath = value;
- localShares.push_back(share);
+ value = params[2];
+ CUtil::AddSlashAtEnd(value);
+ bool bIsSource;
+ if (CUtil::GetMatchingSource(value,localShares,bIsSource) < 0) // path is outside shares - add it as a separate one
+ {
+ CMediaSource share;
+ share.strName = g_localizeStrings.Get(13278);
+ share.strPath = value;
+ localShares.push_back(share);
+ }
}
+ if (CGUIDialogFileBrowser::ShowAndGetFile(localShares, strMask, g_localizeStrings.Get(1033), value))
+ g_settings.SetSkinString(string, value);
}
- if (CGUIDialogFileBrowser::ShowAndGetFile(localShares, strMask, g_localizeStrings.Get(1033), value))
- g_settings.SetSkinString(string, value);
}
else // execute.Equals("skin.setpath"))
{
@@ -1037,10 +1051,7 @@ int CBuiltins::Execute(const CStdString& execString)
if (scanner->IsScanning())
scanner->StopScanning();
else
- {
- SScraperInfo info;
- CGUIWindowVideoBase::OnScan(params.size() > 1 ? params[1] : "",info,settings);
- }
+ CGUIWindowVideoBase::OnScan(params.size() > 1 ? params[1] : "",ADDON::ScraperPtr(),settings);
}
}
}
diff --git a/xbmc/utils/DownloadQueue.cpp b/xbmc/utils/DownloadQueue.cpp
index df61c03a88..eff3c46791 100644
--- a/xbmc/utils/DownloadQueue.cpp
+++ b/xbmc/utils/DownloadQueue.cpp
@@ -51,7 +51,7 @@ CDownloadQueue::~CDownloadQueue(void)
}
-TICKET CDownloadQueue::RequestContent(CStdString& aUrl, IDownloadQueueObserver* aObserver)
+TICKET CDownloadQueue::RequestContent(const CStdString& aUrl, IDownloadQueueObserver* aObserver)
{
EnterCriticalSection(&m_critical);
@@ -64,7 +64,7 @@ TICKET CDownloadQueue::RequestContent(CStdString& aUrl, IDownloadQueueObserver*
return request.ticket;
}
-TICKET CDownloadQueue::RequestFile(CStdString& aUrl, CStdString& aFilePath, IDownloadQueueObserver* aObserver)
+TICKET CDownloadQueue::RequestFile(const CStdString& aUrl, const CStdString& aFilePath, IDownloadQueueObserver* aObserver)
{
EnterCriticalSection(&m_critical);
@@ -97,7 +97,7 @@ void CDownloadQueue::CancelRequests(IDownloadQueueObserver *aObserver)
LeaveCriticalSection(&m_critical);
}
-TICKET CDownloadQueue::RequestFile(CStdString& aUrl, IDownloadQueueObserver* aObserver)
+TICKET CDownloadQueue::RequestFile(const CStdString& aUrl, IDownloadQueueObserver* aObserver)
{
EnterCriticalSection(&m_critical);
diff --git a/xbmc/utils/DownloadQueue.h b/xbmc/utils/DownloadQueue.h
index a1d6c2656b..bbbda88aae 100644
--- a/xbmc/utils/DownloadQueue.h
+++ b/xbmc/utils/DownloadQueue.h
@@ -52,9 +52,9 @@ public:
CDownloadQueue();
virtual ~CDownloadQueue(void);
- TICKET RequestContent(CStdString& aUrl, IDownloadQueueObserver* aObserver);
- TICKET RequestFile(CStdString& aUrl, IDownloadQueueObserver* aObserver);
- TICKET RequestFile(CStdString& aUrl, CStdString& aFilePath, IDownloadQueueObserver* aObserver);
+ TICKET RequestContent(const CStdString& aUrl, IDownloadQueueObserver* aObserver);
+ TICKET RequestFile(const CStdString& aUrl, IDownloadQueueObserver* aObserver);
+ TICKET RequestFile(const CStdString& aUrl, const CStdString& aFilePath, IDownloadQueueObserver* aObserver);
void CancelRequests(IDownloadQueueObserver* aObserver);
VOID Flush();
diff --git a/xbmc/utils/DownloadQueueManager.cpp b/xbmc/utils/DownloadQueueManager.cpp
index a9964a679e..95aa50b9c9 100644
--- a/xbmc/utils/DownloadQueueManager.cpp
+++ b/xbmc/utils/DownloadQueueManager.cpp
@@ -41,7 +41,7 @@ VOID CDownloadQueueManager::Initialize()
}
-TICKET CDownloadQueueManager::RequestContent(CStdString& aUrl, IDownloadQueueObserver* aObserver)
+TICKET CDownloadQueueManager::RequestContent(const CStdString& aUrl, IDownloadQueueObserver* aObserver)
{
EnterCriticalSection(&m_critical);
TICKET ticket = GetNextDownloadQueue()->RequestContent(aUrl, aObserver);
@@ -49,7 +49,7 @@ TICKET CDownloadQueueManager::RequestContent(CStdString& aUrl, IDownloadQueueObs
return ticket;
}
-TICKET CDownloadQueueManager::RequestFile(CStdString& aUrl, CStdString& aFilePath, IDownloadQueueObserver* aObserver)
+TICKET CDownloadQueueManager::RequestFile(const CStdString& aUrl, const CStdString& aFilePath, IDownloadQueueObserver* aObserver)
{
EnterCriticalSection(&m_critical);
TICKET ticket = GetNextDownloadQueue()->RequestFile(aUrl, aFilePath, aObserver);
@@ -57,7 +57,7 @@ TICKET CDownloadQueueManager::RequestFile(CStdString& aUrl, CStdString& aFilePat
return ticket;
}
-TICKET CDownloadQueueManager::RequestFile(CStdString& aUrl, IDownloadQueueObserver* aObserver)
+TICKET CDownloadQueueManager::RequestFile(const CStdString& aUrl, IDownloadQueueObserver* aObserver)
{
EnterCriticalSection(&m_critical);
TICKET ticket = GetNextDownloadQueue()->RequestFile(aUrl, aObserver);
diff --git a/xbmc/utils/DownloadQueueManager.h b/xbmc/utils/DownloadQueueManager.h
index 25b96a4225..4474f97144 100644
--- a/xbmc/utils/DownloadQueueManager.h
+++ b/xbmc/utils/DownloadQueueManager.h
@@ -32,9 +32,9 @@ public:
virtual ~CDownloadQueueManager(void);
VOID Initialize();
- TICKET RequestContent(CStdString& aUrl, IDownloadQueueObserver* aObserver);
- TICKET RequestFile(CStdString& aUrl, IDownloadQueueObserver* aObserver);
- TICKET RequestFile(CStdString& aUrl, CStdString& aFilePath, IDownloadQueueObserver* aObserver);
+ TICKET RequestContent(const CStdString& aUrl, IDownloadQueueObserver* aObserver);
+ TICKET RequestFile(const CStdString& aUrl, IDownloadQueueObserver* aObserver);
+ TICKET RequestFile(const CStdString& aUrl, const CStdString& aFilePath, IDownloadQueueObserver* aObserver);
void CancelRequests(IDownloadQueueObserver *aObserver);
protected:
diff --git a/xbmc/utils/GUIInfoManager.cpp b/xbmc/utils/GUIInfoManager.cpp
index d6c083b046..af7a0b45ff 100644
--- a/xbmc/utils/GUIInfoManager.cpp
+++ b/xbmc/utils/GUIInfoManager.cpp
@@ -79,6 +79,7 @@
using namespace std;
using namespace XFILE;
using namespace MUSIC_INFO;
+using ADDON::CVisualisation;
CGUIInfoManager g_infoManager;
@@ -1513,25 +1514,18 @@ CStdString CGUIInfoManager::GetLabel(int info, int contextWindow)
g_windowManager.SendMessage(msg);
if (msg.GetPointer())
{
- CVisualisation *pVis = (CVisualisation *)msg.GetPointer();
- char *preset = pVis->GetPreset();
- if (preset)
+ CVisualisation* viz = NULL;
+ viz = (CVisualisation*)msg.GetPointer();
+ if (viz)
{
- strLabel = preset;
+ strLabel = viz->GetPresetName();
CUtil::RemoveExtension(strLabel);
}
}
}
break;
case VISUALISATION_NAME:
- {
- strLabel = g_guiSettings.GetString("musicplayer.visualisation");
- if (strLabel != "None" && strLabel.size() > 4)
- { // make it look pretty
- strLabel = strLabel.Left(strLabel.size() - 4);
- strLabel[0] = toupper(strLabel[0]);
- }
- }
+ strLabel = g_guiSettings.GetString("musicplayer.visualisation");
break;
case FANART_COLOR1:
{
diff --git a/xbmc/utils/IAddon.h b/xbmc/utils/IAddon.h
new file mode 100644
index 0000000000..fc603d2e25
--- /dev/null
+++ b/xbmc/utils/IAddon.h
@@ -0,0 +1,111 @@
+#pragma once
+/*
+* 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
+*
+*/
+#include "boost/shared_ptr.hpp"
+#include "StdString.h"
+#include <set>
+#include <map>
+
+class TiXmlElement;
+
+typedef enum
+{
+ CONTENT_PLUGIN = -2, //TODO ditch this, used in scraping code
+ //TODO -1 is used as default in QueryParams.h
+ CONTENT_NONE = 0,
+ CONTENT_MOVIES = 1,
+ CONTENT_TVSHOWS = 2,
+ CONTENT_MUSICVIDEOS = 3,
+ CONTENT_EPISODES = 4,
+ CONTENT_ALBUMS = 6,
+ CONTENT_ARTISTS = 7,
+ CONTENT_PROGRAMS = 8,
+ CONTENT_PICTURES = 9
+} CONTENT_TYPE;
+
+namespace ADDON
+{
+ typedef enum
+ {
+ ADDON_UNKNOWN,
+ ADDON_VIZ,
+ ADDON_VIZ_LIBRARY,
+ ADDON_SKIN,
+ ADDON_PVRDLL,
+ ADDON_SCRIPT,
+ ADDON_SCRAPER,
+ ADDON_SCRAPER_LIBRARY,
+ ADDON_SCREENSAVER,
+ ADDON_PLUGIN
+ } TYPE;
+
+ class IAddon;
+ typedef boost::shared_ptr<IAddon> AddonPtr;
+ class CVisualisation;
+ typedef boost::shared_ptr<CVisualisation> VizPtr;
+
+ class CAddonMgr;
+ struct AddonVersion;
+ typedef std::map<CStdString, std::pair<const AddonVersion, const AddonVersion> > ADDONDEPS;
+ struct AddonProps;
+
+ class IAddon
+ {
+ public:
+ virtual AddonPtr Clone(const AddonPtr& self) const =0;
+ virtual const TYPE Type() const =0;
+ virtual AddonProps Props() const =0;
+ virtual const CStdString UUID() const =0;
+ virtual const AddonPtr Parent() const =0;
+ virtual const CStdString Name() const =0;
+ virtual bool Disabled() const =0;
+ virtual const AddonVersion Version() =0;
+ virtual const CStdString Summary() const =0;
+ virtual const CStdString Description() const =0;
+ virtual const CStdString Path() const =0;
+ virtual const CStdString Profile() const =0;
+ virtual const CStdString LibName() const =0;
+ virtual const CStdString Author() const =0;
+ virtual const CStdString Icon() const =0;
+ virtual const int Stars() const =0;
+ virtual const CStdString Disclaimer() const =0;
+ virtual bool Supports(const CONTENT_TYPE &content) const =0;
+ virtual bool HasSettings() =0;
+ virtual bool LoadSettings() =0;
+ virtual void SaveSettings() =0;
+ virtual void SaveFromDefault() =0;
+ virtual void UpdateSetting(const CStdString& key, const CStdString& value, const CStdString &type = "") =0;
+ virtual CStdString GetSetting(const CStdString& key) const =0;
+ virtual TiXmlElement* GetSettingsXML() =0;
+ virtual CStdString GetString(uint32_t id) const =0;
+ virtual ADDONDEPS GetDeps() =0;
+
+ private:
+ friend class CAddonMgr;
+ virtual bool IsAddonLibrary() =0;
+ virtual void Enable() =0;
+ virtual void Disable() =0;
+ virtual bool LoadStrings() =0;
+ virtual void ClearStrings() =0;
+ virtual void SetDeps(ADDONDEPS& deps) =0;
+ };
+};
+
diff --git a/xbmc/utils/IMDB.cpp b/xbmc/utils/IMDB.cpp
index cb74bf9246..2d4c5ebfdd 100644
--- a/xbmc/utils/IMDB.cpp
+++ b/xbmc/utils/IMDB.cpp
@@ -65,11 +65,11 @@ int CIMDB::InternalFindMovie(const CStdString &strMovie, IMDB_MOVIELIST& movieli
movieTitle.ToLower();
- if (m_info.strContent.Equals("musicvideos"))
+ if (m_info->Content() == CONTENT_MUSICVIDEOS)
movieTitle.Replace("-"," ");
- CLog::Log(LOGDEBUG, "scraper: Searching for '%s' using %s scraper (file: '%s', content: '%s', language: '%s', date: '%s', framework: '%s')",
- movieTitle.c_str(), m_info.strTitle.c_str(), m_info.strPath.c_str(), m_info.strContent.c_str(), m_info.strLanguage.c_str(), m_info.strDate.c_str(), m_info.strFramework.c_str());
+ CLog::Log(LOGDEBUG, "%s: Searching for '%s' using %s scraper (file: '%s', content: '%s')",
+ __FUNCTION__, movieTitle.c_str(), m_info->Name().c_str(), m_info->Path().c_str(), ADDON::TranslateContent(m_info->Content()).c_str());
if (!pUrl)
{
@@ -77,7 +77,7 @@ int CIMDB::InternalFindMovie(const CStdString &strMovie, IMDB_MOVIELIST& movieli
{
GetURL(strMovie, movieTitle, movieYear, scrURL);
}
- else if (m_info.strContent.Equals("musicvideos"))
+ else if (m_info->Content() == CONTENT_MUSICVIDEOS)
{
if (!m_parser.HasFunction("FileNameScrape"))
return false;
@@ -107,7 +107,7 @@ int CIMDB::InternalFindMovie(const CStdString &strMovie, IMDB_MOVIELIST& movieli
for (unsigned int i=0;i<strHTML.size();++i)
m_parser.m_param[i] = strHTML[i];
m_parser.m_param[strHTML.size()] = scrURL.m_url[0].m_url;
- CStdString strXML = m_parser.Parse(strFunction,&m_info.settings);
+ CStdString strXML = m_parser.Parse(strFunction);
CLog::Log(LOGDEBUG,"scraper: %s returned %s",strFunction.c_str(),strXML.c_str());
if (strXML.IsEmpty())
{
@@ -260,7 +260,7 @@ bool CIMDB::InternalGetEpisodeList(const CScraperUrl& url, IMDB_EPISODELIST& det
m_parser.m_param[0] = strHTML;
m_parser.m_param[1] = url.m_url[i].m_url;
- CStdString strXML = m_parser.Parse("GetEpisodeList",&m_info.settings);
+ CStdString strXML = m_parser.Parse("GetEpisodeList");
CLog::Log(LOGDEBUG,"scraper: GetEpisodeList returned %s",strXML.c_str());
if (strXML.IsEmpty())
{
@@ -382,7 +382,7 @@ bool CIMDB::InternalGetDetails(const CScraperUrl& url, CVideoInfoTag& movieDetai
m_parser.m_param[strHTML.size()] = url.strId;
m_parser.m_param[strHTML.size()+1] = url.m_url[0].m_url;
- CStdString strXML = m_parser.Parse(strFunction,&m_info.settings);
+ CStdString strXML = m_parser.Parse(strFunction);
CLog::Log(LOGDEBUG,"scraper: %s returned %s",strFunction.c_str(),strXML.c_str());
if (strXML.IsEmpty())
{
@@ -468,7 +468,7 @@ void CIMDB::GetURL(const CStdString &movieFile, const CStdString &movieName, con
g_charsetConverter.utf8To(m_parser.GetSearchStringEncoding(), movieName, m_parser.m_param[0]);
CUtil::URLEncode(m_parser.m_param[0]);
- scrURL.ParseString(m_parser.Parse("CreateSearchUrl",&m_info.settings));
+ scrURL.ParseString(m_parser.Parse("CreateSearchUrl"));
}
// threaded functions
@@ -482,7 +482,7 @@ void CIMDB::Process()
if (!(m_found=FindMovie(m_strMovie, m_movieList)))
{
// retry without replacing '.' and '-' if searching for a tvshow
- if (m_info.strContent.Equals("tvshows"))
+ if (m_info->Content() == CONTENT_TVSHOWS)
CLog::Log(LOGERROR, "%s: Error looking up tvshow %s", __FUNCTION__, m_strMovie.c_str());
else
CLog::Log(LOGERROR, "%s: Error looking up movie %s", __FUNCTION__, m_strMovie.c_str());
@@ -514,7 +514,7 @@ int CIMDB::FindMovie(const CStdString &strMovie, IMDB_MOVIELIST& movieList, CGUI
//CLog::Log(LOGDEBUG,"CIMDB::FindMovie(%s)", strMovie.c_str());
// load our scraper xml
- if (!m_parser.Load(CUtil::AddFileToFolder("special://xbmc/system/scrapers/video/", m_info.strPath)))
+ if (!m_parser.Load(m_info))
return 0;
m_parser.ClearCache();
@@ -561,7 +561,7 @@ bool CIMDB::GetDetails(const CScraperUrl &url, CVideoInfoTag &movieDetails, CGUI
m_url = url;
m_movieDetails = movieDetails;
// load our scraper xml
- if (!m_parser.Load("special://xbmc/system/scrapers/video/"+m_info.strPath))
+ if (!m_parser.Load(m_info))
return false;
// fill in the defaults
@@ -631,7 +631,7 @@ bool CIMDB::GetEpisodeList(const CScraperUrl& url, IMDB_EPISODELIST& movieDetail
m_episode = movieDetails;
// load our scraper xml
- if (!m_parser.Load(CUtil::AddFileToFolder("special://xbmc/system/scrapers/video/", m_info.strPath)))
+ if (!m_parser.Load(m_info))
return false;
// fill in the defaults
@@ -676,7 +676,7 @@ bool CIMDB::ScrapeFilename(const CStdString& strFileName, CVideoInfoTag& details
CUtil::RemoveExtension(m_parser.m_param[0]);
m_parser.m_param[0].Replace("_"," ");
- CStdString strResult = m_parser.Parse("FileNameScrape",&m_info.settings);
+ CStdString strResult = m_parser.Parse("FileNameScrape");
CLog::Log(LOGDEBUG,"scraper: FileNameScrape returned %s", strResult.c_str());
TiXmlDocument doc;
doc.Parse(strResult.c_str());
diff --git a/xbmc/utils/IMDB.h b/xbmc/utils/IMDB.h
index bd1b71b4bb..ed9adb4dcb 100644
--- a/xbmc/utils/IMDB.h
+++ b/xbmc/utils/IMDB.h
@@ -33,7 +33,7 @@
#include "Thread.h"
#include "ScraperParser.h"
#include "VideoInfoTag.h"
-#include "ScraperSettings.h"
+#include "Scraper.h"
#include "DateTime.h"
#include "FileSystem/FileCurl.h"
@@ -74,8 +74,8 @@ public:
bool GetEpisodeList(const CScraperUrl& url, IMDB_EPISODELIST& details, CGUIDialogProgress *pProgress = NULL);
bool ScrapeFilename(const CStdString& strFileName, CVideoInfoTag& details);
- void SetScraperInfo(const SScraperInfo& info) { m_info.Reset(); m_info = info; }
- const SScraperInfo& GetScraperInfo() const { return m_info; }
+ void SetScraperInfo(const ADDON::ScraperPtr& scraper) { m_info = scraper; }
+ const ADDON::ScraperPtr GetScraperInfo() const { return m_info; }
static void ShowErrorDialog(const TiXmlElement* element);
protected:
@@ -102,7 +102,7 @@ protected:
IMDB_EPISODELIST m_episode;
LOOKUP_STATE m_state;
int m_found;
- SScraperInfo m_info;
+ ADDON::ScraperPtr m_info;
};
#endif // !defined(AFX_IMDB1_H__562A722A_CD2A_4B4A_8A67_32DE8088A7D3__INCLUDED_)
diff --git a/xbmc/utils/Makefile b/xbmc/utils/Makefile
index d280a38773..034e23587b 100644
--- a/xbmc/utils/Makefile
+++ b/xbmc/utils/Makefile
@@ -1,10 +1,14 @@
INCLUDES=-I. -I.. -I../../ -I../linux -I../cores -I../../guilib -I../posix -I../../lib/jsoncpp/jsoncpp/include
-SRCS=AlarmClock.cpp \
+SRCS=Addon.cpp \
+ AddonManager.cpp \
+ AlarmClock.cpp \
Archive.cpp \
Builtins.cpp \
CharsetConverter.cpp \
CriticalSection.cpp \
+ DownloadQueue.cpp \
+ DownloadQueueManager.cpp \
Event.cpp \
fstrcmp.cpp \
GUIInfoManager.cpp \
diff --git a/xbmc/utils/MusicAlbumInfo.cpp b/xbmc/utils/MusicAlbumInfo.cpp
index fb1989d5b1..537afaa4f4 100644
--- a/xbmc/utils/MusicAlbumInfo.cpp
+++ b/xbmc/utils/MusicAlbumInfo.cpp
@@ -21,7 +21,7 @@
#include "MusicAlbumInfo.h"
#include "ScraperParser.h"
-#include "ScraperSettings.h"
+#include "Scraper.h"
#include "XMLUtils.h"
#include "HTMLTable.h"
#include "HTMLUtil.h"
@@ -122,10 +122,10 @@ bool CMusicAlbumInfo::Parse(const TiXmlElement* album, bool bChained)
}
-bool CMusicAlbumInfo::Load(XFILE::CFileCurl& http, const SScraperInfo& info, const CStdString& strFunction, const CScraperUrl* url)
+bool CMusicAlbumInfo::Load(XFILE::CFileCurl& http, const ADDON::ScraperPtr& scraper, const CStdString& strFunction, const CScraperUrl* url)
{
// load our scraper xml
- if (!m_parser.Load("special://xbmc/system/scrapers/music/" + info.strPath))
+ if (!m_parser.Load(scraper))
return false;
bool bChained=true;
@@ -148,7 +148,7 @@ bool CMusicAlbumInfo::Load(XFILE::CFileCurl& http, const SScraperInfo& info, con
for (unsigned int i=0;i<strHTML.size();++i)
m_parser.m_param[i] = strHTML[i];
- CStdString strXML = m_parser.Parse(strFunction,&info.settings);
+ CStdString strXML = m_parser.Parse(strFunction);
CLog::Log(LOGDEBUG,"scraper: %s returned %s",strFunction.c_str(),strXML.c_str());
if (strXML.IsEmpty())
{
@@ -179,7 +179,7 @@ bool CMusicAlbumInfo::Load(XFILE::CFileCurl& http, const SScraperInfo& info, con
if (szFunction)
{
CScraperUrl scrURL(xurl);
- Load(http,info,szFunction,&scrURL);
+ Load(http,scraper,szFunction,&scrURL);
}
xurl = xurl->NextSiblingElement("url");
}
diff --git a/xbmc/utils/MusicAlbumInfo.h b/xbmc/utils/MusicAlbumInfo.h
index 0a57266bcf..bedcac9dda 100644
--- a/xbmc/utils/MusicAlbumInfo.h
+++ b/xbmc/utils/MusicAlbumInfo.h
@@ -23,11 +23,11 @@
#include "Song.h"
#include "Album.h"
+#include "Scraper.h"
#include "ScraperParser.h"
class TiXmlDocument;
class CScraperUrl;
-struct SScraperInfo;
namespace XFILE { class CFileCurl; }
@@ -53,7 +53,7 @@ public:
float GetRelevance() const { return m_relevance; }
void SetTitle(const CStdString& strTitle);
void SetRelevance(float relevance) { m_relevance = relevance; }
- bool Load(XFILE::CFileCurl& http, const SScraperInfo& info, const CStdString& strFunction="GetAlbumDetails", const CScraperUrl* url=NULL);
+ bool Load(XFILE::CFileCurl& http, const ADDON::ScraperPtr& scraper, const CStdString& strFunction="GetAlbumDetails", const CScraperUrl* url=NULL);
bool Parse(const TiXmlElement* album, bool bChained=false);
protected:
CAlbum m_album;
diff --git a/xbmc/utils/MusicArtistInfo.cpp b/xbmc/utils/MusicArtistInfo.cpp
index d8ed90f3a3..d9711b58b7 100644
--- a/xbmc/utils/MusicArtistInfo.cpp
+++ b/xbmc/utils/MusicArtistInfo.cpp
@@ -21,7 +21,7 @@
#include "MusicArtistInfo.h"
#include "ScraperParser.h"
-#include "ScraperSettings.h"
+#include "Scraper.h"
#include "XMLUtils.h"
#include "Settings.h"
#include "CharsetConverter.h"
@@ -77,10 +77,10 @@ bool CMusicArtistInfo::Parse(const TiXmlElement* artist, bool bChained)
return true;
}
-bool CMusicArtistInfo::Load(XFILE::CFileCurl& http, const SScraperInfo& info, const CStdString& strFunction, const CScraperUrl* url)
+bool CMusicArtistInfo::Load(XFILE::CFileCurl& http, const ADDON::ScraperPtr& scraper, const CStdString& strFunction, const CScraperUrl* url)
{
// load our scraper xml
- if (!m_parser.Load("special://xbmc/system/scrapers/music/" + info.strPath))
+ if (!m_parser.Load(scraper))
return false;
bool bChained=true;
@@ -105,7 +105,7 @@ bool CMusicArtistInfo::Load(XFILE::CFileCurl& http, const SScraperInfo& info, co
m_parser.m_param[strHTML.size()] = m_strSearch;
- CStdString strXML = m_parser.Parse(strFunction,&info.settings);
+ CStdString strXML = m_parser.Parse(strFunction);
CLog::Log(LOGDEBUG,"scraper: %s returned %s",strFunction.c_str(),strXML.c_str());
if (strXML.IsEmpty())
{
@@ -136,7 +136,7 @@ bool CMusicArtistInfo::Load(XFILE::CFileCurl& http, const SScraperInfo& info, co
if (szFunction)
{
CScraperUrl scrURL(xurl);
- Load(http,info,szFunction,&scrURL);
+ Load(http,scraper,szFunction,&scrURL);
}
xurl = xurl->NextSiblingElement("url");
}
diff --git a/xbmc/utils/MusicArtistInfo.h b/xbmc/utils/MusicArtistInfo.h
index 6bcfdbf38b..743ef26553 100644
--- a/xbmc/utils/MusicArtistInfo.h
+++ b/xbmc/utils/MusicArtistInfo.h
@@ -23,11 +23,11 @@
#include "Song.h"
#include "Artist.h"
+#include "Scraper.h"
#include "ScraperParser.h"
class TiXmlDocument;
class CScraperUrl;
-struct SScraperInfo;
namespace MUSIC_GRABBER
{
@@ -43,7 +43,7 @@ public:
const CArtist& GetArtist() const;
CArtist& GetArtist();
const CScraperUrl& GetArtistURL() const;
- bool Load(XFILE::CFileCurl& http, const SScraperInfo& info, const CStdString& strFunction="GetArtistDetails", const CScraperUrl* url=NULL);
+ bool Load(XFILE::CFileCurl& http, const ADDON::ScraperPtr& scraper, const CStdString& strFunction="GetArtistDetails", const CScraperUrl* url=NULL);
bool Parse(const TiXmlElement* artist, bool bChained=false);
CStdString m_strSearch;
protected:
diff --git a/xbmc/utils/MusicInfoScraper.cpp b/xbmc/utils/MusicInfoScraper.cpp
index 019564cfe2..14a4ffb478 100644
--- a/xbmc/utils/MusicInfoScraper.cpp
+++ b/xbmc/utils/MusicInfoScraper.cpp
@@ -30,13 +30,15 @@
using namespace MUSIC_GRABBER;
using namespace HTML;
-CMusicInfoScraper::CMusicInfoScraper(const SScraperInfo& info)
+using namespace ADDON;
+
+CMusicInfoScraper::CMusicInfoScraper(const ADDON::ScraperPtr &scraper)
{
m_bSuccessfull=false;
m_bCanceled=false;
m_iAlbum=-1;
m_iArtist=-1;
- m_info = info;
+ m_scraper = scraper;
}
CMusicInfoScraper::~CMusicInfoScraper(void)
@@ -90,27 +92,19 @@ void CMusicInfoScraper::FindAlbuminfo()
CScraperParser parser;
parser.ClearCache();
-
- if (!parser.Load("special://xbmc/system/scrapers/music/" + m_info.strPath) || !parser.HasFunction("CreateAlbumSearchUrl"))
+ if (!parser.Load(m_scraper) || !parser.HasFunction("CreateAlbumSearchUrl"))
return;
- if (!m_info.settings.GetPluginRoot() && m_info.settings.GetSettings().IsEmpty() && parser.HasFunction("GetSettings"))
- {
- m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/music/" + m_info.strPath);
- m_info.settings.SaveFromDefault();
- }
-
parser.m_param[0] = strAlbum;
parser.m_param[1] = m_strArtist;
CUtil::URLEncode(parser.m_param[0]);
CUtil::URLEncode(parser.m_param[1]);
- CLog::Log(LOGDEBUG, "%s: Searching for '%s - %s' using %s scraper (file: '%s', content: '%s', language: '%s', date: '%s', framework: '%s')",
- __FUNCTION__, m_strArtist.c_str(), strAlbum.c_str(), m_info.strTitle.c_str(), m_info.strPath.c_str(), m_info.strContent.c_str(), m_info.strLanguage.c_str(), m_info.strDate.c_str(), m_info.strFramework.c_str());
-
+ CLog::Log(LOGDEBUG, "%s: Searching for '%s - %s' using %s scraper (file: '%s', content: '%s')",
+ __FUNCTION__, m_strArtist.c_str(), strAlbum.c_str(), m_scraper->Name().c_str(), m_scraper->Path().c_str(), ADDON::TranslateContent(m_scraper->Content()).c_str());
CScraperUrl scrURL;
- scrURL.ParseString(parser.Parse("CreateAlbumSearchUrl",&m_info.settings));
+ scrURL.ParseString(parser.Parse("CreateAlbumSearchUrl"));
if (!CScraperUrl::Get(scrURL.m_url[0], strHTML, m_http, parser.GetFilename()) || strHTML.size() == 0)
{
CLog::Log(LOGERROR, "%s: Unable to retrieve web site",__FUNCTION__);
@@ -118,7 +112,7 @@ void CMusicInfoScraper::FindAlbuminfo()
}
parser.m_param[0] = strHTML;
- CStdString strXML = parser.Parse("GetAlbumSearchResults",&m_info.settings);
+ CStdString strXML = parser.Parse("GetAlbumSearchResults");
CLog::Log(LOGDEBUG,"scraper: GetAlbumSearchResults returns %s",strXML.c_str());
if (strXML.IsEmpty())
{
@@ -203,24 +197,23 @@ void CMusicInfoScraper::FindArtistinfo()
CScraperParser parser;
parser.ClearCache();
-
- if (!parser.Load("special://xbmc/system/scrapers/music/" + m_info.strPath) || !parser.HasFunction("CreateArtistSearchUrl"))
+ if (!parser.Load(m_scraper) || !parser.HasFunction("CreateAlbumSearchUrl"))
return;
- if (!m_info.settings.GetPluginRoot() && m_info.settings.GetSettings().IsEmpty() && parser.HasFunction("GetSettings"))
+ if (!m_scraper->GetSettingsXML() && parser.HasFunction("GetSettings"))
{
- m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/music/" + m_info.strPath);
- m_info.settings.SaveFromDefault();
+ m_scraper->LoadSettings();
+ m_scraper->SaveFromDefault();
}
parser.m_param[0] = m_strArtist;
CUtil::URLEncode(parser.m_param[0]);
- CLog::Log(LOGDEBUG, "%s: Searching for '%s' using %s scraper (file: '%s', content: '%s', language: '%s', date: '%s', framework: '%s')",
- __FUNCTION__, m_strArtist.c_str(), m_info.strTitle.c_str(), m_info.strPath.c_str(), m_info.strContent.c_str(), m_info.strLanguage.c_str(), m_info.strDate.c_str(), m_info.strFramework.c_str());
+ CLog::Log(LOGDEBUG, "%s: Searching for '%s' using %s scraper (file: '%s', content: '%s')",
+ __FUNCTION__, m_strArtist.c_str(), m_scraper->Name().c_str(), m_scraper->Path().c_str(), ADDON::TranslateContent(m_scraper->Content()).c_str());
CScraperUrl scrURL;
- scrURL.ParseString(parser.Parse("CreateArtistSearchUrl",&m_info.settings));
+ scrURL.ParseString(parser.Parse("CreateArtistSearchUrl"));
if (!CScraperUrl::Get(scrURL.m_url[0], strHTML, m_http, parser.GetFilename()) || strHTML.size() == 0)
{
CLog::Log(LOGERROR, "%s: Unable to retrieve web site",__FUNCTION__);
@@ -228,7 +221,7 @@ void CMusicInfoScraper::FindArtistinfo()
}
parser.m_param[0] = strHTML;
- CStdString strXML = parser.Parse("GetArtistSearchResults",&m_info.settings);
+ CStdString strXML = parser.Parse("GetArtistSearchResults");
CLog::Log(LOGDEBUG,"scraper: GetArtistSearchResults returns %s",strXML.c_str());
if (strXML.IsEmpty())
{
@@ -309,7 +302,7 @@ void CMusicInfoScraper::LoadAlbuminfo()
CMusicAlbumInfo& album=m_vecAlbums[m_iAlbum];
album.GetAlbum().strArtist.Empty();
- if (album.Load(m_http,m_info))
+ if (album.Load(m_http,m_scraper))
m_bSuccessfull=true;
}
@@ -320,7 +313,7 @@ void CMusicInfoScraper::LoadArtistinfo()
CMusicArtistInfo& artist=m_vecArtists[m_iArtist];
artist.GetArtist().strArtist.Empty();
- if (artist.Load(m_http,m_info))
+ if (artist.Load(m_http,m_scraper))
m_bSuccessfull=true;
}
@@ -387,9 +380,13 @@ void CMusicInfoScraper::Process()
bool CMusicInfoScraper::CheckValidOrFallback(const CStdString &fallbackScraper)
{
CScraperParser parser;
- if (parser.Load("special://xbmc/system/scrapers/music/" + m_info.strPath))
+ if (parser.Load(m_scraper))
return true;
- if (m_info.strPath != fallbackScraper &&
+ else
+ return false;
+/*
+ * TODO handle fallback mechanism
+ if (m_scraper->Path() != fallbackScraper &&
parser.Load("special://xbmc/system/scrapers/music/" + fallbackScraper))
{
CLog::Log(LOGWARNING, "%s - scraper %s fails to load, falling back to %s", __FUNCTION__, m_info.strPath.c_str(), fallbackScraper.c_str());
@@ -402,5 +399,5 @@ bool CMusicInfoScraper::CheckValidOrFallback(const CStdString &fallbackScraper)
m_info.settings.LoadSettingsXML("special://xbmc/system/scrapers/music/" + m_info.strPath);
return true;
}
- return false;
+ return false; */
}
diff --git a/xbmc/utils/MusicInfoScraper.h b/xbmc/utils/MusicInfoScraper.h
index 2c8cfe2466..729fec7d3a 100644
--- a/xbmc/utils/MusicInfoScraper.h
+++ b/xbmc/utils/MusicInfoScraper.h
@@ -23,7 +23,7 @@
#include "MusicAlbumInfo.h"
#include "MusicArtistInfo.h"
-#include "ScraperSettings.h"
+#include "Scraper.h"
#include "Thread.h"
#include "FileSystem/FileCurl.h"
@@ -34,7 +34,7 @@ namespace MUSIC_GRABBER
class CMusicInfoScraper : public CThread
{
public:
- CMusicInfoScraper(const SScraperInfo& info);
+ CMusicInfoScraper(const ADDON::ScraperPtr &scraper);
virtual ~CMusicInfoScraper(void);
void FindAlbuminfo(const CStdString& strAlbum, const CStdString& strArtist = "");
void LoadAlbuminfo(int iAlbum);
@@ -56,9 +56,9 @@ public:
{
return m_vecAlbums;
}
- void SetScraperInfo(const SScraperInfo& info)
+ void SetScraperInfo(const ADDON::ScraperPtr& scraper)
{
- m_info = info;
+ m_scraper = scraper;
}
/*!
\brief Checks whether we have a valid scraper. If not, we try the fallbackScraper
@@ -84,7 +84,7 @@ protected:
bool m_bSuccessfull;
bool m_bCanceled;
XFILE::CFileCurl m_http;
- SScraperInfo m_info;
+ ADDON::ScraperPtr m_scraper;
};
}
diff --git a/xbmc/utils/ScraperParser.cpp b/xbmc/utils/ScraperParser.cpp
index bc1b372458..a623d5738c 100644
--- a/xbmc/utils/ScraperParser.cpp
+++ b/xbmc/utils/ScraperParser.cpp
@@ -25,12 +25,14 @@
#include "system.h"
#endif
+#include "AddonManager.h"
#include "RegExp.h"
#include "HTMLUtil.h"
-#include "ScraperSettings.h"
+#include "Scraper.h"
#include "FileSystem/File.h"
#include "FileSystem/Directory.h"
#include "Util.h"
+#include "StringUtils.h"
#include "AdvancedSettings.h"
#include "FileItem.h"
@@ -38,18 +40,13 @@
#include <cstring>
using namespace std;
+using namespace ADDON;
using namespace XFILE;
CScraperParser::CScraperParser()
{
m_pRootElement = NULL;
- m_name = m_content = NULL;
- m_thumb = NULL;
m_document = NULL;
- m_settings = NULL;
- m_language = NULL;
- m_framework = NULL;
- m_date = NULL;
m_requiressettings = false;
m_SearchStringEncoding = "UTF-8";
}
@@ -68,7 +65,7 @@ CScraperParser &CScraperParser::operator=(const CScraperParser &parser)
Clear();
if (parser.m_document)
{
- m_strFile = parser.m_strFile;
+ m_scraper = parser.m_scraper;
m_persistence = parser.m_persistence;
m_document = new TiXmlDocument(*parser.m_document);
LoadFromXML();
@@ -88,93 +85,107 @@ void CScraperParser::Clear()
delete m_document;
m_document = NULL;
- m_name = m_thumb = m_content = m_language = m_framework = m_date = NULL;
m_requiressettings = false;
- m_settings = NULL;
m_strFile.Empty();
}
bool CScraperParser::Load(const CStdString& strXMLFile)
{
- Clear();
+ //TODO drop loading by UUID support, then remove AddonMgr include
+ if (StringUtils::ValidateUUID(strXMLFile))
+ {
+ AddonPtr scraper;
+ if (!CAddonMgr::Get()->GetAddon(ADDON_SCRAPER, strXMLFile, scraper))
+ return false;
+ else
+ return Load(scraper);
+ }
+ else
+ {
+ Clear();
+
+ m_document = new TiXmlDocument(strXMLFile);
+
+ if (!m_document)
+ return false;
- m_document = new TiXmlDocument(strXMLFile);
+ m_strFile = strXMLFile;
- if (!m_document)
+ if (m_document->LoadFile())
+ return LoadFromXML();
+
+ delete m_document;
+ m_document = NULL;
return false;
+ }
+}
- m_strFile = strXMLFile;
+bool CScraperParser::Load(const AddonPtr& scraper)
+{
+ if (!scraper)
+ return false;
- if (m_document->LoadFile())
- return LoadFromXML();
+ m_scraper = scraper;
- delete m_document;
- m_document = NULL;
- return false;
+ return Load(m_scraper->Path() + m_scraper->LibName());
}
bool CScraperParser::LoadFromXML()
{
- if (!m_document)
+ if (!m_document || !m_scraper)
return false;
- CStdString strPath;
- CUtil::GetDirectory(m_strFile,strPath);
+ CStdString strPath = m_scraper->Path();
m_pRootElement = m_document->RootElement();
CStdString strValue = m_pRootElement->Value();
if (strValue == "scraper")
{
- m_name = m_pRootElement->Attribute("name");
- m_thumb = m_pRootElement->Attribute("thumb");
- m_content = m_pRootElement->Attribute("content");
- m_language = m_pRootElement->Attribute("language");
- m_framework = m_pRootElement->Attribute("framework");
- m_date = m_pRootElement->Attribute("date");
+ CONTENT_TYPE content = TranslateContent(m_pRootElement->Attribute("content"));
if (m_pRootElement->Attribute("cachePersistence"))
m_persistence.SetFromTimeString(m_pRootElement->Attribute("cachePersistence"));
const char* requiressettings;
m_requiressettings = ((requiressettings = m_pRootElement->Attribute("requiressettings")) && strnicmp("true", requiressettings, 4) == 0);
- if (m_name && m_content) // FIXME
+ // check for known content
+ if ( content == CONTENT_TVSHOWS ||
+ content == CONTENT_MOVIES ||
+ content == CONTENT_MUSICVIDEOS ||
+ content == CONTENT_ALBUMS)
{
- // check for known content
- if ((0 == stricmp(m_content,"tvshows")) ||
- (0 == stricmp(m_content,"movies")) ||
- (0 == stricmp(m_content,"musicvideos")) ||
- (0 == stricmp(m_content,"albums")))
+ TiXmlElement* pChildElement = m_pRootElement->FirstChildElement("CreateSearchUrl");
+ if (pChildElement)
{
- TiXmlElement* pChildElement = m_pRootElement->FirstChildElement("CreateSearchUrl");
- if (pChildElement)
+ if (!(m_SearchStringEncoding = pChildElement->Attribute("SearchStringEncoding")))
+ m_SearchStringEncoding = "UTF-8";
+ }
+
+ ADDONDEPS deps = m_scraper->GetDeps();
+ ADDONDEPS::iterator itr = deps.begin();
+ while (itr != deps.end())
+ {
+ AddonPtr dep;
+ if (!CAddonMgr::Get()->GetAddon(ADDON_SCRAPER_LIBRARY, (*itr).first, dep))
{
- if (!(m_SearchStringEncoding = pChildElement->Attribute("SearchStringEncoding")))
- m_SearchStringEncoding = "UTF-8";
+ itr++;
+ continue;
}
-
- // inject includes
- const TiXmlElement* include = m_pRootElement->FirstChildElement("include");
- while (include)
+ CStdString strFile = CUtil::AddFileToFolder(dep->Path(), dep->LibName());
+ TiXmlDocument doc;
+ if (doc.LoadFile(strFile))
{
- if (include->FirstChild())
+ const TiXmlNode* node = doc.RootElement()->FirstChild();
+ while (node)
{
- CStdString strFile = CUtil::AddFileToFolder(strPath,include->FirstChild()->Value());
- TiXmlDocument doc;
- if (doc.LoadFile(strFile))
- {
- const TiXmlNode* node = doc.RootElement()->FirstChild();
- while (node)
- {
- m_pRootElement->InsertEndChild(*node);
- node = node->NextSibling();
- }
- }
+ m_pRootElement->InsertEndChild(*node);
+ node = node->NextSibling();
}
- include = include->NextSiblingElement("include");
}
-
- return true;
+ itr++;
}
+
+ return true;
}
}
delete m_document;
@@ -200,11 +211,11 @@ void CScraperParser::ReplaceBuffers(CStdString& strDest)
}
// insert settings
iIndex = 0;
- while ((size_t)(iIndex = strDest.find("$INFO[",iIndex)) != CStdString::npos && m_settings)
+ while ((size_t)(iIndex = strDest.find("$INFO[",iIndex)) != CStdString::npos)
{
int iEnd = strDest.Find("]",iIndex);
CStdString strInfo = strDest.Mid(iIndex+6,iEnd-iIndex-6);
- CStdString strReplace = m_settings->Get(strInfo);
+ CStdString strReplace = m_scraper->GetSetting(strInfo);
strDest.replace(strDest.begin()+iIndex,strDest.begin()+iEnd+1,strReplace);
iIndex += strReplace.length();
}
@@ -396,8 +407,8 @@ void CScraperParser::ParseNext(TiXmlElement* element)
szConditional++;
}
CStdString strSetting;
- if (m_settings)
- strSetting = m_settings->Get(szConditional);
+ if (m_scraper && m_scraper->HasSettings())
+ strSetting = m_scraper->GetSetting(szConditional);
bExecute = bInverse != strSetting.Equals("true");
}
@@ -408,14 +419,13 @@ void CScraperParser::ParseNext(TiXmlElement* element)
}
}
-const CStdString CScraperParser::Parse(const CStdString& strTag, const CScraperSettings* pSettings)
+const CStdString CScraperParser::Parse(const CStdString& strTag)
{
TiXmlElement* pChildElement = m_pRootElement->FirstChildElement(strTag.c_str());
if(pChildElement == NULL) return "";
int iResult = 1; // default to param 1
pChildElement->QueryIntAttribute("dest",&iResult);
TiXmlElement* pChildStart = pChildElement->FirstChildElement("RegExp");
- m_settings = pSettings;
ParseNext(pChildStart);
CStdString tmp = m_param[iResult-1];
diff --git a/xbmc/utils/ScraperParser.h b/xbmc/utils/ScraperParser.h
index 63fc8572ff..7944a89f63 100644
--- a/xbmc/utils/ScraperParser.h
+++ b/xbmc/utils/ScraperParser.h
@@ -24,6 +24,7 @@
#include <vector>
#include "StdString.h"
+#include "IAddon.h"
#include "DateTime.h"
#define MAX_SCRAPER_BUFFERS 20
@@ -43,15 +44,10 @@ public:
void Clear();
bool Load(const CStdString& strXMLFile);
- const CStdString GetName() { return m_name; }
- const CStdString GetThumb() { return m_thumb; }
- const CStdString GetContent() { return m_content; }
- const CStdString GetLanguage() { return m_language; }
- const CStdString GetFramework() { return m_framework; }
- const CStdString GetDate() { return m_date; }
+ bool Load(const ADDON::AddonPtr& scraper);
const CStdString GetFilename() { return m_strFile; }
const CStdString GetSearchStringEncoding() { return m_SearchStringEncoding; }
- const CStdString Parse(const CStdString& strTag, const CScraperSettings* pSettings=NULL);
+ const CStdString Parse(const CStdString& strTag);
bool HasFunction(const CStdString& strTag);
bool RequiresSettings() { return m_requiressettings; }
@@ -69,22 +65,15 @@ private:
void GetBufferParams(bool* result, const char* attribute, bool defvalue);
void InsertToken(CStdString& strOutput, int buf, const char* token);
+ ADDON::AddonPtr m_scraper;
TiXmlDocument* m_document;
TiXmlElement* m_pRootElement;
- const char* m_name;
- const char* m_thumb;
- const char* m_content;
- const char* m_language;
- const char* m_framework;
- const char* m_date;
const char* m_SearchStringEncoding;
CDateTimeSpan m_persistence;
bool m_requiressettings;
CStdString m_strFile;
-
- const CScraperSettings* m_settings;
};
#endif
diff --git a/xbmc/utils/ScraperUrl.cpp b/xbmc/utils/ScraperUrl.cpp
index afea059ff4..22a31356b3 100644
--- a/xbmc/utils/ScraperUrl.cpp
+++ b/xbmc/utils/ScraperUrl.cpp
@@ -174,7 +174,7 @@ const CScraperUrl::SUrlEntry CScraperUrl::GetSeasonThumb(int season) const
return result;
}
-bool CScraperUrl::Get(const SUrlEntry& scrURL, string& strHTML, XFILE::CFileCurl& http, const CStdString& cacheContext1)
+bool CScraperUrl::Get(const SUrlEntry& scrURL, std::string& strHTML, XFILE::CFileCurl& http, const CStdString& cacheContext1)
{
CURL url(scrURL.m_url);
http.SetReferer(scrURL.m_spoof);
diff --git a/xbmc/visualizations/DirectXSpectrum/directx_spectrum.cpp b/xbmc/visualizations/DirectXSpectrum/directx_spectrum.cpp
index 1214bf0ade..dcff0baa3a 100644
--- a/xbmc/visualizations/DirectXSpectrum/directx_spectrum.cpp
+++ b/xbmc/visualizations/DirectXSpectrum/directx_spectrum.cpp
@@ -28,7 +28,7 @@
*/
-#include "../../../visualisations/xbmc_vis.h"
+#include "../../addons/include/xbmc_vis_dll.h"
#include <math.h>
#include <D3D9.h>
#include <d3dx9math.h>
@@ -51,38 +51,6 @@ typedef struct
#define VERTEX_FORMAT (D3DFVF_XYZ | D3DFVF_DIFFUSE)
-vector<VisSetting> g_vecSettings;
-
-extern "C" void Create(void* pd3dDevice, int iPosX, int iPosY, int iWidth, int iHeight, const char* szVisualisationName,
- float fPixelRatio, const char *szSubModuleName)
-{
- g_device = (LPDIRECT3DDEVICE9)pd3dDevice;
-
- g_vecSettings.clear();
- m_uiVisElements = 0;
- VisSetting scale(VisSetting::SPIN, "Bar Height");
- scale.AddEntry("Default");
- scale.AddEntry("Big");
- scale.AddEntry("Very Big");
- scale.AddEntry("Small");
-
- VisSetting mode(VisSetting::SPIN, "Mode");
- mode.AddEntry("Default");
- mode.AddEntry("Wireframe");
- mode.AddEntry("Points");
-
- VisSetting speed(VisSetting::SPIN, "Speed");
- speed.AddEntry("Default");
- speed.AddEntry("Slow");
- speed.AddEntry("Very Slow");
- speed.AddEntry("Fast");
- speed.AddEntry("Very Fast");
-
- g_vecSettings.push_back( scale );
- g_vecSettings.push_back( mode );
- g_vecSettings.push_back( speed );
-}
-
void draw_vertex(Vertex_t * pVertex, float x, float y, float z, D3DCOLOR color) {
pVertex->col = color;
pVertex->x = x;
@@ -188,6 +156,21 @@ void draw_bars(void)
}
}
+//-- Create -------------------------------------------------------------------
+// Called on load. Addon should fully initalize or return error status
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+ADDON_STATUS Create(void* hdl, void* visProps)
+{
+ if (!visProps)
+ return STATUS_UNKNOWN;
+
+ VIS_PROPS* props = (VIS_PROPS*) visProps;
+ g_device = (LPDIRECT3DDEVICE9) props->device;
+
+ return STATUS_NEED_SETTINGS;
+}
+
//-- Render -------------------------------------------------------------------
// Called once per frame. Do all rendering here.
//-----------------------------------------------------------------------------
@@ -261,7 +244,7 @@ extern "C" void Stop()
}
-extern "C" void AudioData(short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength)
+extern "C" void AudioData(const short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength)
{
int i,c;
int y=0;
@@ -308,11 +291,18 @@ extern "C" void GetInfo(VIS_INFO* pInfo)
pInfo->iSyncDelay = 0;
}
+//-- GetSubModules ------------------------------------------------------------
+// Return any sub modules supported by this vis
+//-----------------------------------------------------------------------------
+extern "C" unsigned int GetSubModules(char ***names)
+{
+ return 0; // this vis supports 0 sub modules
+}
//-- OnAction -----------------------------------------------------------------
// Handle XBMC actions such as next preset, lock preset, album art changed etc
//-----------------------------------------------------------------------------
-extern "C" bool OnAction(long flags, void *param)
+extern "C" bool OnAction(long flags, const void *param)
{
bool ret = false;
return ret;
@@ -321,39 +311,83 @@ extern "C" bool OnAction(long flags, void *param)
//-- GetPresets ---------------------------------------------------------------
// Return a list of presets to XBMC for display
//-----------------------------------------------------------------------------
-extern "C" void GetPresets(char ***pPresets, int *currentPreset, int *numPresets, bool *locked)
+extern "C" unsigned int GetPresets(char ***presets)
+{
+ return 0;
+}
+
+//-- GetPreset ----------------------------------------------------------------
+// Return the index of the current playing preset
+//-----------------------------------------------------------------------------
+extern "C" unsigned GetPreset()
+{
+ return 0;
+}
+
+//-- IsLocked -----------------------------------------------------------------
+// Returns true if this add-on use settings
+//-----------------------------------------------------------------------------
+extern "C" bool IsLocked()
+{
+ return false;
+}
+
+//-- Remove -------------------------------------------------------------------
+// Do everything before unload of this add-on
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" void Remove()
{
+}
+
+//-- HasSettings --------------------------------------------------------------
+// Returns true if this add-on use settings
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" bool HasSettings()
+{
+ return true;
+}
+//-- GetStatus ---------------------------------------------------------------
+// Returns the current Status of this visualisation
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" ADDON_STATUS GetStatus()
+{
+ return STATUS_OK;
}
//-- GetSettings --------------------------------------------------------------
// Return the settings for XBMC to display
+// !!! Add-on master function !!!
//-----------------------------------------------------------------------------
-extern "C" unsigned int GetSettings(StructSetting*** sSet)
-{
- m_uiVisElements = VisUtils::VecToStruct(g_vecSettings, &m_structSettings);
- *sSet = m_structSettings;
- return m_uiVisElements;
+extern "C" unsigned int GetSettings(StructSetting ***sSet)
+{
+ return 0;
}
+//-- FreeSettings --------------------------------------------------------------
+// Free the settings struct passed from XBMC
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+
extern "C" void FreeSettings()
{
- VisUtils::FreeStruct(m_uiVisElements, &m_structSettings);
}
-//-- UpdateSetting ------------------------------------------------------------
-// Handle setting change request from XBMC
+//-- SetSetting ---------------------------------------------------------------
+// Set a specific Setting value (called from XBMC)
+// !!! Add-on master function !!!
//-----------------------------------------------------------------------------
-extern "C" void UpdateSetting(int num, StructSetting*** sSet)
+extern "C" ADDON_STATUS SetSetting(const char *strSetting, const void* value)
{
- VisUtils::StructToVec(m_uiVisElements, sSet, &g_vecSettings);
-
- if ( (int)g_vecSettings.size() <= num || num < 0 )
- return;
+ if (!strSetting || !value)
+ return STATUS_UNKNOWN;
- if (strcmp(g_vecSettings[num].name, "Size")==0)
+ if (strcmp(strSetting, "size")==0)
{
- switch (g_vecSettings[num].current)
+ switch (*(int*) value)
{
case 0:
scale = 1.0f / log(256.0f);
@@ -375,11 +409,12 @@ extern "C" void UpdateSetting(int num, StructSetting*** sSet)
scale = 0.33f / log(256.0f);
break;
}
+ return STATUS_OK;
}
- if (strcmp(g_vecSettings[num].name, "Speed")==0)
+ else if (strcmp(strSetting, "speed")==0)
{
- switch (g_vecSettings[num].current)
+ switch (*(int*) value)
{
case 0:
hSpeed = 0.05f;
@@ -401,11 +436,12 @@ extern "C" void UpdateSetting(int num, StructSetting*** sSet)
hSpeed = 0.20f;
break;
}
+ return STATUS_OK;
}
- if (strcmp(g_vecSettings[num].name, "Mode")==0)
+ else if (strcmp(strSetting, "mode")==0)
{
- switch (g_vecSettings[num].current)
+ switch (*(int*) value)
{
case 0:
g_mode = D3DFILL_SOLID;
@@ -419,13 +455,8 @@ extern "C" void UpdateSetting(int num, StructSetting*** sSet)
g_mode = D3DFILL_POINT;
break;
}
+ return STATUS_OK;
}
+ return STATUS_UNKNOWN;
}
-//-- GetSubModules ------------------------------------------------------------
-// Return any sub modules supported by this vis
-//-----------------------------------------------------------------------------
-extern "C" int GetSubModules(char ***names, char ***paths)
-{
- return 0; // this vis supports 0 sub modules
-} \ No newline at end of file
diff --git a/xbmc/visualizations/DllVisualisation.h b/xbmc/visualizations/DllVisualisation.h
index bc87588658..f5e9fb083f 100644
--- a/xbmc/visualizations/DllVisualisation.h
+++ b/xbmc/visualizations/DllVisualisation.h
@@ -19,20 +19,11 @@
* http://www.gnu.org/copyleft/gpl.html
*
*/
-#include "DynamicDll.h"
-#include "visualizations/VisualisationTypes.h"
-class DllVisualisationInterface
-{
-public:
- void GetModule(struct Visualisation* pScr);
-};
+#include "../DllAddon.h"
+#include "../addons/include/xbmc_vis_types.h"
-class DllVisualisation : public DllDynamic, DllVisualisationInterface
+class DllVisualisation : public DllAddon<Visualisation, VIS_PROPS>
{
- DECLARE_DLL_WRAPPER_TEMPLATE(DllVisualisation)
- DEFINE_METHOD1(void, GetModule, (struct Visualisation* p1))
- BEGIN_METHOD_RESOLVE()
- RESOLVE_METHOD_RENAME(get_module,GetModule)
- END_METHOD_RESOLVE()
+ // this is populated via Macro calls in DllAddon.h
};
diff --git a/xbmc/visualizations/Makefile b/xbmc/visualizations/Makefile
index 0b3a537b5e..7768d61c4b 100644
--- a/xbmc/visualizations/Makefile
+++ b/xbmc/visualizations/Makefile
@@ -1,8 +1,9 @@
-INCLUDES=-I. -I../ -I../linux -I../../guilib -I../utils
+INCLUDES=-I. -I../ -I../linux -I../../guilib -I../utils -I../addons/include
-SRCS=fft.cpp Visualisation.cpp VisualisationFactory.cpp
+SRCS=fft.cpp Visualisation.cpp
LIB=visualization.a
+SLIB=../lib/libvisualisation/libvisualisation.a
include ../../Makefile.include
-include $(OBJS:.o=.P)
diff --git a/xbmc/visualizations/OpenGLSpectrum/Makefile.in b/xbmc/visualizations/OpenGLSpectrum/Makefile.in
index 29dec4e9bd..b8e93c718d 100644
--- a/xbmc/visualizations/OpenGLSpectrum/Makefile.in
+++ b/xbmc/visualizations/OpenGLSpectrum/Makefile.in
@@ -1,10 +1,10 @@
ARCH=@ARCH@
-INCLUDES=-I. -I.. -I../../linux -I../../ -I ../../../guilib
+INCLUDES=-I. -I.. -I../../linux -I../../addons/include -I../../ -I ../../../guilib
DEFINES+=-DHAS_SDL_OPENGL -DHAS_SDL
CXXFLAGS=-fPIC
OBJS=opengl_spectrum.o
-SLIB=../../../visualisations/opengl_spectrum.vis
+SLIB=../../../addons/visualizations/GLSpectrum/opengl_spectrum.vis
$(SLIB): $(OBJS)
ifeq ($(findstring osx,$(ARCH)), osx)
diff --git a/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp b/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp
index 96a185c12d..ee31d92b25 100644
--- a/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp
+++ b/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.cpp
@@ -28,7 +28,8 @@
*/
-#include "../../../visualisations/xbmc_vis.h"
+#include "../../addons/include/xbmc_vis_dll.h"
+#include <string.h>
#include <math.h>
#include <GL/glew.h>
@@ -40,35 +41,6 @@ GLfloat z_angle = 0.0, z_speed = 0.0;
GLfloat heights[16][16], cHeights[16][16], scale;
GLfloat hSpeed = 0.05;
GLenum g_mode = GL_FILL;
-vector<VisSetting> g_vecSettings;
-
-extern "C" void Create(void* pd3dDevice, int iPosX, int iPosY, int iWidth, int iHeight, const char* szVisualisationName,
- float fPixelRatio, const char *szSubModuleName)
-{
- g_vecSettings.clear();
- m_uiVisElements = 0;
- VisSetting scale(VisSetting::SPIN, "Bar Height");
- scale.AddEntry("Default");
- scale.AddEntry("Big");
- scale.AddEntry("Very Big");
- scale.AddEntry("Small");
-
- VisSetting mode(VisSetting::SPIN, "Mode");
- mode.AddEntry("Default");
- mode.AddEntry("Wireframe");
- mode.AddEntry("Points");
-
- VisSetting speed(VisSetting::SPIN, "Speed");
- speed.AddEntry("Default");
- speed.AddEntry("Slow");
- speed.AddEntry("Very Slow");
- speed.AddEntry("Fast");
- speed.AddEntry("Very Fast");
-
- g_vecSettings.push_back( scale );
- g_vecSettings.push_back( mode );
- g_vecSettings.push_back( speed );
-}
void draw_rectangle(GLfloat x1, GLfloat y1, GLfloat z1, GLfloat x2, GLfloat y2, GLfloat z2)
{
@@ -155,8 +127,8 @@ void draw_bars(void)
cHeights[y][x] -= hSpeed;
}
draw_bar(x_offset, z_offset,
- cHeights[y][x], r_base - (x * (r_base / 15.0)),
- x * (1.0 / 15), b_base);
+ cHeights[y][x], r_base - (x * (r_base / 15.0)),
+ x * (1.0 / 15), b_base);
}
}
glEnd();
@@ -164,13 +136,22 @@ void draw_bars(void)
glPopMatrix();
}
+//-- Create -------------------------------------------------------------------
+// Called on load. Addon should fully initalize or return error status
+//-----------------------------------------------------------------------------
+ADDON_STATUS Create(void* hdl, void* props)
+{
+ if (!props)
+ return STATUS_UNKNOWN;
+
+ return STATUS_NEED_SETTINGS;
+}
+
//-- Render -------------------------------------------------------------------
// Called once per frame. Do all rendering here.
//-----------------------------------------------------------------------------
extern "C" void Render()
{
- bool configured = true; //FALSE;
-
glDisable(GL_BLEND);
glMatrixMode(GL_PROJECTION);
glPushMatrix();
@@ -183,22 +164,19 @@ extern "C" void Render()
glDepthFunc(GL_LESS);
glPolygonMode(GL_FRONT, GL_FILL);
//glPolygonMode(GL_BACK, GL_FILL);
- if(configured)
- {
- x_angle += x_speed;
- if(x_angle >= 360.0)
- x_angle -= 360.0;
+ x_angle += x_speed;
+ if(x_angle >= 360.0)
+ x_angle -= 360.0;
- y_angle += y_speed;
- if(y_angle >= 360.0)
- y_angle -= 360.0;
+ y_angle += y_speed;
+ if(y_angle >= 360.0)
+ y_angle -= 360.0;
- z_angle += z_speed;
- if(z_angle >= 360.0)
- z_angle -= 360.0;
+ z_angle += z_speed;
+ if(z_angle >= 360.0)
+ z_angle -= 360.0;
- draw_bars();
- }
+ draw_bars();
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
@@ -233,7 +211,7 @@ extern "C" void Stop()
}
-extern "C" void AudioData(short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength)
+extern "C" void AudioData(const short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength)
{
int i,c;
int y=0;
@@ -281,10 +259,18 @@ extern "C" void GetInfo(VIS_INFO* pInfo)
}
+//-- GetSubModules ------------------------------------------------------------
+// Return any sub modules supported by this vis
+//-----------------------------------------------------------------------------
+extern "C" unsigned int GetSubModules(char ***names)
+{
+ return 0; // this vis supports 0 sub modules
+}
+
//-- OnAction -----------------------------------------------------------------
// Handle XBMC actions such as next preset, lock preset, album art changed etc
//-----------------------------------------------------------------------------
-extern "C" bool OnAction(long flags, void *param)
+extern "C" bool OnAction(long flags, const void *param)
{
bool ret = false;
return ret;
@@ -293,111 +279,154 @@ extern "C" bool OnAction(long flags, void *param)
//-- GetPresets ---------------------------------------------------------------
// Return a list of presets to XBMC for display
//-----------------------------------------------------------------------------
-extern "C" void GetPresets(char ***pPresets, int *currentPreset, int *numPresets, bool *locked)
+extern "C" unsigned int GetPresets(char ***presets)
{
+ return 0;
+}
+
+//-- GetPreset ----------------------------------------------------------------
+// Return the index of the current playing preset
+//-----------------------------------------------------------------------------
+extern "C" unsigned GetPreset()
+{
+ return 0;
+}
+
+//-- IsLocked -----------------------------------------------------------------
+// Returns true if this add-on use settings
+//-----------------------------------------------------------------------------
+extern "C" bool IsLocked()
+{
+ return false;
+}
+//-- Remove -------------------------------------------------------------------
+// Do everything before unload of this add-on
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" void Remove()
+{
+}
+
+//-- HasSettings --------------------------------------------------------------
+// Returns true if this add-on use settings
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" bool HasSettings()
+{
+ return true;
+}
+
+//-- GetStatus ---------------------------------------------------------------
+// Returns the current Status of this visualisation
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" ADDON_STATUS GetStatus()
+{
+ return STATUS_OK;
}
//-- GetSettings --------------------------------------------------------------
// Return the settings for XBMC to display
+// !!! Add-on master function !!!
//-----------------------------------------------------------------------------
-extern "C" unsigned int GetSettings(StructSetting*** sSet)
-{
- m_uiVisElements = VisUtils::VecToStruct(g_vecSettings, &m_structSettings);
- *sSet = m_structSettings;
- return m_uiVisElements;
+extern "C" unsigned int GetSettings(StructSetting ***sSet)
+{
+ return 0;
}
+//-- FreeSettings --------------------------------------------------------------
+// Free the settings struct passed from XBMC
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+
extern "C" void FreeSettings()
{
- VisUtils::FreeStruct(m_uiVisElements, &m_structSettings);
}
-//-- UpdateSetting ------------------------------------------------------------
-// Handle setting change request from XBMC
+//-- SetSetting ---------------------------------------------------------------
+// Set a specific Setting value (called from XBMC)
+// !!! Add-on master function !!!
//-----------------------------------------------------------------------------
-extern "C" void UpdateSetting(int num, StructSetting*** sSet)
+extern "C" ADDON_STATUS SetSetting(const char *strSetting, const void* value)
{
- VisUtils::StructToVec(m_uiVisElements, sSet, &g_vecSettings);
-
- if ( (int)g_vecSettings.size() <= num || num < 0 )
- return;
+ if (!strSetting || !value)
+ return STATUS_UNKNOWN;
- if (strcmp(g_vecSettings[num].name, "Size")==0)
+ if (strcmp(strSetting, "mode")==0)
{
- switch (g_vecSettings[num].current)
+ switch (*(int*) value)
+ {
+ case 1:
+ g_mode = GL_LINE;
+ break;
+
+ case 2:
+ g_mode = GL_POINT;
+ break;
+
+ case 0:
+ default:
+ g_mode = GL_FILL;
+ break;
+ }
+ return STATUS_OK;
+ }
+ else if (strcmp(strSetting, "size")==0)
+ {
+ switch (*(int*) value)
{
- case 0:
- scale = 1.0 / log(256.0);
- break;
-
case 1:
- scale = 2.0 / log(256.0);
+ scale = 2.f / log(256.f);
break;
case 2:
- scale = 3.0 / log(256.0);
+ scale = 3.f / log(256.f);
break;
case 3:
- scale = 0.5 / log(256.0);
+ scale = 0.5f / log(256.f);
break;
case 4:
- scale = 0.33 / log(256.0);
+ scale = 0.33f / log(256.f);
+ break;
+
+ case 0:
+ default:
+ scale = 1.f / log(256.f);
break;
}
+ return STATUS_OK;
}
-
- if (strcmp(g_vecSettings[num].name, "Speed")==0)
+ else if (strcmp(strSetting, "speed")==0)
{
- switch (g_vecSettings[num].current)
+ switch (*(int*) value)
{
- case 0:
- hSpeed = 0.05;
- break;
-
case 1:
- hSpeed = 0.025;
+ hSpeed = 0.025f;
break;
case 2:
- hSpeed = 0.0125;
+ hSpeed = 0.0125f;
break;
case 3:
- hSpeed = 0.10;
+ hSpeed = 0.1f;
break;
case 4:
- hSpeed = 0.20;
+ hSpeed = 0.2f;
break;
- }
- }
- if (strcmp(g_vecSettings[num].name, "Mode")==0)
- {
- switch (g_vecSettings[num].current)
- {
case 0:
- g_mode = GL_FILL;
- break;
-
- case 1:
- g_mode = GL_LINE;
- break;
-
- case 2:
- g_mode = GL_POINT;
+ default:
+ hSpeed = 0.05f;
break;
}
+ return STATUS_OK;
}
-}
-//-- GetSubModules ------------------------------------------------------------
-// Return any sub modules supported by this vis
-//-----------------------------------------------------------------------------
-extern "C" int GetSubModules(char ***names, char ***paths)
-{
- return 0; // this vis supports 0 sub modules
+ return STATUS_UNKNOWN;
}
+
diff --git a/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.vcproj b/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.vcproj
index d2325d6469..b304b54a52 100644
--- a/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.vcproj
+++ b/xbmc/visualizations/OpenGLSpectrum/opengl_spectrum.vcproj
@@ -1,142 +1,211 @@
-<?xml version="1.0" encoding="Windows-1252"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="7.10"
- Name="opengl_spectrum"
- ProjectGUID="{0D91724A-E6F6-4708-AF47-9F88BBE2114B}"
- Keyword="Win32Proj">
- <Platforms>
- <Platform
- Name="Win32"/>
- </Platforms>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="2"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- Optimization="0"
- PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;OPENGL_SPEKTRUM_EXPORTS; HAS_SDL_OPENGL;HAS_SDL;_WIN32PC"
- MinimalRebuild="TRUE"
- BasicRuntimeChecks="3"
- RuntimeLibrary="1"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="4"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="opengl32.lib"
- OutputFile="$(OutDir)/opengl_spectrum.vis"
- LinkIncremental="2"
- GenerateDebugInformation="TRUE"
- ProgramDatabaseFile="$(OutDir)/opengl_spektrum.pdb"
- SubSystem="2"
- ImportLibrary="$(OutDir)/opengl_spektrum.lib"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCXMLDataGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- <Tool
- Name="VCManagedWrapperGeneratorTool"/>
- <Tool
- Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="2"
- CharacterSet="2">
- <Tool
- Name="VCCLCompilerTool"
- PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;HAS_SDL_OPENGL;HAS_SDL;_WIN32PC"
- RuntimeLibrary="0"
- UsePrecompiledHeader="0"
- WarningLevel="3"
- Detect64BitPortabilityProblems="TRUE"
- DebugInformationFormat="3"/>
- <Tool
- Name="VCCustomBuildTool"/>
- <Tool
- Name="VCLinkerTool"
- AdditionalDependencies="opengl32.lib winmm.lib ws2_32.lib"
- OutputFile="$(OutDir)/opengl_spectrum.vis"
- LinkIncremental="1"
- GenerateDebugInformation="FALSE"
- SubSystem="2"
- OptimizeReferences="2"
- EnableCOMDATFolding="2"
- ImportLibrary="$(OutDir)/opengl_spektrum.lib"
- TargetMachine="1"/>
- <Tool
- Name="VCMIDLTool"/>
- <Tool
- Name="VCPostBuildEventTool"/>
- <Tool
- Name="VCPreBuildEventTool"/>
- <Tool
- Name="VCPreLinkEventTool"/>
- <Tool
- Name="VCResourceCompilerTool"/>
- <Tool
- Name="VCWebServiceProxyGeneratorTool"/>
- <Tool
- Name="VCXMLDataGeneratorTool"/>
- <Tool
- Name="VCWebDeploymentTool"/>
- <Tool
- Name="VCManagedWrapperGeneratorTool"/>
- <Tool
- Name="VCAuxiliaryManagedWrapperGeneratorTool"/>
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Quelldateien"
- Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}">
- <File
- RelativePath=".\opengl_spectrum.cpp">
- </File>
- </Filter>
- <Filter
- Name="Headerdateien"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}">
- <File
- RelativePath=".\opengl_spectrum.h">
- </File>
- </Filter>
- <Filter
- Name="Ressourcendateien"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}">
- </Filter>
- <File
- RelativePath=".\ReadMe.txt">
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="opengl_spectrum"
+ ProjectGUID="{0D91724A-E6F6-4708-AF47-9F88BBE2114B}"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="131072"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="Debug"
+ IntermediateDirectory="Debug"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_USRDLL;OPENGL_SPEKTRUM_EXPORTS; HAS_SDL_OPENGL;HAS_SDL;_WIN32PC"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="1"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="opengl32.lib"
+ OutputFile="../../../addons/visualisations/GLSpectrum/opengl_spectrum_win32.vis"
+ LinkIncremental="2"
+ GenerateDebugInformation="true"
+ ProgramDatabaseFile="$(OutDir)/opengl_spektrum.pdb"
+ SubSystem="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(OutDir)/opengl_spektrum.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="Release"
+ IntermediateDirectory="Release"
+ ConfigurationType="2"
+ InheritedPropertySheets="$(VCInstallDir)VCProjectDefaults\UpgradeFromVC71.vsprops"
+ CharacterSet="2"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;HAS_SDL_OPENGL;HAS_SDL;_WIN32PC"
+ RuntimeLibrary="0"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="opengl32.lib winmm.lib ws2_32.lib"
+ OutputFile="$(OutDir)/opengl_spectrum.vis"
+ LinkIncremental="1"
+ GenerateDebugInformation="false"
+ SubSystem="2"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ RandomizedBaseAddress="1"
+ DataExecutionPrevention="0"
+ ImportLibrary="$(OutDir)/opengl_spektrum.lib"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Quelldateien"
+ Filter="cpp;c;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\opengl_spectrum.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Headerdateien"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath=".\opengl_spectrum.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Ressourcendateien"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/xbmc/visualizations/Visualisation.cpp b/xbmc/visualizations/Visualisation.cpp
index 655bbea9fc..39c0270688 100644
--- a/xbmc/visualizations/Visualisation.cpp
+++ b/xbmc/visualizations/Visualisation.cpp
@@ -19,12 +19,10 @@
*
*/
#include "system.h"
-// Visualisation.cpp: implementation of the CVisualisation class.
-//
-//////////////////////////////////////////////////////////////////////
-
#include "Visualisation.h"
-#include "visualizations/VisualisationTypes.h"
+#include "fft.h"
+#include "utils/GUIInfoManager.h"
+#include "Application.h"
#include "MusicInfoTag.h"
#include "Settings.h"
#include "WindowingFactory.h"
@@ -37,49 +35,112 @@
using namespace std;
using namespace MUSIC_INFO;
+using namespace ADDON;
-//////////////////////////////////////////////////////////////////////
-// Construction/Destruction
-//////////////////////////////////////////////////////////////////////
+CAudioBuffer::CAudioBuffer(int iSize)
+{
+ m_iLen = iSize;
+ m_pBuffer = new short[iSize];
+}
-CVisualisation::CVisualisation(struct Visualisation* pVisz, DllVisualisation* pDll,
- const CStdString& strVisualisationName,
- const CStdString& strSubModuleName)
- : m_pVisz(pVisz)
- , m_pDll(pDll)
- , m_strVisualisationName(strVisualisationName)
- , m_strSubModuleName(strSubModuleName)
-{}
+CAudioBuffer::~CAudioBuffer()
+{
+ delete [] m_pBuffer;
+}
-CVisualisation::~CVisualisation()
+const short* CAudioBuffer::Get() const
{
+ return m_pBuffer;
}
-void CVisualisation::Create(int posx, int posy, int width, int height)
+void CAudioBuffer::Set(const unsigned char* psBuffer, int iSize, int iBitsPerSample)
{
- // allow vis. to create internal things needed
- // pass it the location,width,height
- // and the name of the visualisation.
- char szTmp[129];
- sprintf(szTmp, "create:%ix%i at %ix%i %s\n", width, height, posx, posy, m_strVisualisationName.c_str());
- OutputDebugString(szTmp);
-
- float pixelRatio = g_settings.m_ResInfo[g_graphicsContext.GetVideoResolution()].fPixelRatio;
-#ifdef HAS_DX
- // TODO LINUX this is obviously not good, but until we have visualization sorted out, this will have to do
- m_pVisz->Create (g_Windowing.Get3DDevice(), posx, posy, width, height, m_strVisualisationName.c_str(),
- pixelRatio, m_strSubModuleName=="" ? NULL : m_strSubModuleName.c_str() );
-#else
- m_pVisz->Create (0, posx, posy, width, height, m_strVisualisationName.c_str(), pixelRatio,
- m_strSubModuleName=="" ? NULL : m_strSubModuleName.c_str() );
-#endif
+ if (iSize<0)
+ {
+ return;
+ }
+
+ if (iBitsPerSample == 16)
+ {
+ iSize /= 2;
+ for (int i = 0; i < iSize && i < m_iLen; i++)
+ { // 16 bit -> convert to short directly
+ m_pBuffer[i] = ((short *)psBuffer)[i];
+ }
+ }
+ else if (iBitsPerSample == 8)
+ {
+ for (int i = 0; i < iSize && i < m_iLen; i++)
+ { // 8 bit -> convert to signed short by multiplying by 256
+ m_pBuffer[i] = ((short)((char *)psBuffer)[i]) << 8;
+ }
+ }
+ else // assume 24 bit data
+ {
+ iSize /= 3;
+ for (int i = 0; i < iSize && i < m_iLen; i++)
+ { // 24 bit -> ignore least significant byte and convert to signed short
+ m_pBuffer[i] = (((int)psBuffer[3 * i + 1]) << 0) + (((int)((char *)psBuffer)[3 * i + 2]) << 8);
+ }
+ }
+ for (int i = iSize; i < m_iLen;++i) m_pBuffer[i] = 0;
+}
+
+bool CVisualisation::Create(int x, int y, int w, int h)
+{
+ m_pInfo = new VIS_PROPS;
+ m_pInfo->x = x;
+ m_pInfo->y = y;
+ m_pInfo->width = w;
+ m_pInfo->height = h;
+ m_pInfo->pixelRatio = g_settings.m_ResInfo[g_graphicsContext.GetVideoResolution()].fPixelRatio;
+
+ m_pInfo->name = strdup(Name().c_str());
+ m_pInfo->presets = strdup(_P(Path()).c_str());
+ m_pInfo->profile = strdup(_P(Profile()).c_str());
+
+ if (CAddonDll<DllVisualisation, Visualisation, VIS_PROPS>::Create())
+ {
+ // Start the visualisation
+ CStdString strFile = CUtil::GetFileName(g_application.CurrentFile());
+ CLog::Log(LOGDEBUG, "Visualisation::Start()\n");
+ try
+ {
+ m_pStruct->Start(m_iChannels, m_iSamplesPerSec, m_iBitsPerSample, strFile);
+ }
+ catch (std::exception e)
+ {
+ HandleException(e, "m_pStruct->Start() (CVisualisation::Create)");
+ return false;
+ }
+
+ GetPresets();
+ GetSubModules();
+ CreateBuffers();
+
+ if (g_application.m_pPlayer)
+ g_application.m_pPlayer->RegisterAudioCallback(this);
+
+ return true;
+ }
+ return false;
}
void CVisualisation::Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, const CStdString strSongName)
{
// notify visz. that new song has been started
// pass it the nr of audio channels, sample rate, bits/sample and offcourse the songname
- m_pVisz->Start(iChannels, iSamplesPerSec, iBitsPerSample, strSongName.c_str());
+ if (Initialized())
+ {
+ try
+ {
+ m_pStruct->Start(iChannels, iSamplesPerSec, iBitsPerSample, strSongName.c_str());
+ }
+ catch (std::exception e)
+ {
+ HandleException(e, "m_pStruct->Start (CVisualisation::Start)");
+ }
+ }
}
void CVisualisation::AudioData(const short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength)
@@ -89,235 +150,333 @@ void CVisualisation::AudioData(const short* pAudioData, int iAudioDataLength, fl
// iAudioDataLength = length of audiodata array
// pFreqData = fft-ed audio data
// iFreqDataLength = length of pFreqData
- m_pVisz->AudioData(const_cast<short*>(pAudioData), iAudioDataLength, pFreqData, iFreqDataLength);
+ if (Initialized())
+ {
+ try
+ {
+ m_pStruct->AudioData(pAudioData, iAudioDataLength, pFreqData, iFreqDataLength);
+ }
+ catch (std::exception e)
+ {
+ HandleException(e, "m_pStruct->AudioData (CVisualisation::AudioData)");
+ }
+ }
}
void CVisualisation::Render()
{
// ask visz. to render itself
g_graphicsContext.BeginPaint();
- m_pVisz->Render();
+ if (Initialized())
+ {
+ try
+ {
+ m_pStruct->Render();
+ }
+ catch (std::exception e)
+ {
+ HandleException(e, "m_pStruct->Render (CVisualisation::Render)");
+ }
+ }
g_graphicsContext.EndPaint();
}
void CVisualisation::Stop()
{
- // ask visz. to cleanup
- m_pVisz->Stop();
+ if (g_application.m_pPlayer) g_application.m_pPlayer->UnRegisterAudioCallback();
+ if (Initialized())
+ {
+ try
+ {
+ m_pStruct->Stop();
+ }
+ catch (std::exception e)
+ {
+ HandleException(e, "m_pStruct->Stop (CVisualisation::Stop)");
+ }
+ }
}
-
void CVisualisation::GetInfo(VIS_INFO *info)
{
- // get info from vis
- m_pVisz->GetInfo(info);
+ if (Initialized())
+ {
+ try
+ {
+ m_pStruct->GetInfo(info);
+ }
+ catch (std::exception e)
+ {
+ HandleException(e, "m_pStruct->GetInfo (CVisualisation::GetInfo)");
+ }
+ }
}
bool CVisualisation::OnAction(VIS_ACTION action, void *param)
{
+ if (!Initialized())
+ return false;
+
// see if vis wants to handle the input
// returns false if vis doesnt want the input
// returns true if vis handled the input
- if (action != VIS_ACTION_NONE && m_pVisz->OnAction)
+ try
{
- // if this is a VIS_ACTION_UPDATE_TRACK action, copy relevant
- // tags from CMusicInfoTag to VisTag
- if ( action == VIS_ACTION_UPDATE_TRACK && param )
+ if (action != VIS_ACTION_NONE && m_pStruct->OnAction)
{
- const CMusicInfoTag* tag = (const CMusicInfoTag*)param;
- VisTrack track;
-
- track.title = tag->GetTitle().c_str();
- track.artist = tag->GetArtist().c_str();
- track.album = tag->GetAlbum().c_str();
- track.albumArtist = tag->GetAlbumArtist().c_str();
- track.genre = tag->GetGenre().c_str();
- track.comment = tag->GetComment().c_str();
- track.lyrics = tag->GetLyrics().c_str();
- track.trackNumber = tag->GetTrackNumber();
- track.discNumber = tag->GetDiscNumber();
- track.duration = tag->GetDuration();
- track.year = tag->GetYear();
- track.rating = tag->GetRating();
-
- return m_pVisz->OnAction((int)action, (void*)(&track));
+ // if this is a VIS_ACTION_UPDATE_TRACK action, copy relevant
+ // tags from CMusicInfoTag to VisTag
+ if ( action == VIS_ACTION_UPDATE_TRACK && param )
+ {
+ const CMusicInfoTag* tag = (const CMusicInfoTag*)param;
+ VisTrack track;
+ track.title = tag->GetTitle().c_str();
+ track.artist = tag->GetArtist().c_str();
+ track.album = tag->GetAlbum().c_str();
+ track.albumArtist = tag->GetAlbumArtist().c_str();
+ track.genre = tag->GetGenre().c_str();
+ track.comment = tag->GetComment().c_str();
+ track.lyrics = tag->GetLyrics().c_str();
+ track.trackNumber = tag->GetTrackNumber();
+ track.discNumber = tag->GetDiscNumber();
+ track.duration = tag->GetDuration();
+ track.year = tag->GetYear();
+ track.rating = tag->GetRating();
+
+ return m_pStruct->OnAction(action, &track);
+ }
+ return m_pStruct->OnAction((int)action, param);
}
- return m_pVisz->OnAction((int)action, param);
+ }
+ catch (std::exception e)
+ {
+ HandleException(e, "m_pStruct->OnAction (CVisualisation::OnAction)");
}
return false;
}
-
-void CVisualisation::GetSettings(vector<VisSetting> **vecSettings)
+void CVisualisation::OnInitialize(int iChannels, int iSamplesPerSec, int iBitsPerSample)
{
- if (vecSettings) *vecSettings = NULL;
- if (m_pVisz->GetSettings)
- {
- unsigned int iEntries;
- StructSetting** sSet;
- iEntries = m_pVisz->GetSettings(&sSet);
- VisUtils::StructToVec(iEntries, &sSet, &m_vecSettings);
- if(m_pVisz->FreeSettings)
- m_pVisz->FreeSettings();
- }
- *vecSettings = &m_vecSettings;
+ if (!m_pStruct)
+ return ;
+ CLog::Log(LOGDEBUG, "OnInitialize() started");
+
+ m_iChannels = iChannels;
+ m_iSamplesPerSec = iSamplesPerSec;
+ m_iBitsPerSample = iBitsPerSample;
+ UpdateTrack();
+
+ CLog::Log(LOGDEBUG, "OnInitialize() done");
}
-void CVisualisation::UpdateSetting(int num, vector<VisSetting> **vecSettings)
+void CVisualisation::OnAudioData(const unsigned char* pAudioData, int iAudioDataLength)
{
- if (m_pVisz->UpdateSetting)
+ if (!m_pStruct)
+ return ;
+ if (Initialized())
+
+ // FIXME: iAudioDataLength should never be less than 0
+ if (iAudioDataLength<0)
+ return;
+
+ // Save our audio data in the buffers
+ auto_ptr<CAudioBuffer> pBuffer ( new CAudioBuffer(2*AUDIO_BUFFER_SIZE) );
+ pBuffer->Set(pAudioData, iAudioDataLength, m_iBitsPerSample);
+ m_vecBuffers.push_back( pBuffer.release() );
+
+ if ( (int)m_vecBuffers.size() < m_iNumBuffers) return ;
+
+ auto_ptr<CAudioBuffer> ptrAudioBuffer ( m_vecBuffers.front() );
+ m_vecBuffers.pop_front();
+ // Fourier transform the data if the vis wants it...
+ if (m_bWantsFreq)
{
- unsigned int iEntries;
- StructSetting** sSet;
- iEntries = VisUtils::VecToStruct(m_vecSettings, &sSet);
- m_pVisz->UpdateSetting(num, &sSet);
- VisUtils::FreeStruct(iEntries, &sSet);
+ // Convert to floats
+ const short* psAudioData = ptrAudioBuffer->Get();
+ for (int i = 0; i < 2*AUDIO_BUFFER_SIZE; i++)
+ {
+ m_fFreq[i] = (float)psAudioData[i];
+ }
+
+ // FFT the data
+ twochanwithwindow(m_fFreq, AUDIO_BUFFER_SIZE);
+
+ // Normalize the data
+ float fMinData = (float)AUDIO_BUFFER_SIZE * AUDIO_BUFFER_SIZE * 3 / 8 * 0.5 * 0.5; // 3/8 for the Hann window, 0.5 as minimum amplitude
+ float fInvMinData = 1.0f/fMinData;
+ for (int i = 0; i < AUDIO_BUFFER_SIZE + 2; i++)
+ {
+ m_fFreq[i] *= fInvMinData;
+ }
+
+ // Transfer data to our visualisation
+ AudioData(ptrAudioBuffer->Get(), AUDIO_BUFFER_SIZE, m_fFreq, AUDIO_BUFFER_SIZE);
+ }
+ else
+ { // Transfer data to our visualisation
+ AudioData(ptrAudioBuffer->Get(), AUDIO_BUFFER_SIZE, NULL, 0);
}
+ return ;
}
-void CVisualisation::GetPresets(char ***pPresets, int *currentPreset, int *numPresets, bool *locked)
+void CVisualisation::CreateBuffers()
{
- if (m_pVisz->GetPresets)
- m_pVisz->GetPresets(pPresets, currentPreset, numPresets, locked);
+ ClearBuffers();
+
+ // Get the number of buffers from the current vis
+ VIS_INFO info;
+ m_pStruct->GetInfo(&info);
+ m_iNumBuffers = info.iSyncDelay + 1;
+ m_bWantsFreq = (info.bWantsFreq != 0);
+ if (m_iNumBuffers > MAX_AUDIO_BUFFERS)
+ m_iNumBuffers = MAX_AUDIO_BUFFERS;
+ if (m_iNumBuffers < 1)
+ m_iNumBuffers = 1;
}
-int CVisualisation::GetSubModules(map<string, string>& subModules)
+void CVisualisation::ClearBuffers()
{
- if (m_pVisz->GetSubModules)
+ m_bWantsFreq = false;
+ m_iNumBuffers = 0;
+
+ while (m_vecBuffers.size() > 0)
{
- char **names, **paths;
- int count = m_pVisz->GetSubModules(&names, &paths);
- if ( count > 0 )
- {
- while ( count > 0 )
- {
- count--;
- subModules[ string( names[count] ) ] = string( paths[count] );
- free( names[count] );
- free( paths[count] );
- }
- free( names );
- free( paths );
- return subModules.size();
- }
+ CAudioBuffer* pAudioBuffer = m_vecBuffers.front();
+ delete pAudioBuffer;
+ m_vecBuffers.pop_front();
+ }
+ for (int j = 0; j < AUDIO_BUFFER_SIZE*2; j++)
+ {
+ m_fFreq[j] = 0.0f;
}
- return 0;
}
-void CVisualisation::GetCurrentPreset(char **pPreset, bool *locked)
+bool CVisualisation::UpdateTrack()
{
- if (pPreset && locked && m_pVisz->GetPresets)
+ bool handled;
+ if (Initialized())
{
- char **presets = NULL;
- int currentPreset = 0;
- int numPresets = 0;
- *locked = false;
- m_pVisz->GetPresets(&presets, &currentPreset, &numPresets, locked);
- if (presets && currentPreset < numPresets)
- *pPreset = presets[currentPreset];
+ // get the current album art filename
+ m_AlbumThumb = _P(g_infoManager.GetImage(MUSICPLAYER_COVER, WINDOW_INVALID));
+
+ // get the current track tag
+ const CMusicInfoTag* tag = g_infoManager.GetCurrentSongTag();
+
+ if (m_AlbumThumb == "DefaultAlbumCover.png")
+ m_AlbumThumb = "";
+ else
+ CLog::Log(LOGDEBUG,"Updating visualisation albumart: %s", m_AlbumThumb.c_str());
+
+ // inform the visualisation of the current album art
+ if ( m_pStruct->OnAction( VIS_ACTION_UPDATE_ALBUMART,
+ (void*)( m_AlbumThumb.c_str() ) ) )
+ handled = true;
+
+ // inform the visualisation of the current track's tag information
+ if ( tag && m_pStruct->OnAction( VIS_ACTION_UPDATE_TRACK,
+ (void*)tag ) )
+ handled = true;
}
+ return handled;
}
-bool CVisualisation::IsLocked()
+bool CVisualisation::GetPresetList(std::vector<CStdString> &vecpresets)
{
- char *preset;
- bool locked = false;
- GetCurrentPreset(&preset, &locked);
- return locked;
+ vecpresets = m_presets;
+ return !m_presets.empty();
}
-char *CVisualisation::GetPreset()
+bool CVisualisation::GetPresets()
{
- char *preset = NULL;
- bool locked = false;
- GetCurrentPreset(&preset, &locked);
- return preset;
+ m_presets.clear();
+ char **presets = NULL;
+ unsigned int entries = 0;
+ try
+ {
+ entries = m_pStruct->GetPresets(&presets);
+ }
+ catch (std::exception e)
+ {
+ HandleException(e, "m_pStruct->OnAction (CVisualisation::GetPresets)");
+ return false;
+ }
+ if (presets && entries > 0)
+ {
+ for (unsigned i=0; i < entries; i++)
+ {
+ if (presets[i])
+ {
+ m_presets.push_back(presets[i]);
+ }
+ }
+ }
+ return (!m_presets.empty());
}
-CStdString CVisualisation::GetFriendlyName(const char* strVisz,
- const char* strSubModule)
+bool CVisualisation::GetSubModuleList(std::vector<CStdString> &vecmodules)
{
- // should be of the format "moduleName (visName)"
- return CStdString(strSubModule) + " (" + CStdString(strVisz) + ")";
+ vecmodules = m_submodules;
+ return !m_submodules.empty();
}
-CStdString CVisualisation::GetFriendlyName(const char* combinedName)
+bool CVisualisation::GetSubModules()
{
- CStdString moduleName;
- CStdString visName = combinedName;
- int colonPos = visName.ReverseFind(":");
-
- if ( colonPos > 0 )
+ m_submodules.clear();
+ char **modules = NULL;
+ unsigned int entries = 0;
+ try
{
- visName = visName.Mid( colonPos + 1 );
- moduleName = visName.Mid( 0, colonPos - 5 ); // remove .mvis
-
- // should be of the format "moduleName (visName)"
- return moduleName + " (" + visName + ")";
+ entries = m_pStruct->GetSubModules(&modules);
}
- return visName.Left( visName.size() - 4 );
+ catch (...)
+ {
+ CLog::Log(LOGERROR, "Exception in Visualisation::GetSubModules()");
+ return false;
+ }
+ if (modules && entries > 0)
+ {
+ for (unsigned i=0; i < entries; i++)
+ {
+ if (modules[i])
+ {
+ m_submodules.push_back(modules[i]);
+ }
+ }
+ }
+ return (!m_submodules.empty());
}
-CStdString CVisualisation::GetCombinedName(const char* strVisz,
- const char* strSubModule)
+CStdString CVisualisation::GetFriendlyName(const CStdString& strVisz,
+ const CStdString& strSubModule)
{
- // should be of the format "visName.mvis:moduleName"
- return CStdString(strVisz) + ":" + CStdString(strSubModule);
+ // should be of the format "moduleName (visName)"
+ return CStdString(strSubModule + " (" + strVisz + ")");
}
-CStdString CVisualisation::GetCombinedName(const char* friendlyName)
+bool CVisualisation::IsLocked()
{
- CStdString moduleName;
- CStdString fName = friendlyName;
-
- // convert from "module name (vis name)" to "vis name.mvis:module name"
- int startPos = fName.ReverseFind(" (");
+ return false;
+}
- if ( startPos > 0 )
+unsigned CVisualisation::GetPreset()
+{
+ unsigned index = 0;
+ try
+ {
+ index = m_pStruct->GetPreset();
+ }
+ catch(...)
{
- int endPos = fName.ReverseFind(")");
- CStdString moduleName = fName.Left( startPos );
- CStdString visName = fName.Mid( startPos+2, endPos-startPos-2 );
- return visName + ".mvis" + ":" + moduleName;
+ return 0;
}
- return fName + ".vis";
+ return index;
}
-bool CVisualisation::IsValidVisualisation(const CStdString& strVisz)
+CStdString CVisualisation::GetPresetName()
{
- bool bRet = true;
- CStdString strExtension;
-
- if(strVisz.Equals("None"))
- return true;
-
- CUtil::GetExtension(strVisz, strExtension);
- if (strExtension == ".mvis")
- return true; // assume multivis are OK
-
- if (strExtension != ".vis")
- return false;
-
-#ifdef _LINUX
- CStdString visPath(strVisz);
- if(visPath.Find("/") == -1)
- {
- visPath.Format("%s%s", "special://xbmc/visualisations/", strVisz);
- if(!XFILE::CFile::Exists(visPath))
- visPath.Format("%s%s", "special://home/visualisations/", strVisz);
- }
- void *handle = dlopen( _P(visPath).c_str(), RTLD_LAZY );
- if (!handle)
- bRet = false;
+ if (!m_presets.empty())
+ return m_presets[GetPreset()];
else
- dlclose(handle);
-#elif defined(HAS_DX)
- if(strVisz.Right(11).CompareNoCase("win32dx.vis") != 0)
- bRet = false;
-#elif defined(_WIN32)
- if(strVisz.Right(9).CompareNoCase("win32.vis") != 0)
- bRet = false;
-#endif
-
- return bRet;
+ return "";
}
+
diff --git a/xbmc/visualizations/Visualisation.h b/xbmc/visualizations/Visualisation.h
index ab844ffc43..b53aa535e8 100644
--- a/xbmc/visualizations/Visualisation.h
+++ b/xbmc/visualizations/Visualisation.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2008 Team XBMC
+ * Copyright (C) 2005-2009 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
@@ -18,70 +18,90 @@
* http://www.gnu.org/copyleft/gpl.html
*
*/
-// Visualisation.h: interface for the CVisualisation class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_Visualisation_H__99B9A52D_ED09_4540_A887_162A68217A31__INCLUDED_)
-#define AFX_Visualisation_H__99B9A52D_ED09_4540_A887_162A68217A31__INCLUDED_
-
-#if _MSC_VER > 1000
#pragma once
-#endif // _MSC_VER > 1000
+
#include "Key.h"
#include "DllVisualisation.h"
+#include "utils/AddonDll.h"
+#include "cores/IAudioCallback.h"
#include <map>
+#include <list>
#include <memory>
-class CVisualisation
+#define AUDIO_BUFFER_SIZE 512 // MUST BE A POWER OF 2!!!
+#define MAX_AUDIO_BUFFERS 16
+
+class CCriticalSection;
+
+class CAudioBuffer
{
public:
- enum VIS_ACTION { VIS_ACTION_NONE = 0,
- VIS_ACTION_NEXT_PRESET,
- VIS_ACTION_PREV_PRESET,
- VIS_ACTION_LOAD_PRESET,
- VIS_ACTION_RANDOM_PRESET,
- VIS_ACTION_LOCK_PRESET,
- VIS_ACTION_RATE_PRESET_PLUS,
- VIS_ACTION_RATE_PRESET_MINUS,
- VIS_ACTION_UPDATE_ALBUMART,
- VIS_ACTION_UPDATE_TRACK
- };
- CVisualisation(struct Visualisation* pVisz, DllVisualisation* pDll,
- const CStdString& strVisualisationName, const CStdString& strSubModuleName);
- ~CVisualisation();
+ CAudioBuffer(int iSize);
+ virtual ~CAudioBuffer();
+ const short* Get() const;
+ void Set(const unsigned char* psBuffer, int iSize, int iBitsPerSample);
+private:
+ CAudioBuffer();
+ short* m_pBuffer;
+ int m_iLen;
+};
- void Create(int posx, int posy, int width, int height);
- void Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, const CStdString strSongName);
- void AudioData(const short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength);
- void Render();
- void Stop();
- void GetInfo(VIS_INFO *info);
- bool OnAction(VIS_ACTION action, void *param = NULL);
- void GetSettings(std::vector<VisSetting> **vecSettings);
- void UpdateSetting(int num, std::vector<VisSetting> **vecSettings);
- void GetPresets(char ***pPresets, int *currentPreset, int *numPresets, bool *locked);
- void GetCurrentPreset(char **pPreset, bool *locked);
- int GetSubModules(std::map<std::string, std::string>& subModules);
- bool IsLocked();
- char *GetPreset();
+namespace ADDON
+{
+ class CVisualisation : public CAddonDll<DllVisualisation, Visualisation, VIS_PROPS>
+ , public IAudioCallback
+ {
+ public:
+ CVisualisation(const ADDON::AddonProps &props) : CAddonDll<DllVisualisation, Visualisation, VIS_PROPS>(props) {}
+ virtual void OnInitialize(int iChannels, int iSamplesPerSec, int iBitsPerSample);
+ virtual void OnAudioData(const unsigned char* pAudioData, int iAudioDataLength);
+ bool Create(int x, int y, int w, int h);
+ void Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, const CStdString strSongName);
+ void AudioData(const short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength);
+ void Render();
+ void Stop();
+ void GetInfo(VIS_INFO *info);
+ bool OnAction(VIS_ACTION action, void *param = NULL);
+ bool UpdateTrack();
+ bool HasSubModules() { return !m_submodules.empty(); }
+ bool IsLocked();
+ unsigned GetPreset();
+ CStdString GetPresetName();
+ bool GetPresetList(std::vector<CStdString>& vecpresets);
+ bool GetSubModuleList(std::vector<CStdString>& vecmodules);
+ static CStdString GetFriendlyName(const CStdString& vis, const CStdString& module);
- // some helper functions
- static CStdString GetFriendlyName(const char* strVisz, const char* strSubModule);
- static CStdString GetFriendlyName(const char* combinedName);
- static CStdString GetCombinedName(const char* strVisz, const char* strSubModule);
- static CStdString GetCombinedName(const char* friendlyName);
- static bool IsValidVisualisation(const CStdString& strVisz);
+ private:
+ void CreateBuffers();
+ void ClearBuffers();
-protected:
- std::auto_ptr<struct Visualisation> m_pVisz;
- std::auto_ptr<DllVisualisation> m_pDll;
- CStdString m_strVisualisationName;
- CStdString m_strSubModuleName;
+ bool GetPresets();
+ bool GetSubModules();
- std::vector<VisSetting> m_vecSettings;
-};
+ // attributes of the viewport we render to
+ int m_xPos;
+ int m_yPos;
+ int m_width;
+ int m_height;
+ // cached preset list
+ std::vector<CStdString> m_presets;
+ // cached submodule list
+ std::vector<CStdString> m_submodules;
+ int m_currentModule;
-#endif // !defined(AFX_Visualisation_H__99B9A52D_ED09_4540_A887_162A68217A31__INCLUDED_)
+ // audio properties
+ int m_iChannels;
+ int m_iSamplesPerSec;
+ int m_iBitsPerSample;
+ std::list<CAudioBuffer*> m_vecBuffers;
+ int m_iNumBuffers; // Number of Audio buffers
+ bool m_bWantsFreq;
+ float m_fFreq[2*AUDIO_BUFFER_SIZE]; // Frequency data
+ bool m_bCalculate_Freq; // True if the vis wants freq data
+
+ // track information
+ CStdString m_AlbumThumb;
+ };
+}
diff --git a/xbmc/visualizations/VisualisationFactory.cpp b/xbmc/visualizations/VisualisationFactory.cpp
deleted file mode 100644
index 39d112ccea..0000000000
--- a/xbmc/visualizations/VisualisationFactory.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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 "system.h"
-#include "VisualisationFactory.h"
-#include "Util.h"
-#include "FileSystem/File.h"
-
-using namespace XFILE;
-
-CVisualisationFactory::CVisualisationFactory()
-{
-
-}
-
-CVisualisationFactory::~CVisualisationFactory()
-{
-
-}
-
-CVisualisation* CVisualisationFactory::LoadVisualisation(const CStdString& strVisz) const
-{
- CStdString nullModule = "";
- return LoadVisualisation( strVisz, nullModule );
-}
-
-CVisualisation* CVisualisationFactory::LoadVisualisation(const CStdString& strVisz,
- const CStdString& strSubModule) const
-{
- // strip of the path & extension to get the name of the visualisation
- // like goom or spectrum
- CStdString strFileName = strVisz;
- CStdString strName = CUtil::GetFileName(strVisz);
-
- // if it's a relative path or just a name, convert to absolute path
- if ( strFileName[1] != ':' && strFileName[0] != '/' )
- {
- // first check home
- strFileName.Format("special://home/visualisations/%s", strName.c_str() );
-
- // if not found, use system
- if ( ! CFile::Exists( strFileName ) )
- strFileName.Format("special://xbmc/visualisations/%s", strName.c_str() );
- }
- strName = strName.Left(strName.ReverseFind('.'));
-
-#ifdef HAS_VISUALISATION
- // load visualisation
- DllVisualisation* pDll = new DllVisualisation;
- pDll->SetFile(strFileName);
- // FIXME: Some Visualisations do not work
- // when their dll is not unloaded immediatly
- pDll->EnableDelayedUnload(false);
- if (!pDll->Load())
- {
- delete pDll;
- return NULL;
- }
-
- struct Visualisation* pVisz = (struct Visualisation*)malloc(sizeof(struct Visualisation));
- ZeroMemory(pVisz, sizeof(struct Visualisation));
- pDll->GetModule(pVisz);
-
- // and pass it to a new instance of CVisualisation() which will hanle the visualisation
- return new CVisualisation(pVisz, pDll, strName, strSubModule);
-#else
- return NULL;
-#endif
-}
diff --git a/xbmc/visualizations/VisualisationTypes.h b/xbmc/visualizations/VisualisationTypes.h
deleted file mode 100644
index ad1146f6db..0000000000
--- a/xbmc/visualizations/VisualisationTypes.h
+++ /dev/null
@@ -1,262 +0,0 @@
-/*
- * 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
- *
- */
-
-/*
- Common data structures shared between XBMC and XBMC's visualisations
- */
-
-#ifndef __VISUALISATION_TYPES_H__
-#define __VISUALISATION_TYPES_H__
-
-#include <vector>
-
-extern "C"
-{
- ////////////////////////////////////////////////////////////////////
- // The VIS_INFO structure to tell XBMC what data you need.
- ////////////////////////////////////////////////////////////////////
- struct VIS_INFO
- {
- bool bWantsFreq;
- int iSyncDelay;
- };
-
- ////////////////////////////////////////////////////////////////////
- // The VisTrack class for track tag information
- ////////////////////////////////////////////////////////////////////
- class VisTrack
- {
- public:
- VisTrack()
- {
- title = artist = album = albumArtist = NULL;
- genre = comment = lyrics = reserved1 = reserved2 = NULL;
- trackNumber = discNumber = duration = year = 0;
- rating = 0;
- reserved3 = reserved4 = 0;
- }
-
- const char *title;
- const char *artist;
- const char *album;
- const char *albumArtist;
- const char *genre;
- const char *comment;
- const char *lyrics;
- const char *reserved1;
- const char *reserved2;
-
- int trackNumber;
- int discNumber;
- int duration;
- int year;
- char rating;
- int reserved3;
- int reserved4;
- };
-
- ////////////////////////////////////////////////////////////////////
- // The VisSetting class for GUI settings for vis.
- ////////////////////////////////////////////////////////////////////
- class VisSetting
- {
- public:
- enum SETTING_TYPE { NONE=0, CHECK, SPIN };
-
- VisSetting(SETTING_TYPE t, const char *label)
- {
- name = NULL;
- if (label)
- {
- name = new char[strlen(label)+1];
- strcpy(name, label);
- }
- current = 0;
- type = t;
- }
-
- VisSetting(const VisSetting &rhs) // copy constructor
- {
- name = NULL;
- if (rhs.name)
- {
- name = new char[strlen(rhs.name)+1];
- strcpy(name, rhs.name);
- }
- current = rhs.current;
- type = rhs.type;
- for (unsigned int i = 0; i < rhs.entry.size(); i++)
- {
- char *lab = new char[strlen(rhs.entry[i]) + 1];
- strcpy(lab, rhs.entry[i]);
- entry.push_back(lab);
- }
- }
-
- ~VisSetting()
- {
- if (name)
- delete[] name;
- for (unsigned int i=0; i < entry.size(); i++)
- delete[] entry[i];
- }
-
- void AddEntry(const char *label)
- {
- if (!label || type != SPIN) return;
- char *lab = new char[strlen(label) + 1];
- strcpy(lab, label);
- entry.push_back(lab);
- }
-
- // data members
- SETTING_TYPE type;
- char* name;
- int current;
- std::vector<const char *> entry;
- };
-
- ////////////////////////////////
- typedef struct
- {
- public:
- int type;
- char* name;
- int current;
- char** entry;
- unsigned int entry_elements;
- } StructSetting;
-
- class VisUtils
- {
- public:
-
- static unsigned int VecToStruct(std::vector<VisSetting> &vecSet, StructSetting*** sSet)
- {
- *sSet = NULL;
- if(vecSet.size() == 0)
- return 0;
-
- unsigned int uiElements=0;
-
- *sSet = (StructSetting**)malloc(vecSet.size()*sizeof(StructSetting*));
- for(unsigned int i=0;i<vecSet.size();i++)
- {
- (*sSet)[i] = NULL;
- (*sSet)[i] = (StructSetting*)malloc(sizeof(StructSetting));
- (*sSet)[i]->name = NULL;
- uiElements++;
-
- if (vecSet[i].name)
- {
- (*sSet)[i]->name = (char*)malloc(strlen(vecSet[i].name)*sizeof(char*)+1);
- strcpy((*sSet)[i]->name, vecSet[i].name);
- (*sSet)[i]->type = vecSet[i].type;
- (*sSet)[i]->current = vecSet[i].current;
- (*sSet)[i]->entry_elements = 0;
- (*sSet)[i]->entry = NULL;
- if(vecSet[i].type == VisSetting::SPIN && vecSet[i].entry.size() > 0)
- {
- (*sSet)[i]->entry = (char**)malloc(vecSet[i].entry.size()*sizeof(char**));
- for(unsigned int j=0;j<vecSet[i].entry.size();j++)
- {
- if(strlen(vecSet[i].entry[j]) > 0)
- {
- (*sSet)[i]->entry[j] = (char*)malloc(strlen(vecSet[i].entry[j])*sizeof(char*)+1);
- strcpy((*sSet)[i]->entry[j], vecSet[i].entry[j]);
- (*sSet)[i]->entry_elements++;
- }
- }
- }
- }
- }
- return uiElements;
- }
-
- static void StructToVec(unsigned int iElements, StructSetting*** sSet, std::vector<VisSetting> *vecSet)
- {
- if(iElements == 0)
- return;
-
- vecSet->clear();
- for(unsigned int i=0;i<iElements;i++)
- {
- VisSetting vSet((VisSetting::SETTING_TYPE)(*sSet)[i]->type, (*sSet)[i]->name);
- if((*sSet)[i]->type == VisSetting::SPIN)
- {
- for(unsigned int j=0;j<(*sSet)[i]->entry_elements;j++)
- {
- vSet.AddEntry((*sSet)[i]->entry[j]);
- }
- }
- vSet.current = (*sSet)[i]->current;
- vecSet->push_back(vSet);
- }
- }
-
- static void FreeStruct(unsigned int iElements, StructSetting*** sSet)
- {
- if(iElements == 0)
- return;
-
- for(unsigned int i=0;i<iElements;i++)
- {
- if((*sSet)[i]->type == VisSetting::SPIN)
- {
- for(unsigned int j=0;j<(*sSet)[i]->entry_elements;j++)
- {
- if((*sSet)[i]->entry[j])
- free((*sSet)[i]->entry[j]);
- }
- if((*sSet)[i]->entry)
- free((*sSet)[i]->entry);
- }
- if((*sSet)[i]->name)
- free((*sSet)[i]->name);
- if((*sSet)[i])
- free((*sSet)[i]);
- }
- if(*sSet)
- free(*sSet);
- }
- };
-
- struct Visualisation
- {
- public:
- void (__cdecl* Create)(void* unused, int iPosX, int iPosY, int iWidth, int iHeight,
- const char* szVisualisation,float pixelRatio, const char *szSubModule);
- void (__cdecl* Start)(int iChannels, int iSamplesPerSec, int iBitsPerSample, const char* szSongName);
- void (__cdecl* AudioData)(short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength);
- void (__cdecl* Render) ();
- void (__cdecl* Stop)();
- void (__cdecl* GetInfo)(VIS_INFO *info);
- bool (__cdecl* OnAction)(long flags, void *param);
- void (__cdecl *FreeSettings)();
- unsigned int (__cdecl *GetSettings)(StructSetting*** sSet);
- void (__cdecl *UpdateSetting)(int num, StructSetting*** sSet);
- void (__cdecl *GetPresets)(char ***pPresets, int *currentPreset, int *numPresets, bool *locked);
- int (__cdecl *GetSubModules)(char ***names, char ***paths);
- };
-
-}
-
-#endif //__VISUALISATION_TYPES_H__
diff --git a/xbmc/visualizations/WaveForm/Main.cpp b/xbmc/visualizations/WaveForm/Main.cpp
index 4a61936fe8..95a600b3d1 100644
--- a/xbmc/visualizations/WaveForm/Main.cpp
+++ b/xbmc/visualizations/WaveForm/Main.cpp
@@ -1,15 +1,14 @@
// Waveform.vis
// A simple visualisation example by MrC
-#include "../../../visualisations/xbmc_vis.h"
-#ifdef _WIN32
+#include "../../addons/include/xbmc_vis_dll.h"
+#include <stdio.h>
#ifdef HAS_SDL_OPENGL
#include <GL/glew.h>
#else
+#ifdef _WIN32
#include <D3D9.h>
#endif
-#else
-#include "../../../guilib/system.h"
#endif
char g_visName[512];
@@ -29,10 +28,8 @@ typedef struct {
int MinZ;
int MaxZ;
} D3DVIEWPORT9;
-#ifdef _WIN32
typedef unsigned long D3DCOLOR;
#endif
-#endif
D3DVIEWPORT9 g_viewport;
@@ -47,25 +44,28 @@ struct Vertex_t
#endif
//-- Create -------------------------------------------------------------------
-// Called once when the visualisation is created by XBMC. Do any setup here.
+// Called on load. Addon should fully initalize or return error status
//-----------------------------------------------------------------------------
-extern "C" void Create(void* pd3dDevice, int iPosX, int iPosY, int iWidth, int iHeight, const char* szVisualisationName,
- float fPixelRatio, const char *szSubModuleName)
+ADDON_STATUS Create(void* hdl, void* props)
{
- //printf("Creating Waveform\n");
- strcpy(g_visName, szVisualisationName);
- m_uiVisElements = 0;
+ if (!props)
+ return STATUS_UNKNOWN;
+
+ VIS_PROPS* visProps = (VIS_PROPS*)props;
+
#ifndef HAS_SDL_OPENGL
- g_device = (LPDIRECT3DDEVICE9)pd3dDevice;
+ g_device = (LPDIRECT3DDEVICE9)visProps->device;
#else
- g_device = pd3dDevice;
+ g_device = visProps->device;
#endif
- g_viewport.X = iPosX;
- g_viewport.Y = iPosY;
- g_viewport.Width = iWidth;
- g_viewport.Height = iHeight;
+ g_viewport.X = visProps->x;
+ g_viewport.Y = visProps->y;
+ g_viewport.Width = visProps->width;
+ g_viewport.Height = visProps->height;
g_viewport.MinZ = 0;
g_viewport.MaxZ = 1;
+
+ return STATUS_OK;
}
//-- Start --------------------------------------------------------------------
@@ -87,7 +87,7 @@ extern "C" void Stop()
//-- Audiodata ----------------------------------------------------------------
// Called by XBMC to pass new audio data to the vis
//-----------------------------------------------------------------------------
-extern "C" void AudioData(short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength)
+extern "C" void AudioData(const short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength)
{
// Convert the audio data into a floating -1 to +1 range
int ipos=0;
@@ -187,7 +187,7 @@ extern "C" void GetInfo(VIS_INFO* pInfo)
//-- OnAction -----------------------------------------------------------------
// Handle XBMC actions such as next preset, lock preset, album art changed etc
//-----------------------------------------------------------------------------
-extern "C" bool OnAction(long flags, void *param)
+extern "C" bool OnAction(long flags, const void *param)
{
bool ret = false;
return ret;
@@ -196,37 +196,85 @@ extern "C" bool OnAction(long flags, void *param)
//-- GetPresets ---------------------------------------------------------------
// Return a list of presets to XBMC for display
//-----------------------------------------------------------------------------
-extern "C" void GetPresets(char ***pPresets, int *currentPreset, int *numPresets, bool *locked)
+extern "C" unsigned int GetPresets(char ***presets)
{
-
+ return 0;
}
-//-- GetSettings --------------------------------------------------------------
-// Return the settings for XBMC to display
+//-- GetPreset ----------------------------------------------------------------
+// Return the index of the current playing preset
//-----------------------------------------------------------------------------
-extern "C" unsigned int GetSettings(StructSetting*** sSet)
+extern "C" unsigned GetPreset()
{
return 0;
}
-extern "C" void FreeSettings()
+//-- IsLocked -----------------------------------------------------------------
+// Returns true if this add-on use settings
+//-----------------------------------------------------------------------------
+extern "C" bool IsLocked()
+{
+ return false;
+}
+
+//-- GetSubModules ------------------------------------------------------------
+// Return any sub modules supported by this vis
+//-----------------------------------------------------------------------------
+extern "C" unsigned int GetSubModules(char ***names)
+{
+ return 0; // this vis supports 0 sub modules
+}
+
+//-- Remove -------------------------------------------------------------------
+// Do everything before unload of this add-on
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" void Remove()
{
- return;
}
+//-- HasSettings --------------------------------------------------------------
+// Returns true if this add-on use settings
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" bool HasSettings()
+{
+ return false;
+}
-//-- UpdateSetting ------------------------------------------------------------
-// Handle setting change request from XBMC
+//-- GetStatus ---------------------------------------------------------------
+// Returns the current Status of this visualisation
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" ADDON_STATUS GetStatus()
+{
+ return STATUS_OK;
+}
+
+//-- GetSettings --------------------------------------------------------------
+// Return the settings for XBMC to display
+// !!! Add-on master function !!!
//-----------------------------------------------------------------------------
-extern "C" void UpdateSetting(int num, StructSetting*** sSet)
+extern "C" unsigned int GetSettings(StructSetting ***sSet)
{
+ return 0;
+}
+//-- FreeSettings --------------------------------------------------------------
+// Free the settings struct passed from XBMC
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+
+extern "C" void FreeSettings()
+{
}
-//-- GetSubModules ------------------------------------------------------------
-// Return any sub modules supported by this vis
+//-- SetSetting ---------------------------------------------------------------
+// Set a specific Setting value (called from XBMC)
+// !!! Add-on master function !!!
//-----------------------------------------------------------------------------
-extern "C" int GetSubModules(char ***names, char ***paths)
+extern "C" ADDON_STATUS SetSetting(const char *strSetting, const void* value)
{
- return 0; // this vis supports 0 sub modules
+ return STATUS_OK;
}
+
diff --git a/xbmc/visualizations/WaveForm/Makefile.in b/xbmc/visualizations/WaveForm/Makefile.in
index 0d9a65cccb..7888d70873 100644
--- a/xbmc/visualizations/WaveForm/Makefile.in
+++ b/xbmc/visualizations/WaveForm/Makefile.in
@@ -1,10 +1,10 @@
ARCH=@ARCH@
-INCLUDES=-I. -I../../linux -I../../ -I ../../../guilib
+INCLUDES=-I. -I../../addons/include
DEFINES+=-DHAS_SDL_OPENGL -DHAS_SDL
CXXFLAGS=-fPIC
OBJS=Main.o
-SLIB=../../../visualisations/Waveform.vis
+SLIB=../../../addons/visualizations/Waveform/Waveform.vis
$(SLIB): $(OBJS)
ifeq ($(findstring osx,$(ARCH)), osx)
diff --git a/xbmc/visualizations/XBMCProjectM/Main.cpp b/xbmc/visualizations/XBMCProjectM/Main.cpp
index e390a30b63..72c91287b8 100644
--- a/xbmc/visualizations/XBMCProjectM/Main.cpp
+++ b/xbmc/visualizations/XBMCProjectM/Main.cpp
@@ -1,459 +1,427 @@
-
-/*
-xmms-projectM v0.99 - xmms-projectm.sourceforge.net
---------------------------------------------------
-
-Lead Developers: Carmelo Piccione (cep@andrew.cmu.edu) &
- Peter Sperl (peter@sperl.com)
-
-We have also been advised by some professors at CMU, namely Roger B. Dannenberg.
-http://www-2.cs.cmu.edu/~rbd/
-
-The inspiration for this program was Milkdrop by Ryan Geiss. Obviously.
-
-This code is distributed under the GPL.
-
-
-THANKS FOR THE CODE!!!
--------------------------------------------------
-The base for this program was andy@nobugs.org's XMMS plugin tutorial
-http://www.xmms.org/docs/vis-plugin.html
-
-We used some FFT code by Takuya OOURA instead of XMMS' built-in fft code
-fftsg.c - http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html
-
-For font rendering we used GLF by Roman Podobedov
-glf.c - http://astronomy.swin.edu.au/~pbourke/opengl/glf/
-
-and some beat detection code was inspired by Frederic Patin @
-www.gamedev.net/reference/programming/features/beatdetection/
---
-
-"ported" to XBMC by d4rk
-d4rk@xbmc.org
-
-*/
-
-#include "xbmc_vis.h"
-#include <GL/glew.h>
-#include "libprojectM/ConfigFile.h"
-#include "libprojectM/projectM.hpp"
-#include "libprojectM/Preset.hpp"
-#include "libprojectM/PCM.hpp"
-#include <string>
-#ifdef WIN32
-#include "libprojectM/win32-dirent.h"
-#include <io.h>
-#else
-#include "PlatformDefs.h"
-#include "Util.h"
-#include "system.h"
-#include "FileSystem/SpecialProtocol.h"
-#include <dirent.h>
-#endif
-
-#define PRESETS_DIR "special://xbmc/visualisations/projectM"
-#define CONFIG_FILE "special://profile/visualisations/projectM.conf"
-
-projectM *globalPM = NULL;
-
-extern int preset_index;
-
-// some projectm globals
-int maxSamples=512;
-int texsize=512;
-int gx=40,gy=30;
-int fps=100;
-char *disp;
-char g_visName[512];
-char **g_presets=NULL;
-int g_numPresets = 0;
-projectM::Settings g_configPM;
-std::string g_configFile;
-
-#define QUALITY_LOW "Low"
-#define QUALITY_MEDIUM "Medium"
-#define QUALITY_HIGH "High"
-#define QUALITY_MAX "Maximum"
-#define PROJECTM_QUALITY (VIS_ACTION_USER+1)
-
-// Some helper Functions
-
-// case-insensitive alpha sort from projectM's win32-dirent.cc
-#ifndef WIN32
-int alphasort(const void* lhs, const void* rhs)
-{
- const struct dirent* lhs_ent = *(struct dirent**)lhs;
- const struct dirent* rhs_ent = *(struct dirent**)rhs;
- return strcasecmp(lhs_ent->d_name, rhs_ent->d_name);
-}
-#endif
-
-// check for a valid preset extension
-#ifdef __APPLE__
-int check_valid_extension(struct dirent* ent)
-#else
-int check_valid_extension(const struct dirent* ent)
-#endif
-{
- const char* ext = 0;
-
- if (!ent) return 0;
-
- ext = strrchr(ent->d_name, '.');
- if (!ext) ext = ent->d_name;
-
- if (0 == strcasecmp(ext, ".milk")) return 1;
- if (0 == strcasecmp(ext, ".prjm")) return 1;
-
- return 0;
-}
-
-//-- Create -------------------------------------------------------------------
-// Called once when the visualisation is created by XBMC. Do any setup here.
-//-----------------------------------------------------------------------------
-extern "C" void Create(void* pd3dDevice, int iPosX, int iPosY, int iWidth, int iHeight, const char* szVisualisationName,
- float fPixelRatio, const char *szSubModuleName)
-{
- strcpy(g_visName, szVisualisationName);
-
- m_vecSettings.clear();
- m_uiVisElements = 0;
-
- /** Initialise projectM */
-
-#ifdef WIN32
- g_configFile = string(CONFIG_FILE);
- std::string presetsDir = string(PRESETS_DIR);
-#else
- g_configFile = _P(CONFIG_FILE);
- std::string presetsDir = _P(PRESETS_DIR);
-#endif
-
- g_configPM.meshX = gx;
- g_configPM.meshY = gy;
- g_configPM.fps = fps;
- g_configPM.textureSize = texsize;
- g_configPM.windowWidth = iWidth;
- g_configPM.windowHeight = iHeight;
- g_configPM.presetURL = presetsDir;
- g_configPM.smoothPresetDuration = 5;
- g_configPM.presetDuration = 15;
- g_configPM.beatSensitivity = 10.0;
- g_configPM.aspectCorrection = true;
- g_configPM.easterEgg = 0.0;
- g_configPM.shuffleEnabled = true;
- g_configPM.windowLeft = iPosX;
- g_configPM.windowBottom = iPosY;
-
- {
- FILE *f;
- f = fopen(g_configFile.c_str(), "r");
- if (f) { // Config exists. Let's preserve settings except for iWidth, iHeight, iPosX, iPosY
- fclose(f);
- ConfigFile config(g_configFile.c_str());
- if (config.keyExists("Mesh X")) g_configPM.meshX = config.read<int> ("Mesh X", gx);
- if (config.keyExists("Mesh Y")) g_configPM.meshY = config.read<int> ("Mesh Y", gy);
- if (config.keyExists("Texture Size")) g_configPM.textureSize = config.read<int> ("Texture Size", texsize);
- if (config.keyExists("Preset Path")) g_configPM.presetURL = config.read<string> ("Preset Path", presetsDir);
- if (config.keyExists("Smooth Preset Duration")) g_configPM.smoothPresetDuration = config.read<int> ("Smooth Preset Duration", 5);
- if (config.keyExists("Preset Duration")) g_configPM.presetDuration = config.read<int> ("Preset Duration", 15);
- if (config.keyExists("FPS")) g_configPM.fps = config.read<int> ("FPS", fps);
- if (config.keyExists("Hard Cut Sensitivity")) g_configPM.beatSensitivity = config.read<float> ("Hard Cut Sensitivity", 10.0);
- if (config.keyExists("Aspect Correction")) g_configPM.aspectCorrection = config.read<bool> ("Aspect Correction", true);
- if (config.keyExists("Easter Egg")) g_configPM.easterEgg = config.read<float> ("Easter Egg", 0.0);
- if (config.keyExists("Shuffle Enabled")) g_configPM.shuffleEnabled = config.read<bool> ("Shuffle Enabled", true);
- if (config.keyExists("Use FBO")) g_configPM.useFBO = config.read<bool> ("Use FBO", false);
- }
- else {
-#ifndef WIN32
- CStdString strPath;
- CUtil::GetDirectory(g_configFile, strPath);
- CUtil::CreateDirectoryEx(strPath);
-#endif
- f = fopen(g_configFile.c_str(), "w"); // Config does not exist, but we still need at least a blank file.
- fclose(f);
- }
- projectM::writeConfig(g_configFile, g_configPM);
- }
-
- if (globalPM)
- delete globalPM;
-
- globalPM = new projectM(g_configFile);
-
- VisSetting quality(VisSetting::SPIN, "Render Quality");
- quality.AddEntry("Low");
- quality.AddEntry("Medium");
- quality.AddEntry("High");
- quality.AddEntry("Maximum");
- if (g_configPM.textureSize == 2048)
- {
- quality.current = 3;
- }
- else if (g_configPM.textureSize == 1024)
- {
- quality.current = 2;
- }
- else if (g_configPM.textureSize == 512)
- {
- quality.current = 1;
- }
- else if (g_configPM.textureSize == 256)
- {
- quality.current = 0;
- }
- m_vecSettings.push_back(quality);
-
- VisSetting shuffleMode(VisSetting::CHECK, "Shuffle Mode");
- shuffleMode.current = globalPM->isShuffleEnabled();
- m_vecSettings.push_back(shuffleMode);
-
- VisSetting smoothPresetDuration(VisSetting::SPIN, "Smooth Preset Duration");
- for (int i=0; i < 50; i++)
- {
- char temp[10];
- sprintf(temp, "%i secs", i);
- smoothPresetDuration.AddEntry(temp);
- }
- smoothPresetDuration.current = (int)(g_configPM.smoothPresetDuration);
- m_vecSettings.push_back(smoothPresetDuration);
-
- VisSetting presetDuration(VisSetting::SPIN, "Preset Duration");
- for (int i=0; i < 50; i++)
- {
- char temp[10];
- sprintf(temp, "%i secs", i);
- presetDuration.AddEntry(temp);
- }
- presetDuration.current = (int)(g_configPM.presetDuration);
- m_vecSettings.push_back(presetDuration);
-
- VisSetting beatSensitivity(VisSetting::SPIN, "Beat Sensitivity");
- for (int i=0; i <= 100; i++)
- {
- char temp[10];
- sprintf(temp, "%2.1f", (float)(i + 1)/5);
- beatSensitivity.AddEntry(temp);
- }
- beatSensitivity.current = (int)(g_configPM.beatSensitivity * 5 - 1);
- m_vecSettings.push_back(beatSensitivity);
-}
-
-//-- Start --------------------------------------------------------------------
-// Called when a new soundtrack is played
-//-----------------------------------------------------------------------------
-extern "C" void Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, const char* szSongName)
-{
- //printf("Got Start Command\n");
-}
-
-//-- Stop ---------------------------------------------------------------------
-// Called when the visualisation is closed by XBMC
-//-----------------------------------------------------------------------------
-extern "C" void Stop()
-{
- if (globalPM)
- {
- projectM::writeConfig(g_configFile,globalPM->settings());
- delete globalPM;
- globalPM = NULL;
- }
- if (g_presets)
- {
- for (int i = 0 ; i<g_numPresets ; i++)
- {
- free(g_presets[i]);
- }
- free(g_presets);
- g_presets = NULL;
- }
- m_vecSettings.clear();
-}
-
-//-- Audiodata ----------------------------------------------------------------
-// Called by XBMC to pass new audio data to the vis
-//-----------------------------------------------------------------------------
-extern "C" void AudioData(short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength)
-{
- globalPM->pcm()->addPCM16Data(pAudioData, iAudioDataLength);
-}
-
-
-//-- Render -------------------------------------------------------------------
-// Called once per frame. Do all rendering here.
-//-----------------------------------------------------------------------------
-extern "C" void Render()
-{
- globalPM->renderFrame();
-}
-
-//-- GetInfo ------------------------------------------------------------------
-// Tell XBMC our requirements
-//-----------------------------------------------------------------------------
-extern "C" void GetInfo(VIS_INFO* pInfo)
-{
- pInfo->bWantsFreq = false;
- pInfo->iSyncDelay = 0;
-}
-
-//-- OnAction -----------------------------------------------------------------
-// Handle XBMC actions such as next preset, lock preset, album art changed etc
-//-----------------------------------------------------------------------------
-extern "C" bool OnAction(long flags, void *param)
-{
- bool ret = false;
-
- if (flags == VIS_ACTION_LOAD_PRESET && param)
- {
- int pindex = *((int *)param);
- globalPM->selectPreset(pindex);
- ret = true;
- }
- else if (flags == VIS_ACTION_NEXT_PRESET)
- {
-// switchPreset(ALPHA_NEXT, SOFT_CUT);
- if (!globalPM->isShuffleEnabled())
- globalPM->key_handler(PROJECTM_KEYDOWN, PROJECTM_K_n, PROJECTM_KMOD_CAPS); //ignore PROJECTM_KMOD_CAPS
- else
- globalPM->key_handler(PROJECTM_KEYDOWN, PROJECTM_K_r, PROJECTM_KMOD_CAPS); //ignore PROJECTM_KMOD_CAPS
- ret = true;
- }
- else if (flags == VIS_ACTION_PREV_PRESET)
- {
-// switchPreset(ALPHA_PREVIOUS, SOFT_CUT);
- if (!globalPM->isShuffleEnabled())
- globalPM->key_handler(PROJECTM_KEYDOWN, PROJECTM_K_p, PROJECTM_KMOD_CAPS); //ignore PROJECTM_KMOD_CAPS
- else
- globalPM->key_handler(PROJECTM_KEYDOWN, PROJECTM_K_r, PROJECTM_KMOD_CAPS); //ignore PROJECTM_KMOD_CAPS
-
- ret = true;
- }
- else if (flags == VIS_ACTION_RANDOM_PRESET)
- {
- globalPM->setShuffleEnabled(!globalPM->isShuffleEnabled());
- ret = true;
- }
- else if (flags == VIS_ACTION_LOCK_PRESET)
- {
- globalPM->setPresetLock(!globalPM->isPresetLocked());
- ret = true;
- }
- return ret;
-}
-
-//-- GetPresets ---------------------------------------------------------------
-// Return a list of presets to XBMC for display
-//-----------------------------------------------------------------------------
-extern "C" void GetPresets(char ***pPresets, int *currentPreset, int *numPresets, bool *locked)
-{
- if (!g_presets)
- {
- if (globalPM->getPlaylistSize() > 0)
- {
- g_numPresets = globalPM->getPlaylistSize();
- g_presets = (char **)malloc(sizeof(char*)*globalPM->getPlaylistSize());
- if (g_presets)
- {
- for (unsigned int i = 0; i < globalPM->getPlaylistSize() ; i++)
- {
- g_presets[i] = (char*)malloc(strlen(globalPM->getPresetName(i).c_str())+2);
- if (g_presets[i])
- {
- strcpy(g_presets[i], globalPM->getPresetName(i).c_str());
- }
- }
- }
- }
- }
-
-
- if (g_presets)
- {
- *pPresets = g_presets;
- *numPresets = g_numPresets;
- unsigned int presetIndex;
- if (globalPM->selectedPresetIndex(presetIndex) && presetIndex >= 0 &&
- (int)presetIndex < g_numPresets)
- *currentPreset = presetIndex;
- }
- *locked = globalPM->isPresetLocked();
-}
-
-//-- GetSettings --------------------------------------------------------------
-// Return the settings for XBMC to display
-//-----------------------------------------------------------------------------
-
-extern "C" unsigned int GetSettings(StructSetting*** sSet)
-{
- m_uiVisElements = VisUtils::VecToStruct(m_vecSettings, &m_structSettings);
- *sSet = m_structSettings;
- return m_uiVisElements;
-}
-
-extern "C" void FreeSettings()
-{
- VisUtils::FreeStruct(m_uiVisElements, &m_structSettings);
-}
-
-//-- UpdateSetting ------------------------------------------------------------
-// Handle setting change request from XBMC
-//-----------------------------------------------------------------------------
-extern "C" void UpdateSetting(int num, StructSetting*** sSet)
-{
- VisUtils::StructToVec(m_uiVisElements, sSet, &m_vecSettings);
- VisSetting &setting = m_vecSettings[num];
- if (strcasecmp(setting.name, "Use Preset")==0)
- OnAction(34, (void*)&setting.current);
- else if (strcasecmp(setting.name, "Shuffle Mode")==0)
- OnAction(VIS_ACTION_RANDOM_PRESET, (void*)&setting.current);
- else {
- if (globalPM)
- {
- g_configPM = globalPM->settings();
- projectM::writeConfig(g_configFile,globalPM->settings());
- delete globalPM;
- globalPM = NULL;
- }
- if (strcasecmp(setting.name, "Smooth Preset Duration")==0)
- g_configPM.smoothPresetDuration = setting.current;
- else if (strcasecmp(setting.name,"Preset Duration")==0)
- g_configPM.presetDuration = setting.current;
- else if (strcasecmp(setting.name, "Beat Sensitivity")==0)
- g_configPM.beatSensitivity = (float)(setting.current + 1) / 5.0f;
- else if (strcasecmp(setting.name, "Render Quality")==0)
- {
- if ( setting.current == 0 ) // low
- {
- g_configPM.useFBO = false;
- g_configPM.textureSize = 256;
- }
- else if ( setting.current == 1 ) // med
- {
- g_configPM.useFBO = false;
- g_configPM.textureSize = 512;
- }
- else if ( setting.current == 2 ) // high
- {
- g_configPM.useFBO = false;
- g_configPM.textureSize = 1024;
- }
- else if ( setting.current == 3 ) // max
- {
- g_configPM.useFBO = false;
- g_configPM.textureSize = 2048;
- }
- }
- projectM::writeConfig(g_configFile, g_configPM);
- globalPM = new projectM(g_configFile);
- }
-
-}
-
-//-- GetSubModules ------------------------------------------------------------
-// Return any sub modules supported by this vis
-//-----------------------------------------------------------------------------
-extern "C" int GetSubModules(char ***names, char ***paths)
-{
- return 0; // this vis supports 0 sub modules
-}
+
+/*
+xmms-projectM v0.99 - xmms-projectm.sourceforge.net
+--------------------------------------------------
+
+Lead Developers: Carmelo Piccione (cep@andrew.cmu.edu) &
+ Peter Sperl (peter@sperl.com)
+
+We have also been advised by some professors at CMU, namely Roger B. Dannenberg.
+http://www-2.cs.cmu.edu/~rbd/
+
+The inspiration for this program was Milkdrop by Ryan Geiss. Obviously.
+
+This code is distributed under the GPL.
+
+
+THANKS FOR THE CODE!!!
+-------------------------------------------------
+The base for this program was andy@nobugs.org's XMMS plugin tutorial
+http://www.xmms.org/docs/vis-plugin.html
+
+We used some FFT code by Takuya OOURA instead of XMMS' built-in fft code
+fftsg.c - http://momonga.t.u-tokyo.ac.jp/~ooura/fft.html
+
+For font rendering we used GLF by Roman Podobedov
+glf.c - http://astronomy.swin.edu.au/~pbourke/opengl/glf/
+
+and some beat detection code was inspired by Frederic Patin @
+www.gamedev.net/reference/programming/features/beatdetection/
+--
+
+"ported" to XBMC by d4rk
+d4rk@xbmc.org
+
+*/
+
+#include "xbmc_vis_dll.h"
+#include "xbmc_addon_cpp_dll.h"
+#include <GL/glew.h>
+#include "libprojectM/ConfigFile.h"
+#include "libprojectM/projectM.hpp"
+#include <string>
+
+projectM *globalPM = NULL;
+
+// some projectm globals
+int maxSamples=512;
+int texsize=512;
+int gx=40,gy=30;
+int fps=100;
+char *disp;
+char g_visName[512];
+char **g_presets=NULL;
+unsigned int g_numPresets = 0;
+projectM::Settings g_configPM;
+std::string g_configFile;
+
+// settings vector
+std::vector<DllSetting> g_vecSettings;
+StructSetting** g_structSettings;
+unsigned int g_uiVisElements;
+
+//-- Create -------------------------------------------------------------------
+// Called once when the visualisation is created by XBMC. Do any setup here.
+//-----------------------------------------------------------------------------
+extern "C" ADDON_STATUS Create(void* hdl, void* props)
+{
+ if (!props)
+ return STATUS_UNKNOWN;
+
+ g_vecSettings.clear();
+ g_uiVisElements = 0;
+
+
+ VIS_PROPS* visprops = (VIS_PROPS*)props;
+
+ strcpy(g_visName, visprops->name);
+ g_configFile = string(visprops->profile) + string("/projectm.conf");
+ std::string presetsDir = "special://xbmc/addons/visualizations/ProjectM/resources/presets.zip/";
+
+ g_configPM.meshX = gx;
+ g_configPM.meshY = gy;
+ g_configPM.fps = fps;
+ g_configPM.textureSize = texsize;
+ g_configPM.windowWidth = visprops->width;
+ g_configPM.windowHeight = visprops->height;
+ g_configPM.presetURL = presetsDir;
+ g_configPM.smoothPresetDuration = 5;
+ g_configPM.presetDuration = 15;
+ g_configPM.beatSensitivity = 10.0;
+ g_configPM.aspectCorrection = true;
+ g_configPM.easterEgg = 0.0;
+ g_configPM.shuffleEnabled = true;
+ g_configPM.windowLeft = visprops->x;
+ g_configPM.windowBottom = visprops->y;
+
+ // if no config file exists, create a blank one as Config ctor throws an exception!
+ FILE *f;
+ f = fopen(g_configFile.c_str(), "r");
+ if (!f) f = fopen(g_configFile.c_str(), "w");
+ fclose(f);
+
+ // save our config
+ try
+ {
+ projectM::writeConfig(g_configFile, g_configPM);
+ }
+ catch (...)
+ {
+ printf("exception in projectM::WriteConfig");
+ return STATUS_UNKNOWN;
+ }
+
+ if (globalPM)
+ delete globalPM;
+
+ try
+ {
+ globalPM = new projectM(g_configFile);
+ }
+ catch (...)
+ {
+ printf("exception in projectM ctor");
+ return STATUS_UNKNOWN;
+ }
+
+ DllSetting quality(DllSetting::SPIN, "quality", "30000");
+ quality.AddEntry("30001");
+ quality.AddEntry("30002");
+ quality.AddEntry("30003");
+ quality.AddEntry("30004");
+ if (g_configPM.textureSize == 2048)
+ {
+ quality.current = 3;
+ }
+ else if (g_configPM.textureSize == 1024)
+ {
+ quality.current = 2;
+ }
+ else if (g_configPM.textureSize == 512)
+ {
+ quality.current = 1;
+ }
+ else if (g_configPM.textureSize == 256)
+ {
+ quality.current = 0;
+ }
+ g_vecSettings.push_back(quality);
+
+ DllSetting shuffleMode(DllSetting::CHECK, "shuffle", "30005");
+ shuffleMode.current = globalPM->isShuffleEnabled();
+ g_vecSettings.push_back(shuffleMode);
+
+ DllSetting smoothPresetDuration(DllSetting::SPIN, "smooth_duration", "30006");
+ for (int i=0; i < 50; i++)
+ {
+ char temp[10];
+ sprintf(temp, "%i secs", i);
+ smoothPresetDuration.AddEntry(temp);
+ }
+ smoothPresetDuration.current = (int)(g_configPM.smoothPresetDuration);
+ g_vecSettings.push_back(smoothPresetDuration);
+
+ DllSetting presetDuration(DllSetting::SPIN, "preset_duration", "30007");
+ for (int i=0; i < 50; i++)
+ {
+ char temp[10];
+ sprintf(temp, "%i secs", i);
+ presetDuration.AddEntry(temp);
+ }
+ presetDuration.current = (int)(g_configPM.presetDuration);
+ g_vecSettings.push_back(presetDuration);
+
+ DllSetting beatSensitivity(DllSetting::SPIN, "beat_sens", "30008");
+ for (int i=0; i <= 100; i++)
+ {
+ char temp[10];
+ sprintf(temp, "%2.1f", (float)(i + 1)/5);
+ beatSensitivity.AddEntry(temp);
+ }
+ beatSensitivity.current = (int)(g_configPM.beatSensitivity * 5 - 1);
+ g_vecSettings.push_back(beatSensitivity);
+
+ return STATUS_NEED_SETTINGS;
+}
+
+//-- Start --------------------------------------------------------------------
+// Called when a new soundtrack is played
+//-----------------------------------------------------------------------------
+extern "C" void Start(int iChannels, int iSamplesPerSec, int iBitsPerSample, const char* szSongName)
+{
+ //printf("Got Start Command\n");
+}
+
+//-- Stop ---------------------------------------------------------------------
+// Called when the visualisation is closed by XBMC
+//-----------------------------------------------------------------------------
+extern "C" void Stop()
+{
+ if (globalPM)
+ {
+ projectM::writeConfig(g_configFile,globalPM->settings());
+ delete globalPM;
+ globalPM = NULL;
+ }
+ if (g_presets)
+ {
+ for (unsigned i = 0; i <g_numPresets; i++)
+ {
+ free(g_presets[i]);
+ }
+ free(g_presets);
+ g_presets = NULL;
+ }
+ g_numPresets = 0;
+}
+
+//-- Audiodata ----------------------------------------------------------------
+// Called by XBMC to pass new audio data to the vis
+//-----------------------------------------------------------------------------
+extern "C" void AudioData(const short* pAudioData, int iAudioDataLength, float *pFreqData, int iFreqDataLength)
+{
+ globalPM->pcm()->addPCM16Data(pAudioData, iAudioDataLength);
+}
+
+//-- Render -------------------------------------------------------------------
+// Called once per frame. Do all rendering here.
+//-----------------------------------------------------------------------------
+extern "C" void Render()
+{
+ globalPM->renderFrame();
+}
+
+//-- GetInfo ------------------------------------------------------------------
+// Tell XBMC our requirements
+//-----------------------------------------------------------------------------
+extern "C" void GetInfo(VIS_INFO* pInfo)
+{
+ pInfo->bWantsFreq = false;
+ pInfo->iSyncDelay = 0;
+}
+
+//-- OnAction -----------------------------------------------------------------
+// Handle XBMC actions such as next preset, lock preset, album art changed etc
+//-----------------------------------------------------------------------------
+extern "C" bool OnAction(long flags, const void *param)
+{
+ bool ret = false;
+
+ if (flags == VIS_ACTION_LOAD_PRESET && param)
+ {
+ int pindex = *((int *)param);
+ globalPM->selectPreset(pindex);
+ ret = true;
+ }
+ else if (flags == VIS_ACTION_NEXT_PRESET)
+ {
+// switchPreset(ALPHA_NEXT, SOFT_CUT);
+ if (!globalPM->isShuffleEnabled())
+ globalPM->key_handler(PROJECTM_KEYDOWN, PROJECTM_K_n, PROJECTM_KMOD_CAPS); //ignore PROJECTM_KMOD_CAPS
+ else
+ globalPM->key_handler(PROJECTM_KEYDOWN, PROJECTM_K_r, PROJECTM_KMOD_CAPS); //ignore PROJECTM_KMOD_CAPS
+ ret = true;
+ }
+ else if (flags == VIS_ACTION_PREV_PRESET)
+ {
+// switchPreset(ALPHA_PREVIOUS, SOFT_CUT);
+ if (!globalPM->isShuffleEnabled())
+ globalPM->key_handler(PROJECTM_KEYDOWN, PROJECTM_K_p, PROJECTM_KMOD_CAPS); //ignore PROJECTM_KMOD_CAPS
+ else
+ globalPM->key_handler(PROJECTM_KEYDOWN, PROJECTM_K_r, PROJECTM_KMOD_CAPS); //ignore PROJECTM_KMOD_CAPS
+
+ ret = true;
+ }
+ else if (flags == VIS_ACTION_RANDOM_PRESET)
+ {
+ globalPM->setShuffleEnabled(g_configPM.shuffleEnabled);
+ ret = true;
+ }
+ else if (flags == VIS_ACTION_LOCK_PRESET)
+ {
+ globalPM->setPresetLock(!globalPM->isPresetLocked());
+ ret = true;
+ }
+ return ret;
+}
+
+//-- GetPresets ---------------------------------------------------------------
+// Return a list of presets to XBMC for display
+//-----------------------------------------------------------------------------
+extern "C" unsigned int GetPresets(char ***presets)
+{
+ g_numPresets = globalPM->getPlaylistSize();
+ if (g_numPresets > 0)
+ {
+ g_presets = (char**) malloc(sizeof(char*)*g_numPresets);
+ for (unsigned i = 0; i < g_numPresets; i++)
+ {
+ g_presets[i] = (char*) malloc(strlen(globalPM->getPresetName(i).c_str())+2);
+ if (g_presets[i])
+ strcpy(g_presets[i], globalPM->getPresetName(i).c_str());
+ }
+ *presets = g_presets;
+ }
+ return g_numPresets;
+}
+
+//-- GetPreset ----------------------------------------------------------------
+// Return the index of the current playing preset
+//-----------------------------------------------------------------------------
+extern "C" unsigned GetPreset()
+{
+ if (g_presets)
+ {
+ unsigned preset;
+ if(globalPM->selectedPresetIndex(preset))
+ return preset;
+ }
+ return 0;
+}
+
+//-- IsLocked -----------------------------------------------------------------
+// Returns true if this add-on use settings
+//-----------------------------------------------------------------------------
+extern "C" bool IsLocked()
+{
+ if(globalPM)
+ return globalPM->isPresetLocked();
+ else
+ return false;
+}
+
+//-- Remove -------------------------------------------------------------------
+// Do everything before unload of this add-on
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" void Remove()
+{
+}
+
+//-- HasSettings --------------------------------------------------------------
+// Returns true if this add-on use settings
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" bool HasSettings()
+{
+ return true;
+}
+
+//-- GetStatus ---------------------------------------------------------------
+// Returns the current Status of this visualisation
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" ADDON_STATUS GetStatus()
+{
+ return STATUS_OK;
+}
+
+//-- GetSettings --------------------------------------------------------------
+// Return the settings for XBMC to display
+//-----------------------------------------------------------------------------
+
+extern "C" unsigned int GetSettings(StructSetting ***sSet)
+{
+ g_uiVisElements = DllUtils::VecToStruct(g_vecSettings, &g_structSettings);
+ *sSet = g_structSettings;
+ return g_uiVisElements;
+}
+
+//-- FreeSettings --------------------------------------------------------------
+// Free the settings struct passed from XBMC
+//-----------------------------------------------------------------------------
+
+extern "C" void FreeSettings()
+{
+ DllUtils::FreeStruct(g_uiVisElements, &g_structSettings);
+}
+
+//-- UpdateSetting ------------------------------------------------------------
+// Handle setting change request from XBMC
+//-----------------------------------------------------------------------------
+extern "C" ADDON_STATUS SetSetting(const char* id, const void* value)
+{
+ if (!id || !value)
+ return STATUS_UNKNOWN;
+
+ if (strcmp(id, "quality")==0)
+ {
+ switch (*(int*) value)
+ {
+ case 0:
+ g_configPM.textureSize = 256;
+ break;
+ case 1:
+ g_configPM.textureSize = 512;
+ break;
+ case 2:
+ g_configPM.textureSize = 1024;
+ break;
+ case 3:
+ g_configPM.textureSize = 2048;
+ break;
+ }
+ }
+ else if (strcmp(id, "shuffle")==0)
+ {
+ g_configPM.shuffleEnabled = !g_configPM.shuffleEnabled;
+ if (globalPM)
+ OnAction(VIS_ACTION_RANDOM_PRESET, value);
+ }
+ else if (strcmp(id, "smooth_duration")==0)
+ g_configPM.smoothPresetDuration = *(int*)value;
+ else if (strcmp(id, "preset_duration")==0)
+ g_configPM.presetDuration = *(int*)value;
+ else if (strcmp(id, "beat_sens")==0)
+ g_configPM.beatSensitivity = *(int*)value;
+
+ return STATUS_OK;
+}
+
+//-- GetSubModules ------------------------------------------------------------
+// Return any sub modules supported by this vis
+//-----------------------------------------------------------------------------
+extern "C" unsigned int GetSubModules(char ***names)
+{
+ return 0; // this vis supports 0 sub modules
+}
diff --git a/xbmc/visualizations/XBMCProjectM/Makefile.in b/xbmc/visualizations/XBMCProjectM/Makefile.in
index a81d771193..72d687b021 100644
--- a/xbmc/visualizations/XBMCProjectM/Makefile.in
+++ b/xbmc/visualizations/XBMCProjectM/Makefile.in
@@ -1,7 +1,8 @@
ARCH=@ARCH@
-INCLUDES=-I. -I.. -I../../linux -I../../ -I../../../guilib -I../../../visualisations
+INCLUDES=-I. -I../../addons/include
OBJS=Main.o
-SLIB=../../../visualisations/ProjectM.vis
+SLIB=../../../addons/visualizations/ProjectM/projectM.vis
+DEFINES+=-DHAS_SDL_OPENGL -DHAS_SDL
CXXFLAGS=-fPIC
DIRS=libprojectM
diff --git a/xbmc/visualizations/XBMCProjectM/libprojectM/Preset.cpp b/xbmc/visualizations/XBMCProjectM/libprojectM/Preset.cpp
index d3ecf3cd7b..7f0874cfa2 100644
--- a/xbmc/visualizations/XBMCProjectM/libprojectM/Preset.cpp
+++ b/xbmc/visualizations/XBMCProjectM/libprojectM/Preset.cpp
@@ -22,6 +22,7 @@
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
+#include <fcntl.h>
#ifdef WIN32
#include "win32-dirent.h"
#else
@@ -35,8 +36,7 @@
#include "InitCondUtils.hpp"
#include "fatal.h"
#include <iostream>
-#include <fstream>
-
+#include <sstream>
Preset::Preset(std::istream & in, const std::string & presetName, PresetInputs & presetInputs, PresetOutputs & presetOutputs):
builtinParams(presetInputs, presetOutputs),
@@ -515,17 +515,30 @@ return PROJECTM_SUCCESS;
by the given pathname */
int Preset::loadPresetFile(const std::string & pathname)
{
-
-
/* Open the file corresponding to pathname */
- std::ifstream fs(pathname.c_str());
- if (!fs || fs.eof()) {
+ FILE* f = fopen(pathname.c_str(), "r");
+ if (!f) {
if (PRESET_DEBUG)
std::cerr << "loadPresetFile: loading of file \"" << pathname << "\" failed!\n";
return PROJECTM_ERROR;
}
- return readIn(fs);
+ fseek(f, 0, SEEK_END);
+ long fsize = ftell(f);
+ rewind(f);
+ std::vector<char> buffer(fsize);
+
+ int err = fread(&buffer[0], 1, fsize, f);
+ if (!err)
+ {
+ printf("read failed\n");
+ fclose(f);
+ return PROJECTM_ERROR;
+ }
+ fclose(f);
+ std::stringstream stream;
+ stream.rdbuf()->pubsetbuf(&buffer[0],buffer.size());
+ return readIn(stream);
}
diff --git a/xbmc/visualizations/iTunes/Main.cpp b/xbmc/visualizations/iTunes/Main.cpp
index 602bb4537e..3ccd0f839f 100644
--- a/xbmc/visualizations/iTunes/Main.cpp
+++ b/xbmc/visualizations/iTunes/Main.cpp
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2009 Team XBMC
+ * Copyright (C) 2005-2010 Team XBMC
* http://www.xbmc.org
*
* This Program is free software; you can redistribute it and/or modify
@@ -19,32 +19,14 @@
*
*/
-
/*
iTunes Visualization Wrapper for XBMC
*/
-
#include "xbmc_vis.h"
#include <GL/glew.h>
#include <string>
-#ifdef _WIN32
-#ifndef _MINGW
-#include "win32-dirent.h"
-#endif
-#include <io.h>
-#else
-#include "system.h"
-#include <dirent.h>
-#endif
-#ifdef _LINUX
-#include <dlfcn.h>
-#endif
-#ifdef __APPLE__
#include "itunes_vis.h"
-#endif
-
-using namespace std;
int g_tex_width = 512;
int g_tex_height = 512;
@@ -64,23 +46,23 @@ long g_tex_buffer_size = 0;
ITunesVis* g_plugin = NULL;
//-- Create -------------------------------------------------------------------
-// Called once when the visualisation is created by XBMC. Do any setup here.
+// Called on load. Addon should fully initalize or return error status
//-----------------------------------------------------------------------------
-extern "C" void Create(void* pd3dDevice, int iPosX, int iPosY, int iWidth,
- int iHeight, const char* szVisualisationName,
- float fPixelRatio, const char *szSubModuleName)
+ADDON_STATUS Create(void* hdl, void* visProps)
{
- if ( szVisualisationName )
- g_vis_name = szVisualisationName;
- m_vecSettings.clear();
- m_uiVisElements = 0;
+ if (!visProps)
+ return STATUS_UNKNOWN;
+
+ VIS_PROPS* props = (VIS_PROPS*) visProps;
+
+ g_vis_name = props->name;
+ g_sub_module = props->submodule;
/* copy window dimensions */
- g_window_width = g_tex_width = iWidth;
- g_window_height = g_tex_height = iHeight;
- g_window_xpos = iPosX;
- g_window_ypos = iPosY;
- g_sub_module = szSubModuleName;
+ g_window_width = g_tex_width = props->width;
+ g_window_height = g_tex_height = props->height;
+ g_window_xpos = props->x;
+ g_window_ypos = props->y
/* create texture buffer */
g_tex_buffer_size = g_tex_width * g_tex_height * 4;
@@ -116,7 +98,7 @@ extern "C" void Create(void* pd3dDevice, int iPosX, int iPosY, int iWidth,
ivis_start( g_plugin );
}
- return;
+ return STATUS_OK;
}
//-- Start --------------------------------------------------------------------
@@ -148,7 +130,7 @@ extern "C" void Stop()
//-- Audiodata ----------------------------------------------------------------
// Called by XBMC to pass new audio data to the vis
//-----------------------------------------------------------------------------
-extern "C" void AudioData(short* pAudioData, int iAudioDataLength,
+extern "C" void AudioData(const short* pAudioData, int iAudioDataLength,
float *pFreqData, int iFreqDataLength)
{
int copysize = iAudioDataLength < (int)sizeof( g_audio_data ) ? iAudioDataLength : (int)sizeof( g_audio_data );
@@ -270,7 +252,7 @@ extern "C" void GetInfo(VIS_INFO* pInfo)
//-- OnAction -----------------------------------------------------------------
// Handle XBMC actions such as next preset, lock preset, album art changed etc
//-----------------------------------------------------------------------------
-extern "C" bool OnAction(long flags, void *param)
+extern "C" bool OnAction(long flags, const void *param)
{
bool ret = false;
@@ -308,36 +290,69 @@ extern "C" bool OnAction(long flags, void *param)
//-- GetPresets ---------------------------------------------------------------
// Return a list of presets to XBMC for display
//-----------------------------------------------------------------------------
-extern "C" void GetPresets(char ***pPresets, int *currentPreset, int *numPresets,
- bool *locked)
+extern "C" unsigned int GetPresets(char ***pPresets)
{
+ return 0;
+}
+//-- GetSubModules ------------------------------------------------------------
+// Return a list of names and paths for submodules
+//-----------------------------------------------------------------------------
+extern "C" int GetSubModules(char ***names, char ***paths)
+{
+ return ivis_get_visualisations( names, paths );
+}
+
+//-- Remove -------------------------------------------------------------------
+// Do everything before unload of this add-on
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" void Remove()
+{
+}
+
+//-- HasSettings --------------------------------------------------------------
+// Returns true if this add-on use settings
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" bool HasSettings()
+{
+ return true;
+}
+
+//-- GetStatus ---------------------------------------------------------------
+// Returns the current Status of this visualisation
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+extern "C" ADDON_STATUS GetStatus()
+{
+ return STATUS_OK;
}
//-- GetSettings --------------------------------------------------------------
// Return the settings for XBMC to display
+// !!! Add-on master function !!!
//-----------------------------------------------------------------------------
-extern "C" unsigned int GetSettings(StructSetting*** sSet)
-{
- m_uiVisElements = VisUtils::VecToStruct(m_vecSettings, &m_structSettings);
- *sSet = m_structSettings;
- return m_uiVisElements;
+extern "C" unsigned int GetSettings(StructSetting ***sSet)
+{
+ return 0;
}
+//-- FreeSettings --------------------------------------------------------------
+// Free the settings struct passed from XBMC
+// !!! Add-on master function !!!
+//-----------------------------------------------------------------------------
+
extern "C" void FreeSettings()
{
- VisUtils::FreeStruct(m_uiVisElements, &m_structSettings);
}
-//-- UpdateSetting ------------------------------------------------------------
-// Handle setting change request from XBMC
+//-- SetSetting ---------------------------------------------------------------
+// Set a specific Setting value (called from XBMC)
+// !!! Add-on master function !!!
//-----------------------------------------------------------------------------
-extern "C" void UpdateSetting(int num, StructSetting*** sSet)
+extern "C" ADDON_STATUS SetSetting(const char *strSetting, const void* value)
{
- //VisSetting &setting = m_vecSettings[num];
+ return STATUS_OK;
}
-extern "C" int GetSubModules(char ***names, char ***paths)
-{
- return ivis_get_visualisations( names, paths );
-}
diff --git a/xbmc/visualizations/iTunes/Makefile.in b/xbmc/visualizations/iTunes/Makefile.in
index bf7f250e85..4d4c1c600a 100644
--- a/xbmc/visualizations/iTunes/Makefile.in
+++ b/xbmc/visualizations/iTunes/Makefile.in
@@ -1,8 +1,8 @@
ARCH=@ARCH@
-INCLUDES=-I. -I.. -I../../../xbmc/linux -I../../../xbmc -I../../../guilib -I../../../visualisations -I/opt/local/include
+INCLUDES=-I. -I../../addons/include -I/opt/local/include
OBJS=Main.o itunes_vis.o qview.o common_osx.o
CXXFLAGS=-Wall -g -fPIC
-SLIB=../../../visualisations/iTunes.mvis
+SLIB=../../../addons/visualizations/iTunes/iTunes.mvis
$(SLIB): $(OBJS)
ifeq ($(findstring osx,$(ARCH)), osx)
diff --git a/xbmc/win32/PlatformDefs.h b/xbmc/win32/PlatformDefs.h
index c19c980ce1..93fc5544b3 100644
--- a/xbmc/win32/PlatformDefs.h
+++ b/xbmc/win32/PlatformDefs.h
@@ -88,6 +88,7 @@ typedef unsigned long ThreadIdentifier;
#define strtoll(p, e, b) _strtoi64(p, e, b)
extern "C" char * strptime(const char *buf, const char *fmt, struct tm *tm);
+extern "C" int strverscmp (const char *s1, const char *s2);
#endif // _WIN32
diff --git a/xbmc/win32/strverscmp.cpp b/xbmc/win32/strverscmp.cpp
new file mode 100644
index 0000000000..6641e8a880
--- /dev/null
+++ b/xbmc/win32/strverscmp.cpp
@@ -0,0 +1,135 @@
+extern "C" {
+/* Compare strings while treating digits characters numerically.
+ Copyright (C) 1997, 2000 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jean-Franois Bignolles <bignolle@ecoledoc.ibp.fr>, 1997.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Library General Public License as
+ published by the Free Software Foundation; either version 2 of the
+ License, or (at your option) any later version.
+
+ The GNU C Library 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
+ Library General Public License for more details.
+
+ You should have received a copy of the GNU Library General Public
+ License along with the GNU C Library; see the file COPYING.LIB. If not,
+ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ Boston, MA 02111-1307, USA. */
+
+#if HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <string.h>
+#include <ctype.h>
+
+/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
+ fractional parts, S_Z: idem but with leading Zeroes only */
+#define S_N 0x0
+#define S_I 0x4
+#define S_F 0x8
+#define S_Z 0xC
+
+/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
+#define CMP 2
+#define LEN 3
+
+
+/* ISDIGIT differs from isdigit, as follows:
+ - Its arg may be any int or unsigned int; it need not be an unsigned char.
+ - It's guaranteed to evaluate its argument exactly once.
+ - It's typically faster.
+ Posix 1003.2-1992 section 2.5.2.1 page 50 lines 1556-1558 says that
+ only '0' through '9' are digits. Prefer ISDIGIT to isdigit unless
+ it's important to use the locale's definition of `digit' even when the
+ host does not conform to Posix. */
+#define ISDIGIT(c) ((unsigned) (c) - '0' <= 9)
+
+#undef __strverscmp
+#undef strverscmp
+
+#ifndef weak_alias
+# define __strverscmp strverscmp
+#endif
+
+/* Compare S1 and S2 as strings holding indices/version numbers,
+ returning less than, equal to or greater than zero if S1 is less than,
+ equal to or greater than S2 (for more info, see the texinfo doc).
+*/
+
+int
+__strverscmp (const char *s1, const char *s2)
+{
+ const unsigned char *p1 = (const unsigned char *) s1;
+ const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+ int state;
+ int diff;
+
+ /* Symbol(s) 0 [1-9] others (padding)
+ Transition (10) 0 (01) d (00) x (11) - */
+ static const unsigned int next_state[] =
+ {
+ /* state x d 0 - */
+ /* S_N */ S_N, S_I, S_Z, S_N,
+ /* S_I */ S_N, S_I, S_I, S_I,
+ /* S_F */ S_N, S_F, S_F, S_F,
+ /* S_Z */ S_N, S_F, S_Z, S_Z
+ };
+
+ static const int result_type[] =
+ {
+ /* state x/x x/d x/0 x/- d/x d/d d/0 d/-
+ 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */
+
+ /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ /* S_I */ CMP, -1, -1, CMP, 1, LEN, LEN, CMP,
+ 1, LEN, LEN, CMP, CMP, CMP, CMP, CMP,
+ /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ /* S_Z */ CMP, 1, 1, CMP, -1, CMP, CMP, CMP,
+ -1, CMP, CMP, CMP
+ };
+
+ if (p1 == p2)
+ return 0;
+
+ c1 = *p1++;
+ c2 = *p2++;
+ /* Hint: '0' is a digit too. */
+ state = S_N | ((c1 == '0') + (ISDIGIT (c1) != 0));
+
+ while ((diff = c1 - c2) == 0 && c1 != '\0')
+ {
+ state = next_state[state];
+ c1 = *p1++;
+ c2 = *p2++;
+ state |= (c1 == '0') + (ISDIGIT (c1) != 0);
+ }
+
+ state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT (c2) != 0))];
+
+ switch (state)
+ {
+ case CMP:
+ return diff;
+
+ case LEN:
+ while (ISDIGIT (*p1++))
+ if (!ISDIGIT (*p2++))
+ return 1;
+
+ return ISDIGIT (*p2) ? -1 : diff;
+
+ default:
+ return state;
+ }
+}
+#ifdef weak_alias
+weak_alias (__strverscmp, strverscmp)
+#endif
+}