Added:
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CNN/carbondefault.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CNN/glassdefault.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/default.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/default.tbn (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/button-focus.png (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/button-nofocus.png (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/gt_background_nolines.jpg (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/gt_dialog_background.jpg (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/gt_submenu_bottom.jpg (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/gt_submenu_top.jpg (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/ClientCookie.zip (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/GameTrailers.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/GameTrailers.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/cachedhttp.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/cachedhttp.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/gt.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/gt.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/gtweb.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/gtweb.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/rss.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/rss.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/textwindow.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/textwindow.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/license.txt
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/readme.txt
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/ComedyCentral/carbondefault.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/ComedyCentral/glassdefault.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/G4tv.com xbmcCAST/carbondefault.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/G4tv.com xbmcCAST/glassdefault.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/default.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/default.tbn (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/img/
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/img/button-focus.png (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/img/button-nofocus.png (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/img/gt_background_nolines.jpg (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/img/gt_dialog_background.jpg (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/img/gt_submenu_bottom.jpg (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/img/gt_submenu_top.jpg (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/ClientCookie.zip (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/GameTrailers.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/GameTrailers.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/cachedhttp.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/cachedhttp.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/gt.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/gt.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/gtweb.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/gtweb.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/rss.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/rss.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/textwindow.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/lib/textwindow.pyo (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/license.txt
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GlassGameTrailersRssReader/readme.txt
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/Keymap.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/carbon-ani.gif (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/default-ani.gif (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/glass-ani.gif (contents, props changed)
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/switchkeymap.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1198_ResetSkinSettings.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1968_RestartRequiredDialog.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1976_MissingFileDialog.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/DialogVideoInfo.xml
Removed:
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/background-ani.gif
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1971_MissingXBEDialog.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1976_MissingScriptDialog.xml
Modified:
trunk/MC360 v1.x Video Marketplace Mod/INSTALL.txt
trunk/MC360 v1.x Video Marketplace Mod/README.txt
trunk/MC360 v1.x Video Marketplace Mod/WOL & SDOL README.txt
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CNN/default.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/ComedyCentral/default.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/G4tv.com xbmcCAST/default.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/GameTrailersRssReader/lib/GameTrailers.py
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1977_CategoryConfig6.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1978_CategoryConfig5.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1979_CategoryConfig4.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1980_CategoryConfig3.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1981_CategoryConfig2.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1982_CategoryConfig1.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1983_CategoryButton6.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1984_CategoryButton5.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1985_CategoryButton4.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1986_CategoryButton3.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1987_CategoryButton2.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1988_CategoryButton1.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1989_MarketplaceButton6.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1990_MarketplaceButton5.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1991_MarketplaceButton4.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1992_MarketplaceButton3.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1993_MarketplaceButton2.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Custom1994_MarketplaceButton1.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/Home.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/custom1112_GamesHome.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/custom1115_GuideFavorites.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/custom1969_FavoritesConfig.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/custom1970_GuideSkinModOptions2.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/custom1973_VideoMarketplaceConfiguration2.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/custom1974_VideoMarketplace2.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/custom1995_VideoMarketplaceConfiguration.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/custom1996_VideoMarketplace.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL/custom1999_GuideSkinModOptions.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL16x9/Home.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/PAL16x9/custom1112_GamesHome.xml
trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Sounds/sounds.xml
Log:
[MC360] Added: Custom MC360 Keymap Option for Spaceman2004's custom MC360 keymap (included)
Added: Play and Resume buttons in Video Info window
Modified: Combined all XBE and Single Script modes into "File Mode," using new Skin.SetFile() function. You now must specify an file, not just its folder.
Modified: Updated README's
Modified: Made background animations in default scripts change to match current theme (only if it's one of the default themes; otherwise, defaults to default swirl animation)
Modified: trunk/MC360 v1.x Video Marketplace Mod/INSTALL.txt
==============================================================================
--- trunk/MC360 v1.x Video Marketplace Mod/INSTALL.txt (original)
+++ trunk/MC360 v1.x Video Marketplace Mod/INSTALL.txt Tue Apr 24 17:26:57 2007
@@ -28,6 +28,8 @@
6. Go to the MC360 Guide by pressing Start on the controller or selecting the MC360 Guide button in the Media blade with the remote control. Go to "Personal Settings" and then "Skin Mod Settings." Configure things as you like. Things are fairly self explanatory. MCE stands for Media Center Extender. WOL/SOL stands for Wake-On-LAN and Shutdown-On-LAN and enables the button to remotely start and shutdown your computer.
+NOTE: If you are using a profile other than Master User that was created before installed this mod, things may not work correctly right away. You will have to either create a new profile to replace the old one, or I believe that you can simply change to a different skin, restart, and then change back to MC360 (not tested - It would be nice if somebody could
+
++++++++++++++++++++++++++++++++++++
@@ -76,4 +78,15 @@
- See separate text document entitled "WOL & SDOL README.txt."
+
+
+
+
+++++++++++++++++++++++++++++++++++++++++++
+"Enable Custom Keymap" Option:
+++++++++++++++++++++++++++++++++++++++++++
+
+The keymap.xml was created by Spaceman2004 with the help of Jeroen_JRP and Manturafs. The script which allows in-skin switching of keymaps was a slight modification of the Splash swapping script by Asteron. For more information on the keymap about its functions and differences from the default, see here:
+
+http://xboxmediacenter.com/wiki/index.php?title=MC360_keymap.xml_mod
Modified: trunk/MC360 v1.x Video Marketplace Mod/README.txt
==============================================================================
--- trunk/MC360 v1.x Video Marketplace Mod/README.txt (original)
+++ trunk/MC360 v1.x Video Marketplace Mod/README.txt Tue Apr 24 17:26:57 2007
@@ -52,8 +52,6 @@
- Add bookmarks to category scripts dialogs
-- Make custom square image icon thing for marketplace. I have almost no experience with Illustrator. If someone wants to whip up a custom icon for the Video Marketplace and it looks good, I'd be happy to include it in place of the eX button, since that's somewhat redundant, already found in the XBMC Live Place.
-
- Add names of current script in category config dialog
@@ -62,11 +60,8 @@
- Fix Launch Browser script to replace current "News Videos" button with "Music Videos" to replicate the actual 360 setup. Not sure how likely this is to happen, since I know hardly anything about python...
-- Skin all default scripts to match mc360 better
-
KNOWN BUGS:
-- Video preview doesn't fade with window changes. Not sure if this is fixable, since it does it in the video playlist window too...
- Some textures randomly disappear when watching certain video files. Help? Not sure how to fix this.
Modified: trunk/MC360 v1.x Video Marketplace Mod/WOL & SDOL README.txt
==============================================================================
--- trunk/MC360 v1.x Video Marketplace Mod/WOL & SDOL README.txt (original)
+++ trunk/MC360 v1.x Video Marketplace Mod/WOL & SDOL README.txt Tue Apr 24 17:26:57 2007
@@ -1,6 +1,6 @@
MC360 Remote Computer Startup/Shutdown Mod for v1.0 (works with newer versions as well...and the xml files this changes aren't likely to change in the official build any time soon.)
-If you have any problems with this script, feel free to post in the thread, or PM on xbox-scene, as screen name timdog82001
+If you have any problems with this script, feel free to post in the thread, or PM on xbox-scene, at screen name timdog82001
HOW TO SET UP SCRIPTS:
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CNN/carbondefault.py
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CNN/carbondefault.py Tue Apr 24 17:26:57 2007
@@ -0,0 +1,460 @@
+###################################################################
+#
+# CNN v1.5
+# Orginal by asteron. Lastest update by DC.
+#
+# Watch hundreds of video reports from CNN.com, select from
+# different categories.
+#
+#------------------------------------------------------------------
+# Version History:
+# 10/15/05 - AST - Initial creation
+# 10/16/05 - AST - logo, description, NITN support
+# 10/17/05 - AST - NITN format is different on somedays. Added
+# regular expression to fix lockup.
+# 12/10/05 - AST - More stability, remember category on left side
+# 1.2 08/09/06 - DC - Updated for changes CNN did to website
+# and video formats.
+# Works with 03-07-2006 version of XBMC.
+# 1.3 08/10/06 - DC - Now in the news link being a pain.
+# Changed to use podcasting video link.
+# 1.4 08/19/06 - DC - RSS link changed. Encoding changed as well.
+# Now using feedparser to get rss feed.
+# 1.5 09/19/06 - DC - CNN Now in the news link changed again. Fixed.
+# Increased HTTP timeout.
+# Corrected problem moving between categories.
+# 1.6 09/20/06 - DC - CNN decided to add HTML to their descriptions
+# Needed to strip.
+# 1.7 01/05/06 - AST - CNN changed their rss again
+# Switched from MMS to http to avoid playlist
+###################################################################
+
+
+from string import *
+import codecs, datetime, os, re, sys, threading, urllib, urllib2
+import xbmc, xbmcgui
+
+#----- XBMC constants ---------------------------------------------
+
+ACTION_MOVE_LEFT = 1
+ACTION_MOVE_RIGHT = 2
+ACTION_MOVE_UP = 3
+ACTION_MOVE_DOWN = 4
+ACTION_PAGE_UP = 5
+ACTION_PAGE_DOWN = 6
+ACTION_SELECT_ITEM = 7
+ACTION_HIGHLIGHT_ITEM = 8
+ACTION_PARENT_DIR = 9
+ACTION_PREVIOUS_MENU = 10
+ACTION_SHOW_INFO = 11
+ACTION_PAUSE = 12
+ACTION_STOP = 13
+ACTION_NEXT_ITEM = 14
+ACTION_PREV_ITEM = 15
+ACTION_SCROLL_UP = 111
+ACTION_SCROLL_DOWN = 112
+
+XBFONT_LEFT = 0x00000000
+XBFONT_RIGHT = 0x00000001
+XBFONT_CENTER_X = 0x00000002
+XBFONT_CENTER_Y = 0x00000004
+XBFONT_TRUNCATED = 0x00000008
+
+COORD_1080I = 0
+COORD_720P = 1
+COORD_480P_4X3 = 2
+COORD_480P_16X9 = 3
+COORD_NTSC_4X3 = 4
+COORD_NTSC_16X9 = 5
+COORD_PAL_4X3 = 6
+COORD_PAL_16X9 = 7
+COORD_PAL60_4X3 = 8
+COORD_PAL60_16X9 = 9
+
+#------------------------------------------------------------------
+
+ROOT_DIR = os.getcwd()[:-1]+'\\'
+
+import feedparser
+Dependencies = ["time"]
+
+HTTP_TIMEOUT = 30.0 # Max. seconds to wait for a response when fetching webpages
+
+
+CNN_RSS_FEED = 'http://feeds.feedburner.com/cnn/video?format=usm'
+
+# Need to parse this to get the current NITN URL
+# DC - Using podcasting page to get filename for Now in the News.
+CNN_NOW_IN_THE_NEWS_PAGE = 'http://rss.cnn.com/services/podcasting/nitn/rss'
+
+
+class Item:
+ def __init__(self, title, url, desc, category, date):
+ self.title = title
+ self.url = url
+ self.description = desc
+ self.category = category
+ self.date = date
+
+#possible categories are below
+#[u'world', u'us', u'offbeat', u'sports', u'politics', u'showbiz', u'bestoftv', u'health', u'business', u'law', u'tech', u'education', u'specials', u'moos']
+CATEGORIES = ['All','World','US','Politics','Showbiz','Sports','Tech','Business','Law','BestofTV','Offbeat','Other']
+
+
+# Global progress dialog
+dialogProgress = xbmcgui.DialogProgress()
+
+
+#----- DC - Set DO_LOGGING = 1 to enable logging to Q:\scripts\CNN\log.txt.
+DO_LOGGING = 1
+try:
+ LOG_FILE.close()
+except Exception:
+ pass
+if DO_LOGGING:
+ LOG_FILE = open(ROOT_DIR + '\\log.txt','w')
+def LOG(message):
+ if DO_LOGGING:
+ LOG_FILE.write(str(message)+"\n")
+ LOG_FILE.flush()
+def LOGCLOSE():
+ if DO_LOGGING:
+ LOG_FILE.close()
+
+
+txdata = None
+txheaders = {
+ 'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6) Gecko/20060728 Firefox/1.5.0.6',
+ 'Accept-Language': 'en-US',
+ 'Accept-Encoding': 'gzip, deflate, compress;q=0.9',
+ 'Keep-Alive': '300',
+ 'Connection': 'keep-alive',
+ 'Cache-Control': 'max-age=0',
+}
+
+items = []
+
+FeedDate = datetime.date.today()
+
+def FetchURL(url):
+ LOG('FetchURL url=' + url)
+ def SubthreadProc(url, result):
+ try:
+ req = urllib2.Request(url, txdata, txheaders)
+ data = urllib2.urlopen(req).read()
+ except Exception:
+ # Could be a socket error or an HTTP error--either way, we
+ # don't care--it's a failure to us.
+ result.append(-1)
+ else:
+ result.append(data)
+ result = []
+ subThread = threading.Thread(target=SubthreadProc, args=(url, result))
+ subThread.setDaemon(True)
+ LOG(' starting url retrieval')
+ subThread.start()
+ subThread.join(HTTP_TIMEOUT)
+ LOG(' finished url retrieval')
+ if dialogProgress.iscanceled():
+ dialogProgress.close()
+ xbmcgui.Dialog().ok('ERROR','Cancelled.')
+ return ''
+ elif result == []:
+ # Subthread hasn't give a result yet. Consider it timed out.
+ dialogProgress.close()
+ xbmcgui.Dialog().ok('TIMEOUT','Video listing download timed out.')
+ return ''
+ elif result[0] == -1:
+ dialogProgress.close()
+ xbmcgui.Dialog().ok('ERROR','Failed to retrieve video listing')
+ return ''
+ else:
+ return result[0]
+
+
+HTMLRe = re.compile('<(.|\n)+?>',re.MULTILINE + re.DOTALL + re.IGNORECASE)
+
+def StripHtml(arHtml):
+ stripped = replace(arHtml, '<br>', ' ')
+ stripped = HTMLRe.sub('',stripped)
+ return stripped;
+
+
+class CNNBrowser(xbmcgui.Window):
+ def __init__(self):
+ self.setCoordinateResolution(COORD_NTSC_4X3)
+
+
+ # background animation
+ self.imgBackgroundani = xbmcgui.ControlImage(0, 0, 720, 476, "Q:\\Skin\\MC360\\Extras\\carbon-ani.gif")
+ self.addControl(self.imgBackgroundani)
+ # background image
+ self.imgBackgroundBlue = xbmcgui.ControlImage(0, 0, 720, 576, 'background-blue-alpha.png')
+ self.addControl(self.imgBackgroundBlue)
+ # custom background image
+ self.imgCustomBackground = xbmcgui.ControlImage(0, 0, 720, 576, xbmc.getInfoLabel('Skin.String(Media)'))
+ self.addControl(self.imgCustomBackground)
+ self.imgCustomBackground.setColorDiffuse('D1FFFFFF')
+ # Whitewash glass top left
+ self.addControl(xbmcgui.ControlImage(70, 0, 16, 64, 'bkgd-whitewash-glass-top-left.png'))
+ # Whitewash glass top middle
+ self.addControl(xbmcgui.ControlImage(86, 0, 592, 64, 'bkgd-whitewash-glass-top-middle.png'))
+ # Whitewash glass top right
+ self.addControl(xbmcgui.ControlImage(678, 0, 16, 64, 'bkgd-whitewash-glass-top-right.png'))
+ # Whitewash glass bottom left
+ self.addControl(xbmcgui.ControlImage(70, 412, 16, 64, 'bkgd-whitewash-glass-bottom-left.png'))
+ # Whitewash glass bottom middle
+ self.addControl(xbmcgui.ControlImage(86, 412, 592, 64, 'bkgd-whitewash-glass-bottom-middle.png'))
+ # Whitewash glass bottom right
+ self.addControl(xbmcgui.ControlImage(678, 412, 16, 64, 'bkgd-whitewash-glass-bottom-right.png'))
+ # Whitewash overlay left
+ self.addControl(xbmcgui.ControlImage(60, 0, 32, 476, 'background-overlay-whitewash-left.png'))
+ # Whitewash overlay middle
+ self.addControl(xbmcgui.ControlImage(92, 0, 553, 476, 'background-overlay-whitewash-centertile.png'))
+ # Whitewash overlay right
+ self.addControl(xbmcgui.ControlImage(645, 0, 64, 476, 'background-overlay-whitewash-right.png'))
+ # Left blade runner
+ self.addControl(xbmcgui.ControlImage(-61, 0, 128, 476, 'blades-runner-left.png'))
+ # Right blade runner
+ self.addControl(xbmcgui.ControlImage(665, 0, 128, 476, 'blades-runner-right.png'))
+ # Y Button
+ self.addControl(xbmcgui.ControlImage(125, 420, 21, 21, 'button-Y-turnedoff.png'))
+ # X Button
+ self.addControl(xbmcgui.ControlImage(112, 440, 21, 21, 'button-X.png'))
+ # Back Button
+ self.addControl(xbmcgui.ControlImage(620, 420, 21, 21, 'button-back.png'))
+ # A Button
+ self.addControl(xbmcgui.ControlImage(633, 440, 21, 21, 'button-A.png'))
+ # Header Blade
+ self.addControl(xbmcgui.ControlImage(18, 0, 80, 476, 'blades-size4-header.png'))
+ self.lstVideos = xbmcgui.ControlList(290,63,375,390,imageWidth=30, textColor='0xFF000000', imageHeight=30)
+ self.addControl(self.lstVideos)
+ self.setFocus(self.lstVideos)
+ self.makeButtons()
+ self.addControl(xbmcgui.ControlImage(80, 10, 122, 53,ROOT_DIR + 'default.tbn'))
+ self.lblDescription = xbmcgui.ControlTextBox(221,25,455,5000,'font12','0xFFFFFFFF')
+ self.addControl(self.lblDescription)
+ self.currentCategory = 0
+ self.addControl(xbmcgui.ControlLabel(79,129,100,20,'media','font14','0xFF000000',angle=270))
+ self.addControl(xbmcgui.ControlLabel(145,443,375,20,'Full Screen Visualization','font12','0xFFFFFFFF'))
+ self.addControl(xbmcgui.ControlLabel(580,423,80,20,'Back','font12','0xFFFFFFFF'))
+ self.addControl(xbmcgui.ControlLabel(577,443,80,20,'Select','font12','0xFFFFFFFF'))
+
+ def makeButtons(self):
+ self.btnCategories = []
+ for i in range(len(CATEGORIES)):
+ btn = xbmcgui.ControlButton(85, 80+27*i, 140, 27, CATEGORIES[i], textColor='0xFF000000', textXOffset=17)
+ self.addControl(btn)
+ self.btnCategories.append(btn)
+
+ for i in range(len(CATEGORIES)):
+ self.btnCategories[i].controlUp(self.btnCategories[i-1])
+ self.btnCategories[i].controlDown(self.btnCategories[(i+1) % len(CATEGORIES)])
+ self.btnCategories[i].controlRight(self.lstVideos)
+
+
+
+ def onAction(self, action):
+ if action == ACTION_PREVIOUS_MENU:
+ self.close()
+
+ elif (action == ACTION_MOVE_LEFT or action == ACTION_MOVE_RIGHT
+ or action == ACTION_MOVE_UP or action == ACTION_MOVE_DOWN
+ or action == ACTION_PAGE_UP or action == ACTION_PAGE_DOWN
+ or action == ACTION_SCROLL_UP or action == ACTION_SCROLL_DOWN):
+
+ def SubthreadUpdate(self):
+ self.lblDescription.reset()
+ try:
+ self.lblDescription.setText(self.listedItems[self.lstVideos.getSelectedPosition()].description)
+ except:
+ pass
+
+ subThread = threading.Thread(target=SubthreadUpdate, args=[self])
+ subThread.setDaemon(True)
+ xbmcgui.lock()
+ subThread.start()
+ subThread.join(0.05)
+ xbmcgui.unlock()
+
+ if action == ACTION_MOVE_LEFT:
+ self.setFocus(self.btnCategories[self.currentCategory])
+
+ def onControl(self, control):
+
+ if control == self.lstVideos:
+ item = self.listedItems[self.lstVideos.getSelectedPosition()]
+ LOG("perform action")
+ url = item.url
+ LOG("original url is: " +url)
+ if item == items[0]: #now in the news needs to do some additional parsing
+ url = self.findNowInTheNewsURL(item.url)
+ if url == "":
+ return
+ try:
+ LOG("Opening file " + url)
+ """
+ # DC - play(url) does not seem to work consistently with MMS: stream. Use playlist instead.
+ # xbmc.Player().play(url)
+ pls = xbmc.PlayList(2)
+ pls.clear()
+ pls.add(url)
+ xbmc.Player().play(pls)
+
+ pls.clear()
+ """
+ # Ast - This works fine... just use http instead of mms
+ xbmc.Player().play(url)
+ LOG("Found address " + url)
+
+ except:
+ xbmcgui.Dialog().ok('ERROR','Failed to connect to video server')
+ return
+
+ for i in range(len(CATEGORIES)):
+ if control == self.btnCategories[i]:
+ self.filterList(i)
+ self.lstVideos.selectItem(0)
+
+
+ def filterList(self, idx):
+ LOG("selecting " + str(idx))
+ self.btnCategories[self.currentCategory].setLabel(CATEGORIES[self.currentCategory], "font13", "0xFF000000")
+ self.btnCategories[idx].setLabel(CATEGORIES[idx], "font13",'0xFF000000')
+ self.currentCategory = idx
+ self.filterListOn(CATEGORIES[idx].lower())
+
+ def filterListOn(self, cat):
+ if cat == 'all':
+ self.listedItems = items[:]
+ elif cat == 'other':
+ cats = [cat.lower() for cat in CATEGORIES][:-1]
+ self.listedItems = filter(lambda item: item.category.lower() not in cats,items)
+ else:
+ self.listedItems = filter(lambda item: item.category == cat,items)
+ self.populateList()
+
+ def reformURL(self,url):
+ try:
+ start = url.index("?url=/video/") + len ("?url=/video/")
+ end = url.index("&date")
+ return ("http://wmscnn.stream.aol.com.edgestreams.net/cnn/"+url[start:end]+".ws.wmv").encode("utf8")#?MSWMExt=.asf"
+ except:
+ return ""
+
+ def findNowInTheNewsURL(self, inUrl):
+ LOG("findNowInTheNewsURL inUrl=" + inUrl)
+ try:
+ url = CNN_NOW_IN_THE_NEWS_PAGE
+ data = urllib.urlopen(url).read()
+
+ current = re.search ( '(<enclosure url=")(.*?)(.m4v?)',data).group(2)
+ LOG(" found string: " + current)
+ theUrl = current+".m4v"
+ LOG(" theUrl=" + theUrl)
+ return theUrl
+ except:
+ pass
+
+ xbmcgui.Dialog().ok("'Now in the News' Podcast Not Available.","Will try the 1st edition of 'Now in the News'.")
+
+ # Sometimes podcasting page is blank. Try another way to get link.
+ #
+ # There appear to be 12 editions of Now in the News created each day.
+ # Unfortunately I do not know the logic behind generating the 12 editions.
+ # Default to using the first one for now. Hopefully there. DC.
+ try:
+ theDay = FeedDate.strftime("%d")
+ theMonth = FeedDate.strftime("%m")
+ theYear = FeedDate.strftime("%Y")
+ current = theYear + '/' + theMonth + '/' + theDay
+
+ LOG(" current: " + current)
+ theUrl = 'http://wmscnn.stream.aol.com.edgestreams.net/cnn/nitn/' + current + '/nitn.edition.01.cnn.ws.wmv'
+ LOG(" theUrl=" + theUrl)
+ return theUrl
+ except:
+ xbmcgui.Dialog().ok('ERROR',"Failed to retrieve 'Now in the News'.")
+ return ""
+
+ def downloadFeed(self):
+ dialogProgress.create("Downloading...", "Fetching video listing.")
+ LOG('downloadFeed')
+ self.getVideoListing()
+ dialogProgress.close()
+ self.filterList(0)
+
+ def populateList(self):
+ xbmcgui.lock()
+ self.lstVideos.reset()
+ for item in self.listedItems:
+ self.lstVideos.addItem(xbmcgui.ListItem(label=item.title,label2=item.date,thumbnailImage='defaultVideo.png'))
+ self.lblDescription.reset()
+ self.lblDescription.setText(self.listedItems[0].description)
+ xbmcgui.unlock()
+
+ def getVideoListing(self):
+ LOG('getVideoListing')
+
+ try:
+ data = feedparser.parse(CNN_RSS_FEED)
+ except:
+ LOG(' Problem parsing RSS feed.')
+ return
+
+ if data == '':
+ return
+
+ if data.has_key("channel"):
+ mytitle = data["channel"].get("title", "No title")
+ LOG(' RSS Title=' + mytitle)
+
+ FeedDate = data["channel"].get("date", datetime.date.today())
+
+ try:
+ rssItems = data.get('items', None)
+ except:
+ LOG(' Problem parsing items from RSS feed.')
+ return
+
+ if rssItems:
+ for rssItem in rssItems:
+ try:
+ title = rssItem.get('title','')
+ url = rssItem.get('feedburner_origlink','')
+ date = rssItem.get('date','')
+ desc = StripHtml(rssItem.get('description',''))
+ category = rssItem.get('category','')
+ except:
+ LOG(' Problem reading item fields from RSS feed.')
+ return
+
+ try:
+ items.append(Item(title, url, desc, category,date))
+ except:
+ LOG(' Problem adding item info to items.')
+ return
+ # some post processing
+ lookup = 'JanFebMarAprMayJunJulAugSepOctNovDec'
+ for item in items:
+ if item != items[0]:
+ item.url = self.reformURL(item.url)
+ try:
+ date = item.date.split()
+ item.date = date[0] + ' ' + str(lookup.index(date[2])/3+1) + '/' + date[1] + ' ' + ':'.join(date[4].split(':')[0:2])
+ except:
+ pass
+ else:
+ LOG(' RSS Feed has no items.')
+ else:
+ LOG(' RSS Feed has no channel')
+
+
+w = CNNBrowser()
+w.downloadFeed()
+w.doModal()
+
+LOGCLOSE()
+
+if dialogProgress:
+ dialogProgress.close()
Modified: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CNN/default.py
==============================================================================
--- trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CNN/default.py (original)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CNN/default.py Tue Apr 24 17:26:57 2007
@@ -186,7 +186,7 @@
# background animation
- self.imgBackgroundani = xbmcgui.ControlImage(0, 0, 720, 476, "Q:\\Skin\\MC360\\Extras\\background-ani.gif")
+ self.imgBackgroundani = xbmcgui.ControlImage(0, 0, 720, 476, "Q:\\Skin\\MC360\\Extras\\default-ani.gif")
self.addControl(self.imgBackgroundani)
# background image
self.imgBackgroundBlue = xbmcgui.ControlImage(0, 0, 720, 576, 'background-blue-alpha.png')
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CNN/glassdefault.py
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CNN/glassdefault.py Tue Apr 24 17:26:57 2007
@@ -0,0 +1,460 @@
+###################################################################
+#
+# CNN v1.5
+# Orginal by asteron. Lastest update by DC.
+#
+# Watch hundreds of video reports from CNN.com, select from
+# different categories.
+#
+#------------------------------------------------------------------
+# Version History:
+# 10/15/05 - AST - Initial creation
+# 10/16/05 - AST - logo, description, NITN support
+# 10/17/05 - AST - NITN format is different on somedays. Added
+# regular expression to fix lockup.
+# 12/10/05 - AST - More stability, remember category on left side
+# 1.2 08/09/06 - DC - Updated for changes CNN did to website
+# and video formats.
+# Works with 03-07-2006 version of XBMC.
+# 1.3 08/10/06 - DC - Now in the news link being a pain.
+# Changed to use podcasting video link.
+# 1.4 08/19/06 - DC - RSS link changed. Encoding changed as well.
+# Now using feedparser to get rss feed.
+# 1.5 09/19/06 - DC - CNN Now in the news link changed again. Fixed.
+# Increased HTTP timeout.
+# Corrected problem moving between categories.
+# 1.6 09/20/06 - DC - CNN decided to add HTML to their descriptions
+# Needed to strip.
+# 1.7 01/05/06 - AST - CNN changed their rss again
+# Switched from MMS to http to avoid playlist
+###################################################################
+
+
+from string import *
+import codecs, datetime, os, re, sys, threading, urllib, urllib2
+import xbmc, xbmcgui
+
+#----- XBMC constants ---------------------------------------------
+
+ACTION_MOVE_LEFT = 1
+ACTION_MOVE_RIGHT = 2
+ACTION_MOVE_UP = 3
+ACTION_MOVE_DOWN = 4
+ACTION_PAGE_UP = 5
+ACTION_PAGE_DOWN = 6
+ACTION_SELECT_ITEM = 7
+ACTION_HIGHLIGHT_ITEM = 8
+ACTION_PARENT_DIR = 9
+ACTION_PREVIOUS_MENU = 10
+ACTION_SHOW_INFO = 11
+ACTION_PAUSE = 12
+ACTION_STOP = 13
+ACTION_NEXT_ITEM = 14
+ACTION_PREV_ITEM = 15
+ACTION_SCROLL_UP = 111
+ACTION_SCROLL_DOWN = 112
+
+XBFONT_LEFT = 0x00000000
+XBFONT_RIGHT = 0x00000001
+XBFONT_CENTER_X = 0x00000002
+XBFONT_CENTER_Y = 0x00000004
+XBFONT_TRUNCATED = 0x00000008
+
+COORD_1080I = 0
+COORD_720P = 1
+COORD_480P_4X3 = 2
+COORD_480P_16X9 = 3
+COORD_NTSC_4X3 = 4
+COORD_NTSC_16X9 = 5
+COORD_PAL_4X3 = 6
+COORD_PAL_16X9 = 7
+COORD_PAL60_4X3 = 8
+COORD_PAL60_16X9 = 9
+
+#------------------------------------------------------------------
+
+ROOT_DIR = os.getcwd()[:-1]+'\\'
+
+import feedparser
+Dependencies = ["time"]
+
+HTTP_TIMEOUT = 30.0 # Max. seconds to wait for a response when fetching webpages
+
+
+CNN_RSS_FEED = 'http://feeds.feedburner.com/cnn/video?format=usm'
+
+# Need to parse this to get the current NITN URL
+# DC - Using podcasting page to get filename for Now in the News.
+CNN_NOW_IN_THE_NEWS_PAGE = 'http://rss.cnn.com/services/podcasting/nitn/rss'
+
+
+class Item:
+ def __init__(self, title, url, desc, category, date):
+ self.title = title
+ self.url = url
+ self.description = desc
+ self.category = category
+ self.date = date
+
+#possible categories are below
+#[u'world', u'us', u'offbeat', u'sports', u'politics', u'showbiz', u'bestoftv', u'health', u'business', u'law', u'tech', u'education', u'specials', u'moos']
+CATEGORIES = ['All','World','US','Politics','Showbiz','Sports','Tech','Business','Law','BestofTV','Offbeat','Other']
+
+
+# Global progress dialog
+dialogProgress = xbmcgui.DialogProgress()
+
+
+#----- DC - Set DO_LOGGING = 1 to enable logging to Q:\scripts\CNN\log.txt.
+DO_LOGGING = 1
+try:
+ LOG_FILE.close()
+except Exception:
+ pass
+if DO_LOGGING:
+ LOG_FILE = open(ROOT_DIR + '\\log.txt','w')
+def LOG(message):
+ if DO_LOGGING:
+ LOG_FILE.write(str(message)+"\n")
+ LOG_FILE.flush()
+def LOGCLOSE():
+ if DO_LOGGING:
+ LOG_FILE.close()
+
+
+txdata = None
+txheaders = {
+ 'User-Agent': 'Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.0.6) Gecko/20060728 Firefox/1.5.0.6',
+ 'Accept-Language': 'en-US',
+ 'Accept-Encoding': 'gzip, deflate, compress;q=0.9',
+ 'Keep-Alive': '300',
+ 'Connection': 'keep-alive',
+ 'Cache-Control': 'max-age=0',
+}
+
+items = []
+
+FeedDate = datetime.date.today()
+
+def FetchURL(url):
+ LOG('FetchURL url=' + url)
+ def SubthreadProc(url, result):
+ try:
+ req = urllib2.Request(url, txdata, txheaders)
+ data = urllib2.urlopen(req).read()
+ except Exception:
+ # Could be a socket error or an HTTP error--either way, we
+ # don't care--it's a failure to us.
+ result.append(-1)
+ else:
+ result.append(data)
+ result = []
+ subThread = threading.Thread(target=SubthreadProc, args=(url, result))
+ subThread.setDaemon(True)
+ LOG(' starting url retrieval')
+ subThread.start()
+ subThread.join(HTTP_TIMEOUT)
+ LOG(' finished url retrieval')
+ if dialogProgress.iscanceled():
+ dialogProgress.close()
+ xbmcgui.Dialog().ok('ERROR','Cancelled.')
+ return ''
+ elif result == []:
+ # Subthread hasn't give a result yet. Consider it timed out.
+ dialogProgress.close()
+ xbmcgui.Dialog().ok('TIMEOUT','Video listing download timed out.')
+ return ''
+ elif result[0] == -1:
+ dialogProgress.close()
+ xbmcgui.Dialog().ok('ERROR','Failed to retrieve video listing')
+ return ''
+ else:
+ return result[0]
+
+
+HTMLRe = re.compile('<(.|\n)+?>',re.MULTILINE + re.DOTALL + re.IGNORECASE)
+
+def StripHtml(arHtml):
+ stripped = replace(arHtml, '<br>', ' ')
+ stripped = HTMLRe.sub('',stripped)
+ return stripped;
+
+
+class CNNBrowser(xbmcgui.Window):
+ def __init__(self):
+ self.setCoordinateResolution(COORD_NTSC_4X3)
+
+
+ # background animation
+ self.imgBackgroundani = xbmcgui.ControlImage(0, 0, 720, 476, "Q:\\Skin\\MC360\\Extras\\glass-ani.gif")
+ self.addControl(self.imgBackgroundani)
+ # background image
+ self.imgBackgroundBlue = xbmcgui.ControlImage(0, 0, 720, 576, 'background-blue-alpha.png')
+ self.addControl(self.imgBackgroundBlue)
+ # custom background image
+ self.imgCustomBackground = xbmcgui.ControlImage(0, 0, 720, 576, xbmc.getInfoLabel('Skin.String(Media)'))
+ self.addControl(self.imgCustomBackground)
+ self.imgCustomBackground.setColorDiffuse('D1FFFFFF')
+ # Whitewash glass top left
+ self.addControl(xbmcgui.ControlImage(70, 0, 16, 64, 'bkgd-whitewash-glass-top-left.png'))
+ # Whitewash glass top middle
+ self.addControl(xbmcgui.ControlImage(86, 0, 592, 64, 'bkgd-whitewash-glass-top-middle.png'))
+ # Whitewash glass top right
+ self.addControl(xbmcgui.ControlImage(678, 0, 16, 64, 'bkgd-whitewash-glass-top-right.png'))
+ # Whitewash glass bottom left
+ self.addControl(xbmcgui.ControlImage(70, 412, 16, 64, 'bkgd-whitewash-glass-bottom-left.png'))
+ # Whitewash glass bottom middle
+ self.addControl(xbmcgui.ControlImage(86, 412, 592, 64, 'bkgd-whitewash-glass-bottom-middle.png'))
+ # Whitewash glass bottom right
+ self.addControl(xbmcgui.ControlImage(678, 412, 16, 64, 'bkgd-whitewash-glass-bottom-right.png'))
+ # Whitewash overlay left
+ self.addControl(xbmcgui.ControlImage(60, 0, 32, 476, 'background-overlay-whitewash-left.png'))
+ # Whitewash overlay middle
+ self.addControl(xbmcgui.ControlImage(92, 0, 553, 476, 'background-overlay-whitewash-centertile.png'))
+ # Whitewash overlay right
+ self.addControl(xbmcgui.ControlImage(645, 0, 64, 476, 'background-overlay-whitewash-right.png'))
+ # Left blade runner
+ self.addControl(xbmcgui.ControlImage(-61, 0, 128, 476, 'blades-runner-left.png'))
+ # Right blade runner
+ self.addControl(xbmcgui.ControlImage(665, 0, 128, 476, 'blades-runner-right.png'))
+ # Y Button
+ self.addControl(xbmcgui.ControlImage(125, 420, 21, 21, 'button-Y-turnedoff.png'))
+ # X Button
+ self.addControl(xbmcgui.ControlImage(112, 440, 21, 21, 'button-X.png'))
+ # Back Button
+ self.addControl(xbmcgui.ControlImage(620, 420, 21, 21, 'button-back.png'))
+ # A Button
+ self.addControl(xbmcgui.ControlImage(633, 440, 21, 21, 'button-A.png'))
+ # Header Blade
+ self.addControl(xbmcgui.ControlImage(18, 0, 80, 476, 'blades-size4-header.png'))
+ self.lstVideos = xbmcgui.ControlList(290,63,375,390,imageWidth=30, textColor='0xFF000000', imageHeight=30)
+ self.addControl(self.lstVideos)
+ self.setFocus(self.lstVideos)
+ self.makeButtons()
+ self.addControl(xbmcgui.ControlImage(80, 10, 122, 53,ROOT_DIR + 'default.tbn'))
+ self.lblDescription = xbmcgui.ControlTextBox(221,25,455,5000,'font12','0xFFFFFFFF')
+ self.addControl(self.lblDescription)
+ self.currentCategory = 0
+ self.addControl(xbmcgui.ControlLabel(79,129,100,20,'media','font14','0xFF000000',angle=270))
+ self.addControl(xbmcgui.ControlLabel(145,443,375,20,'Full Screen Visualization','font12','0xFFFFFFFF'))
+ self.addControl(xbmcgui.ControlLabel(580,423,80,20,'Back','font12','0xFFFFFFFF'))
+ self.addControl(xbmcgui.ControlLabel(577,443,80,20,'Select','font12','0xFFFFFFFF'))
+
+ def makeButtons(self):
+ self.btnCategories = []
+ for i in range(len(CATEGORIES)):
+ btn = xbmcgui.ControlButton(85, 80+27*i, 140, 27, CATEGORIES[i], textColor='0xFF000000', textXOffset=17)
+ self.addControl(btn)
+ self.btnCategories.append(btn)
+
+ for i in range(len(CATEGORIES)):
+ self.btnCategories[i].controlUp(self.btnCategories[i-1])
+ self.btnCategories[i].controlDown(self.btnCategories[(i+1) % len(CATEGORIES)])
+ self.btnCategories[i].controlRight(self.lstVideos)
+
+
+
+ def onAction(self, action):
+ if action == ACTION_PREVIOUS_MENU:
+ self.close()
+
+ elif (action == ACTION_MOVE_LEFT or action == ACTION_MOVE_RIGHT
+ or action == ACTION_MOVE_UP or action == ACTION_MOVE_DOWN
+ or action == ACTION_PAGE_UP or action == ACTION_PAGE_DOWN
+ or action == ACTION_SCROLL_UP or action == ACTION_SCROLL_DOWN):
+
+ def SubthreadUpdate(self):
+ self.lblDescription.reset()
+ try:
+ self.lblDescription.setText(self.listedItems[self.lstVideos.getSelectedPosition()].description)
+ except:
+ pass
+
+ subThread = threading.Thread(target=SubthreadUpdate, args=[self])
+ subThread.setDaemon(True)
+ xbmcgui.lock()
+ subThread.start()
+ subThread.join(0.05)
+ xbmcgui.unlock()
+
+ if action == ACTION_MOVE_LEFT:
+ self.setFocus(self.btnCategories[self.currentCategory])
+
+ def onControl(self, control):
+
+ if control == self.lstVideos:
+ item = self.listedItems[self.lstVideos.getSelectedPosition()]
+ LOG("perform action")
+ url = item.url
+ LOG("original url is: " +url)
+ if item == items[0]: #now in the news needs to do some additional parsing
+ url = self.findNowInTheNewsURL(item.url)
+ if url == "":
+ return
+ try:
+ LOG("Opening file " + url)
+ """
+ # DC - play(url) does not seem to work consistently with MMS: stream. Use playlist instead.
+ # xbmc.Player().play(url)
+ pls = xbmc.PlayList(2)
+ pls.clear()
+ pls.add(url)
+ xbmc.Player().play(pls)
+
+ pls.clear()
+ """
+ # Ast - This works fine... just use http instead of mms
+ xbmc.Player().play(url)
+ LOG("Found address " + url)
+
+ except:
+ xbmcgui.Dialog().ok('ERROR','Failed to connect to video server')
+ return
+
+ for i in range(len(CATEGORIES)):
+ if control == self.btnCategories[i]:
+ self.filterList(i)
+ self.lstVideos.selectItem(0)
+
+
+ def filterList(self, idx):
+ LOG("selecting " + str(idx))
+ self.btnCategories[self.currentCategory].setLabel(CATEGORIES[self.currentCategory], "font13", "0xFF000000")
+ self.btnCategories[idx].setLabel(CATEGORIES[idx], "font13",'0xFF000000')
+ self.currentCategory = idx
+ self.filterListOn(CATEGORIES[idx].lower())
+
+ def filterListOn(self, cat):
+ if cat == 'all':
+ self.listedItems = items[:]
+ elif cat == 'other':
+ cats = [cat.lower() for cat in CATEGORIES][:-1]
+ self.listedItems = filter(lambda item: item.category.lower() not in cats,items)
+ else:
+ self.listedItems = filter(lambda item: item.category == cat,items)
+ self.populateList()
+
+ def reformURL(self,url):
+ try:
+ start = url.index("?url=/video/") + len ("?url=/video/")
+ end = url.index("&date")
+ return ("http://wmscnn.stream.aol.com.edgestreams.net/cnn/"+url[start:end]+".ws.wmv").encode("utf8")#?MSWMExt=.asf"
+ except:
+ return ""
+
+ def findNowInTheNewsURL(self, inUrl):
+ LOG("findNowInTheNewsURL inUrl=" + inUrl)
+ try:
+ url = CNN_NOW_IN_THE_NEWS_PAGE
+ data = urllib.urlopen(url).read()
+
+ current = re.search ( '(<enclosure url=")(.*?)(.m4v?)',data).group(2)
+ LOG(" found string: " + current)
+ theUrl = current+".m4v"
+ LOG(" theUrl=" + theUrl)
+ return theUrl
+ except:
+ pass
+
+ xbmcgui.Dialog().ok("'Now in the News' Podcast Not Available.","Will try the 1st edition of 'Now in the News'.")
+
+ # Sometimes podcasting page is blank. Try another way to get link.
+ #
+ # There appear to be 12 editions of Now in the News created each day.
+ # Unfortunately I do not know the logic behind generating the 12 editions.
+ # Default to using the first one for now. Hopefully there. DC.
+ try:
+ theDay = FeedDate.strftime("%d")
+ theMonth = FeedDate.strftime("%m")
+ theYear = FeedDate.strftime("%Y")
+ current = theYear + '/' + theMonth + '/' + theDay
+
+ LOG(" current: " + current)
+ theUrl = 'http://wmscnn.stream.aol.com.edgestreams.net/cnn/nitn/' + current + '/nitn.edition.01.cnn.ws.wmv'
+ LOG(" theUrl=" + theUrl)
+ return theUrl
+ except:
+ xbmcgui.Dialog().ok('ERROR',"Failed to retrieve 'Now in the News'.")
+ return ""
+
+ def downloadFeed(self):
+ dialogProgress.create("Downloading...", "Fetching video listing.")
+ LOG('downloadFeed')
+ self.getVideoListing()
+ dialogProgress.close()
+ self.filterList(0)
+
+ def populateList(self):
+ xbmcgui.lock()
+ self.lstVideos.reset()
+ for item in self.listedItems:
+ self.lstVideos.addItem(xbmcgui.ListItem(label=item.title,label2=item.date,thumbnailImage='defaultVideo.png'))
+ self.lblDescription.reset()
+ self.lblDescription.setText(self.listedItems[0].description)
+ xbmcgui.unlock()
+
+ def getVideoListing(self):
+ LOG('getVideoListing')
+
+ try:
+ data = feedparser.parse(CNN_RSS_FEED)
+ except:
+ LOG(' Problem parsing RSS feed.')
+ return
+
+ if data == '':
+ return
+
+ if data.has_key("channel"):
+ mytitle = data["channel"].get("title", "No title")
+ LOG(' RSS Title=' + mytitle)
+
+ FeedDate = data["channel"].get("date", datetime.date.today())
+
+ try:
+ rssItems = data.get('items', None)
+ except:
+ LOG(' Problem parsing items from RSS feed.')
+ return
+
+ if rssItems:
+ for rssItem in rssItems:
+ try:
+ title = rssItem.get('title','')
+ url = rssItem.get('feedburner_origlink','')
+ date = rssItem.get('date','')
+ desc = StripHtml(rssItem.get('description',''))
+ category = rssItem.get('category','')
+ except:
+ LOG(' Problem reading item fields from RSS feed.')
+ return
+
+ try:
+ items.append(Item(title, url, desc, category,date))
+ except:
+ LOG(' Problem adding item info to items.')
+ return
+ # some post processing
+ lookup = 'JanFebMarAprMayJunJulAugSepOctNovDec'
+ for item in items:
+ if item != items[0]:
+ item.url = self.reformURL(item.url)
+ try:
+ date = item.date.split()
+ item.date = date[0] + ' ' + str(lookup.index(date[2])/3+1) + '/' + date[1] + ' ' + ':'.join(date[4].split(':')[0:2])
+ except:
+ pass
+ else:
+ LOG(' RSS Feed has no items.')
+ else:
+ LOG(' RSS Feed has no channel')
+
+
+w = CNNBrowser()
+w.downloadFeed()
+w.doModal()
+
+LOGCLOSE()
+
+if dialogProgress:
+ dialogProgress.close()
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/default.py
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/default.py Tue Apr 24 17:26:57 2007
@@ -0,0 +1,26 @@
+'''
+This file is part of the 'XBMC GameTrailersRssReader script'.
+
+'XBMC GameTrailersRssReader script' is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+'XBMC GameTrailersRssReader script' 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 software; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+'''
+import sys
+import xbmcgui
+
+sys.path.append(sys.path[0] + '\\lib')
+import GameTrailers
+
+mydisplay = GameTrailers.MyClass()
+mydisplay .doModal()
+del mydisplay
\ No newline at end of file
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/default.tbn
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/button-focus.png
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/button-nofocus.png
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/gt_background_nolines.jpg
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/gt_dialog_background.jpg
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/gt_submenu_bottom.jpg
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/img/gt_submenu_top.jpg
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/ClientCookie.zip
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/GameTrailers.py
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/GameTrailers.py Tue Apr 24 17:26:57 2007
@@ -0,0 +1,693 @@
+'''
+This file is part of the 'XBMC GameTrailersRssReader script'.
+
+'XBMC GameTrailersRssReader script' is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+'XBMC GameTrailersRssReader script' 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 software; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+'''
+import xbmc, xbmcgui
+import xml.dom.minidom, sys, urllib, os, string
+
+try: Emulating = xbmcgui.Emulating
+except: Emulating = False
+
+if (not Emulating): sys.path.append(sys.path[0] + '\\lib')
+import cachedhttp, textwindow, rss
+
+try:
+ reload(gtweb)
+except:
+ import gtweb
+try:
+ reload(gt)
+except:
+ import gt
+
+
+#
+# Path init
+#
+
+PATH_ROOT = os.getcwd().replace(";","") + "\\"
+if Emulating: PATH_IMAGE = PATH_ROOT + "../img/"
+else: PATH_IMAGE = PATH_ROOT + "img\\"
+PATH_DOWNLOAD = PATH_ROOT + "download\\"
+
+
+# RSS elements that is read by the RSSParser class when parsing the RSS
+RSS_CHANNEL_ELEMENTS = ['title','link','description']
+RSS_ITEM_ELEMENTS = ['exInfo:gameID', 'exInfo:gameName','exInfo:movieTitle','description','pubDate', 'exInfo:image','exInfo:downloadsThisWeek', 'exInfo:totalDownloads', 'rating', 'guid']
+
+COORD_1080I = 0 # HDTV_1080i = 0, (1920x1080, 16:9, pixels are 1:1)
+COORD_720P = 1 # HDTV_720p = 1, (1280x720, 16:9, pixels are 1:1)
+COORD_480P_4X3 = 2 # HDTV_480p_4x3 = 2, (720x480, 4:3, pixels are 4320:4739)
+COORD_480P_16X9 = 3 # HDTV_480p_16x9 = 3, (720x480, 16:9, pixels are 5760:4739)
+COORD_NTSC_4X3 = 4 # NTSC_4x3 = 4, (720x480, 4:3, pixels are 4320:4739)
+COORD_NTSC_16X9 = 5 # NTSC_16x9 = 5, (720x480, 16:9, pixels are 5760:4739)
+COORD_PAL_4X3 = 6 # PAL_4x3 = 6, (720x576, 4:3, pixels are 128:117)
+COORD_PAL_16X9 = 7 # PAL_16x9 = 7, (720x576, 16:9, pixels are 512:351)
+COORD_PAL60_4X3 = 8 # PAL60_4x3 = 8, (720x480, 4:3, pixels are 4320:4739)
+COORD_PAL60_16X9 = 9 # PAL60_16x9 = 9 (720x480, 16:9, pixels are 5760:4739)
+
+ACTION_MOVE_LEFT = 1
+ACTION_MOVE_RIGHT = 2
+ACTION_MOVE_UP = 3
+ACTION_MOVE_DOWN = 4
+ACTION_PAGE_UP = 5
+ACTION_PAGE_DOWN = 6
+ACTION_SELECT_ITEM = 7
+ACTION_HIGHLIGHT_ITEM = 8
+ACTION_PARENT_DIR = 9
+ACTION_PREVIOUS_MENU = 10
+ACTION_SHOW_INFO = 11
+ACTION_PAUSE = 12
+ACTION_STOP = 13
+ACTION_NEXT_ITEM = 14
+ACTION_PREV_ITEM = 15
+ACTION_MUSIC_PLAY = 79
+ACTION_CONTEXT_MENU = 117
+
+
+DISPLAY_TRAILERS = 0
+DISPLAY_SEARCH_RESULT = 1
+DISPLAY_GAME = 2
+
+DOWNLOAD_TYPE_TRAILER_PAGE = 0
+DOWNLOAD_TYPE_RSS = 1
+
+
+MENU_X_POS = 95
+MENU_Y_POS = 80
+MENU_HEIGHT = 25
+MENU_WIDTH = 170
+MENU_SUB_Y_POS = 230
+MENU_SUB_HEIGHT = 24
+
+INFO_Y_POS = 55
+INFO_HEIGHT = 25
+INFO_KEY_X_POS = 310
+INFO_KEY_WIDTH = 100
+INFO_VALUE_X_POS = 420
+INFO_VALUE_WIDTH = 300
+
+VERSION_STR = "0.4.2"
+
+class MyClass(xbmcgui.Window):
+
+ def __init__(self):
+ if Emulating: xbmcgui.Window.__init__(self)
+ self.setCoordinateResolution(COORD_PAL_4X3) # scales objects automatically
+
+ # background animation
+ self.imgBackgroundani = xbmcgui.ControlImage(0, 0, 720, 576, "Q:\\skin\\MC360\\Extras\\carbon-ani.gif")
+ self.addControl(self.imgBackgroundani)
+
+ # background image
+ self.imgBackground = xbmcgui.ControlImage(0, 0, 720, 576, 'background-blue-alpha.png')
+ self.addControl(self.imgBackground)
+
+ # custom background image
+ self.imgCustomBackground = xbmcgui.ControlImage(0, 0, 720, 576, xbmc.getInfoLabel('Skin.String(Media)'))
+ self.addControl(self.imgCustomBackground)
+ self.imgCustomBackground.setColorDiffuse('D1FFFFFF')
+
+ # Whitewash glass top left
+ self.imgWhiteTL = xbmcgui.ControlImage(70, 0, 16, 64, 'bkgd-whitewash-glass-top-left.png')
+ self.addControl(self.imgWhiteTL)
+
+ # Whitewash glass top middle
+ self.imgWhiteTMID = xbmcgui.ControlImage(86, 0, 592, 64, 'bkgd-whitewash-glass-top-middle.png')
+ self.addControl(self.imgWhiteTMID)
+
+ # Whitewash glass top right
+ self.imgWhiteTR = xbmcgui.ControlImage(678, 0, 16, 64, 'bkgd-whitewash-glass-top-right.png')
+ self.addControl(self.imgWhiteTR)
+
+ # Whitewash glass bottom left
+ self.imgWhiteBL = xbmcgui.ControlImage(70, 512, 16, 64, 'bkgd-whitewash-glass-bottom-left.png')
+ self.addControl(self.imgWhiteBL)
+
+ # Whitewash glass bottom middle
+ self.imgWhiteBMID = xbmcgui.ControlImage(86, 512, 592, 64, 'bkgd-whitewash-glass-bottom-middle.png')
+ self.addControl(self.imgWhiteBMID)
+
+ # Whitewash glass bottom right
+ self.imgWhiteBR = xbmcgui.ControlImage(678, 512, 16, 64, 'bkgd-whitewash-glass-bottom-right.png')
+ self.addControl(self.imgWhiteBR)
+
+ # Whitewash overlay left
+ self.imgWhitewashL = xbmcgui.ControlImage(60, 0, 32, 576, 'background-overlay-whitewash-left.png')
+ self.addControl(self.imgWhitewashL)
+
+ # Whitewash overlay middle
+ self.imgWhitewashMID = xbmcgui.ControlImage(92, 0, 553, 576, 'background-overlay-whitewash-centertile.png')
+ self.addControl(self.imgWhitewashMID)
+
+ # Whitewash overlay right
+ self.imgWhitewashR = xbmcgui.ControlImage(645, 0, 64, 576, 'background-overlay-whitewash-right.png')
+ self.addControl(self.imgWhitewashR)
+
+ # Left blade runner
+ self.imgBladerunL = xbmcgui.ControlImage(-61, 0, 128, 576, 'blades-runner-left.png')
+ self.addControl(self.imgBladerunL)
+
+ # Right blade runner
+ self.imgBladerunR = xbmcgui.ControlImage(665, 0, 128, 576, 'blades-runner-right.png')
+ self.addControl(self.imgBladerunR)
+
+ # Header Blade
+ self.imgBlade = xbmcgui.ControlImage(18, 0, 80, 576, 'blades-size4-header.png')
+ self.addControl(self.imgBlade)
+
+ # Y Button
+ self.addControl(xbmcgui.ControlImage(125, 520, 21, 21, 'button-Y-turnedoff.png'))
+ # X Button
+ self.addControl(xbmcgui.ControlImage(112, 540, 21, 21, 'button-X.png'))
+ # Back Button
+ self.addControl(xbmcgui.ControlImage(620, 520, 21, 21, 'button-back.png'))
+ # A Button
+ self.addControl(xbmcgui.ControlImage(633, 540, 21, 21, 'button-A.png'))
+ self.addControl(xbmcgui.ControlLabel(79,149,100,20,'media','font14','0xFF000000',angle=270))
+ self.addControl(xbmcgui.ControlLabel(145,543,375,20,'Full Screen Visualization','font12','0xFFFFFFFF'))
+ self.addControl(xbmcgui.ControlLabel(580,523,80,20,'Back','font12','0xFFFFFFFF'))
+ self.addControl(xbmcgui.ControlLabel(577,543,80,20,'Select','font12','0xFFFFFFFF'))
+
+
+ # top title bar with channel info
+ if (Emulating): self.lblScreenTitle = xbmcgui.ControlLabel(102, 42, 620, 10, "font18", "0xFFFFFFFF")
+ else: self.lblScreenTitle = xbmcgui.ControlFadeLabel(102, 42, 620, 10, "font18", "0xFFFFFFFF")
+ self.addControl(self.lblScreenTitle)
+ self.setTitle("GameTrailers.com - RSS Reader v" + VERSION_STR)
+
+ # bottom bar with copyright stuff
+ self.lblCopyright = xbmcgui.ControlFadeLabel(70, 570, 550, 10, "font12", "0xFFFFFFFF")
+ self.addControl(self.lblCopyright)
+ self.lblCopyright.addLabel("All logotypes, videos, text is Copyright (c) 2005 Gametrailers.com, all rights reserved.")
+ self.lblCopyright.addLabel("GameTrailers.com RSS Reader v" + VERSION_STR + " developed by RedSolo. For latest version check www.xbmcscripts.com.")
+
+ self.isGameInfoVisible = True
+ self.lblInfoKeys = []
+ self.lblInfoValues = []
+ self.lblInfoNextYPos = INFO_Y_POS
+ self.addInfoLabel("Release")
+ self.addInfoLabel("Platforms")
+ self.addInfoLabel("Publisher")
+ self.addInfoLabel("Developer")
+ self.addInfoLabel("Genres")
+ self.addInfoLabel("ESRB")
+ self.imgBoxArt = None
+
+ # media list
+ if (Emulating): self.listMedia = xbmcgui.ControlList(290, 85 + 162, 375, 390 - 200, "font14", "0xFF000000")
+ else: self.listMedia = xbmcgui.ControlList(290, 85, 375, 390, "font14", "0xFF000000")
+ self.listMedia.setItemHeight(30)
+ self.addControl(self.listMedia)
+
+ self.btnNextYPos = MENU_Y_POS
+ self.btnTemp = None
+
+ self.mapMenu = {}
+ self.btnMenuFirst = None
+ self.btnMenuLast = None
+ self.btnMenuNewest = self.addMenu("Newest", "newest", DOWNLOAD_TYPE_RSS)
+ self.btnMenuTop20 = self.addMenu("Top Media", "top20", DOWNLOAD_TYPE_TRAILER_PAGE)
+ self.btnMenuTopRated = self.addMenu("Top Rated", "toprated", DOWNLOAD_TYPE_TRAILER_PAGE)
+ self.btnMenuTopRated = self.addMenu("Reviews", "reviews", DOWNLOAD_TYPE_TRAILER_PAGE)
+ self.btnMenuTopRated = self.addMenu("GT.Tv", "topgttv", DOWNLOAD_TYPE_TRAILER_PAGE)
+ self.btnMenuSearch = self.addMenu("Search", "search", None)
+ self.btnMenuLast.controlDown(self.btnMenuFirst)
+ self.btnMenuFirst.controlUp(self.btnMenuLast)
+ self.ctrlCurrentMainMenu = None
+
+ self.isSubMenuVisible = True
+ self.mapSubMenu = {}
+ self.btnNextYPos = MENU_SUB_Y_POS
+ self.btnSubMenuFirst = None
+ self.btnSubMenuLast = None
+ self.btnSubMenuAll = self.addSubMenu("All", "")
+ self.btnSubMenuPC = self.addSubMenu("PC", "pc")
+ self.btnSubMenuPs2 = self.addSubMenu("Playstation 2", "ps2")
+ self.btnSubMenuPs3 = self.addSubMenu("Playstation 3", "ps3")
+ self.btnSubMenuXbox = self.addSubMenu("Xbox", "xbox")
+ self.btnSubMenuXbox360 = self.addSubMenu("Xbox 360", "xb360")
+ self.btnSubMenuGc = self.addSubMenu("Gamecube", "gc")
+ self.btnSubMenuWii = self.addSubMenu("Nintendo Wii", "rev")
+ self.btnSubMenuDS = self.addSubMenu("Nintendo DS", "ds")
+ self.btnSubMenuGba = self.addSubMenu("GameBoy Adv", "gba")
+ self.btnSubMenuPsp = self.addSubMenu("PSP", "psp")
+ #self.btnSubMenuNgage = self.addSubMenu("N-Gage", "ngage")
+ #self.btnSubMenuHand = self.addSubMenu("Handhelds", "hand")
+
+ self.imgSubMenuTop = xbmcgui.ControlImage(MENU_X_POS, MENU_SUB_Y_POS - MENU_SUB_HEIGHT, MENU_WIDTH, MENU_SUB_HEIGHT, PATH_IMAGE + "fuckthisimage.jpg")
+ self.addControl(self.imgSubMenuTop)
+ self.imgSubMenuBottom = xbmcgui.ControlImage(MENU_X_POS, self.btnNextYPos, MENU_WIDTH, MENU_SUB_HEIGHT, PATH_IMAGE + "fuckthisimage.jpg")
+ self.addControl(self.imgSubMenuBottom)
+
+ self.listMedia.controlLeft(self.btnMenuNewest)
+ self.setFocus(self.btnMenuNewest)
+
+ self.setSubMenuVisible(False)
+ self.setGameInfoVisible(False)
+
+ # Web objects
+ self.httpFetcher=cachedhttp.CachedHTTPWithProgress()
+ self.gtWeb = gtweb.GtPage(self.httpFetcher)
+ self.rssParser = rss.RSSParser(RSS_CHANNEL_ELEMENTS , RSS_ITEM_ELEMENTS)
+
+ self.mediaTrailers = None
+ self.searchResult = None
+
+ self.displayState = DISPLAY_TRAILERS
+ self.searchStr = ""
+
+ def onAction(self, action):
+ if (action == ACTION_PREVIOUS_MENU):
+ self.close()
+ if (action == ACTION_CONTEXT_MENU):
+ if (self.getFocus() == self.listMedia) and (self.displayState == DISPLAY_TRAILERS):
+ self.onContextMenuClick()
+ if (action == ACTION_MUSIC_PLAY):
+ if (self.getFocus() == self.listMedia) and (self.displayState == DISPLAY_TRAILERS):
+ self.onListControlClick()
+ if (action == ACTION_SHOW_INFO):
+ if (self.getFocus() == self.listMedia) and (self.displayState == DISPLAY_TRAILERS):
+ self.onDisplayGame()
+ if Emulating:
+ if (action == ACTION_SELECT_ITEM):
+ self.onListControlClick()
+ if (action == ACTION_MOVE_UP):
+ self.onDisplayGame()
+ if (action == ACTION_MOVE_DOWN):
+ self.downloadAndPlay()
+ if (action == ACTION_MOVE_RIGHT):
+ self.onContextMenuClick()
+
+ def onControl(self, control):
+ if (control == self.listMedia):
+ self.onListControlClick()
+ if (self.mapMenu.has_key(control.getId())):
+ self.onMainMenuClick(control)
+ if (self.mapSubMenu.has_key(control.getId())):
+ self.onSubMenuClick(control)
+
+ def onContextMenuClick(self):
+ choices = ["Show game info", "Play trailer", "Download & play"]
+ if (self.searchResult <> None):
+ choices.append("Last search result")
+ dialog = xbmcgui.Dialog()
+ choice = dialog.select("Game menu", choices)
+ if choice == 0: self.onDisplayGame()
+ if choice == 1: self.playMedia()
+ if choice == 2: self.downloadAndPlay()
+ if choice == 3: self.displayTrailerList(searchResult)
+
+ def onMainMenuClick(self, control):
+ self.listMedia.controlLeft(control)
+ self.ctrlCurrentMainMenu = self.mapMenu[control.getId()]
+ if (control == self.btnMenuSearch):
+ self.setSubMenuVisible(False)
+ self.searchForGame()
+ else:
+ self.setSubMenuVisible(True)
+ if (self.ctrlCurrentMainMenu.downloadType == DOWNLOAD_TYPE_RSS):
+ self.downloadRss(self.ctrlCurrentMainMenu.getLinkStr())
+ else:
+ self.setTitle("GameTrailers.com - " + self.ctrlCurrentMainMenu.getFullName())
+ self.displayTrailerList(self.gtWeb.retrieveTrailers(self.ctrlCurrentMainMenu.getLinkStr(), None))
+
+ def onSubMenuClick(self, control):
+ self.listMedia.controlLeft(control)
+ subMenu = self.mapSubMenu[control.getId()]
+ if (self.ctrlCurrentMainMenu.downloadType == DOWNLOAD_TYPE_RSS):
+ if (control == self.btnSubMenuWii):
+ self.showMessageBox("GameTrailers.com has no RSS for the Nintendo Wii. Sorry.")
+ else:
+ self.downloadRss(self.ctrlCurrentMainMenu.getLinkStr(), subMenu.getLinkStr())
+ else:
+ self.setTitle("GameTrailers.com - " + self.ctrlCurrentMainMenu.getFullName() + " - " + subMenu.getFullName())
+ self.displayTrailerList(self.gtWeb.retrieveTrailers(self.ctrlCurrentMainMenu.getLinkStr(), subMenu.getLinkStr()))
+
+ def onListControlClick(self):
+ if (self.displayState == DISPLAY_SEARCH_RESULT):
+ if (len(self.searchResult) > 0):
+ game = self.searchResult[self.listMedia.getSelectedPosition()]
+ if (game <> None):
+ self.displayGame(game.guid)
+ else:
+ self.playMedia()
+
+ def onDisplayGame(self):
+ if (len(self.mediaTrailers) == 0):
+ return
+ trailer = self.mediaTrailers[self.listMedia.getSelectedPosition()]
+ if (trailer == None):
+ return
+ self.displayGame(trailer.gameGuid)
+
+ def setTitle(self, text):
+ if (Emulating):
+ self.lblScreenTitle.setLabel(text)
+ else:
+ self.lblScreenTitle.reset()
+ self.lblScreenTitle.addLabel(text)
+
+ def showMessageBox(self, body, title = None ):
+ dialog = textwindow.Dialog()
+ if (title <> None):
+ dialog.setTitle(title)
+ dialog.setBody(body)
+ dialog.doModal()
+
+ def updateBoxArt(self, boxArtLink):
+ if (self.imgBoxArt <> None):
+ self.removeControl(self.imgBoxArt)
+ try:
+ localFile = self.httpFetcher.urlretrieve(boxArtLink)
+ self.imgBoxArt = xbmcgui.ControlImage(200, 60, 70 * 1.4, 100 * 1.4, localFile)
+ self.addControl(self.imgBoxArt)
+ except:
+ self.imgBoxArt = None
+ if (Emulating): raise
+
+ def displayGameList(self, gameList):
+ self.listMedia.reset()
+ self.listMedia.setImageDimensions(60,74)
+ xbmcgui.lock()
+ self.mediaTrailers = None
+ shouldDisplayBoxArt = len(gameList) < 20
+ for game in gameList:
+ listItem = xbmcgui.ListItem(game.toString())
+ if (shouldDisplayBoxArt and (game.boxArtLink <> None)):
+ try:
+ imageUrl = game.boxArtLink
+ localFile = self.httpFetcher.urlretrieve(imageUrl)
+ listItem.setThumbnailImage(localFile)
+ except:
+ pass
+ self.listMedia.addItem(listItem)
+ xbmcgui.unlock()
+
+ def displayTrailerList(self, trailerList):
+ self.listMedia.reset()
+ self.listMedia.setImageDimensions(178,74)
+ xbmcgui.lock()
+ self.mediaTrailers = trailerList
+ for trailer in self.mediaTrailers:
+ listItem = xbmcgui.ListItem(trailer.toString())
+ if (trailer.thumbnailLink <> None):
+ try:
+ imageUrl = trailer.thumbnailLink
+ localFile = self.httpFetcher.urlretrieve(imageUrl)
+ listItem.setThumbnailImage(localFile)
+ except:
+ pass
+ self.listMedia.addItem(listItem)
+ xbmcgui.unlock()
+
+ def displayGame(self, guid):
+ try:
+ self.clearGame()
+ self.listMedia.reset()
+ game = self.gtWeb.retrieveGameInfo(guid)
+ self.setDisplayState(DISPLAY_GAME)
+ self.setTitle(game.name)
+ self.lblInfoValues[0].setLabel(game.release)
+ self.lblInfoValues[1].setLabel(game.getPlatformStr())
+ self.lblInfoValues[2].setLabel(game.publisher)
+ self.lblInfoValues[3].setLabel(game.developer)
+ self.lblInfoValues[4].setLabel(game.genres)
+ self.lblInfoValues[5].setLabel(game.rating)
+ self.updateBoxArt(game.boxArtLink)
+ self.displayTrailerList(self.gtWeb.retrieveGameTrailerList(guid))
+ except:
+ self.showMessageBox("There was a problem downloading the game information, either GameTrailers has changed the media links or the game is not currently available. Actual error: " + str(sys.exc_info()[0]), "Error")
+ if (Emulating): raise
+
+ def clearGame(self):
+ self.setTitle("")
+ self.lblInfoValues[0].setLabel("")
+ self.lblInfoValues[1].setLabel("")
+ self.lblInfoValues[2].setLabel("")
+ self.lblInfoValues[3].setLabel("")
+ self.lblInfoValues[4].setLabel("")
+ self.lblInfoValues[5].setLabel("")
+ if (self.imgBoxArt <> None):
+ self.removeControl(self.imgBoxArt)
+ self.imgBoxArt = None
+
+ def searchForGame(self, searchStr = None, platformStr = None):
+ if (searchStr == None):
+ if Emulating: dialog = xbmc.Keyboard()
+ else: dialog = xbmc.Keyboard(self.searchStr, "Enter the search string")
+ dialog.doModal()
+ if (dialog.isConfirmed()):
+ self.searchStr = dialog.getText()
+ searchStr = self.searchStr
+
+ if (searchStr <> None):
+ try:
+ title = "GameTrailers.com - Searching for '" + self.searchStr + "'"
+ if (platformStr <> None):
+ title = title + " - " + platformStr
+ self.setTitle(title)
+ self.searchResult = self.gtWeb.gameSearch(self.searchStr, platformStr)
+ self.setDisplayState( DISPLAY_SEARCH_RESULT )
+ title = "GameTrailers.com - Search result for '" + self.searchStr + "'"
+ if (platformStr <> None):
+ title = title + " - " + platformStr
+ self.setTitle(title)
+ self.displayGameList(self.searchResult)
+ except:
+ self.showMessageBox("There was a problem searching for a game. GameTrailers has probably changed the search links. Actual error: " + str(sys.exc_info()[0]), "Error")
+ if (Emulating): raise
+
+ def downloadRss(self, feedName, platformName = None):
+ '''
+ downloadRss(string feedName, string platformName) -- .
+
+ feedName : name of the feed to download, ie newest, top20, toprated
+ platformName : name of the specific platform to download, pc, ps2, ps3. If none, rss for all platforms will be downloaded.
+ '''
+ #xbmcgui.lock()
+ try:
+ url = "http://www.gametrailers.com/rss/"
+ url = url + feedName
+
+ if (platformName <> None):
+ url = url + platformName
+ url = url + ".xml"
+
+ rssFeedFile = self.httpFetcher.urlretrieve(url)
+
+ self.rssParser.feedFromFile(rssFeedFile)
+ self.rssParser.parse()
+
+ text = self.rssParser.getChannelInfo().getElement("title")
+ print text
+ if (self.mapSubMenu.has_key(self.getFocus().getId())):
+ text = text + " - " + self.mapSubMenu[self.getFocus().getId()].getFullName()
+ else:
+ text = text + " - All"
+ self.setTitle(text)
+
+ self.setDisplayState( DISPLAY_TRAILERS )
+ trailers = []
+ for item in self.rssParser.getItems():
+ trailer = gt.Trailer()
+ trailer.copyFromRssItem(item)
+ trailers.append(trailer)
+ self.displayTrailerList(trailers)
+
+ except :
+ self.showMessageBox("There was a problem downloading the '" + url + "'. Actual error: " + str(sys.exc_info()[0]),
+ "Rss feed download error")
+ if (Emulating): raise
+ #xbmcgui.unlock()
+
+ def playMedia(self):
+ '''
+ Plays the current selected media in the media list.
+ '''
+ if (len(self.mediaTrailers) == 0):
+ return
+ trailer = self.mediaTrailers[self.listMedia.getSelectedPosition()]
+ if (trailer == None):
+ return
+
+ try:
+ streamStr = self.gtWeb.retrieveStreamLinkQuick(trailer)
+ if (streamStr <> None):
+ xbmc.Player().play(streamStr)
+ else:
+ self.showMessageBox("There was a problem retrieving the stream URL. Perhaps the GameTrailers.com site has changed.", "Retriving data error")
+ except:
+ self.showMessageBox("There was a problem playing the media stream, either GameTrailers has changed the media links or the media is not currently available. Actual error: " + str(sys.exc_info()[0]), "Error")
+ if (Emulating): raise
+
+ def downloadAndPlay(self):
+ '''
+ Plays the current selected media in the media list.
+ '''
+ if (len(self.mediaTrailers) == 0):
+ return
+ trailer = self.mediaTrailers[self.listMedia.getSelectedPosition()]
+ if (trailer == None):
+ return
+
+ try:
+ streamStr = self.gtWeb.retrieveStreamLinkQuick(trailer)
+ if (streamStr <> None):
+ file = self.httpFetcher.urlretrieve(streamStr, None, PATH_ROOT + "temp", "wmv")
+ xbmc.Player().play(file)
+ else:
+ self.showMessageBox("There was a problem retrieving the stream URL. Perhaps the GameTrailers.com site has changed.", "Retriving data error")
+ except:
+ self.showMessageBox("There was a problem playing the media stream, either GameTrailers has changed the media links or the media is not currently available. Actual error: " + str(sys.exc_info()[0]), "Error")
+ if (Emulating): raise
+
+ def addMenu(self, text, link, downloadtype):
+ '''
+ addMenu(string text) -- .
+ Adds a menu item to menu list.
+
+ text : The button text.
+ '''
+ btn = xbmcgui.ControlButton(MENU_X_POS, self.btnNextYPos, MENU_WIDTH, MENU_HEIGHT, text, PATH_IMAGE + "button-focus.png", PATH_IMAGE + "button-nofocus.png")
+ self.addControl(btn)
+ btn.setLabel(text, "font12", "0xFF000000", "0xFF000000")
+ self.mapMenu[btn.getId()] = MenuItem(text, link, downloadtype)
+ if (self.btnTemp <> None):
+ btn.controlUp(self.btnTemp)
+ self.btnTemp.controlDown(btn)
+ btn.controlRight(self.listMedia)
+ self.btnTemp = btn
+ self.btnNextYPos = self.btnNextYPos + MENU_HEIGHT
+ if (self.btnMenuFirst == None):
+ self.btnMenuFirst = btn
+ self.btnMenuLast = btn
+ return btn
+
+ def addSubMenu(self, text, link):
+ '''
+ addSubMenu(string text) -- .
+ Adds a sub menu item to menu list.
+
+ text : The button text.
+ abbrev : String that is used when building the rss feed list to retrieve. (Check http://www.gametrailers.com/rss/ for more info)
+ '''
+ btn = xbmcgui.ControlButton(MENU_X_POS, self.btnNextYPos, MENU_WIDTH, MENU_SUB_HEIGHT, text, PATH_IMAGE + "button-focus.png", PATH_IMAGE + "button-nofocus.png")
+ self.addControl(btn)
+ btn.setLabel(text, "font12", "0xFF000000", "0xFF000000")
+ self.mapSubMenu[btn.getId()] = MenuItem(text, link)
+ if (self.btnTemp <> None):
+ btn.controlUp(self.btnTemp)
+ self.btnTemp.controlDown(btn)
+ btn.controlRight( self.listMedia )
+ self.btnTemp = btn
+ self.btnNextYPos = self.btnNextYPos + MENU_SUB_HEIGHT
+ if (self.btnSubMenuFirst == None):
+ self.btnSubMenuFirst = btn
+ self.btnSubMenuLast = btn
+ return btn
+
+ def addInfoLabel(self, text):
+ '''
+ addMenu(string text) -- .
+ Adds a menu item to menu list.
+
+ text : The button text.
+ '''
+ lblKey = xbmcgui.ControlLabel(INFO_KEY_X_POS, self.lblInfoNextYPos, INFO_KEY_WIDTH, 10, text, "font13", "0xFF000000")
+ self.addControl(lblKey)
+ lblValue = xbmcgui.ControlLabel(INFO_VALUE_X_POS, self.lblInfoNextYPos, INFO_VALUE_WIDTH, 10, "", "font13", "0xFF000000")
+ self.addControl(lblValue)
+
+ self.lblInfoKeys.append(lblKey)
+ self.lblInfoValues.append(lblValue)
+ self.lblInfoNextYPos = self.lblInfoNextYPos + INFO_HEIGHT
+
+ def setSubMenuVisible(self, visible):
+ '''
+ setSubMenuVisible(boolean visible) -- .
+ Hides or shows the sub menu.
+
+ visible : True if the sub menu show be visibled; False otherwise.
+ '''
+ xbmcgui.lock()
+ if (self.isSubMenuVisible <> visible):
+ if (visible):
+ self.btnMenuLast.controlDown(self.btnSubMenuFirst)
+ self.btnSubMenuFirst.controlUp(self.btnMenuLast)
+ self.btnSubMenuLast.controlDown(self.btnMenuFirst)
+ self.btnMenuFirst.controlUp(self.btnSubMenuLast)
+ else:
+ self.btnMenuLast.controlDown(self.btnMenuFirst)
+ self.btnMenuFirst.controlUp(self.btnMenuLast)
+
+ self.imgSubMenuBottom.setVisible(visible)
+ self.imgSubMenuTop.setVisible(visible)
+ self.isSubMenuVisible = visible
+ for btnId in self.mapSubMenu.iterkeys():
+ if (self.getControl(btnId)<>None):
+ self.getControl(btnId).setVisible(visible)
+ xbmcgui.unlock()
+
+ def setGameInfoVisible(self, visible):
+ '''
+ setSubMenuVisible(boolean visible) -- .
+ Hides or shows the sub menu.
+
+ visible : True if the sub menu show be visibled; False otherwise.
+ '''
+ xbmcgui.lock()
+ if (self.isGameInfoVisible <> visible):
+
+ for control in self.lblInfoKeys:
+ control.setVisible(visible)
+ for control in self.lblInfoValues:
+ control.setVisible(visible)
+ if (self.imgBoxArt <> None):
+ self.imgBoxArt.setVisible(visible)
+
+ self.isGameInfoVisible = visible
+
+ if (visible):
+ #print "setting smaller view"
+ self.listMedia.setPosition(290, 85 + 162)
+ self.listMedia.setHeight(386 - 162)
+ else:
+ #print "setting bigger view"
+ self.listMedia.setPosition(290, 85)
+ self.listMedia.setHeight(386)
+ xbmcgui.unlock()
+
+ def setDisplayState(self, newState):
+ self.displayState = newState
+ if (self.displayState == DISPLAY_GAME):
+ self.setGameInfoVisible(True)
+ else:
+ self.setGameInfoVisible(False)
+
+
+class MenuItem:
+ def __init__(self, fullName, linkStr, downloadType = None):
+ self.fullName = fullName
+ self.linkStr = linkStr
+ self.downloadType = downloadType
+ #self.isRss = isRss
+
+ def getFullName(self):
+ return self.fullName
+
+ def getLinkStr(self):
+ return self.linkStr
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/GameTrailers.pyo
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/cachedhttp.py
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/cachedhttp.py Tue Apr 24 17:26:57 2007
@@ -0,0 +1,373 @@
+#ScriptName : cachedhttp (formerly cachemanager)
+Version = '1.3'
+# Author : Van der Phunck aka Aslak Grinsted. a...@phunck.cmo <- not cmo but com
+# Desc : cache manager
+#
+#
+
+import sys, traceback, os.path, re
+ScriptPath = os.path.split(sys.modules['cachedhttp'].__file__)[0]+'\\' #this should always work! (note... os.getcwd() doesn't)
+
+sys.path.insert(0, ScriptPath+'ClientCookie.zip')
+
+import urllib2, re, time, string, random
+import socket,md5,urlparse
+import xbmc,xbmcgui
+import mimetypes
+import httplib
+import ClientCookie
+import base64
+import urllib
+import shutil
+
+Debug=True
+DefaultCacheTime=24*60.0 #minutes
+
+
+try: Emulating = xbmcgui.Emulating #Thanks alot to alexpoet for the xbmc.py,xmbcgui.py emulator. Very useful!
+except: Emulating = False
+
+
+def fileExists(fname):
+ return os.path.exists(fname)
+
+def readCacheMeta(fname):
+ if not fileExists(fname): return None
+ try:
+ fid=file(fname,'rb')
+ info=httplib.HTTPMessage(fid)
+ fid.close()
+ return info
+ except:
+ return None
+
+def isInFolder(fname,folder):
+ fname=os.path.split(fname)
+ fnamefolder=fname[0].lower()+'\\'
+ if not (fnamefolder[-1]=='\\'): fnamefolder=fnamefolder+'\\'
+ return (fnamefolder==folder.lower())
+
+Rauth=re.compile('^(.*):(.*)@(.*)$',re.IGNORECASE)
+def parseAuthUrl(url):
+ fields=urlparse.urlparse(url)
+ fields=[fields[0],fields[1],fields[2],fields[3],fields[4],fields[5]]
+ fauth=Rauth.findall(fields[1])
+ if len(fauth)==0: return [url,'','']
+ fields[1]=fauth[0][2] #host
+ name=urllib.unquote(fauth[0][0]) #username
+ pwd=urllib.unquote(fauth[0][1]) #password
+ url=urlparse.urlunparse(fields)
+ return [url,name,pwd]
+
+
+Rwhitespace=re.compile('\s\s+',re.IGNORECASE)
+Rillegalchars=re.compile('[^\.\_\w\d-]',re.IGNORECASE)
+Rfilename=re.compile('[^\\/]*$',re.IGNORECASE)
+Rdot2=re.compile('[\.\s]+',re.IGNORECASE)
+def urltoxfilename(url):
+ fields=urlparse.urlparse(url)
+ fname=Rfilename.findall(fields[2])
+ if len(fname)==0: fname=['']
+ fname=fname[0]
+ if len(fname)==0:
+ fname=Rfilename.findall(fields[1])
+ fname=fname[0]
+ fname=fname.replace('.','-')
+ fname=fname.replace(',',' ')
+ fname=Rillegalchars.sub(' ',fname)
+ fname=Rwhitespace.sub(' ',fname)
+ fname=Rdot2.sub('.',fname)
+ if len(fname)>40: #i think 42 is the limit?
+ ext=os.path.splitext(fname)[1]
+ fname=fname[0:40-max(len(ext),7)] #7 because a different extension might be added because of the mimetype...
+ if fname[-1]=='.': fname=fname[0:-1]
+ fname=fname+ext
+ return fname
+
+
+class CustomHandler(ClientCookie.HTTPCookieProcessor):
+ def http_error_304(self, req, fp, code, message, headers):
+ addinfourl = urllib2.addinfourl(fp, headers, req.get_full_url())
+ addinfourl.code = code
+ return addinfourl
+
+
+class CachedHTTP:
+ def __init__(self):
+ self.userAgent='OobaCacheMgr/'+Version
+ self.referer=None
+ self.urlContext=''
+ self.socketTimeout=7.0
+ self.cacheFolder='Z:\\~HttpCache\\'
+
+ if Emulating: self.cacheFolder=ScriptPath+'Cache\\'
+ try:
+ os.makedirs(self.cacheFolder)
+ except: pass
+
+ self.cookiefile=self.cacheFolder+'~cookies.txt'
+ #the tilde is there to ensure that url2xfilename doesn't create a file that might overwrite this
+
+ self.defaultCachetime=24*60.0 #minutes
+
+ self.cookies=ClientCookie.LWPCookieJar()
+ try:
+ self.cookies.revert(self.cookiefile)
+ except:
+ print('Could not open cookie file: '+self.cookiefile)
+
+ hh=CustomHandler(self.cookies)
+
+ self.opener=ClientCookie.build_opener(hh)
+
+ def saveCookies(self):
+ self.cookies.save(self.cookiefile)
+
+ def getCookieJar(self): return self.cookies
+
+ def getUserAgent(self): return self.userAgent
+ def setUserAgent(self,val): self.userAgent=val
+
+ def setReferer(self,val): self.referer=val
+
+ def getSocketTimeout(self): return self.socketTimeout
+ def setSocketTimeout(self,val): self.socketTimeout=float(val)
+
+ def getCacheFolder(self): return self.cacheFolder
+# def setCacheFolder(self,val): #you shouldn't call this really
+# self.cacheFolder=str(val)
+# if not (self.cacheFolder[-1]=='\\'): self.cacheFolder=self.cacheFolder+'\\'
+
+ def getUrlContext(self): return self.urlContext
+ def setUrlContext(self,val): self.urlContext=str(val)
+
+ def getDefaultCachetime(self): return self.defaultCachetime
+ def setDefaultCachetime(self,val): self.defaultCachetime=float(val)
+
+ def getFullUrl(self,url):
+ if len(url)>0:
+ if url[0]=='?':
+ f=urlparse.urlparse(self.urlContext)
+ baseurl=urlparse.urlunparse([f[0],f[1],f[2],'','',''])
+ return (baseurl+url).encode('iso-8859-1')
+ return urlparse.urljoin(self.urlContext,url).encode('iso-8859-1')
+
+ def onDataRetrieved(self, bytesRead, totalSize, url, localfile):
+ return True
+ def onDownloadFinished(self,success):
+ pass
+
+ def url2cachemetafile(self,url): #returns the filename of the meta file associated with url ... Note it does not necessarily exist
+ m = md5.new()
+ m.update(url)
+ digest=m.hexdigest()
+ return self.cacheFolder+'~'+digest
+
+
+ def cacheFilename(self,url):
+ urlmetafile=self.url2cachemetafile(url)
+ if fileExists(urlmetafile):
+ info=readCacheMeta(urlmetafile)
+ localfile=info['CM-Localfile']
+ if fileExists(localfile): return localfile
+ return ''
+
+ def flushCache(self,url):
+ urlmetafile=self.url2cachemetafile(url)
+ if not fileExists(urlmetafile): return
+ info=readCacheMeta(urlmetafile)
+ os.remove(urlmetafile)
+ if info is None: return #couldn't understand meta file...
+ try:
+ localfile=info['CM-localfile']
+ if fileExists(localfile):
+ if isInFolder(localfile,self.cacheFolder):
+ os.remove(localfile)
+ except: pass
+
+ def getCacheMeta(self,urlmetafile,expiretime=None): #returns None if the file doesn't exist or if the data is too old.
+ #expiretime is a way of overriding cachetime information in the metafile...
+ if not fileExists(urlmetafile): return None
+ info=readCacheMeta(urlmetafile)
+ isMetaOK=not (info is None)
+ try:
+ if isMetaOK:
+ localfile=info['CM-localfile']
+ timestamp=float(info['CM-TimeStamp'])
+ cachetime=float(info['CM-CacheTime'])
+ if not expiretime is None: cachetime=expiretime
+ if cachetime>=0: #(that is not permanent)
+ isMetaOK=isMetaOK & (abs(time.time()-timestamp)<(cachetime*60))
+ if fileExists(localfile):
+ contentlength=int(info['Content-Length'])
+ isMetaOK=isMetaOK & (os.path.getsize(localfile)==contentlength)
+ if (not isMetaOK) and isInFolder(localfile,self.cacheFolder):
+ os.remove(localfile)
+ else:
+ isMetaOK=False
+ except:
+ isMetaOK=False
+ if not isMetaOK:
+ os.remove(urlmetafile)
+ return None
+ return info
+
+
+ def cleanCache(self,expiretime=None):
+ files=os.listdir(self.cacheFolder)
+ Rmetafile=re.compile('^\~[\dabcdef]{32}$',re.IGNORECASE)
+ for filename in files:
+ try:
+ fname=filename.lower()
+ if Rmetafile.match(fname):
+ filename=self.cacheFolder+fname
+ info=self.getCacheMeta(filename,expiretime)
+ except:
+ pass
+
+ def urlretrieve(self,url,cachetime=None,localfile=None,ext=None,postdata=None):
+ url=self.getFullUrl(url)
+ urlmetafile=self.url2cachemetafile(url)
+ if cachetime is None: cachetime=self.defaultCachetime
+ metainfo = self.getCacheMeta(urlmetafile)
+ furl=None
+ fcache=None
+ isDownloadCompleted=False
+ try:
+ self.onDataRetrieved(0, None, url, '')
+ oldtimeout=socket.getdefaulttimeout()
+ socket.setdefaulttimeout(self.socketTimeout)
+ authurl=parseAuthUrl(url)
+ if len(authurl[1])>0: #todo use HTTPBasicAuthHandler instead....
+ url=authurl[0]
+ base64string=base64.encodestring('%s:%s' % (authurl[1],authurl[2]))[:-1]
+ authheader = "Basic %s" % base64string
+ request = ClientCookie.Request(url)
+ request.add_header('User-Agent',self.userAgent)
+ if (self.referer <> None):
+ request.add_header('Referer',self.referer)
+ if len(authurl[1])>0: request.add_header("Authorization", authheader)
+ #if len(self.urlContext)>0: #TODO: not always
+ # request.add_header('Referer',self.urlContext)
+ if not (metainfo is None):
+ try:
+ etag=metainfo['ETag']
+ request.add_header('If-None-Match', etag)
+ except: pass
+ try:
+ lastmodified = metainfo['Last-Modified']
+ request.add_header('If-Modified-Since', lastmodified)
+ except: pass
+ furl=self.opener.open(request,postdata)
+ info=furl.info()
+ if not (metainfo is None):
+ if hasattr(furl, 'code') and furl.code == 304:
+ self.urlContext=metainfo['CM-UrlContext']
+ temp=os.path.split(metainfo['CM-Localfile'])
+ isDownloadCompleted=True
+ if not (localfile is None):
+ nameext=os.path.splitext(metainfo['CM-Localfile'])
+ if not (localfile.lower()==nameext[0].lower()):
+ localfile=localfile+nameext[1]
+ shutil.copyfile(metainfo['CM-Localfile'],localfile)
+ return localfile
+ return metainfo['CM-Localfile']
+ else:
+ self.flushCache(url)
+ try:
+ totalSize=int(info['Content-Length'])
+ except:
+ totalSize=None
+
+ #------------ construct local file name ---------
+ xfname=os.path.splitext(urltoxfilename(url)) #tuple: suggested (filename,ext)
+ xfname=[xfname[0],xfname[1]] #otherwise you cannot write to it
+ try:
+ mimetype=info['Content-Type'].split(';') # also understand "Content-Type: text/html; charset=utf-8"
+ mimetype=mimetype[0].strip()
+ mimeext=mimetypes.guess_extension(mimetype)
+ if (not (mimeext is None)) and (len(mimeext)>0):
+ if mimeext=='.m1v': mimeext='.mpg'
+ xfname[1]=mimeext #override the one based on url alone
+ except:
+ pass
+ if not (ext is None): xfname[1]=ext #override with manual extension
+ ext=xfname[1]
+ xfname=xfname[0]
+ if len(ext)>0:
+ if not (ext[0]=='.'): ext='.'+ext
+ ext=ext[0:7] #do not allow so long extensions... Just truncate
+ if localfile is None: #then autogenerate a file name for the cache
+ localfile=self.cacheFolder+xfname+ext
+ i=1
+ while fileExists(localfile):
+ i=min(i*10,100000) #add a random number to minimize fileexist checks
+ localfile=self.cacheFolder+xfname[0:30]+'['+str(random.randint(0,i-1))+']'+ext
+ else:
+ localfile=localfile+ext
+ #------------------------------------------------
+ fcache=file(localfile,'wb')
+ iscanceled=not self.onDataRetrieved(0, totalSize, url, localfile)
+ data='...'
+ blockSize=8192
+ pval=0
+ while len(data)>0:
+ if not totalSize is None:
+ if pval>totalSize: totalSize=pval*2
+ data = furl.read(blockSize)
+ pval=pval+len(data)
+ if len(data)>0: fcache.write(data)
+ if len(data)<blockSize: break
+ iscanceled=not self.onDataRetrieved(pval, totalSize, url, localfile)
+ if iscanceled: break
+ isDownloadCompleted=not iscanceled
+ self.urlContext=furl.url
+ finally:
+ self.onDownloadFinished(isDownloadCompleted)
+ try:
+ if not fcache is None: fcache.close()
+ if not furl is None: furl.close()
+ socket.setdefaulttimeout(oldtimeout)
+ if not isDownloadCompleted: os.remove(localfile)
+ except:
+ pass
+ if not isDownloadCompleted:
+ return None
+ #------------- write url meta file ------------
+ #TODO: maybe do something if info['cache-control']=private?
+ info['Content-Length']=str(pval)
+ info['CM-Localfile']=localfile
+ info['CM-urlContext']=self.urlContext
+ info['CM-CacheTime']=str(cachetime)
+ info['CM-TimeStamp']=str(time.time())
+ info['CM-url']=url
+ fuc=file(urlmetafile,'wb')
+ fuc.write(str(info))
+ fuc.close()
+ return localfile
+
+ def urlopen(self,url,data=None):
+ localfile=self.urlretrieve(url,postdata=data)
+ f=file(localfile, 'rb')
+ data = f.read()
+ f.close()
+ return data
+
+
+
+class CachedHTTPWithProgress(CachedHTTP):
+ def onDataRetrieved(self, bytesRead, totalSize, url, localfile):
+ if (not hasattr(self,'progressbar')): self.progressbar=None
+ if self.progressbar is None:
+ self.progressbar=xbmcgui.DialogProgress()
+ self.progressbar.create("Downloading...",url,"> "+localfile)
+ if (not (bytesRead is None))&(not (totalSize is None)):
+ pct=int((bytesRead % (totalSize+1))*100.0/totalSize)
+ self.progressbar.update(pct)
+ return not self.progressbar.iscanceled()
+
+ def onDownloadFinished(self,success):
+ try:
+ self.progressbar.close()
+ except: pass
+ self.progressbar=None
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/cachedhttp.pyo
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/gt.py
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/gt.py Tue Apr 24 17:26:57 2007
@@ -0,0 +1,126 @@
+'''
+This file is part of the 'XBMC GameTrailersRssReader script'.
+
+'XBMC GameTrailersRssReader script' is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+'XBMC GameTrailersRssReader script' 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 software; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+'''
+import string
+
+def copySeperatedTuple(str, value, seperator = " - "):
+ if (value == None):
+ return str
+ if (len(value) == 0):
+ return str
+ if (str <> None) and (len(str) > 0):
+ return str + seperator + value
+ else:
+ return value
+
+class Game:
+ def __init__(self):
+ self.name = None
+ self.release = None
+ self.platforms = None
+ self.publisher = None
+ self.developer = None
+ self.genres = None
+ self.rating = None
+ self.guid = None
+ self.boxArtLink = None
+
+ def getListStr(self, list):
+ str = None
+ if (list <> None):
+ for item in list:
+ str = copySeperatedTuple(str, item.capitalize(), ", ")
+ return str
+
+ def getPlatformStr(self):
+ return self.getListStr(self.platforms)
+
+ def getGenreStr(self):
+ return self.getListStr(self.genres)
+
+ def __str__(self):
+ return "[guid=" + str(self.guid) + ", name=" + str(self.name) + ", release=" + str(self.release) + ", publisher=" + \
+ str(self.publisher) + ", developer=" + str(self.developer) + ", genres=" + \
+ str(self.genres) + ", rating=" + str(self.rating) + ", platforms=" + str(self.getPlatformStr()) + \
+ ", boxArtLink=" + str(self.boxArtLink) + "]"
+
+ def toString(self):
+ str = ""
+ if (self.name <> None):
+ str = self.name
+ if (self.platforms <> None):
+ str = str + " - " + self.getPlatformStr()
+ return str
+
+class Trailer:
+ def __init__(self):
+ self.guid = None
+ self.gameGuid = None
+ self.gameName = None
+ self.description = None
+ self.title = None
+ self.publishedDate = None
+ self.thumbnailLink = None
+ self.downloadsYesterday = None
+ self.downloadsThisWeek = None
+ self.downloadsTotal = None
+ self.rating = None
+ self.externalLink = None
+
+ def __str__(self):
+ return "[guid=" + str(self.guid) + ", gameGuid=" + str(self.gameGuid) + ", gameName=" + \
+ str(self.gameName) + ", description=" + str(self.description) + ", title=" + \
+ str(self.title) + ", date=" + str(self.publishedDate) + ", rating=" + \
+ str(self.rating) + ", downloads=" + str(self.downloadsTotal) + " (" + \
+ str(self.downloadsYesterday) + " / " + str(self.downloadsThisWeek) + \
+ "), thumbLink=" + str(self.thumbnailLink) + " externaLink=" + str(self.externalLink) + "]"
+
+ def toString(self):
+ str = self.gameName
+ #str = copySeperatedTuple(str, self.guid)
+ str = copySeperatedTuple(str, self.title)
+ str = copySeperatedTuple(str, self.description)
+ if (self.downloadsYesterday <> None):
+ str = copySeperatedTuple(str, "Downloads yesterday: " + self.downloadsYesterday)
+ if (self.downloadsThisWeek <> None):
+ str = copySeperatedTuple(str, "Downloads this week: " + self.downloadsThisWeek)
+ if (self.downloadsTotal <> None):
+ str = copySeperatedTuple(str, "Total downloads: " + self.downloadsTotal)
+ if (self.rating <> None):
+ str = copySeperatedTuple(str, "Rating: " + self.rating)
+ str = copySeperatedTuple(str, self.publishedDate)
+ return str
+
+ def copyFromRssItem(self, item):
+ self.gameName = str(item.getElement("exInfo:gameName"))
+ self.guid = str(item.getElement("guid"))
+ self.thumbnailLink = string.replace(item.getElement("exInfo:image"), ' ', '%20')
+
+ if (item.hasElement("exInfo:movieTitle")):
+ self.title = str(item.getElement("exInfo:movieTitle"))
+ if (item.hasElement("description")):
+ self.description = str(item.getElement("description"))
+ if (item.hasElement("exInfo:downloadsThisWeek")):
+ self.downloadsThisWeek = str(item.getElement("exInfo:downloadsThisWeek"))
+ if (item.hasElement("exInfo:totalDownloads")):
+ self.downloadsTotal = str(item.getElement("exInfo:totalDownloads"))
+ if (item.hasElement("rating")):
+ self.rating = str(item.getElement("rating"))
+ if (item.hasElement("pubDate")):
+ self.publishedDate = str(item.getElement("pubDate"))
+ if (item.hasElement("exInfo:gameID")):
+ self.gameGuid = str(item.getElement("exInfo:gameID"))
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/gt.pyo
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/gtweb.py
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/gtweb.py Tue Apr 24 17:26:57 2007
@@ -0,0 +1,335 @@
+'''
+This file is part of the 'XBMC GameTrailersRssReader script'.
+
+'XBMC GameTrailersRssReader script' is free software; you can redistribute it
+and/or modify it under the terms of the GNU General Public License as
+published by the Free Software Foundation; either version 2 of the License,
+or (at your option) any later version.
+
+'XBMC GameTrailersRssReader script' 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 software; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+'''
+import xml.dom.minidom, sys, urllib, os, os.path, string, re
+import cachedhttp
+
+try:
+ reload(gt)
+except:
+ import gt
+
+class GtPage:
+
+ def __init__(self, cachedHttp):
+ self.httpFetcher = cachedHttp
+ self.gameInfoRegEx = None
+ self.gameInfoTextRegEx = None
+ self.gameInfoLinkRegEx = None
+ self.gameInfoPlatformsRegEx = None
+ self.gameInfoNameRegEx = None
+ self.gameInfoBoxRegEx = None
+
+ self.gameTrailerRegEx = None
+ self.gameTrailerInfoRegEx = None
+ self.gameTrailerImageLinkRegEx = None
+
+ self.searchRegEx = None
+ self.searchGuidRegEx = None
+ self.searchNameRegEx = None
+ self.searchGenresRegEx = None
+ self.searchReleaseRegEx = None
+ self.searchBoxRegEx = None
+ self.searchPlatRegEx = None
+ self.searchPlatTwoRegEx = None
+
+ self.regExPlayer = re.compile('''player.php[^+]*?type=''')
+
+ self.regExTrailersWithThumbs = re.compile('''moses/moviesthumbs[^+]*?nowrap''')
+ self.regExTrailersWithoutThumbs = re.compile('''<table border="0"id="table9"[^+]*?</table>''')
+ self.regExPageGameNameOne = re.compile('''<a href="gamepage.php?[^+]*?</a''')
+ self.regExPageGameNameTwo = re.compile('''>[^+]*?<''')
+ self.regExPageGameGuid = re.compile('''gamepage.php[^+]*?" class''')
+ self.regExPageTitle = re.compile('''topmedia_sub">[^+]*?</div>''')
+ self.regExPageDownloadsTotal = re.compile('''Downloads:[^+]*?</div>''')
+ self.regExPageDownloadsYesterday = re.compile('''Yesterday:[^+]*?<b''')
+ self.regExPageDescOne = re.compile('''_text[^+]*?</div>''')
+ self.regExPageDescTwo = re.compile('''>[^+]*?<''')
+ self.regExPageThumbLink = re.compile('''moses/moviesthumb[^+]*?.jpg''')
+ self.regExExternalLink = re.compile('''<a target="_blank" href="[^+]*?"''')
+ self.regExNumber = re.compile('''[ >][0-9,]*?[< ]''')
+
+ def trace(self, str):
+ print str
+
+ def gameSearch(self, searchStr, platformStr = None, searchPageIndex = 0):
+ if (self.searchGuidRegEx == None):
+ self.searchGuidRegEx = re.compile('''gamepage.php[^+]*?"><''')
+ if (self.searchNameRegEx == None):
+ self.searchNameRegEx = re.compile('''search_title_link[^+]*?</a></div></td''')
+ if (self.searchGenresRegEx == None):
+ self.searchGenresRegEx = re.compile('''<b>Genres:</b>[^+]*?</div>''')
+ if (self.searchReleaseRegEx == None):
+ self.searchReleaseRegEx = re.compile('''<b>Release Date:</b>[^+]*?</div>''')
+ if (self.searchBoxRegEx == None):
+ self.searchBoxRegEx = re.compile('''moses/boxart[^+]*?.jpg''')
+ if (self.searchPlatRegEx == None):
+ self.searchPlatRegEx = re.compile('''<b>Platforms:</b>[^+]*?<b>''')
+ if (self.searchPlatTwoRegEx == None):
+ self.searchPlatTwoRegEx = re.compile('''[a-zA-Z0-9][^,]*''')
+ if (self.searchRegEx == None):
+ self.searchRegEx = re.compile('''<a href="gamepage.php?[^+]*?<div class="search_stats">''')
+
+ # must URL code saerch str
+ searchPageLink = "http://www.gametrailers.com/search.php?s=" + searchStr + "&submit_x=0&submit_y=0"
+ #if (platformStr <> None):
+ # searchPageLink = searchPageLink + "&p=" + platformStr
+ if (searchPageIndex > 0):
+ searchPageLink = searchPageLink + "&page=" + str(searchPageIndex * 10)
+
+ searchResultStr = self.httpFetcher.urlopen(searchPageLink)
+
+ posStart = searchResultStr.find('<div id="showsearch">')
+ posStop = searchResultStr.find('<td class="right_shinedark">')
+ trailersStr = searchResultStr[posStart:posStop]
+
+ games = []
+
+ regMatches = self.searchRegEx.findall(trailersStr)
+ for match in regMatches:
+ game = gt.Game()
+ game.guid = self.searchGuidRegEx.findall(match)[0][21:-3]
+ game.name = self.searchNameRegEx.findall(match)[0][48 + len(str(game.guid)):-14]
+ game.genres = self.searchGenresRegEx.findall(match)[0][15:-6]
+ game.release = self.searchReleaseRegEx.findall(match)[0][21:-6]
+ game.boxArtLink = "http://www.gametrailers.com/" + self.searchBoxRegEx.findall(match)[0]
+ games.append(game)
+
+ platforms = []
+ platsStr = self.searchPlatRegEx.findall(match)[0]
+ for platStr in self.searchPlatTwoRegEx.findall(platsStr[19:-5]):
+ platforms.append(platStr)
+ game.platforms = platforms
+
+ if (trailersStr.find('&submit_x=0&submit_y=0">Next') <> -1):
+ nextSearchPageGames = self.gameSearch(searchStr, platformStr, searchPageIndex + 1)
+ games.extend(nextSearchPageGames)
+
+ return games
+
+ # WORKS
+ def retrieveTopTrailers(self, platformStr = None):
+ return self.retrieveTrailers("top20", platformStr)
+ def retrieveTopRatedTrailers(self, platformStr = None):
+ return self.retrieveTrailers("toprated", platformStr)
+ def retrieveTopGtTvTrailers(self):
+ return self.retrieveTrailers("topgttv", None)
+ def retrieveReviewTrailers(self, platformStr = None):
+ return self.retrieveTrailers("reviews", platformStr)
+ def retrieveE32005Trailers(self, platformStr = None):
+ return self.retrieveTrailers("e32k5", platformStr)
+
+ # works with special regex
+ def retrieveE32006Trailers(self, platformStr = None):
+ return self.retrieveTrailers("e32k6", platformStr)
+
+ # does not work
+ def retrieveTopUserTrailers(self, platformStr = None):
+ return self.retrieveTrailers("umlisting", platformStr)
+ def retrieveNewestTrailers(self, platformStr = None):
+ return self.retrieveTrailers("newest_noflash", platformStr)
+ def retrievePreviewTrailers(self, platformStr = None):
+ return self.retrieveTrailers("previews", platformStr)
+
+ def retrieveTrailers(self, basePage, platformStr):
+ topMediaPageLink = "http://www.gametrailers.com/" + basePage + ".php"
+ postData = None
+ if (platformStr <> None):
+ postData = "p=" + platformStr
+ fileStr = self.httpFetcher.urlopen(topMediaPageLink, postData)
+
+ posStart = fileStr.find('<table border="0" cellspacing="0" width="100%"')
+ posStop = fileStr.find('<table border="0" cellspacing="0" width="480" cellpadding="0"', posStart)
+ trailersStr = fileStr[posStart:posStop]
+
+ trailers = []
+ regMatches = self.regExTrailersWithThumbs.findall(trailersStr)
+ #regMatches = re.compile('''player.php[^+]*?</table>''').findall(trailersStr)
+ for match in regMatches:
+ trailer = self.readTrailerFromPage(match)
+ trailers.append(trailer)
+ regMatches = self.regExTrailersWithoutThumbs.findall(trailersStr)
+ for match in regMatches:
+ trailer = self.readTrailerFromPage(match)
+ trailers.append(trailer)
+ return trailers
+
+ def readTrailerFromPage(self, match):
+ trailer = gt.Trailer()
+ tmpStr = self.regExPageGameNameOne.findall(match)[0]
+ trailer.gameName = self.regExPageGameNameTwo.findall(tmpStr)[0][1:-1]
+
+ trailer.gameGuid = self.regExPageGameGuid.findall(match)[0][16:-7]
+
+ tmpMatch = self.regExPageTitle.findall(match)
+ if (len(tmpMatch) > 0):
+ trailer.title = tmpMatch[0][14:-6]
+
+ tmpMatch = self.regExPageDownloadsTotal.findall(match)
+ if (len(tmpMatch) > 0):
+ trailer.downloadsTotal = self.regExNumber.findall(tmpMatch[0][14:])[0][1:-1]
+
+ tmpMatch = self.regExPageDownloadsYesterday.findall(match)
+ if (len(tmpMatch) > 0):
+ trailer.downloadsYesterday = self.regExNumber.findall(tmpMatch[0][14:])[0][1:-1]
+
+ tmpMatch = self.regExPageDescOne.findall(match)
+ if (len(tmpMatch) > 0):
+ str = tmpMatch[0]
+ tmpMatch = self.regExPageDescTwo.findall(str)
+ if (len(tmpMatch) > 0):
+ str = tmpMatch[0][1:-1]
+ if (len(str) > 0):
+ trailer.description = str
+
+ tmpMatch = self.regExPageThumbLink.findall(match)
+ if (len(tmpMatch) > 0):
+ trailer.thumbnailLink = "http://www.gametrailers.com/" + tmpMatch[0]
+
+ tmpMatch = self.regExPlayer.findall(match)
+ if (len(tmpMatch) > 0):
+ trailer.guid = tmpMatch[0][14:-6]
+ else:
+ trailer.externalLink = self.regExExternalLink.findall(match)[0][25:-1]
+
+ return trailer
+
+
+ def retrieveGameInfo(self, gameId):
+ if (self.gameInfoRegEx == None):
+ self.gameInfoRegEx = re.compile('''<div class="game_data"[^+]*?</div>''')
+ if (self.gameInfoNameRegEx == None):
+ self.gameInfoNameRegEx = re.compile('''game_title">[^+]*?</div>''')
+ if (self.gameInfoPlatformsRegEx == None):
+ self.gameInfoPlatformsRegEx = re.compile('''light[^+]*?gif''')
+ if (self.gameInfoTextRegEx == None):
+ self.gameInfoTextRegEx = re.compile('''> [^+]*?<''')
+ if (self.gameInfoLinkRegEx == None):
+ self.gameInfoLinkRegEx = re.compile('''link">[^+]*?</a>''')
+ if (self.gameInfoBoxRegEx == None):
+ self.gameInfoBoxRegEx = re.compile('''http://www.gametrailers.com/moses/boxart[^+]*?.jpg''')
+
+ gameInfoPageLink = "http://gametrailers.com/gamepage.php?id=" + str(gameId)
+ fileStr = self.httpFetcher.urlopen(gameInfoPageLink)
+ regMatches = self.gameInfoRegEx.findall(fileStr)
+
+ gameInfo = gt.Game()
+ gameInfo.name = self.gameInfoNameRegEx.findall(fileStr)[0][12:-6]
+ gameInfo.guid = str(gameId)
+ gameInfo.release = self.gameInfoTextRegEx.findall(regMatches[0])[0][2:-1]
+ gameInfo.genres= self.gameInfoTextRegEx.findall(regMatches[5])[0][2:-1]
+ gameInfo.rating = self.gameInfoTextRegEx.findall(regMatches[6])[0][2:-1]
+ gameInfo.publisher = self.gameInfoLinkRegEx.findall(regMatches[2])[0][6:-4]
+ gameInfo.developer = self.gameInfoLinkRegEx.findall(regMatches[3])[0][6:-4]
+ gameInfo.boxArtLink = self.gameInfoBoxRegEx.findall(fileStr)[0]
+
+ platforms = []
+ for platStr in self.gameInfoPlatformsRegEx.findall(regMatches[1]):
+ platforms.append(platStr[6:-4])
+ gameInfo.platforms = platforms
+
+ return gameInfo
+
+ def retrieveGameTrailerList(self, gameId):
+ if (self.gameTrailerRegEx == None):
+ self.gameTrailerRegEx = re.compile('''src="http://www.gametrailers.com/moses/[^+]*?Downloads</div></td>''')
+ if (self.gameTrailerInfoRegEx == None):
+ self.gameTrailerInfoRegEx = re.compile('''<div class="media_[^+]*?</div>''')
+ if (self.gameTrailerImageLinkRegEx == None):
+ self.gameTrailerImageLinkRegEx = re.compile('''http://www.gametrailers.com/moses/moviesthumb[^+]*?.jpg''')
+
+ gameInfoPageLink = "http://gametrailers.com/gamepage.php?id=" + str(gameId)
+ fileStr = self.httpFetcher.urlopen(gameInfoPageLink)
+
+ posStart = fileStr.find('<!-- MEDIA CONTENT -->')
+ posStop = fileStr.find('<!-- END MEDIA CONTENT -->')
+ fileStr = fileStr[posStart:posStop]
+ regMatches = self.gameTrailerRegEx.findall(fileStr)
+ trailerList = []
+ for match in regMatches:
+ trailerInfo = gt.Trailer()
+ playerMatch = self.regExPlayer.findall(match)
+ if (len(playerMatch) > 0):
+ trailerInfo.guid = playerMatch[0][14:-6]
+ trailerInfo.gameGuid = str(gameId)
+
+ mediaMatches = self.gameTrailerInfoRegEx.findall(match)
+ trailerInfo.title = mediaMatches[0][25:-6]
+ trailerInfo.description = mediaMatches[3][24:-6]
+ trailerInfo.publishedDate = mediaMatches[1][28:-6]
+ trailerInfo.downloadsTotal = mediaMatches[4][29:-16]
+
+ texts = self.gameTrailerImageLinkRegEx .findall(match)
+ if (len(texts) > 0):
+ trailerInfo.thumbnailLink = texts[0]
+
+ trailerList.append(trailerInfo)
+ return trailerList
+
+ def retrieveStreamLinkQuick(self, trailer):
+ if (trailer.externalLink <> None):
+ return trailer.externalLink
+ else:
+ playerPageLink = "http://www.gametrailers.com/player.php?r=1&type=wmv&id=" + str(trailer.guid)
+ fileStr = self.httpFetcher.urlopen(playerPageLink)
+ regMatches = re.compile('''playNowCall.+;''').findall(fileStr)
+ regMatches = re.compile("'.+?'").findall(regMatches[0])
+ filenameStr = regMatches[1]
+ url = "http://trailers.gametrailers.com/gt_vault/" + filenameStr[1:- 1] + ".wmv"
+ return url
+
+ def retrieveStreamStr(self, trailerId):
+ try:
+ self.trace("Building URL: ")
+ playerPageLink = "http://www.gametrailers.com/player.php?r=1&type=wmv&id=" + str(trailerId)
+ #print "Player page '" + playerPageLink + "'"
+
+ # Get the player page so we can find out the link to the ad server
+ self.trace("Retriving player page: " + str(trailerId))
+ self.trace(playerPageLink)
+ fileStr = self.httpFetcher.urlopen(playerPageLink)
+ # Get the complete stream link from the ad server
+
+ self.httpFetcher.setReferer(playerPageLink)
+
+ self.trace("Regex matching on player page")
+ regMatches = re.compile('''["']http://ad.doubleclick.net/adj/gametrailers.mtvi[^+]*?['"]''').findall(fileStr)
+ adServerLink = regMatches[0][1:len(regMatches[0]) - 1]
+
+ self.trace("Retriving ad page")
+ fileStr = self.httpFetcher.urlopen(adServerLink)
+
+ # Get the stream data and parse out the entry tags
+ self.trace("Regex macthing on ad page")
+ regMatches = re.compile('''["']http://moses.gametrailers.com/streambuilder.php[^+]*?['"]''').findall(fileStr)
+ streamLink = regMatches[0][1:len(regMatches[0]) - 1]
+
+ self.trace("Retrieving stream page")
+ fileStr = self.httpFetcher.urlopen(streamLink)
+
+ # Build up a new stream str with only the first two streams
+ self.trace("Regex matching on stream page")
+ regMatches = re.compile('''<Entry[^+]*?Entry>''').findall(fileStr)
+ #asxStreamStr = '<ASX version="3.0">'
+ #for link in regMatches[0:2]:
+ # asxStreamStr = asxStreamStr + link
+ #asxStreamStr = asxStreamStr + '</ASX>'
+
+ return regMatches
+ except:
+ print "There was a problem: " + str(sys.exc_info()[0])
+ return None
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/gtweb.pyo
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/rss.py
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/rss.py Tue Apr 24 17:26:57 2007
@@ -0,0 +1,133 @@
+import xml.dom.minidom, urllib, os, os.path, string, traceback, time
+
+# Parser that parses version 2.0 RSS documents
+class RSSParser:
+ def __init__(self, channelElements, itemElements):
+ # Document Object Model of the XML document
+ self.dom = None
+ # RSS channel information
+ self.channelInfo = None
+ # RSS items
+ self.items = {}
+ self.channelElements = channelElements
+ self.itemElements = itemElements
+
+ def reset(self):
+ # Document Object Model of the XML document
+ self.dom = None
+ # RSS channel information
+ self.channelInfo = None
+ # RSS items
+ self.items = {}
+
+ # feeds the xml document from given url to the parser
+ def feed(self, url):
+ self.dom = None
+ self.channelInfo = None
+ self.items = {}
+ f = urllib.urlopen(url)
+ xmlDocument = f.read()
+ f.close()
+ self.dom = xml.dom.minidom.parseString(xmlDocument)
+ # feeds the xml document from given url to the parser
+ def feedFromFile(self, file):
+ self.dom = None
+ self.channelInfo = None
+ self.items = {}
+ try:
+ f = open(file)
+ xmlDocument = f.read()
+ except IOError:
+ pass
+ f.close()
+ self.dom = xml.dom.minidom.parseString(xmlDocument)
+
+ # parses the RSS document, for now it assumes that RSS document is valid
+ def parse(self):
+ self.channelInfo = None
+ self.items = {}
+ self.channelInfo = self.__parseChannelInfo()
+ self.items = self.__parseItems()
+
+ # parses channel info and returns RSSChannelInfo object containing the info
+ def __parseChannelInfo(self):
+ channel = self.dom.getElementsByTagName("channel")[0]
+ info = {}
+ for channelElement in self.channelElements:
+ try:
+ info[channelElement] = channel.getElementsByTagName(channelElement)[0].childNodes[0].data
+ except IndexError:
+ pass
+ return RSSChannelInfo(info)
+
+ # parses RSS document items and returns an list containing RSSItem objects
+ def __parseItems(self):
+ items = self.dom.getElementsByTagName("item")
+ itemObjects = []
+ for item in items:
+ elements = {}
+ for itemElement in self.itemElements:
+ try:
+ elements[itemElement] = item.getElementsByTagName(itemElement)[0].childNodes[0].data
+ except IndexError:
+ pass
+ itemObjects.append(RSSItem(elements))
+ return itemObjects
+
+ # returns the channelinfo on this parser
+ def getChannelInfo(self):
+ return self.channelInfo
+
+ # returns items from this parser
+ def getItems(self):
+ return self.items
+
+class RSSChannelInfo:
+ def __init__(self, info):
+ # dictionary that includes channel elements
+ self.info = info
+
+ def getElementNames(self):
+ return self.info.keys()
+
+ def hasElement(self, element):
+ return self.info.has_key(element)
+
+ def getElement(self, element):
+ return self.info[element]
+
+class RSSItem:
+ def __init__(self, elements):
+ # list that includes required item elements
+ self.elements = elements
+
+ def getElement(self, element):
+ return self.elements[element]
+
+ def getElementNames(self):
+ return self.elements.keys()
+
+ def hasElement(self, element):
+ return self.elements.has_key(element)
+
+class RSSCategory:
+ def __init__(self, name, feeds):
+ self.name = name
+ self.feeds = feeds
+
+ def getName(self):
+ return self.name
+
+ def getFeeds(self):
+ return self.feeds
+
+class RSSFeed:
+ def __init__(self, title, link):
+ self.title = title
+ self.link = link
+
+ def getTitle(self):
+ return self.title
+
+ def getLink(self):
+ return self.link
\ No newline at end of file
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/rss.pyo
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/textwindow.py
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/textwindow.py Tue Apr 24 17:26:57 2007
@@ -0,0 +1,56 @@
+'''
+ textwindow.py - Simple window for displaying long texts
+
+ Version changelog:
+ 0.1 (13 may 2006):
+ First version
+
+ The dialog was copied from the Aftonbladet XBMC script created by Anders Willstedt and can
+ be downloaded fully from www.xbmcscripts.com.
+'''
+import os, xbmc, xbmcgui, rss, sys
+import xml.dom.minidom, urllib, os, os.path, string, traceback, time
+
+try: Emulating = xbmcgui.Emulating
+except: Emulating = False
+
+ACTION_SELECT_ITEM = 7
+ACTION_PREVIOUS_MENU = 10
+
+if Emulating: PATH_ROOT = os.getcwd() + "/"
+else: PATH_ROOT = "Q:\\scripts\\GameTrailersRssReader\\"
+if Emulating: PATH_IMAGE = PATH_ROOT + "../img/"
+else: PATH_IMAGE = PATH_ROOT + "img\\"
+
+class Dialog(xbmcgui.WindowDialog):
+ def __init__(self):
+ if Emulating: xbmcgui.Window.__init__(self)
+ self.setCoordinateResolution(6) # scales objects automatically
+
+ imageWidth = 400
+ imageHeight = 300
+
+ xPos = (self.getWidth() - imageWidth) / 2
+ yPos = (self.getHeight() - 300) / 2
+
+ self.imgBackground = xbmcgui.ControlImage(xPos, yPos, imageWidth, imageHeight, PATH_IMAGE + "gt_dialog_background.jpg")
+ self.addControl(self.imgBackground)
+
+ self.lblTitle = xbmcgui.ControlLabel(xPos + 10, yPos + 5, imageWidth - 10, 20, "", "font14", "0xFF000000")
+ self.addControl(self.lblTitle)
+ self.textBoxBody = xbmcgui.ControlTextBox(xPos + 10, yPos + 50, imageWidth - 20, imageHeight - 40, "font12", "0xFF000000")
+ self.addControl(self.textBoxBody)
+
+ def setTitle(self, title):
+ self.lblTitle.setLabel(title)
+
+ def setBody(self, body):
+ self.textBoxBody.reset()
+ self.textBoxBody.setText(body)
+ print body
+
+ def onAction(self, action):
+ if action == ACTION_SELECT_ITEM:
+ self.close()
+ if (action == ACTION_PREVIOUS_MENU):
+ self.close()
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/lib/textwindow.pyo
==============================================================================
Binary file. No diff available.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/license.txt
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/license.txt Tue Apr 24 17:26:57 2007
@@ -0,0 +1,339 @@
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
+
+ How to Apply These Terms to Your New Programs
+
+ If you develop a new program, and you want it to be of the greatest
+possible use to the public, the best way to achieve this is to make it
+free software which everyone can redistribute and change under these terms.
+
+ To do so, attach the following notices to the program. It is safest
+to attach them to the start of each source file to most effectively
+convey the exclusion of warranty; and each file should have at least
+the "copyright" line and a pointer to where the full notice is found.
+
+ <one line to give the program's name and a brief idea of what it does.>
+ Copyright (C) <year> <name of author>
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+
+Also add information on how to contact you by electronic and paper mail.
+
+If the program is interactive, make it output a short notice like this
+when it starts in an interactive mode:
+
+ Gnomovision version 69, Copyright (C) year name of author
+ Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
+ This is free software, and you are welcome to redistribute it
+ under certain conditions; type `show c' for details.
+
+The hypothetical commands `show w' and `show c' should show the appropriate
+parts of the General Public License. Of course, the commands you use may
+be called something other than `show w' and `show c'; they could even be
+mouse-clicks or menu items--whatever suits your program.
+
+You should also get your employer (if you work as a programmer) or your
+school, if any, to sign a "copyright disclaimer" for the program, if
+necessary. Here is a sample; alter the names:
+
+ Yoyodyne, Inc., hereby disclaims all copyright interest in the program
+ `Gnomovision' (which makes passes at compilers) written by James Hacker.
+
+ <signature of Ty Coon>, 1 April 1989
+ Ty Coon, President of Vice
+
+This General Public License does not permit incorporating your program into
+proprietary programs. If your program is a subroutine library, you may
+consider it more useful to permit linking proprietary applications with the
+library. If this is what you want to do, use the GNU Lesser General
+Public License instead of this License.
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/readme.txt
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/CarbonGameTrailersRssReader/readme.txt Tue Apr 24 17:26:57 2007
@@ -0,0 +1,101 @@
+GameTrailersRSSReader.py - RSS Reader from GameTrailers.com RSS Feeds
+
+ With this script it is possible to watch game trailers on your XBox,
+ courtesy of GameTrailers.com. The script will download the RSS feeds
+ from GT, and display them with descriptions and thumbnails. It can
+ also parse the GT web pages and return review list, top rated and most
+ downloaded trailers.
+ With the search feature, it is possible to search for any game and see
+ all trailers for that game.
+
+ This is my first xbmc script (and python) so bare with me if you find
+ any bugs. Please report all bugs to me so I can fix them in the next
+ release. Unfortunately I was a little late for E3 2006, but at least
+ now it is possible to stream from GT again.
+
+Installation and usage:
+ Copy the GameTrailersRSSReader folder to the xbmc scripts folder.
+ Start the script and select one of the feeds (newest, top 20, top
+ rated) and watch the trailers.
+
+ To see the game page for a trailer, mark the trailer and press Info.
+ To show the context menu, mark a trailer and press Title.
+
+Changelog:
+ 0.4.2 (14th february 2007):
+ Fixed backgruond image resize issues in other resolutions than PAL 4x3
+ Fixed issue when script restarted when it was stopped
+ 0.4.1 (5 february 2007):
+ Fixed broken parsing
+ Updated to follow guidelines for www.xbmcscripts.com
+ 0.4 (2 june 2006):
+ Added parsing of the GT webpages since most of the RSS feeds wasnt
+ updated very often.
+ Added search functionality, now it is possible to search for any game.
+ Added "Download & Play" so you can download the trailer before
+ playing it. It will take a while to download the trailer but
+ it will not freeze during playback because buffering.
+ Added Game information for a trailer. Now you can view information
+ about the any game and see all trailers for it.
+ Put all python script files into lib except the main script
+ Fixed a thumbnail for the main script.
+ 0.3 (18 may 2006):
+ Find out the actual name of the trailer instead of relying on
+ the name of the thumbnail. Now all trailers should work.
+ 0.2 (14 may 2006):
+ Fixed the trailer problem by streaming to the actual wmv file directly.
+ 0.1 (13 may 2006):
+ First version with PAL 4:3 support only
+
+Known issues:
+ Layout issues in other TV formats. I need help with GUI layouts for
+ other display formats than PAL 4:3, please send me source patches for
+ other formats if they are needed.
+ Currently there is no Nintendo Wii RSS feed, so it is not possible to
+ get the latest trailers for the platform.
+ Some trailers has no thumbnail. The GT web pages will most of the time
+ only show thumbnails for the first five trailers.
+
+Todo:
+ Add the Nintendo Wii RSS feed (GT has no specific feed for this
+ platform yet)
+ Fix layouts for widescreen, ntsc and all other formats out there.
+ If you can test and fix it for me, send me the source on how to
+ fix it. I can't do anything here.
+ Add videos ad support so gametrailers.com wont lose any income because
+ of this script. Hey, its free and it should be kept that way!
+
+Other script resources that has been used to create this script:
+ The following scripts were used in order to create this script,
+ some parts from them may be copied and re-used in this script. I would
+ like to thank you those who made the scripts. To get the real versions
+ of the scripts, visit www.xbmcscripts.com.
+
+ cachedhttp.py v1.3 script - Script created by Aslak Grinsted. Script
+ copied as a seperate file.
+ rss.py v1.5 - RSS logic copied from Multi RSS Reader created by Affini -
+ aka Aaron . Script copied into a seperate file.
+ aftonbladet.py v2.01 - The seperate dialog window was copied from the
+ Aftonbladet XBMC script created by Anders Willstedt..
+
+Support:
+ For bugs/enhancements/ideas/etc go to http://xbmc.ramfelt.se
+
+License:
+ GNU General Public License.
+ TV.com XBMC script is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ TV.com XBMC 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 TV.com XBMC; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+
+Last words:
+ Have fun!
\ No newline at end of file
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/ComedyCentral/carbondefault.py
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/ComedyCentral/carbondefault.py Tue Apr 24 17:26:57 2007
@@ -0,0 +1,824 @@
+#############################################################################
+#
+# Comedy Central Video Browser
+# v1.01 by Joshatdot (josh...@gmail.com)
+#
+# Credit goes to Sander van Grieken
+# I edited his GAN v1.2 script
+#
+# Changelog:
+# 2006-09-05 Initial Release
+# 2006-09-13 GUI changes
+#
+#############################################################################
+
+from string import *
+from types import *
+
+import urllib, re, random, string, os.path, htmlentitydefs
+import xbmc, xbmcgui
+
+try: Emulating = xbmcgui.Emulating
+except: Emulating = False
+
+ACTION_MOVE_LEFT = 1
+ACTION_MOVE_RIGHT = 2
+ACTION_MOVE_UP = 3
+ACTION_MOVE_DOWN = 4
+ACTION_PAGE_UP = 5
+ACTION_PAGE_DOWN = 6
+ACTION_SELECT_ITEM = 7
+ACTION_HIGHLIGHT_ITEM = 8
+ACTION_PARENT_DIR = 9
+ACTION_PREVIOUS_MENU = 10
+ACTION_SHOW_INFO = 11
+ACTION_PAUSE = 12
+ACTION_STOP = 13
+ACTION_NEXT_ITEM = 14
+ACTION_PREV_ITEM = 15
+
+######################################################################
+
+RootDir = os.getcwd().replace(";","")+"\\"
+if Emulating:
+ RootDir = "./"
+ImageDir = RootDir + "images\\"
+if Emulating:
+ ImageDir = RootDir + "images/"
+
+controller = "true"
+
+entpat=re.compile("&#?([\w\d]+)[;\s]", re.IGNORECASE)
+def HTMLDecode(name): #make titles look nicer in menu
+ nameout=''
+ lastidx=0
+ for match in entpat.finditer(name):
+ newchar = '?'
+ try:
+ ent=unichr(int(match.group(1)))
+ except:
+ try:
+ ent=unichr(htmlentitydefs.name2codepoint[match.group(1)])
+ newchar = ent.encode('iso-8859-1')
+ except:
+ dummy = 0
+ nameout=nameout+name[lastidx:match.start()]+newchar
+ lastidx=match.end()
+ nameout=nameout+name[lastidx:]
+ nameout=nameout.replace('\xa0',' ') #make nbsp into normal space
+ return str(nameout)
+
+def HTMLStrip(text):
+ newtext = re.sub('<[^>]*>','',text)
+ return newtext
+
+######################################################################
+# Generic Stream Browser container classes.
+class CCVB:
+ urldata = None
+ urlheaders = {'User-Agent': 'Mozilla/4.0 (compatible; CCVB Stream Browser 0.1; XBMC)',
+ 'Accept-Language': 'en-us',
+ }
+ def download(self,url):
+ f = urllib.urlopen(url,self.urldata,self.urlheaders)
+ data = f.read()
+ f.close()
+ return data
+
+class PageAdapterItem(CCVB):
+ adapterclass = None
+ def __init__(self,title,url,adapter=None):
+ # no specified adapter parameter or adapterclass attribute != None means the url points to a stream
+ self.title = replace(title, "&", "&")
+ self.url = replace(url,"&","&")
+ if adapter == None and self.adapterclass != None:
+ self.adapter = self.adapterclass(self.title,self.url)
+ else:
+ self.adapter = adapter
+
+ def isStream(self):
+ return (self.adapter == None)
+
+ def isAdapter(self):
+ return not self.isStream()
+
+ def getURL(self): # override if stream item url should be preprocessed (parsing .asx for instance)
+ return self.url # normally just returns the provided url
+
+class PageAdapter(CCVB):
+ regex = '^$' # used in matching the url & title of items
+ imgregex = None # used to find a single image url for this page
+ detailregex = None # used to find a single detail description for this page
+ urlprefix = '' # prefix prepended in url matches
+ nameprefix = '' # prefix prepended in title matches
+ imgurlprefix = '' # prefix prepended in imgurl matches
+ itemclass = PageAdapterItem # Class type used for items
+
+ def __init__(self,title,url):
+ self.url = url
+ self.title = title
+ self.parent = None
+ self.items = []
+ self.index = None # index of sub-PageAdapters, or None if parent's index should be used
+ self.scroller = ''
+ self.image = None
+ self.position = 0
+
+ self.isRetrieved = False
+
+ def getItem(self, index):
+ return self.items[index]
+
+ def hasIndex(self):
+ return (self.index != None)
+
+ def __iter__(self):
+ self.iter_index = 0
+ return self
+
+ def next(self):
+ if self.iter_index < len(self.items):
+ self.iter_index = self.iter_index + 1
+ return self.items[self.iter_index - 1]
+ else:
+ raise StopIteration
+
+ def setURL(self,url):
+ self.url = url
+
+ def retrieve(self):
+ print 'retrieving page url : ' + self.url
+ if self.isRetrieved:
+ return
+ self.data = self.download(self.url)
+ self.parse()
+ self.isRetrieved = True
+
+ def parse(self):
+ # for PageAdapter subclasses, provide an easy means to override just the 'regex' attribute without
+ # needing to override the parse method. Just redefine 'regex' when subclassing. This default method
+ # uses the named regular expression groups 'title' and 'url' (and optionally 'detail' and 'imgurl')
+ # for populating the list of PageAdapterItem objects.
+ # For more complex parsing, override this method.
+ cre = re.compile(self.regex, re.DOTALL + re.IGNORECASE)
+ result = cre.finditer(self.data)
+ for item in result:
+ print 'item found : ' + item.group('title')
+ newitem = self.itemclass(self.nameprefix + self.processtitle(item.group('title')), self.urlprefix + self.processurl(item.group('url')))
+ if newitem.adapter != None:
+ # propagate detail and imgurl to new adapter (when this data cannot be found
+ # on the next page, but can be found one link earlier)
+ try:
+ newitem.adapter.scroller = self.processdetail(item.group('detail'))
+ except:
+ pass
+ try:
+ newitem.adapter.image = self.processimgurl(item.group('imgurl'))
+ except:
+ pass
+ self.items.append(newitem)
+
+ if self.imgregex != None:
+ cire = re.compile(self.imgregex, re.DOTALL + re.IGNORECASE)
+ result = cire.findall(self.data)
+ try:
+ self.image = self.processimgurl(self.imgurlprefix + result[0])
+ print "imgurl : " + result[0]
+ except:
+ self.image = RootDir + "none.png"
+
+ if self.detailregex != None:
+ cdre = re.compile(self.detailregex, re.DOTALL + re.IGNORECASE)
+ result = cdre.findall(self.data)
+ try:
+ self.scroller = self.processdetail(result[0])
+ except:
+ self.scroller = 'no detail information found'
+
+ print 'detailinfo : ' + self.scroller
+
+
+ def processtitle(self,text):
+ # standard html tag and excessive whitespace remover
+ return re.sub('[\n\r]|\s\s+',' ',HTMLStrip(text))
+
+ def processurl(self,text):
+ return text
+
+ def processdetail(self,text):
+ # standard html tag and excessive whitespace remover
+ return HTMLDecode(re.sub('[\n\r]|\s\s+',' ',HTMLStrip(text)))
+
+ def processimgurl(self,text):
+ return text
+
+ def toControlList(self, controllist):
+ # copy object's itemlist to GUI ControlList
+ controllist.reset()
+ for item in self.items:
+ controllist.addItem(item.title)
+
+ controllist.selectItem(2)
+
+ def setSelected(self,pos):
+ self.position = pos
+
+
+#
+######################################################################
+#
+class MainAdapter(PageAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Comedy Central Video Browser v1.0','')
+ self.scroller = 'Comedy Central Video Browser - Main Index Page'
+ self.items = [ PageAdapterItem('All Access: Middle Ages','',AllAccessAdapter()),
+ PageAdapterItem('Blue Collar Comedy Tour','',BlueCollarAdapter()),
+ PageAdapterItem('Chappelle Show','',ChappelleAdapter()),
+ PageAdapterItem('The Colbert Report','',ColbertReportAdapter()),
+ PageAdapterItem('Comedians of Comedy','',ComediansAdapter()),
+ PageAdapterItem('Comedy Central Movies','',MoviesAdapter()),
+ PageAdapterItem('Comedy Central Presents','',PresentsAdapter()),
+ PageAdapterItem('Roast of Jeff Foxworthy','',FoxworthyAdapter()),
+ PageAdapterItem('Roast of Pamela Anderson','',AndersonAdapter()),
+ PageAdapterItem('Roast of William Shatner','',ShatnerAdapter()),
+ PageAdapterItem('Roast: Denis Leary','',LearyAdapter()),
+ PageAdapterItem('Con','',ConAdapter()),
+ PageAdapterItem('Crank Yankers','',YankersAdapter()),
+ PageAdapterItem('The Daily Show With Jon Stewart','',DailyShowAdapter()),
+ PageAdapterItem('Denis Learys Merry Fuckin Christmas Special','',Leary2Adapter()),
+ PageAdapterItem('Distraction','',DistractionAdapter()),
+ PageAdapterItem('Dog Bites Man','',DogAdapter()),
+ PageAdapterItem('Dr. Katz Professional Therapist','',KatzAdapter()),
+ PageAdapterItem('Drawn Together','',DrawnAdapter()),
+ PageAdapterItem('Galaxy of the Black Stars','',GalaxyAdapter()),
+ PageAdapterItem('Golden Age','',GoldenAgeAdapter()),
+ PageAdapterItem('Drew Careys Green Screen Show','',CareyAdapter()),
+ PageAdapterItem('The Hollow Men','',HollowAdapter()),
+ PageAdapterItem('I Love the 30s','',Love30sAdapter()),
+ PageAdapterItem('Insomniac Special','',InsomniacSpecialAdapter()),
+ PageAdapterItem('Insomniac With Dave Attell','',DaveAttellAdapter()),
+ PageAdapterItem('Jump Cuts','',JumpCutsAdapter()),
+ PageAdapterItem('Kid Notorious','',KidNotoriousAdapter()),
+ PageAdapterItem('Last Laugh 2005','',LastLaugh2005Adapter()),
+ PageAdapterItem('Live at Gotham','',LiveatGothamAdapter()),
+ PageAdapterItem('Mind of Mencia','',MindofMenciaAdapter()),
+ PageAdapterItem('Premium Blend','',PremiumBlendAdapter()),
+ PageAdapterItem('Primetime Glick','',PrimetimeGlickAdapter()),
+ PageAdapterItem('RENO 911','',RENO911Adapter()),
+ PageAdapterItem('Shorties Watchin Shorties','',ShortiesAdapter()),
+ PageAdapterItem('Showbiz Show','',ShowbizShowAdapter()),
+ PageAdapterItem('South Park','',SouthParkAdapter()),
+ PageAdapterItem('Stella','',StellaAdapter()),
+ PageAdapterItem('Strangers With Candy','',StrangersAdapter()),
+ PageAdapterItem('Test Pilots','',TestPilotsAdapter()),
+ PageAdapterItem('Thats My Bush','',ThatsMyBushAdapter()),
+ PageAdapterItem('Tiny Hands','',TinyHandsAdapter()),
+ PageAdapterItem('Too Late with Adam Carolla','',CarollaAdapter()),
+ PageAdapterItem('Trigger Happy TV','',TriggerHappyTVAdapter()),
+ PageAdapterItem('TV Funhouse','',TVFunhouseAdapter()),
+ PageAdapterItem('Upright Citizens Brigade','',UCBAdapter()),
+ PageAdapterItem('Wanda Does It','',WandaDoesItAdapter()),
+ PageAdapterItem('Wanderlust','',WanderlustAdapter()),
+ PageAdapterItem('Weekends at the DL','',WeekendsAdapter()),
+ PageAdapterItem('Odd Todd','',OddToddAdapter()),
+ PageAdapterItem('Shadow Rock','',ShadowRockAdapter()),
+ PageAdapterItem('The Clip Joint','',TheClipJointAdapter())
+ ]
+ def retrieve(self): # no downloading for this adapter. it's static
+ return
+
+#
+######################################################################
+#
+
+class DailyShowStream(PageAdapterItem):
+ def getURL(self):
+ data = self.download(self.url)
+ result = re.compile('<input[^<>]+value="([^">]+)"', re.DOTALL + re.IGNORECASE)
+ url = result.findall(data)
+ data = self.download(url[0])
+ result = re.compile('<ref\s+href="(mms\:[^"]+)"', re.DOTALL + re.IGNORECASE)
+ url = result.findall(data)
+ return url[0]
+
+class DailyShowAdapter(PageAdapter):
+ regex = '<a[^<>]*href="(?P<url>play\.jhtml[^<>"]+)"[^<>]*>(?P<title>[^\n]+)</a>'
+ urlprefix = 'http://www.comedycentral.com/sitewide/media_player/'
+ itemclass = DailyShowStream
+ def __init__(self):
+ PageAdapter.__init__(self,'The Daily Show with Jon Stewart','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=934')
+ self.scroller = 'The Daily Show with Jon Stewart'
+
+#
+#######################################################################
+#
+
+class AllAccessAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'All Access: Middle Ages','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=61092')
+ self.scroller = 'All Access: Middle Ages'
+
+class BlueCollarAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Blue Collar Comedy Tour','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=63792')
+ self.scroller = 'Blue Collar Comedy Tour'
+
+class ChappelleAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Chappelle Show','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=936')
+ self.scroller = 'Chappelle Show'
+
+class ColbertReportAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'The Colbert Report','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=18252')
+ self.scroller = 'The Colbert Report'
+
+class ComediansAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Comedians of Comedy','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=24456')
+ self.scroller = 'Comedians of Comedy'
+
+class MoviesAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Comedy Central Movies','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=16629')
+ self.scroller = 'Comedy Central Movies'
+
+class PresentsAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Comedy Central Presents','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=931')
+ self.scroller = 'Comedy Central Presents'
+
+class FoxworthyAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Roast of Jeff Foxworthy','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=930')
+ self.scroller = 'Roast of Jeff Foxworthy'
+
+class AndersonAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Roast of Pamela Anderson','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=16194')
+ self.scroller = 'Roast of Pamela Anderson'
+
+class ShatnerAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Roast of William Shatner','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=70867')
+ self.scroller = 'Roast of William Shatner'
+
+class LearyAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Roast: Denis Leary','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=15171')
+ self.scroller = 'Roast: Denis Leary'
+
+class ConAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Con','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=929')
+ self.scroller = 'Con'
+
+class YankersAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Crank Yankers','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=928')
+ self.scroller = 'Crank Yankers'
+
+class Leary2Adapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Denis Learys Merry Fuckin Christmas Special','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=24795')
+ self.scroller = 'Denis Learys Merry Fuckin Christmas Special'
+
+class DistractionAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Distraction','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=927')
+ self.scroller = 'Distraction'
+
+class DogAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Dog Bites Man','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=68819')
+ self.scroller = 'Dog Bites Man'
+
+class KatzAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Dr. Katz Professional Therapist','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=61884')
+ self.scroller = 'Dr. Katz Professional Therapist'
+
+class DrawnAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Drawn Together','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=932')
+ self.scroller = 'Drawn Together'
+
+class GalaxyAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Galaxy of the Black Stars','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=55082')
+ self.scroller = 'Galaxy of the Black Stars'
+
+class GoldenAgeAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Golden Age','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=63830')
+ self.scroller = 'Golden Age'
+
+class CareyAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Drew Careys Green Screen Show','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=18056')
+ self.scroller = 'Drew Careys Green Screen Show'
+
+class HollowAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'The Hollow Men','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=926')
+ self.scroller = 'The Hollow Men'
+
+class Love30sAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'I Love the 30s','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=68905')
+ self.scroller = 'I Love the 30s'
+
+class InsomniacSpecialAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Insomniac Special','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=17218')
+ self.scroller = 'Insomniac Special'
+
+class DaveAttellAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Insomniac With Dave Attell','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=925')
+ self.scroller = 'Insomniac With Dave Attell'
+
+class JumpCutsAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Jump Cuts','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=17384')
+ self.scroller = 'Jump Cuts'
+
+class KidNotoriousAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Kid Notorious','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=17514')
+ self.scroller = 'Kid Notorious'
+
+class LastLaugh2005Adapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Last Laugh 2005','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=24970')
+ self.scroller = 'Last Laugh 2005'
+
+class LiveatGothamAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Live at Gotham','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=60735')
+ self.scroller = 'Live at Gotham'
+
+class MindofMenciaAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Mind of Mencia','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=15463')
+ self.scroller = 'Mind of Mencia'
+
+class PremiumBlendAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Premium Blend','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=923')
+ self.scroller = 'Premium Blend'
+
+class PrimetimeGlickAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Primetime Glick','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=16051')
+ self.scroller = 'Primetime Glick'
+
+class RENO911Adapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'RENO 911','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=935')
+ self.scroller = 'RENO 911'
+
+class ShortiesAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Shorties Watchin Shorties','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=922')
+ self.scroller = 'Shorties Watchin Shorties'
+
+class ShowbizShowAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Showbiz Show','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=17199')
+ self.scroller = 'Showbiz Show'
+
+class SouthParkAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'South Park','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=933')
+ self.scroller = 'South Park'
+
+class StellaAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Stella','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=15187')
+ self.scroller = 'Stella'
+
+class StrangersAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Strangers With Candy','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=61976')
+ self.scroller = 'Strangers With Candy'
+
+class TestPilotsAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Test Pilots','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=60343')
+ self.scroller = 'Test Pilots'
+
+class ThatsMyBushAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Thats My Bush','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=17852')
+ self.scroller = 'Thats My Bush'
+
+class TinyHandsAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Tiny Hands','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=63805')
+ self.scroller = 'Tiny Hands'
+
+class CarollaAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Too Late with Adam Carolla','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=16111')
+ self.scroller = 'Too Late with Adam Carolla'
+
+class TriggerHappyTVAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Trigger Happy TV','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=16797')
+ self.scroller = 'Trigger Happy TV'
+
+class TVFunhouseAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'TV Funhouse','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=17721')
+ self.scroller = 'TV Funhouse'
+
+class UCBAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Upright Citizens Brigade','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=61907')
+ self.scroller = 'Upright Citizens Brigade'
+
+class WandaDoesItAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Wanda Does It','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=921')
+ self.scroller = 'Wanda Does It'
+
+class WanderlustAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Wanderlust','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=17386')
+ self.scroller = 'Wanderlust'
+
+class WeekendsAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Weekends at the DL','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=16053')
+ self.scroller = 'Weekends at the DL'
+
+class OddToddAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Odd Todd','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=69944')
+ self.scroller = 'Odd Todd'
+
+class ShadowRockAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Shadow Rock','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=69497')
+ self.scroller = 'Shadow Rock'
+
+class TheClipJointAdapter(DailyShowAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'The Clip Joint','http://www.comedycentral.com/sitewide/media_player/browseresults.jhtml?showId=70150')
+ self.scroller = 'The Clip Joint'
+
+#
+######################################################################
+######################################################################
+
+class MainWindow(xbmcgui.Window):
+ currentAdapter = None
+
+ def __init__(self):
+ if Emulating: xbmcgui.Window.__init__(self)
+
+ # background animation
+ self.imgBackgroundani = xbmcgui.ControlImage(0, 0, 720, 476, "Q:\\skin\\MC360\\Extras\\carbon-ani.gif")
+ self.addControl(self.imgBackgroundani)
+
+ # background image
+ self.imgBackground = xbmcgui.ControlImage(0, 0, 720, 576, 'background-blue-alpha.png')
+ self.addControl(self.imgBackground)
+
+ # custom background image
+ self.imgCustomBackground = xbmcgui.ControlImage(0, 0, 720, 576, xbmc.getInfoLabel('Skin.String(Media)'))
+ self.addControl(self.imgCustomBackground)
+ self.imgCustomBackground.setColorDiffuse('D1FFFFFF')
+
+ # Whitewash glass top left
+ self.imgWhiteTL = xbmcgui.ControlImage(70, 0, 16, 64, 'bkgd-whitewash-glass-top-left.png')
+ self.addControl(self.imgWhiteTL)
+
+ # Whitewash glass top middle
+ self.imgWhiteTMID = xbmcgui.ControlImage(86, 0, 592, 64, 'bkgd-whitewash-glass-top-middle.png')
+ self.addControl(self.imgWhiteTMID)
+
+ # Whitewash glass top right
+ self.imgWhiteTR = xbmcgui.ControlImage(678, 0, 16, 64, 'bkgd-whitewash-glass-top-right.png')
+ self.addControl(self.imgWhiteTR)
+
+ # Whitewash glass bottom left
+ self.imgWhiteBL = xbmcgui.ControlImage(70, 412, 16, 64, 'bkgd-whitewash-glass-bottom-left.png')
+ self.addControl(self.imgWhiteBL)
+
+ # Whitewash glass bottom middle
+ self.imgWhiteBMID = xbmcgui.ControlImage(86, 412, 592, 64, 'bkgd-whitewash-glass-bottom-middle.png')
+ self.addControl(self.imgWhiteBMID)
+
+ # Whitewash glass bottom right
+ self.imgWhiteBR = xbmcgui.ControlImage(678, 412, 16, 64, 'bkgd-whitewash-glass-bottom-right.png')
+ self.addControl(self.imgWhiteBR)
+
+ # Whitewash overlay left
+ self.imgWhitewashL = xbmcgui.ControlImage(60, 0, 32, 476, 'background-overlay-whitewash-left.png')
+ self.addControl(self.imgWhitewashL)
+
+ # Whitewash overlay middle
+ self.imgWhitewashMID = xbmcgui.ControlImage(92, 0, 553, 476, 'background-overlay-whitewash-centertile.png')
+ self.addControl(self.imgWhitewashMID)
+
+ # Whitewash overlay right
+ self.imgWhitewashR = xbmcgui.ControlImage(645, 0, 64, 476, 'background-overlay-whitewash-right.png')
+ self.addControl(self.imgWhitewashR)
+
+ # Left blade runner
+ self.imgBladerunL = xbmcgui.ControlImage(-61, 0, 128, 476, 'blades-runner-left.png')
+ self.addControl(self.imgBladerunL)
+
+ # Right blade runner
+ self.imgBladerunR = xbmcgui.ControlImage(665, 0, 128, 476, 'blades-runner-right.png')
+ self.addControl(self.imgBladerunR)
+
+ # Header Blade
+ self.imgBlade = xbmcgui.ControlImage(18, 0, 80, 476, 'blades-size4-header.png')
+ self.addControl(self.imgBlade)
+
+ # Y Button
+ self.imgybutton = xbmcgui.ControlImage(125, 420, 21, 21, 'button-Y-turnedoff.png')
+ self.addControl(self.imgybutton)
+
+ # X Button
+ self.imgxbutton = xbmcgui.ControlImage(112, 440, 21, 21, 'button-X.png')
+ self.addControl(self.imgxbutton)
+
+ # Back Button
+ self.imgbackbutton = xbmcgui.ControlImage(620, 420, 21, 21, 'button-back.png')
+ self.addControl(self.imgbackbutton)
+
+ # A Button
+ self.imgabutton = xbmcgui.ControlImage(633, 440, 21, 21, 'button-A.png')
+ self.addControl(self.imgabutton)
+
+ self.medialabel = xbmcgui.ControlLabel(79,129,100,20,'media','font14','0xFF000000',angle=270)
+ self.vislabel = xbmcgui.ControlLabel(145,443,375,20,'Full Screen Visualization','font12','0xFFFFFFFF')
+ self.backlabel = xbmcgui.ControlLabel(580,423,80,20,'Back','font12','0xFFFFFFFF')
+ self.selectlabel = xbmcgui.ControlLabel(577,443,80,20,'Select','font12','0xFFFFFFFF')
+
+ self.addControl(self.medialabel)
+ self.addControl(self.vislabel)
+ self.addControl(self.backlabel)
+ self.addControl(self.selectlabel)
+
+ self.title = xbmcgui.ControlLabel(90, 30, 576, 40, "", "font18", "0xFFFFFFFF")
+ self.addControl(self.title)
+
+ self.itemsControlList = xbmcgui.ControlList(92, 64, 578, 385,'font14','0xFF000000')
+ self.addControl(self.itemsControlList)
+ self.activelist = self.itemsControlList
+
+ self.image = xbmcgui.ControlImage(72, 140, 180, 180, RootDir + "small.png")
+ self.addControl(self.image)
+ self.image.setVisible(0)
+
+ self.detail = xbmcgui.ControlTextBox(280, 140, 360, 190, 'font13', '0xFFFFFFFF')
+ self.addControl(self.detail)
+ self.detail.setVisible(0)
+
+ self.smallControlList = xbmcgui.ControlList(72, 340, 570, 160,'font14','0xFF000000')
+ self.addControl(self.smallControlList)
+ self.smallControlList.setVisible(0)
+
+ self.smallControlList.controlRight(self.detail)
+ self.smallControlList.controlLeft(self.detail)
+ self.detail.controlRight(self.smallControlList)
+ self.detail.controlLeft(self.smallControlList)
+
+ self.scroller = xbmcgui.ControlFadeLabel(72, 432, 576, 30, 'font13', '0xE0AAAAFF')
+ self.scroller.reset()
+ self.addControl(self.scroller)
+
+ self.mainadapter = MainAdapter()
+ self.currentAdapter = self.mainadapter
+ self.applyAdapter(self.mainadapter)
+
+ ######################################################################
+
+ def getImage(self, imageurl):
+ print "getting image : " + imageurl
+ pe = split(imageurl,'/')
+ fname = pe[len(pe)-1]
+ fname = re.sub('[^a-zA-Z0-9\.]','',fname)
+ if len(fname) > 12:
+ fname = fname[len(fname)-12:len(fname)] # to 8.3 filename format
+
+ # TODO : check supported extension
+ localfname = ImageDir + fname
+ print "local name : " + localfname
+ if not os.path.exists(localfname):
+ try:
+ print "retrieveing image"
+ urllib.urlretrieve((imageurl), (localfname))
+ except:
+ print "image retrieve impossible"
+ localfname = RootDir + "none.png"
+
+ self.removeControl(self.image)
+ self.image = xbmcgui.ControlImage(80,140,180,180, localfname)
+ self.addControl(self.image)
+ self.image.setVisible(1)
+
+ ######################################################################
+
+ def applyAdapter(self, adapter):
+ dialog = xbmcgui.Dialog()
+
+ self.title.setLabel(adapter.title)
+
+ # fire the retrieve method
+ try:
+ self.activelist.reset()
+ self.activelist.addItem("downloading. please wait...")
+ if not Emulating:
+ adapter.retrieve()
+ except:
+ dialog.ok("Comedy Central Script","Could not retrieve online information.")
+ self.applyAdapter(self.currentAdapter)
+ return
+
+ if Emulating:
+ adapter.retrieve()
+
+ if adapter.image == None:
+ self.smallControlList.setVisible(0)
+ self.image.setVisible(0)
+ self.detail.setVisible(0)
+ self.itemsControlList.setVisible(1)
+ self.activelist = self.itemsControlList
+ else:
+ self.getImage(adapter.image)
+ self.smallControlList.setVisible(1)
+ self.image.setVisible(1)
+ self.detail.setVisible(1)
+ self.itemsControlList.setVisible(0)
+ self.activelist = self.smallControlList
+
+ # copy items
+ adapter.toControlList(self.activelist)
+ #self.setScroller(adapter.scroller)
+ self.setDetail(adapter.scroller) # to be changed
+ # create local reference to current adapter
+ self.currentAdapter = adapter
+
+ self.setFocus(self.activelist)
+
+ self.activelist.selectItem(adapter.position)
+
+ ######################################################################
+
+ def onAction(self, action):
+ if action == ACTION_PARENT_DIR:
+ if self.currentAdapter == None:
+ return
+ if self.currentAdapter.parent == None:
+ return
+ self.applyAdapter(self.currentAdapter.parent)
+
+ if action == ACTION_PREVIOUS_MENU:
+ self.close()
+
+ ######################################################################
+
+ def onControl(self, control):
+ if control == self.activelist:
+ selectedAdapterItem = self.currentAdapter.items[self.activelist.getSelectedPosition()]
+ # set navpoint
+ self.currentAdapter.setSelected(self.activelist.getSelectedPosition())
+ if selectedAdapterItem.isAdapter():
+ selectedAdapterItem.adapter.parent = self.currentAdapter
+ self.applyAdapter(selectedAdapterItem.adapter)
+ if selectedAdapterItem.isStream():
+ self.playMovie(selectedAdapterItem.getURL())
+
+ ######################################################################
+
+ def playMovie(self,url):
+ print 'playing URL: ' + url
+ try:
+ xbmc.Player().play(url)
+ except:
+ dialog = xbmcgui.Dialog()
+ dialog.ok("Comedy Central","Stream not found.")
+
+ def setScroller(self,text):
+ self.scroller.reset()
+ if type(text) is StringType:
+ self.scroller.addLabel(text)
+ if type(text) is ListType:
+ for item in text:
+ self.scroller.addLabel(item)
+
+ def setDetail(self,text):
+ detailtext = text
+ if type(text) is ListType:
+ detailtext = join(detailtext)
+ self.detail.setText(strip(detailtext))
+
+win = MainWindow()
+win.doModal()
+del win
Modified: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/ComedyCentral/default.py
==============================================================================
--- trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/ComedyCentral/default.py (original)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/ComedyCentral/default.py Tue Apr 24 17:26:57 2007
@@ -579,7 +579,7 @@
if Emulating: xbmcgui.Window.__init__(self)
# background animation
- self.imgBackgroundani = xbmcgui.ControlImage(0, 0, 720, 476, "Q:\\skin\\MC360\\Extras\\background-ani.gif")
+ self.imgBackgroundani = xbmcgui.ControlImage(0, 0, 720, 476, "Q:\\skin\\MC360\\Extras\\default-ani.gif")
self.addControl(self.imgBackgroundani)
# background image
Added: trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/ComedyCentral/glassdefault.py
==============================================================================
--- (empty file)
+++ trunk/MC360 v1.x Video Marketplace Mod/XBMC/Skin/MC360/Extras/ComedyCentral/glassdefault.py Tue Apr 24 17:26:57 2007
@@ -0,0 +1,824 @@
+#############################################################################
+#
+# Comedy Central Video Browser
+# v1.01 by Joshatdot (josh...@gmail.com)
+#
+# Credit goes to Sander van Grieken
+# I edited his GAN v1.2 script
+#
+# Changelog:
+# 2006-09-05 Initial Release
+# 2006-09-13 GUI changes
+#
+#############################################################################
+
+from string import *
+from types import *
+
+import urllib, re, random, string, os.path, htmlentitydefs
+import xbmc, xbmcgui
+
+try: Emulating = xbmcgui.Emulating
+except: Emulating = False
+
+ACTION_MOVE_LEFT = 1
+ACTION_MOVE_RIGHT = 2
+ACTION_MOVE_UP = 3
+ACTION_MOVE_DOWN = 4
+ACTION_PAGE_UP = 5
+ACTION_PAGE_DOWN = 6
+ACTION_SELECT_ITEM = 7
+ACTION_HIGHLIGHT_ITEM = 8
+ACTION_PARENT_DIR = 9
+ACTION_PREVIOUS_MENU = 10
+ACTION_SHOW_INFO = 11
+ACTION_PAUSE = 12
+ACTION_STOP = 13
+ACTION_NEXT_ITEM = 14
+ACTION_PREV_ITEM = 15
+
+######################################################################
+
+RootDir = os.getcwd().replace(";","")+"\\"
+if Emulating:
+ RootDir = "./"
+ImageDir = RootDir + "images\\"
+if Emulating:
+ ImageDir = RootDir + "images/"
+
+controller = "true"
+
+entpat=re.compile("&#?([\w\d]+)[;\s]", re.IGNORECASE)
+def HTMLDecode(name): #make titles look nicer in menu
+ nameout=''
+ lastidx=0
+ for match in entpat.finditer(name):
+ newchar = '?'
+ try:
+ ent=unichr(int(match.group(1)))
+ except:
+ try:
+ ent=unichr(htmlentitydefs.name2codepoint[match.group(1)])
+ newchar = ent.encode('iso-8859-1')
+ except:
+ dummy = 0
+ nameout=nameout+name[lastidx:match.start()]+newchar
+ lastidx=match.end()
+ nameout=nameout+name[lastidx:]
+ nameout=nameout.replace('\xa0',' ') #make nbsp into normal space
+ return str(nameout)
+
+def HTMLStrip(text):
+ newtext = re.sub('<[^>]*>','',text)
+ return newtext
+
+######################################################################
+# Generic Stream Browser container classes.
+class CCVB:
+ urldata = None
+ urlheaders = {'User-Agent': 'Mozilla/4.0 (compatible; CCVB Stream Browser 0.1; XBMC)',
+ 'Accept-Language': 'en-us',
+ }
+ def download(self,url):
+ f = urllib.urlopen(url,self.urldata,self.urlheaders)
+ data = f.read()
+ f.close()
+ return data
+
+class PageAdapterItem(CCVB):
+ adapterclass = None
+ def __init__(self,title,url,adapter=None):
+ # no specified adapter parameter or adapterclass attribute != None means the url points to a stream
+ self.title = replace(title, "&", "&")
+ self.url = replace(url,"&","&")
+ if adapter == None and self.adapterclass != None:
+ self.adapter = self.adapterclass(self.title,self.url)
+ else:
+ self.adapter = adapter
+
+ def isStream(self):
+ return (self.adapter == None)
+
+ def isAdapter(self):
+ return not self.isStream()
+
+ def getURL(self): # override if stream item url should be preprocessed (parsing .asx for instance)
+ return self.url # normally just returns the provided url
+
+class PageAdapter(CCVB):
+ regex = '^$' # used in matching the url & title of items
+ imgregex = None # used to find a single image url for this page
+ detailregex = None # used to find a single detail description for this page
+ urlprefix = '' # prefix prepended in url matches
+ nameprefix = '' # prefix prepended in title matches
+ imgurlprefix = '' # prefix prepended in imgurl matches
+ itemclass = PageAdapterItem # Class type used for items
+
+ def __init__(self,title,url):
+ self.url = url
+ self.title = title
+ self.parent = None
+ self.items = []
+ self.index = None # index of sub-PageAdapters, or None if parent's index should be used
+ self.scroller = ''
+ self.image = None
+ self.position = 0
+
+ self.isRetrieved = False
+
+ def getItem(self, index):
+ return self.items[index]
+
+ def hasIndex(self):
+ return (self.index != None)
+
+ def __iter__(self):
+ self.iter_index = 0
+ return self
+
+ def next(self):
+ if self.iter_index < len(self.items):
+ self.iter_index = self.iter_index + 1
+ return self.items[self.iter_index - 1]
+ else:
+ raise StopIteration
+
+ def setURL(self,url):
+ self.url = url
+
+ def retrieve(self):
+ print 'retrieving page url : ' + self.url
+ if self.isRetrieved:
+ return
+ self.data = self.download(self.url)
+ self.parse()
+ self.isRetrieved = True
+
+ def parse(self):
+ # for PageAdapter subclasses, provide an easy means to override just the 'regex' attribute without
+ # needing to override the parse method. Just redefine 'regex' when subclassing. This default method
+ # uses the named regular expression groups 'title' and 'url' (and optionally 'detail' and 'imgurl')
+ # for populating the list of PageAdapterItem objects.
+ # For more complex parsing, override this method.
+ cre = re.compile(self.regex, re.DOTALL + re.IGNORECASE)
+ result = cre.finditer(self.data)
+ for item in result:
+ print 'item found : ' + item.group('title')
+ newitem = self.itemclass(self.nameprefix + self.processtitle(item.group('title')), self.urlprefix + self.processurl(item.group('url')))
+ if newitem.adapter != None:
+ # propagate detail and imgurl to new adapter (when this data cannot be found
+ # on the next page, but can be found one link earlier)
+ try:
+ newitem.adapter.scroller = self.processdetail(item.group('detail'))
+ except:
+ pass
+ try:
+ newitem.adapter.image = self.processimgurl(item.group('imgurl'))
+ except:
+ pass
+ self.items.append(newitem)
+
+ if self.imgregex != None:
+ cire = re.compile(self.imgregex, re.DOTALL + re.IGNORECASE)
+ result = cire.findall(self.data)
+ try:
+ self.image = self.processimgurl(self.imgurlprefix + result[0])
+ print "imgurl : " + result[0]
+ except:
+ self.image = RootDir + "none.png"
+
+ if self.detailregex != None:
+ cdre = re.compile(self.detailregex, re.DOTALL + re.IGNORECASE)
+ result = cdre.findall(self.data)
+ try:
+ self.scroller = self.processdetail(result[0])
+ except:
+ self.scroller = 'no detail information found'
+
+ print 'detailinfo : ' + self.scroller
+
+
+ def processtitle(self,text):
+ # standard html tag and excessive whitespace remover
+ return re.sub('[\n\r]|\s\s+',' ',HTMLStrip(text))
+
+ def processurl(self,text):
+ return text
+
+ def processdetail(self,text):
+ # standard html tag and excessive whitespace remover
+ return HTMLDecode(re.sub('[\n\r]|\s\s+',' ',HTMLStrip(text)))
+
+ def processimgurl(self,text):
+ return text
+
+ def toControlList(self, controllist):
+ # copy object's itemlist to GUI ControlList
+ controllist.reset()
+ for item in self.items:
+ controllist.addItem(item.title)
+
+ controllist.selectItem(2)
+
+ def setSelected(self,pos):
+ self.position = pos
+
+
+#
+######################################################################
+#
+class MainAdapter(PageAdapter):
+ def __init__(self):
+ PageAdapter.__init__(self,'Comedy Central Video Browser v1.0','')
+ self.scroller = 'Comedy Central Video Browser - Main Index Page'
+ self.items = [ PageAdapterItem('All Access: Middle Ages','',AllAccessAdapter()),
+ PageAdapterItem('Blue Collar Comedy Tour','',BlueCollarAdapter()),
+ PageAdapterItem('Chappelle Show','',ChappelleAdapter()),
+ PageAdapterItem('The Colbert Report','',ColbertReportAdapter()),
+ PageAdapterItem('Comedians of Comedy','',ComediansAdapter()),
+ PageAdapterItem('Comedy Central Movies','',MoviesAdapter()),
+ PageAdapterItem('Comedy Central Presents','',PresentsAdapter()),
+ PageAdapterItem('Roast of Jeff Foxworthy','',FoxworthyAdapter()),
+ PageAdapterItem('Roast of Pamela Anderson','',AndersonAdapter()),
+ PageAdapterItem('Roast of William Shatner','',ShatnerAdapter()),
+ PageAdapterItem('Roast: Denis Leary','',LearyAdapter()),
+ PageAdapterItem('Con','',ConAdapter()),
+ PageAdapterItem('Crank Yankers','',YankersAdapter()),
+ PageAdapterItem('The Daily Show With Jon Stewart','',DailyShowAdapter()),
==============================================================================
Diff truncated at 200k characters