diff options
author | jmarshallnz <jmarshallnz@svn> | 2010-09-10 22:53:16 +0000 |
---|---|---|
committer | jmarshallnz <jmarshallnz@svn> | 2010-09-10 22:53:16 +0000 |
commit | 112f568bcf2a5bc2220fe387e1ee7c897de3b3a5 (patch) | |
tree | 36e80cd60a0c2b9e84cd898ffac22dd8eb4ee6ce | |
parent | 7466d20b04523569cb443ae63809773a55144ce3 (diff) |
merged: webinterface branch into trunk.
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@33665 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
29 files changed, 613 insertions, 200 deletions
diff --git a/XBMC.xcodeproj/project.pbxproj b/XBMC.xcodeproj/project.pbxproj index f6a05cddb3..df56146179 100644 --- a/XBMC.xcodeproj/project.pbxproj +++ b/XBMC.xcodeproj/project.pbxproj @@ -7204,7 +7204,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "#!/bin/bash\n\necho \"copy root files\"\n\nif [ \"$ACTION\" = build ] ; then\n\n# for external testing\n#TARGET_NAME=XBMC.app\n#SRCROOT=/Users/Shared/xbmc_svn/XBMC\n#TARGET_BUILD_DIR=/Users/Shared/xbmc_svn/XBMC/build/Debug\n\n# Force TARGET_NAME on ppc (do not use XBMC_ppc.app)\nTARGET_NAME=XBMC.app\n\n# rsync command with exclusions for items we don't want in the app package\nSYNC=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude *.dll --exclude *.DLL --exclude *linux.* --exclude *.zlib --exclude *.a\"\n\n# rsync command for excluding pngs and jpgs as well. Note that if the skin itself is not compiled\n# using XBMCTex then excluding the pngs and jpgs will most likely make the skin unusable \nSYNCSKIN=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude *.dll --exclude *.DLL --exclude *linux.* --exclude *.png --exclude *.jpg --exclude *.bat\"\n\n# rsync command for including everything but the skins\nADDONSYNC=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude skin.confluence\"\n\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/language\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/media\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/sounds\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/system\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/userdata\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/media\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/web\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/tools/osx\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/extras/user\"\n\n${SYNC} \"$SRCROOT/LICENSE.GPL\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/\"\n${SYNC} \"$SRCROOT/xbmc/osx/Credits.html\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/\"\n${SYNC} \"$SRCROOT/tools/osx\"\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/tools\"\n${ADDONSYNC} \"$SRCROOT/addons\"\t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/language\"\t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/media\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNCSKIN} \"$SRCROOT/addons/skin.confluence\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons\"\n${SYNC} \"$SRCROOT/addons/skin.confluence/backgrounds\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons/skin.confluence\"\n${SYNC} \"$SRCROOT/addons/skin.confluence/icon.png\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons/skin.confluence\"\n${SYNC} \"$SRCROOT/sounds\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/system\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/userdata\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/web/poc_jsonrpc/\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/web\"\n\n# copy extra packages if applicable\nif [ -d \"$SRCROOT/extras/system\" ]; then\n\t${SYNC} \"$SRCROOT/extras/system/\" \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\nfi\n\n# copy extra user packages if applicable\nif [ -d \"$SRCROOT/extras/user\" ]; then\n\t${SYNC} \"$SRCROOT/extras/user/\" \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/extras/user\"\nfi\n\n\n\n# magic that gets the icon to update\ntouch \"$TARGET_BUILD_DIR/$TARGET_NAME\"\n\n# not sure we want to do this with out major testing, many scripts cannot handle the spaces in the app name\n#mv \"$TARGET_BUILD_DIR/$TARGET_NAME\" \"$TARGET_BUILD_DIR/XBMC Media Center.app\"\n\nfi"; + shellScript = "#!/bin/bash\n\necho \"copy root files\"\n\nif [ \"$ACTION\" = build ] ; then\n\n# for external testing\n#TARGET_NAME=XBMC.app\n#SRCROOT=/Users/Shared/xbmc_svn/XBMC\n#TARGET_BUILD_DIR=/Users/Shared/xbmc_svn/XBMC/build/Debug\n\n# Force TARGET_NAME on ppc (do not use XBMC_ppc.app)\nTARGET_NAME=XBMC.app\n\n# rsync command with exclusions for items we don't want in the app package\nSYNC=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude *.dll --exclude *.DLL --exclude *linux.* --exclude *.zlib --exclude *.a\"\n\n# rsync command for excluding pngs and jpgs as well. Note that if the skin itself is not compiled\n# using XBMCTex then excluding the pngs and jpgs will most likely make the skin unusable \nSYNCSKIN=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude *.dll --exclude *.DLL --exclude *linux.* --exclude *.png --exclude *.jpg --exclude *.bat\"\n\n# rsync command for including everything but the skins\nADDONSYNC=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude skin.confluence\"\n\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/language\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/media\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/sounds\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/system\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/userdata\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/media\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/web\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/tools/osx\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/extras/user\"\n\n${SYNC} \"$SRCROOT/LICENSE.GPL\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/\"\n${SYNC} \"$SRCROOT/xbmc/osx/Credits.html\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/\"\n${SYNC} \"$SRCROOT/tools/osx\"\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/tools\"\n${ADDONSYNC} \"$SRCROOT/addons\"\t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/language\"\t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/media\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNCSKIN} \"$SRCROOT/addons/skin.confluence\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons\"\n${SYNC} \"$SRCROOT/addons/skin.confluence/backgrounds\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons/skin.confluence\"\n${SYNC} \"$SRCROOT/addons/skin.confluence/icon.png\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons/skin.confluence\"\n${SYNC} \"$SRCROOT/sounds\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/system\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/userdata\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/web/\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/web\"\n\n# copy extra packages if applicable\nif [ -d \"$SRCROOT/extras/system\" ]; then\n\t${SYNC} \"$SRCROOT/extras/system/\" \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\nfi\n\n# copy extra user packages if applicable\nif [ -d \"$SRCROOT/extras/user\" ]; then\n\t${SYNC} \"$SRCROOT/extras/user/\" \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/extras/user\"\nfi\n\n\n\n# magic that gets the icon to update\ntouch \"$TARGET_BUILD_DIR/$TARGET_NAME\"\n\n# not sure we want to do this with out major testing, many scripts cannot handle the spaces in the app name\n#mv \"$TARGET_BUILD_DIR/$TARGET_NAME\" \"$TARGET_BUILD_DIR/XBMC Media Center.app\"\n\nfi"; }; F5A1CBDF0F6B0B4700A96ABD /* copy frameworks */ = { isa = PBXShellScriptBuildPhase; @@ -7247,7 +7247,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/bash; - shellScript = "#!/bin/bash\n\necho \"copy root files\"\n\nif [ \"$ACTION\" = build ] ; then\n\n# for external testing\n#TARGET_NAME=XBMC.app\n#SRCROOT=/Users/Shared/xbmc_svn/XBMC\n#TARGET_BUILD_DIR=/Users/Shared/xbmc_svn/XBMC/build/Debug\n\n# rsync command with exclusions for items we don't want in the app package\nSYNC=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude *.dll --exclude *.DLL --exclude *linux.* --exclude *.zlib --exclude *.a\"\n\n# rsync command for excluding pngs and jpgs as well. Note that if the skin itself is not compiled\n# using XBMCTex then excluding the pngs and jpgs will most likely make the skin unusable \nSYNCSKIN=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude *.dll --exclude *.DLL --exclude *linux.* --exclude *.png --exclude *.jpg --exclude *.bat\"\n\n# rsync command for including everything but the skins\nADDONSYNC=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude skin.confluence\"\n\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/language\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/media\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/sounds\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/system\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/userdata\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/media\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/web\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/tools/osx\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/extras/user\"\n\n${SYNC} \"$SRCROOT/LICENSE.GPL\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/\"\n${SYNC} \"$SRCROOT/xbmc/osx/Credits.html\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/\"\n${SYNC} \"$SRCROOT/tools/osx\"\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/tools\"\n${ADDONSYNC} \"$SRCROOT/addons\"\t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/language\"\t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/media\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNCSKIN} \"$SRCROOT/addons/skin.confluence\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons\"\n${SYNC} \"$SRCROOT/addons/skin.confluence/backgrounds\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons/skin.confluence\"\n${SYNC} \"$SRCROOT/addons/skin.confluence/icon.png\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons/skin.confluence\"\n${SYNC} \"$SRCROOT/sounds\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/system\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/userdata\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/web/poc_jsonrpc/\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/web\"\n\n# copy extra packages if applicable\nif [ -d \"$SRCROOT/extras/system\" ]; then\n\t${SYNC} \"$SRCROOT/extras/system/\" \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\nfi\n\n# copy extra user packages if applicable\nif [ -d \"$SRCROOT/extras/user\" ]; then\n\t${SYNC} \"$SRCROOT/extras/user/\" \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/extras/user\"\nfi\n\n\n\n# magic that gets the icon to update\ntouch \"$TARGET_BUILD_DIR/$TARGET_NAME\"\n\n# not sure we want to do this with out major testing, many scripts cannot handle the spaces in the app name\n#mv \"$TARGET_BUILD_DIR/$TARGET_NAME\" \"$TARGET_BUILD_DIR/XBMC Media Center.app\"\n\nfi"; + shellScript = "#!/bin/bash\n\necho \"copy root files\"\n\nif [ \"$ACTION\" = build ] ; then\n\n# for external testing\n#TARGET_NAME=XBMC.app\n#SRCROOT=/Users/Shared/xbmc_svn/XBMC\n#TARGET_BUILD_DIR=/Users/Shared/xbmc_svn/XBMC/build/Debug\n\n# rsync command with exclusions for items we don't want in the app package\nSYNC=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude *.dll --exclude *.DLL --exclude *linux.* --exclude *.zlib --exclude *.a\"\n\n# rsync command for excluding pngs and jpgs as well. Note that if the skin itself is not compiled\n# using XBMCTex then excluding the pngs and jpgs will most likely make the skin unusable \nSYNCSKIN=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude *.dll --exclude *.DLL --exclude *linux.* --exclude *.png --exclude *.jpg --exclude *.bat\"\n\n# rsync command for including everything but the skins\nADDONSYNC=\"rsync -av --exclude CVS* --exclude .svn* --exclude .cvsignore* --exclude .cvspass* --exclude .DS_Store* --exclude skin.confluence\"\n\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/language\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/media\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/sounds\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/system\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/userdata\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/media\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/web\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/tools/osx\"\nmkdir -p \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/extras/user\"\n\n${SYNC} \"$SRCROOT/LICENSE.GPL\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/\"\n${SYNC} \"$SRCROOT/xbmc/osx/Credits.html\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/\"\n${SYNC} \"$SRCROOT/tools/osx\"\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/tools\"\n${ADDONSYNC} \"$SRCROOT/addons\"\t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/language\"\t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/media\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNCSKIN} \"$SRCROOT/addons/skin.confluence\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons\"\n${SYNC} \"$SRCROOT/addons/skin.confluence/backgrounds\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons/skin.confluence\"\n${SYNC} \"$SRCROOT/addons/skin.confluence/icon.png\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/addons/skin.confluence\"\n${SYNC} \"$SRCROOT/sounds\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/system\" \t\t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/userdata\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\n${SYNC} \"$SRCROOT/web/\" \t\"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/web\"\n\n# copy extra packages if applicable\nif [ -d \"$SRCROOT/extras/system\" ]; then\n\t${SYNC} \"$SRCROOT/extras/system/\" \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC\"\nfi\n\n# copy extra user packages if applicable\nif [ -d \"$SRCROOT/extras/user\" ]; then\n\t${SYNC} \"$SRCROOT/extras/user/\" \"$TARGET_BUILD_DIR/$TARGET_NAME/Contents/Resources/XBMC/extras/user\"\nfi\n\n\n\n# magic that gets the icon to update\ntouch \"$TARGET_BUILD_DIR/$TARGET_NAME\"\n\n# not sure we want to do this with out major testing, many scripts cannot handle the spaces in the app name\n#mv \"$TARGET_BUILD_DIR/$TARGET_NAME\" \"$TARGET_BUILD_DIR/XBMC Media Center.app\"\n\nfi"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ diff --git a/addons/webinterface.default/css/core.css b/addons/webinterface.default/css/core.css index 7dcbdf23b8..d276f8408b 100644 --- a/addons/webinterface.default/css/core.css +++ b/addons/webinterface.default/css/core.css @@ -6,23 +6,251 @@ body { #header {
position: relative;
- height: 150px;
- background: #333;
+ height: 50px;
+ border-bottom: 1px solid #000;
}
#header .logo {
+ padding-top: 1px;
+ }
+
+#navigation {
+ float: right;
+ }
+
+#spinner {
+ float: right;
+ padding: 11px 10px;
+ }
+
+#navigation ul {
+ list-style-type: none;
+ border-right: 1px solid #969696;
+ margin: 0;
+ padding: 0;
+ }
+
+#navigation ul li {
+ float: left;
+ color: #000;
+ cursor: pointer;
+ line-height: 50px;
+ margin: 0;
+ padding: 0 24px;
+ border-left: 1px solid #969696;
+ font-family: Verdana, sans-serif;
+ font-size: 18px;
+ font-weight: 700;
+ }
+
+#navigation ul li.selected,
+#navigation ul li:hover {
+ background: url('/images/header-selected-bg.png') repeat-x;
+ color: #fff;
+ }
+
+.floatableAlbum {
+ float: left;
+ width: 130px;
+ height: 150px;
padding: 10px;
- height: 100px;
}
-#nowPlayingPanel {
- background: #333;
- width: 480px;
+.floatableMovieCover {
+ float: left;
+ width: 130px;
+ height: 200px;
+ padding: 10px;
+ }
+
+.floatableTVShowCover {
+ float: left;
+ padding: 10px;
+ width: 379px;
+ height: 70px;
+ }
+
+#libraryContainer .floatableAlbum,
+#movieLibraryContainer .floatableMovieCover,
+#tvshowLibraryContainer .floatableTVShowCover {
+ cursor: pointer;
+ }
+
+.floatableAlbum div.imgWrapper,
+.floatableMovieCover div.imgWrapper,
+.floatableTVShowCover div.imgWrapper {
+ width: 130px;
height: 130px;
+ display: table-cell;
+ vertical-align: middle;
+ text-align: center;
+ }
+
+div.imgWrapper div.inner {
+ overflow: hidden;
+ width: 130px;
+ }
+
+.floatableMovieCover div.imgWrapper,
+.floatableMovieCover div.imgWrapper div.inner {
+ height: 190px;
+ }
+
+#overlay {
+ top: 50px;
+ left: 0;
+ right: 0;
+ bottom: 150px;
+ background: #3f3f3f;
+ position: fixed;
+ opacity: 0.8;
+ z-index: 2000; /* Above contentContainer's */
+ }
+
+.floatableTVShowCover div.imgWrapper,
+.floatableTVShowCover img,
+.floatableTVShowCover div.imgWrapper div.inner {
+ height: 70px;
+ width: 379px;
+ }
+
+.floatableAlbum img {
+ width: 130px;
+ }
+
+.floatableMovieCover img {
+ height: 180px;
+ }
+
+.floatableAlbum p.album,
+.floatableMovieCover p.album {
+ font-size: 12px;
+ font-weight: 700;
+ color: #000;
+ text-align: center;
+ margin: 0;
+ padding: 0;
+ width: 130px;
+ white-space: nowrap;
+ overflow: hidden;
+ }
+
+.floatableAlbum p.artist,
+.floatableMovieCover p.artist {
+ font-size: 11px;
+ color: #777;
+ text-align: center;
+ margin: 0;
+ padding: 0;
+ }
+
+.contentContainer {
+ overflow-x: hidden;
+ overflow-y: auto;
+ position: absolute;
+ top: 51px;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ background: #fff;
+ padding-bottom: 150px;
+ }
+
+.albumView .track {
+ cursor: pointer;
+ line-height: 10px;
+ font-size: 14px;
+ padding: 1px 0;
+ }
+
+/* Movie Overlay */
+
+.moviePopoverContainer {
+ z-index: 3000; /* Above overlay */
+ border: 1px solid #000;
padding: 10px;
+ margin: 10px;
+ position: fixed;
+ background: #3f3f3f;
+ top: 50px;
+ bottom: 150px;
+ left: 10%;
+ right: 10%;
+ opacity: 0.9;
+ }
+
+.moviePopoverContainer .closeButton {
+ float: right;
+ cursor: pointer;
+ }
+
+.moviePopoverContainer .movieCover {
+ height: 100%;
+ padding-right: 20px;
+ float: left;
+ z-index: 3100;
+ }
+
+.moviePopoverContainer .movieTitle {
+ font-size: 24px;
+ font-weight: 700;
+ color: #fff;
+ margin: 0;
+ }
+
+.moviePopoverContainer .runtime,
+.moviePopoverContainer .director,
+.moviePopoverContainer .genre,
+.moviePopoverContainer .plot {
+ color: #fff;
+ }
+
+.movieTitle .year {
+ font-weight: 400;
+ font-size: 18px;
+ }
+
+.playIcon {
+ background: url('/images/play-icon.png') center center no-repeat;
position: absolute;
- top: 0px;
- right: 0px;
+ z-index: 3500;
+ cursor: pointer;
+ opacity: 0.8;
+ }
+
+.playIcon:hover {
+ opacity: 1;
+ }
+
+/* Effects */
+
+#topScrollFade {
+ position: fixed;
+ top: 51px;
+ height: 33px;
+ z-index: 101;
+ left: 0;
+ right: 0;
+ background: url('/images/top-fade.png') top left repeat-x;
+ }
+
+/* Now Playing */
+
+#footerPopover {
+ position: fixed;
+ height: 150px;
+ bottom: 0;
+ left: 0;
+ right: 0;
+ z-index: 10000; /* Top most always */
+ background: #333;
+ opacity: 0.98;
+ }
+
+#nowPlayingPanel {
+ height: 130px;
+ width: 480px;
+ padding: 10px;
}
#audioCoverArt img {
@@ -119,6 +347,7 @@ body { width: 416px;
float: right;
cursor: pointer;
+ z-index: 1000;
}
#nowPlayingPlaylist {
@@ -244,91 +473,4 @@ body { #pbNext:hover {
background: url('/images/OSDNextTrackFO.png') no-repeat;
- }
-
-#navigation {
- position: absolute;
- top: 100px;
- left: 0;
- }
-
-#navigation ul {
- list-style-type: none;
- }
-
-#navigation ul li {
- float: left;
- background: #ccc;
- color: #fff;
- cursor: pointer;
- border: 2px solid #333;
- margin: 2px;
- padding: 4px;
- }
-
-#navigation ul li.selected,
-#navigation ul li:hover {
- background: #aaa;
- color: #333;
- }
-
-.floatableAlbum {
- float: left;
- width: 130px;
- height: 150px;
- padding: 10px;
- }
-
-#libraryContainer .floatableAlbum {
- cursor: pointer;
- }
-
-.floatableAlbum div.imgWrapper {
- width: 130px;
- height: 130px;
- display: table-cell;
- vertical-align: middle;
- }
-
-.floatableAlbum img {
- width: 130px;
- }
-
-.floatableAlbum p.album {
- font-size: 12px;
- font-weight: 700;
- color: #000;
- text-align: center;
- margin: 0;
- padding: 0;
- width: 130px;
- white-space: nowrap;
- overflow: hidden;
- }
-
-.floatableAlbum p.artist {
- font-size: 11px;
- color: #777;
- text-align: center;
- margin: 0;
- padding: 0;
- }
-
-.contentContainer {
- overflow-x: hidden;
- overflow-y: auto;
- position: absolute;
- top: 150px;
- bottom: 0;
- left: 0;
- right: 0;
- background: #fff;
- }
-
-.albumView .track {
- cursor: pointer;
- line-height: 10px;
- font-size: 14px;
- padding: 1px 0;
- }
-
+ }
\ No newline at end of file diff --git a/addons/webinterface.default/images/ajax-loader.gif b/addons/webinterface.default/images/ajax-loader.gif Binary files differnew file mode 100644 index 0000000000..4fb7c23522 --- /dev/null +++ b/addons/webinterface.default/images/ajax-loader.gif diff --git a/addons/webinterface.default/images/close-button.png b/addons/webinterface.default/images/close-button.png Binary files differnew file mode 100644 index 0000000000..767727a701 --- /dev/null +++ b/addons/webinterface.default/images/close-button.png diff --git a/addons/webinterface.default/images/header-selected-bg.png b/addons/webinterface.default/images/header-selected-bg.png Binary files differnew file mode 100644 index 0000000000..b60d4aed0b --- /dev/null +++ b/addons/webinterface.default/images/header-selected-bg.png diff --git a/addons/webinterface.default/images/logo.png b/addons/webinterface.default/images/logo.png Binary files differindex 8001cdb2f6..0f1b681877 100644 --- a/addons/webinterface.default/images/logo.png +++ b/addons/webinterface.default/images/logo.png diff --git a/addons/webinterface.default/images/play-icon.png b/addons/webinterface.default/images/play-icon.png Binary files differnew file mode 100644 index 0000000000..e75fa97be2 --- /dev/null +++ b/addons/webinterface.default/images/play-icon.png diff --git a/addons/webinterface.default/images/subheader-selected-bg.png b/addons/webinterface.default/images/subheader-selected-bg.png Binary files differnew file mode 100644 index 0000000000..83725c9f2c --- /dev/null +++ b/addons/webinterface.default/images/subheader-selected-bg.png diff --git a/addons/webinterface.default/images/top-fade.png b/addons/webinterface.default/images/top-fade.png Binary files differnew file mode 100644 index 0000000000..21cc82bb1a --- /dev/null +++ b/addons/webinterface.default/images/top-fade.png diff --git a/addons/webinterface.default/index.html b/addons/webinterface.default/index.html index 8dfa157b28..c4690a36e5 100644 --- a/addons/webinterface.default/index.html +++ b/addons/webinterface.default/index.html @@ -9,13 +9,30 @@ <link rel="shortcut icon" href="/favicon.ico" type="image/x-icon">
<!-- <link href="/images/logo.png" rel="image_src" /> -->
<meta name="robots" content="NOINDEX, NOFOLLOW">
- <link href="/css/core.css" rel="stylesheet" type="text/css">
+ <link href="/css/core.css?1.1.0" rel="stylesheet" type="text/css">
<script type="text/javascript" src="/js/jquery-1.4.2.js"></script>
<script type="text/javascript" src="/js/Launcher.js?1.0.0"></script>
</head>
<body>
<div id="header">
<img src="/images/logo.png" alt="XBMC Logo" class="logo">
+ <div id="navigation">
+ <ul>
+ <li id="remoteControl">Remote</li>
+ <li id="movieLibrary">Movies</li>
+ <li id="tvshowLibrary">TV Shows</li>
+ <li id="musicLibrary">Music</li>
+ <li id="settingsPanel">Settings</li>
+ </ul>
+ </div>
+ <img src="/images/ajax-loader.gif" alt="Loading please wait" id="spinner" style="display: none">
+ </div>
+ <div id="body">
+ <div id="topScrollFade" style="display: none;"></div>
+ <div id="content"></div>
+ <div id="overlay" style="display: none;"></div>
+ </div>
+ <div id="footerPopover">
<div id="nowPlayingPanel" style="display: none;">
<div id="nowPlayingContent">
<div id="audioDescription">
@@ -48,23 +65,8 @@ </div>
</div>
<span id="nextText">Next:</span>
- <div id="nextTrack" style="display: none;">
-
- </div>
- <div id="nowPlayingPlaylist" style="display: none;">
-
- </div>
- </div>
- </div>
- <div id="body">
- <div id="navigation">
- <ul>
- <li id="musicLibrary">Music</li>
- <li id="videoLibrary">Videos</li>
- </ul>
- </div>
- <div id="content">
-
+ <div id="nextTrack" style="display: none;"></div>
+ <div id="nowPlayingPlaylist" style="display: none;"></div>
</div>
</div>
<script type="text/javascript">
diff --git a/addons/webinterface.default/js/Launcher.js b/addons/webinterface.default/js/Launcher.js index 07a984c3b3..9751704f23 100644 --- a/addons/webinterface.default/js/Launcher.js +++ b/addons/webinterface.default/js/Launcher.js @@ -44,33 +44,38 @@ //
// For details, see the script.aculo.us web site: http://script.aculo.us/
+var DEBUG_MODE = true; /* Set to false to enable cached javascript */
+
var Launcher = {
VERSION: '1.0.0',
REQUIRED_JQUERY: '1.4.2',
load: function(libraryName) {
- document.write('<script type="text/javascript" src="' + libraryName + '?' + this.VERSION + '"><\/script>');
+ document.write('<script type="text/javascript" src="' + libraryName + '?' + (DEBUG_MODE ? this.randomValue() : this.VERSION) + '"><\/script>');
},
init: function() {
- function convertVersionString(versionString) {
- var v = versionString.replace(/_.*|\./g, '');
- v = parseInt(v + (v.length == 4 ? '' : '0'));
- return versionString.indexOf('_') > -1 ? v-1 : v;
- }
+ function convertVersionString(versionString) {
+ var v = versionString.replace(/_.*|\./g, '');
+ v = parseInt(v + (v.length == 4 ? '' : '0'));
+ return versionString.indexOf('_') > -1 ? v-1 : v;
+ }
- if(!jQuery || (convertVersionString(jQuery.fn.jquery) < convertVersionString(Launcher.REQUIRED_JQUERY)))
- throw("XBMC Web Interface requires the jQuery JavaScript framework >= " + Launcher.REQUIRED_JQUERY);
+ if(!jQuery || (convertVersionString(jQuery.fn.jquery) < convertVersionString(Launcher.REQUIRED_JQUERY)))
+ throw("XBMC Web Interface requires the jQuery JavaScript framework >= " + Launcher.REQUIRED_JQUERY);
- var js = /Launcher\.js(\?.*)?$/;
- $('html').find('script[src]').each(
- function(i, s) {
- if (s.src.match(js)) {
- var path = s.src.replace(js, ''),
- includes = s.src.match(/\?.*load=([a-z,]*)/);
- $.each((includes ? includes[1] : 'jquery.lazyload,Core,MediaLibrary,NowPlayingManager').split(','), function(i, include) {
- Launcher.load(path + include + '.js')
- });
- }
- });
+ var js = /Launcher\.js(\?.*)?$/;
+ $('html').find('script[src]').each(
+ function(i, s) {
+ if (s.src.match(js)) {
+ var path = s.src.replace(js, ''),
+ includes = s.src.match(/\?.*load=([a-z,]*)/);
+ $.each((includes ? includes[1] : 'jquery.lazyload,Core,MediaLibrary,NowPlayingManager').split(','), function(i, include) {
+ Launcher.load(path + include + '.js')
+ });
+ }
+ });
+ },
+ randomValue: function() {
+ return Math.random();
}
}
diff --git a/addons/webinterface.default/js/MediaLibrary.js b/addons/webinterface.default/js/MediaLibrary.js index c3375b21ae..20e0e0af66 100644 --- a/addons/webinterface.default/js/MediaLibrary.js +++ b/addons/webinterface.default/js/MediaLibrary.js @@ -30,14 +30,24 @@ MediaLibrary.prototype = { },
bindControls: function() {
$('#musicLibrary').click(jQuery.proxy(this.musicLibraryOpen, this));
- $('#videoLibrary').click(jQuery.proxy(this.videoLibraryOpen, this));
+ $('#movieLibrary').click(jQuery.proxy(this.movieLibraryOpen, this));
+ $('#tvshowLibrary').click(jQuery.proxy(this.tvshowLibraryOpen, this));
+ $('#overlay').click(jQuery.proxy(this.hideOverlay, this));
+ $(window).resize(jQuery.proxy(this.updatePlayButtonLocation, this));
+ },
+ resetPage: function() {
+ $('#musicLibrary').removeClass('selected');
+ $('#movieLibrary').removeClass('selected');
+ $('#tvshowLibrary').removeClass('selected');
+ this.hideOverlay();
},
musicLibraryOpen: function(event) {
+ this.resetPage();
$('#musicLibrary').addClass('selected');
- $('#videoLibrary').removeClass('selected');
$('.contentContainer').css('z-index', 1);
var libraryContainer = $('#libraryContainer');
if (!libraryContainer || libraryContainer.length == 0) {
+ $('#spinner').show();
jQuery.post(JSON_RPC + '?GetAlbums', '{"jsonrpc": "2.0", "method": "AudioLibrary.GetAlbums", "params": { "start": 0, "fields": ["album_description", "album_theme", "album_mood", "album_style", "album_type", "album_label", "album_artist", "album_genre", "album_rating", "album_title"] }, "id": 1}', jQuery.proxy(function(data) {
if (data && data.result && data.result.albums) {
libraryContainer = $('<div>');
@@ -49,19 +59,26 @@ MediaLibrary.prototype = { libraryContainer.html('');
}
$.each($(data.result.albums), jQuery.proxy(function(i, item) {
- var floatableAlbum = this.generateAlbumThumb(item.thumbnail, item.album_title, item.album_artist);
- floatableAlbum.bind('click', {album: item, }, jQuery.proxy(this.displayAlbumDetails, this));
+ var floatableAlbum = this.generateThumb('album', item.thumbnail, item.album_title, item.album_artist);
+ floatableAlbum.bind('click', { album: item }, jQuery.proxy(this.displayAlbumDetails, this));
libraryContainer.append(floatableAlbum);
}, this));
+ $('#spinner').hide();
//$('#libraryContainer img').lazyload();
+ libraryContainer.bind('scroll', { activeLibrary: libraryContainer }, jQuery.proxy(this.updateScrollEffects, this));
+ libraryContainer.trigger('scroll');
}, this), 'json');
} else {
libraryContainer.css('z-index', 100);
+ libraryContainer.trigger('scroll');
}
},
- generateAlbumThumb: function(thumbnail, album_title, album_artist) {
+ getThumbnailPath: function(thumbnail) {
+ return thumbnail ? ('/vfs/' + thumbnail) : DEFAULT_ALBUM_COVER;
+ },
+ generateThumb: function(type, thumbnail, album_title, album_artist) {
var floatableAlbum = $('<div>');
- var path = thumbnail ? ('/vfs/' + thumbnail) : DEFAULT_ALBUM_COVER;
+ var path = this.getThumbnailPath(thumbnail);
var title = album_title;
var artist = album_artist;
if (title.length > 18 && !(title.length <= 21)) {
@@ -70,14 +87,29 @@ MediaLibrary.prototype = { if (artist.length > 20 && !(artist.length <= 22)) {
artist = album_artist.substring(0, 20) + '...';
}
- floatableAlbum.addClass('floatableAlbum')
- .html('<div class="imgWrapper"><img src="' + path + '" alt="" /></div><p class="album" title="' + album_title + '">' + title + '</p><p class="artist" title="' + album_artist + '">' + artist + '</p>');
- return floatableAlbum
+ var className = '';
+ var code = '';
+ switch(type) {
+ case 'album':
+ className = 'floatableAlbum';
+ code = '<p class="album" title="' + album_title + '">' + title + '</p><p class="artist" title="' + album_artist + '">' + artist + '</p>';
+ break;
+ case 'movie':
+ className = 'floatableMovieCover';
+ code = '<p class="album" title="' + album_title + '">' + title + '</p>';
+ break;
+ case 'tvshow':
+ className = 'floatableTVShowCover';
+ break;
+ }
+ floatableAlbum.addClass(className).html('<div class="imgWrapper"><div class="inner"><img src="' + path + '" alt="" /></div></div>' + code);
+ return floatableAlbum;
},
displayAlbumDetails: function(event) {
-
var albumDetailsContainer = $('#albumDetails' + event.data.album.albumid);
+ $('#topScrollFade').hide();
if (!albumDetailsContainer || albumDetailsContainer.length == 0) {
+ $('#spinner').show();
jQuery.post(JSON_RPC + '?GetSongs', '{"jsonrpc": "2.0", "method": "AudioLibrary.GetSongs", "params": { "fields": ["title", "artist", "genre", "tracknumber", "discnumber", "duration", "year"], "albumid" : ' + event.data.album.albumid + ' }, "id": 1}', jQuery.proxy(function(data) {
albumDetailsContainer = $('<div>');
albumDetailsContainer.attr('id', 'albumDetails' + event.data.album.albumid)
@@ -97,19 +129,19 @@ MediaLibrary.prototype = { trackRow.append(albumTD);
}
var trackNumberTD = $('<td>');
- trackNumberTD.html(item.tracknumber).addClass('track').bind('click', { song: item }, jQuery.proxy(this.playTrack, this));
+ trackNumberTD.html(item.tracknumber).addClass('track').bind('click', { song: item, album: event.data.album }, jQuery.proxy(this.playTrack, this));
trackRow.append(trackNumberTD);
var trackTitleTD = $('<td>');
- trackTitleTD.html(item.title).addClass('track').bind('click', { song: item }, jQuery.proxy(this.playTrack, this));
+ trackTitleTD.html(item.title).addClass('track').bind('click', { song: item, album: event.data.album }, jQuery.proxy(this.playTrack, this));
trackRow.append(trackTitleTD);
var trackDurationTD = $('<td>');
- trackDurationTD.html(durationToString(item.duration)).addClass('track').bind('click', { song: item }, jQuery.proxy(this.playTrack, this));
+ trackDurationTD.html(durationToString(item.duration)).addClass('track').bind('click', { song: item, album: event.data.album }, jQuery.proxy(this.playTrack, this));
trackRow.append(trackDurationTD);
var trackArtistTD = $('<td>');
- trackArtistTD.html(item.artist).addClass('track').bind('click', { song: item }, jQuery.proxy(this.playTrack, this));
+ trackArtistTD.html(item.artist).addClass('track').bind('click', { song: item, album: event.data.album }, jQuery.proxy(this.playTrack, this));
trackRow.append(trackArtistTD);
var trackGenreTD = $('<td>');
- trackGenreTD.html(item.genre).addClass('track').bind('click', { song: item }, jQuery.proxy(this.playTrack, this));
+ trackGenreTD.html(item.genre).addClass('track').bind('click', { song: item, album: event.data.album }, jQuery.proxy(this.playTrack, this));
trackRow.append(trackGenreTD);
$('#albumDetails' + event.data.album.albumid + ' .resultSet').append(trackRow);
}, this));
@@ -132,22 +164,167 @@ MediaLibrary.prototype = { trackRow.append(trackGenreTD);
$('#albumDetails' + event.data.album.albumid + ' .resultSet').append(trackRow);
}
- $('#albumDetails' + event.data.album.albumid + ' .albumThumb').append(this.generateAlbumThumb(albumThumbnail, albumTitle, albumArtist));
+ $('#albumDetails' + event.data.album.albumid + ' .albumThumb').append(this.generateThumb('album', albumThumbnail, albumTitle, albumArtist));
$('.contentContainer').css('z-index', 1);
+ $('#spinner').hide();
}, this), 'json');
} else {
$('.contentContainer').css('z-index', 1);
$('#albumDetails' + event.data.album.albumid).css('z-index', 100);
}
},
- playTrack: function(event) {
- jQuery.post(JSON_RPC + '?PlaySong', '{"jsonrpc": "2.0", "method": "XBMC.Play", "params": { "songid": ' + event.data.song.songid + ' }, "id": 1}', jQuery.proxy(function(data) {
+ hideOverlay: function(event) {
+ if (this.activeCover) {
+ $(this.activeCover).remove();
+ this.activeCover = null;
+ }
+ $('#overlay').hide();
+ },
+ updatePlayButtonLocation: function(event) {
+ var movieContainer = $('.movieCover');
+ if (movieContainer.length > 0) {
+ var playIcon = $('.playIcon');
+ if (playIcon.length > 0) {
+ playIcon.width($(movieContainer[0]).width());
+ playIcon.height($(movieContainer[0]).height());
+ }
+ }
+ },
+ playMovie: function(event) {
+ jQuery.post(JSON_RPC + '?PlayMovie', '{"jsonrpc": "2.0", "method": "XBMC.Play", "params": { "movieid": ' + event.data.movie.movieid + ' }, "id": 1}', jQuery.proxy(function(data) {
+
+ this.hideOverlay();
+ }, this), 'json');
+ },
+ displayMovieDetails: function(event) {
+ var movieDetails = $('<div>');
+ movieDetails.attr('id', 'movie-' + event.data.movie.movieid);
+ movieDetails.addClass('moviePopoverContainer');
+ var closeButton = $('<img>');
+ closeButton.attr('src', '/images/close-button.png');
+ closeButton.addClass('closeButton').bind('click', jQuery.proxy(this.hideOverlay, this));
+ movieDetails.append(closeButton);
+ var movieCover = $('<img>');
+ movieCover.attr('src', this.getThumbnailPath(event.data.movie.thumbnail)).addClass('movieCover');
+ movieDetails.append(movieCover);
+ var playIcon = $('<div>');
+ playIcon.addClass('playIcon');
+ playIcon.bind('click', {movie: event.data.movie}, jQuery.proxy(this.playMovie, this));
+ movieDetails.append(playIcon);
+ var movieTitle = $('<p>');
+ movieTitle.addClass('movieTitle');
+ var yearText = event.data.movie.year ? ' <span class="year">(' + event.data.movie.year + ')</span>' : '';
+ movieTitle.html(event.data.movie.title + yearText);
+ movieDetails.append(movieTitle);
+ if (event.data.movie.runtime) {
+ var runtime = $('<p>');
+ runtime.addClass('runtime').html('<strong>Runtime:</strong> ' + event.data.movie.runtime + ' minutes');
+ movieDetails.append(runtime);
+ }
+ if (event.data.movie.plot) {
+ var plot = $('<p>');
+ plot.addClass('plot').html(event.data.movie.plot);
+ movieDetails.append(plot);
+ }
+ if (event.data.movie.genre) {
+ var genre = $('<p>');
+ genre.addClass('genre').html('<strong>Genre:</strong> ' + event.data.movie.genre);
+ movieDetails.append(genre);
+ }
+ if (event.data.movie.rating) {
+ //Todo
+ }
+ if (event.data.movie.director) {
+ var director = $('<p>');
+ director.addClass('director').html('<strong>Directed By:</strong> ' + event.data.movie.director);
+ movieDetails.append(director);
+ }
+ this.activeCover = movieDetails;
+ $('body').append(movieDetails);
+ $('#overlay').show();
+ this.updatePlayButtonLocation();
+ },
+ displayTVShowDetails: function(event) {
+ },
+ playTrack: function(event) {
+ jQuery.post(JSON_RPC + '?ClearPlaylist', '{"jsonrpc": "2.0", "method": "AudioPlaylist.Clear", "id": 1}', jQuery.proxy(function(data) {
+ //check that clear worked.
+ jQuery.post(JSON_RPC + '?AddAlbumToPlaylist', '{"jsonrpc": "2.0", "method": "AudioPlaylist.Add", "params": { "albumid": ' + event.data.album.albumid + ' }, "id": 1}', jQuery.proxy(function(data) {
+ //play specific song in playlist
+ jQuery.post(JSON_RPC + '?PlaylistItemPlay', '{"jsonrpc": "2.0", "method": "AudioPlaylist.Play", "params": { "songid": ' + event.data.song.songid + ' }, "id": 1}', function() {}, 'json');
+ }, this), 'json');
}, this), 'json');
},
- videoLibraryOpen: function() {
- $('#musicLibrary').removeClass('selected');
- $('#videoLibrary').addClass('selected');
- $('#content').html('');
+ movieLibraryOpen: function() {
+ this.resetPage();
+ $('#movieLibrary').addClass('selected');
+ $('.contentContainer').css('z-index', 1);
+ var libraryContainer = $('#movieLibraryContainer');
+ if (!libraryContainer || libraryContainer.length == 0) {
+ $('#spinner').show();
+ jQuery.post(JSON_RPC + '?GetMovies', '{"jsonrpc": "2.0", "method": "VideoLibrary.GetMovies", "params": { "start": 0, "fields": ["genre", "director", "trailer", "tagline", "plot", "plotoutline", "title", "originaltitle", "lastplayed", "showtitle", "firstaired", "duration", "season", "episode", "runtime", "year", "playcount", "rating"] }, "id": 1}', jQuery.proxy(function(data) {
+ if (data && data.result && data.result.movies) {
+ libraryContainer = $('<div>');
+ libraryContainer.css('z-index', 100)
+ .attr('id', 'movieLibraryContainer')
+ .addClass('contentContainer');
+ $('#content').append(libraryContainer);
+ } else {
+ libraryContainer.html('');
+ }
+ $.each($(data.result.movies), jQuery.proxy(function(i, item) {
+ var floatableMovieCover = this.generateThumb('movie', item.thumbnail, item.title, "");
+ floatableMovieCover.bind('click', { movie: item }, jQuery.proxy(this.displayMovieDetails, this));
+ libraryContainer.append(floatableMovieCover);
+ }, this));
+ $('#spinner').hide();
+ libraryContainer.bind('scroll', { activeLibrary: libraryContainer }, jQuery.proxy(this.updateScrollEffects, this));
+ libraryContainer.trigger('scroll');
+ //$('#libraryContainer img').lazyload();
+ }, this), 'json');
+ } else {
+ libraryContainer.css('z-index', 100);
+ libraryContainer.trigger('scroll');
+ }
+ },
+ tvshowLibraryOpen: function() {
+ this.resetPage();
+ $('#tvshowLibrary').addClass('selected');
+ $('.contentContainer').css('z-index', 1);
+ var libraryContainer = $('#tvshowLibraryContainer');
+ if (!libraryContainer || libraryContainer.length == 0) {
+ $('#spinner').show();
+ jQuery.post(JSON_RPC + '?GetTVShows', '{"jsonrpc": "2.0", "method": "VideoLibrary.GetTVShows", "params": { "start": 0, "fields": ["genre", "director", "trailer", "tagline", "plot", "plotoutline", "title", "originaltitle", "lastplayed", "showtitle", "firstaired", "duration", "season", "episode", "runtime", "year", "playcount", "rating"] }, "id": 1}', jQuery.proxy(function(data) {
+ if (data && data.result && data.result.tvshows) {
+ libraryContainer = $('<div>');
+ libraryContainer.css('z-index', 100)
+ .attr('id', 'tvshowLibraryContainer')
+ .addClass('contentContainer');
+ $('#content').append(libraryContainer);
+ } else {
+ libraryContainer.html('');
+ }
+ $.each($(data.result.tvshows), jQuery.proxy(function(i, item) {
+ var floatableTVShowCover = this.generateThumb('tvshow', item.thumbnail, item.title, "");
+ floatableTVShowCover.bind('click', { tvshow: item }, jQuery.proxy(this.displayTVShowDetails, this));
+ libraryContainer.append(floatableTVShowCover);
+ }, this));
+ //$('#libraryContainer img').lazyload();
+ $('#spinner').hide();
+ libraryContainer.bind('scroll', { activeLibrary: libraryContainer }, jQuery.proxy(this.updateScrollEffects, this));
+ libraryContainer.trigger('scroll');
+ }, this), 'json');
+ } else {
+ libraryContainer.css('z-index', 100);
+ libraryContainer.trigger('scroll');
+ }
+ },
+ updateScrollEffects: function(event) {
+ if (event.data.activeLibrary && $(event.data.activeLibrary).scrollTop() > 0) {
+ $('#topScrollFade').fadeIn();
+ } else {
+ $('#topScrollFade').fadeOut();
+ }
}
}
\ No newline at end of file diff --git a/addons/webinterface.default/js/NowPlayingManager.js b/addons/webinterface.default/js/NowPlayingManager.js index d608bd86f6..29278ece3f 100644 --- a/addons/webinterface.default/js/NowPlayingManager.js +++ b/addons/webinterface.default/js/NowPlayingManager.js @@ -35,7 +35,7 @@ NowPlayingManager.prototype = { $(window).bind('click', jQuery.proxy(this.hidePlaylist, this));
},
updateState: function() {
- jQuery.post(JSON_RPC, '{"jsonrpc": "2.0", "method": "Player.GetActivePlayers", "id": 1}', jQuery.proxy(function(data) {
+ jQuery.post(JSON_RPC + '?UpdateState', '{"jsonrpc": "2.0", "method": "Player.GetActivePlayers", "id": 1}', jQuery.proxy(function(data) {
if (data && data.result) {
if (data.result.audio) {
this.activePlayer = 'Audio';
@@ -166,8 +166,8 @@ NowPlayingManager.prototype = { data: '{"jsonrpc": "2.0", "method": "AudioPlaylist.GetItems", "params": { "fields": ["title", "album", "artist", "duration"] }, "id": 1}',
success: jQuery.proxy(function(data) {
if (data && data.result && data.result.items && data.result.total > 0) {
- //Compare new playlist to active playlist, only redraw if a change is noticed.
- if (this.playlistChanged(data.result.items) || (this.activePlaylistItem && (this.activePlaylistItem.seq != data.result.current))) {
+ //Compare new playlist to active playlist, only redraw if a change is noticed
+ if (!this.activePlaylistItem || this.playlistChanged(data.result.items) || (this.activePlaylistItem && (this.activePlaylistItem.seq != data.result.current))) {
var ul = $('<ul>');
var activeItem;
$.each($(data.result.items), jQuery.proxy(function(i, item) {
@@ -179,16 +179,17 @@ NowPlayingManager.prototype = { li.addClass('activeItem');
}
if (i == (data.result.current + 1)) {
- $('#nextTrack').html(code);
- $('#nextTrack').show();
+ $('#nextTrack').html(code).show();
}
li.bind('click', jQuery.proxy(this.playPlaylistItem, this));
ul.append(li.attr('seq', i).html(code));
}, this));
if (data.result.total > 1) {
+ if (activeItem && data.result.total-1 == activeItem.seq) {
+ $('#nextTrack').html('<div class="trackInfo">Last track in playlist</div>').show();
+ }
$('#nextText').show();
- $('#nowPlayingPlaylist').html('')
- .append(ul);
+ $('#nowPlayingPlaylist').html('').append(ul);
} else {
$('#nextText').hide();
$('#nowPlayingPlaylist').hide();
@@ -226,12 +227,10 @@ NowPlayingManager.prototype = { });
},
stopAudioPlaylistUpdate: function() {
- this.stopRefreshTime();
this.autoRefreshAudioPlaylist = false;
this.updateActiveItemDurationRunOnce = false;
},
stopVideoPlaylistUpdate: function() {
- this.stopRefreshTime();
this.autoRefreshVideoPlaylist = false;
this.updateActiveItemDurationRunOnce = false;
},
@@ -255,10 +254,10 @@ NowPlayingManager.prototype = { this.refreshVideoData();
}
}
- if (this.autoRefreshData && !this.activeItemTimer) {
- this.activeItemTimer = 1;
- setTimeout(jQuery.proxy(this.updateActiveItemDurationLoop, this), 1000);
- }
+ }
+ if (this.autoRefreshData && !this.activeItemTimer) {
+ this.activeItemTimer = 1;
+ setTimeout(jQuery.proxy(this.updateActiveItemDurationLoop, this), 1000);
}
}, this), 'json');
},
@@ -409,15 +408,17 @@ NowPlayingManager.prototype = { li.addClass('activeItem');
}
if (i == (data.result.current + 1)) {
- $('#nextTrack').html(code);
+ $('#nextTrack').html(code).show();
}
li.bind('click', jQuery.proxy(this.playPlaylistItem, this));
ul.append(li.attr('seq', i).html(code));
}, this));
if (data.result.total > 1) {
$('#nextText').show();
- $('#nowPlayingPlaylist').html('')
- .append(ul);
+ if (activeItem && data.result.total == activeItem.seq) {
+ $('#nextTrack').html('<div class="trackInfo">Last track in playlist</div>').show();
+ }
+ $('#nowPlayingPlaylist').html('').append(ul);
} else {
$('#nextText').hide();
$('#nowPlayingPlaylist').hide();
diff --git a/tools/Linux/packaging/debian/rules.hardy b/tools/Linux/packaging/debian/rules.hardy index 74ca818b2f..fbb7a5c871 100755 --- a/tools/Linux/packaging/debian/rules.hardy +++ b/tools/Linux/packaging/debian/rules.hardy @@ -45,7 +45,7 @@ binary: binary-arch binary-indep binary-indep: dh binary-indep --until dh_installdirs - $(MAKE) install-web install-datas install-livedatas prefix=$(CURDIR)/debian/tmp/usr/ + $(MAKE) install-datas install-livedatas prefix=$(CURDIR)/debian/tmp/usr/ mkdir -p $(CURDIR)/debian/tmp/usr/share/applications $(CURDIR)/debian/tmp/usr/share/pixmaps cp $(CURDIR)/tools/Linux/xbmc.png $(CURDIR)/debian/tmp/usr/share/pixmaps/ cp $(CURDIR)/tools/Linux/xbmc.desktop $(CURDIR)/debian/tmp/usr/share/applications/ diff --git a/xbmc/ApplicationMessenger.cpp b/xbmc/ApplicationMessenger.cpp index 0b87b85f28..3020102892 100644 --- a/xbmc/ApplicationMessenger.cpp +++ b/xbmc/ApplicationMessenger.cpp @@ -471,7 +471,13 @@ case TMSG_POWERDOWN: g_playlistPlayer.Play(pMsg->dwParam1); else g_playlistPlayer.Play(); + break; + case TMSG_PLAYLISTPLAYER_PLAY_SONG_ID: + if (pMsg->dwParam1 != (DWORD) -1) + g_playlistPlayer.PlaySongId(pMsg->dwParam1); + else + g_playlistPlayer.Play(); break; case TMSG_PLAYLISTPLAYER_NEXT: @@ -763,6 +769,12 @@ void CApplicationMessenger::PlayListPlayerPlay(int iSong) SendMessage(tMsg, true); } +void CApplicationMessenger::PlayListPlayerPlaySongId(int songId) +{ + ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_PLAY_SONG_ID, songId}; + SendMessage(tMsg, true); +} + void CApplicationMessenger::PlayListPlayerNext() { ThreadMessage tMsg = {TMSG_PLAYLISTPLAYER_NEXT}; diff --git a/xbmc/ApplicationMessenger.h b/xbmc/ApplicationMessenger.h index 8f10eeb860..cd0ea75e03 100644 --- a/xbmc/ApplicationMessenger.h +++ b/xbmc/ApplicationMessenger.h @@ -49,6 +49,7 @@ class CGUIDialog; #define TMSG_PLAYLISTPLAYER_CLEAR 214 #define TMSG_PLAYLISTPLAYER_SHUFFLE 215 #define TMSG_PLAYLISTPLAYER_GET_ITEMS 216 +#define TMSG_PLAYLISTPLAYER_PLAY_SONG_ID 217 #define TMSG_PICTURE_SHOW 220 #define TMSG_PICTURE_SLIDESHOW 221 @@ -117,6 +118,7 @@ public: void PlayListPlayerPlay(); void PlayListPlayerPlay(int iSong); + void PlayListPlayerPlaySongId(int songId); void PlayListPlayerNext(); void PlayListPlayerPrevious(); void PlayListPlayerAdd(int playlist, const CFileItem &item); diff --git a/xbmc/DateTime.cpp b/xbmc/DateTime.cpp index eb499c50d5..5be49c31ea 100644 --- a/xbmc/DateTime.cpp +++ b/xbmc/DateTime.cpp @@ -1208,3 +1208,35 @@ CStdString CDateTime::GetAsLocalizedDateTime(bool longDate/*=false*/, bool withS { return GetAsLocalizedDate(longDate)+" "+GetAsLocalizedTime("", withSeconds); } + +CDateTime CDateTime::GetAsUTCDateTime() const +{ + TIME_ZONE_INFORMATION tz; + + CDateTime time(m_time); + switch(GetTimeZoneInformation(&tz)) + { + case TIME_ZONE_ID_DAYLIGHT: + time += CDateTimeSpan(0, 0, tz.Bias + tz.DaylightBias, 0); + break; + case TIME_ZONE_ID_STANDARD: + time += CDateTimeSpan(0, 0, tz.Bias + tz.StandardBias, 0); + break; + case TIME_ZONE_ID_UNKNOWN: + time += CDateTimeSpan(0, 0, tz.Bias, 0); + break; + } + + return time; +} + +static const char *DAY_NAMES[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; +static const char *MONTH_NAMES[] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" }; + +CStdString CDateTime::GetAsRFC1123DateTime() const +{ + CDateTime time(GetAsUTCDateTime()); + CStdString result; + result.Format("%s, %02i %s %04i %02i:%02i:%02i GMT", DAY_NAMES[time.GetDayOfWeek()], time.GetDay(), MONTH_NAMES[time.GetMonth()-1], time.GetYear(), time.GetHour(), time.GetMinute(), time.GetSecond()); + return result; +}
\ No newline at end of file diff --git a/xbmc/DateTime.h b/xbmc/DateTime.h index b1dbc48b9a..5483ace239 100644 --- a/xbmc/DateTime.h +++ b/xbmc/DateTime.h @@ -176,11 +176,13 @@ public: void GetAsTm(tm& time) const; void GetAsTimeStamp(FILETIME& time) const; + CDateTime GetAsUTCDateTime() const; CStdString GetAsDBDateTime() const; CStdString GetAsDBDate() const; CStdString GetAsLocalizedDate(bool longDate=false) const; CStdString GetAsLocalizedTime(const CStdString &format, bool withSeconds=true) const; CStdString GetAsLocalizedDateTime(bool longDate=false, bool withSeconds=true) const; + CStdString GetAsRFC1123DateTime() const; void SetValid(bool yesNo); bool IsValid() const; diff --git a/xbmc/FileSystem/MusicDatabaseDirectory/DirectoryNodeAlbum.cpp b/xbmc/FileSystem/MusicDatabaseDirectory/DirectoryNodeAlbum.cpp index 81477d81e2..c7688096e8 100644 --- a/xbmc/FileSystem/MusicDatabaseDirectory/DirectoryNodeAlbum.cpp +++ b/xbmc/FileSystem/MusicDatabaseDirectory/DirectoryNodeAlbum.cpp @@ -45,7 +45,7 @@ bool CDirectoryNodeAlbum::GetContent(CFileItemList& items) CQueryParams params; CollectQueryParams(params); - bool bSuccess=musicdatabase.GetAlbumsNav(BuildPath(), items, params.GetGenreId(), params.GetArtistId()); + bool bSuccess=musicdatabase.GetAlbumsNav(BuildPath(), items, params.GetGenreId(), params.GetArtistId(),-1,-1); musicdatabase.Close(); diff --git a/xbmc/GUIDialogSmartPlaylistRule.cpp b/xbmc/GUIDialogSmartPlaylistRule.cpp index 5b7a903765..991cdc544c 100644 --- a/xbmc/GUIDialogSmartPlaylistRule.cpp +++ b/xbmc/GUIDialogSmartPlaylistRule.cpp @@ -140,7 +140,7 @@ void CGUIDialogSmartPlaylistRule::OnBrowse() else if (m_rule.m_field == CSmartPlaylistRule::FIELD_ALBUM) { if (m_type.Equals("songs") || m_type.Equals("mixed") || m_type.Equals("albums")) - database.GetAlbumsNav("musicdb://6/",items,-1,-1); + database.GetAlbumsNav("musicdb://6/",items,-1,-1,-1,-1); if (m_type.Equals("musicvideos") || m_type.Equals("mixed")) { CFileItemList items2; diff --git a/xbmc/MusicDatabase.cpp b/xbmc/MusicDatabase.cpp index d67be637fc..c7f42948c9 100644 --- a/xbmc/MusicDatabase.cpp +++ b/xbmc/MusicDatabase.cpp @@ -2813,8 +2813,15 @@ bool CMusicDatabase::GetAlbumFromSong(const CSong &song, CAlbum &album) return false; } -bool CMusicDatabase::GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist) +bool CMusicDatabase::GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist, int start, int end) { + //Create limit + CStdString limit; + if (start >= 0 && end >= 0) + { + limit.Format(" limit %i,%i", start, end); + } + // where clause CStdString strWhere; if (idGenre!=-1) @@ -2830,7 +2837,7 @@ bool CMusicDatabase::GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& i "join exgenresong on song.idSong=exgenresong.idSong " "where exgenresong.idGenre=%i" ")" - ") " + ") " + limit , idGenre, idGenre); } @@ -2862,15 +2869,15 @@ bool CMusicDatabase::GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& i "select exartistalbum.idAlbum from exartistalbum " // All albums where extra album artists fit "where exartistalbum.idArtist=%i" ")" - ") " + ") " + limit , idArtist, idArtist, idArtist, idArtist); } else { // no artist given, so exclude any single albums (aka empty tagged albums) if (strWhere.IsEmpty()) - strWhere += "where albumview.strAlbum <> ''"; + strWhere += "where albumview.strAlbum <> ''" + limit; else - strWhere += "and albumview.strAlbum <> ''"; + strWhere += "and albumview.strAlbum <> ''" + limit; } bool bResult = GetAlbumsByWhere(strBaseDir, strWhere, "", items); diff --git a/xbmc/MusicDatabase.h b/xbmc/MusicDatabase.h index 45450ff190..e59bba9341 100644 --- a/xbmc/MusicDatabase.h +++ b/xbmc/MusicDatabase.h @@ -158,7 +158,7 @@ public: bool GetGenresNav(const CStdString& strBaseDir, CFileItemList& items); bool GetYearsNav(const CStdString& strBaseDir, CFileItemList& items); bool GetArtistsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, bool albumArtistsOnly); - bool GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist); + bool GetAlbumsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist, int start, int end); bool GetAlbumsByYear(const CStdString &strBaseDir, CFileItemList& items, int year); bool GetSongsNav(const CStdString& strBaseDir, CFileItemList& items, int idGenre, int idArtist,int idAlbum); bool GetSongsByYear(const CStdString& baseDir, CFileItemList& items, int year); diff --git a/xbmc/MusicInfoScanner.cpp b/xbmc/MusicInfoScanner.cpp index e4614d3fb4..475c1a0a03 100644 --- a/xbmc/MusicInfoScanner.cpp +++ b/xbmc/MusicInfoScanner.cpp @@ -237,7 +237,7 @@ void CMusicInfoScanner::FetchAlbumInfo(const CStdString& strDirectory) if (strDirectory.IsEmpty()) { m_musicDatabase.Open(); - m_musicDatabase.GetAlbumsNav("musicdb://3/",items,-1,-1); + m_musicDatabase.GetAlbumsNav("musicdb://3/",items,-1,-1,-1,-1); m_musicDatabase.Close(); } else diff --git a/xbmc/PlayListPlayer.cpp b/xbmc/PlayListPlayer.cpp index eb6c0c5f03..d81bfae895 100644 --- a/xbmc/PlayListPlayer.cpp +++ b/xbmc/PlayListPlayer.cpp @@ -30,6 +30,7 @@ #include "PlayList.h" #include "utils/log.h" #include "utils/TimeUtils.h" +#include "MusicInfoTag.h" using namespace PLAYLIST; @@ -203,6 +204,26 @@ void CPlayListPlayer::Play() Play(0); } +void CPlayListPlayer::PlaySongId(int songId) +{ + if (m_iCurrentPlayList == PLAYLIST_NONE) + return; + + CPlayList& playlist = GetPlaylist(m_iCurrentPlayList); + if (playlist.size() <= 0) + Play(); + + for (int i = 0; i < playlist.size(); i++) + { + if (playlist[i]->HasMusicInfoTag() && playlist[i]->GetMusicInfoTag()->GetDatabaseId() == songId) + { + Play(i); + return; + } + } + Play(); +} + void CPlayListPlayer::Play(int iSong, bool bAutoPlay /* = false */, bool bPlayPrevious /* = false */) { if (m_iCurrentPlayList == PLAYLIST_NONE) diff --git a/xbmc/PlayListPlayer.h b/xbmc/PlayListPlayer.h index 0b4a5cf354..103cd1e545 100644 --- a/xbmc/PlayListPlayer.h +++ b/xbmc/PlayListPlayer.h @@ -58,7 +58,7 @@ public: \sa PlayNext */ void PlayPrevious(); - + void PlaySongId(int songId); void Play(); /*! \brief Start playing a particular entry in the current playlist diff --git a/xbmc/lib/libjsonrpc/AVPlaylistOperations.cpp b/xbmc/lib/libjsonrpc/AVPlaylistOperations.cpp index 11dad4ac48..755e14329c 100644 --- a/xbmc/lib/libjsonrpc/AVPlaylistOperations.cpp +++ b/xbmc/lib/libjsonrpc/AVPlaylistOperations.cpp @@ -40,7 +40,13 @@ JSON_STATUS CAVPlaylistOperations::Play(const CStdString &method, ITransportLaye if (parameterObject.isInt()) g_application.getApplicationMessenger().PlayListPlayerPlay(parameterObject.asInt()); else - g_application.getApplicationMessenger().PlayListPlayerPlay(); + { + int songId = (parameterObject.isMember("songid") && parameterObject["songid"].isInt()) ? parameterObject["songid"].asInt() : 0; + if (songId > 0) + g_application.getApplicationMessenger().PlayListPlayerPlaySongId(songId); + else + g_application.getApplicationMessenger().PlayListPlayerPlay(); + } NotifyAll(); return ACK; diff --git a/xbmc/lib/libjsonrpc/AudioLibrary.cpp b/xbmc/lib/libjsonrpc/AudioLibrary.cpp index 6a6025f74e..dae895074e 100644 --- a/xbmc/lib/libjsonrpc/AudioLibrary.cpp +++ b/xbmc/lib/libjsonrpc/AudioLibrary.cpp @@ -69,9 +69,11 @@ JSON_STATUS CAudioLibrary::GetAlbums(const CStdString &method, ITransportLayer * int artistID = ParameterAsInt(param, -1, "artistid"); int genreID = ParameterAsInt(param, -1, "genreid"); + int start = ParameterAsInt(param, -1, "start"); + int end = ParameterAsInt(param, -1, "end"); CFileItemList items; - if (musicdatabase.GetAlbumsNav("", items, genreID, artistID)) + if (musicdatabase.GetAlbumsNav("", items, genreID, artistID, start, end)) HandleFileItemList("albumid", false, "albums", items, param, result); musicdatabase.Close(); diff --git a/xbmc/lib/libjsonrpc/JSONRPC.cpp b/xbmc/lib/libjsonrpc/JSONRPC.cpp index 5768660cf8..a8c8baf6d4 100644 --- a/xbmc/lib/libjsonrpc/JSONRPC.cpp +++ b/xbmc/lib/libjsonrpc/JSONRPC.cpp @@ -302,7 +302,6 @@ JSON_STATUS CJSONRPC::Announce(const CStdString &method, ITransportLayer *transp CStdString CJSONRPC::MethodCall(const CStdString &inputString, ITransportLayer *transport, IClient *client) { - CLog::Log(LOGDEBUG, "JSONRPC: %s", inputString.c_str()); Value inputroot, outputroot, result; JSON_STATUS errorCode = OK; diff --git a/xbmc/utils/WebServer.cpp b/xbmc/utils/WebServer.cpp index 1ef7f740d1..ebdb38890b 100644 --- a/xbmc/utils/WebServer.cpp +++ b/xbmc/utils/WebServer.cpp @@ -28,6 +28,7 @@ #include "../Util.h" #include "log.h" #include "SingleLock.h" +#include "DateTime.h" #include "addons/AddonManager.h" #ifdef _WIN32 @@ -111,8 +112,6 @@ int CWebServer::AnswerToConnection(void *cls, struct MHD_Connection *connection, unsigned int *upload_data_size, void **con_cls) #endif { - CLog::Log(LOGNOTICE, "WebServer: %s | %s", method, url); - CWebServer *server = (CWebServer *)cls; CStdString strURL = url; CStdString originalURL = url; @@ -210,10 +209,6 @@ int CWebServer::JSONRPC(CWebServer *server, void **con_cls, struct MHD_Connectio { CStdString *jsoncall = (CStdString *)(*con_cls); - if (jsoncall->size() > 2000) - CLog::Log(LOGINFO, "JSONRPC: Recieved a jsonrpc call wich is longer than 2000 characters, skipping logging it"); - else - CLog::Log(LOGINFO, "JSONRPC: Recieved a jsonrpc call - %s", jsoncall->c_str()); CHTTPClient client; CStdString jsonresponse = CJSONRPC::MethodCall(*jsoncall, server, &client); @@ -261,13 +256,14 @@ int CWebServer::CreateFileDownloadResponse(struct MHD_Connection *connection, co { int ret = MHD_NO; CFile *file = new CFile(); - if (file->Open(strURL)) + + if (file->Open(strURL, READ_NO_CACHE)) { struct MHD_Response *response; response = MHD_create_response_from_callback ( file->GetLength(), 2048, &CWebServer::ContentReaderCallback, file, - &CWebServer::ContentReaderFreeCallback); + &CWebServer::ContentReaderFreeCallback); CStdString ext = CUtil::GetExtension(strURL); ext = ext.ToLower(); @@ -275,7 +271,12 @@ int CWebServer::CreateFileDownloadResponse(struct MHD_Connection *connection, co if (mime) MHD_add_response_header(response, "Content-Type", mime); + CDateTime expiryTime = CDateTime::GetCurrentDateTime(); + expiryTime += CDateTimeSpan(1, 0, 0, 0); + MHD_add_response_header(response, "Expires", expiryTime.GetAsRFC1123DateTime()); + ret = MHD_queue_response(connection, MHD_HTTP_OK, response); + MHD_destroy_response(response); } else @@ -284,7 +285,6 @@ int CWebServer::CreateFileDownloadResponse(struct MHD_Connection *connection, co CLog::Log(LOGERROR, "WebServer: Failed to open %s", strURL.c_str()); return CreateErrorResponse(connection, MHD_HTTP_NOT_FOUND, GET); /* GET Assumed Temporarily */ } - return ret; } @@ -353,10 +353,12 @@ bool CWebServer::Start(const char *ip, int port) // WARNING: when using MHD_USE_THREAD_PER_CONNECTION, set MHD_OPTION_CONNECTION_TIMEOUT to something higher than 1 // otherwise on libmicrohttpd 0.4.4-1 it spins a busy loop - // To stream perfectly we should probably have MHD_USE_THREAD_PER_CONNECTION instead of MHD_USE_SELECT_INTERNALLY as it provides multiple clients concurrently - m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_IPv6, port, NULL, NULL, &CWebServer::AnswerToConnection, this, MHD_OPTION_END); + unsigned int timeout = 60 * 60 * 24; + // MHD_USE_THREAD_PER_CONNECTION = one thread per connection + // MHD_USE_SELECT_INTERNALLY = use main thread for each connection, can only handle one request at a time [unless you set the thread pool size] + m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY | MHD_USE_IPv6, port, NULL, NULL, &CWebServer::AnswerToConnection, this, MHD_OPTION_THREAD_POOL_SIZE, 8, MHD_OPTION_CONNECTION_LIMIT, 512, MHD_OPTION_CONNECTION_TIMEOUT, timeout, MHD_OPTION_END); if (!m_daemon) //try IPv4 - m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, port, NULL, this, &CWebServer::AnswerToConnection, this, MHD_OPTION_END); + m_daemon = MHD_start_daemon(MHD_USE_SELECT_INTERNALLY, port, NULL, this, &CWebServer::AnswerToConnection, this, MHD_OPTION_THREAD_POOL_SIZE, 8, MHD_OPTION_CONNECTION_LIMIT, 512, MHD_OPTION_CONNECTION_TIMEOUT, timeout, MHD_OPTION_END); m_running = m_daemon != NULL; if (m_running) CLog::Log(LOGNOTICE, "WebServer: Started the webserver"); @@ -373,7 +375,8 @@ bool CWebServer::Stop() MHD_stop_daemon(m_daemon); m_running = false; CLog::Log(LOGNOTICE, "WebServer: Stopped the webserver"); - } + } else + CLog::Log(LOGNOTICE, "WebServer: Stopped failed because its not running"); return !m_running; } |