The branch, dharma has been updated
via a74f7f71dfb1a45d597e81dc7c3f4acf633082cf (commit)
from b1a5042a687eedfff2b7277fd8f8f31e85a53b9b (commit)
- Log -----------------------------------------------------------------
http://xbmc.git.sourceforge.net/git/gitweb.cgi?p=xbmc/plugins;a=commit;h=a74f7f71dfb1a45d597e81dc7c3f4acf633082cf
commit a74f7f71dfb1a45d597e81dc7c3f4acf633082cf
Author: spiff <[email protected]>
Date: Wed Aug 17 13:18:40 2011 +0200
[plugin.video.academicearth] updated to version 1.1.1
diff --git a/plugin.video.academicearth/addon.py
b/plugin.video.academicearth/addon.py
index feb949b..c97673d 100755
--- a/plugin.video.academicearth/addon.py
+++ b/plugin.video.academicearth/addon.py
@@ -1,231 +1,292 @@
-# Copyright 2010 Jonathan Beluch.
-#
-# 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 3 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, see <http://www.gnu.org/licenses/>.
-import re
-from urllib import unquote_plus
+#!/usr/bin/env python
+# Copyright 2011 Jonathan Beluch.
+#
+# 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 3 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, see <http://www.gnu.org/licenses/>.
+from xbmcswift import Plugin, download_page
from BeautifulSoup import BeautifulSoup as BS, SoupStrainer as SS
-from resources.lib.xbmcvideoplugin import (XBMCVideoPlugin, DialogProgress,
- urlread, async_urlread, parse_qs)
-
-"""Currently doesn't support all lectures on the website. Some lectures
-use a third party video hosting site (which are currently working) and
-some lectures use embedded youtube videos (which are not currently
-supported)."""
-
-IGNORE_LIST = ['Online Bachelor\'s Degrees',
- 'Online Courses for Credit',
- 'Online Master\'s Degrees',
- 'Online Professional Certificates',
- 'Courses for Credit',
- 'Online Degrees']
-
-class AcademicEarth(XBMCVideoPlugin):
- base_url = 'http://academicearth.org'
- subjects_url = '%s/subjects' % base_url
-
- def display_subjects(self, url):
- """Takes a url and displays subjects."""
- html = urlread(url)
- div_tags = BS(html,
- parseOnlyThese=SS('div', {'class': 'institution-list'}))
- #Build the list of subjects. Sometimes there is more than one div_tag,
- #so loop through each div_tag, and then for each div_tag, loop through
- #all the <a> tags and parse the subject information.
- dirs = [{'name': a.text,
- 'url': self._urljoin(a['href']),
- 'mode': '1'}
- for div in div_tags for a in div('a')]
- #Filter out the paid courses subjects
- dirs = [d for d in dirs if d['name'] not in IGNORE_LIST]
- self.add_dirs(dirs)
-
- def display_topics(self, url):
- """Takes a subject url and displays a list of all topics on the page"""
- html = urlread(url)
- #get the div which contains all of the topic <a> tags
- div_topics = BS(html,
- parseOnlyThese=SS('div', {'class': 'results-side'}))
- #create the list of dirs by parsing all the a tags in the div
- dirs = [{'name': a.text, 'url': self._urljoin(a['href']), 'mode': '2'}
- for a in div_topics('a')]
- #filter out paid courses and the 'All' listing, since we build our own
- dirs = [d for d in dirs if d['name'].startswith('Online') == False and
- 'Courses for Credit' not in d['name'] and
- d['name'].startswith('All') == False]
- #make the first choice on the list = 'View All'
- dirs.insert(0, {'name': self.getString(30100),
- 'url': url, 'mode': '4'})
- self.add_dirs(dirs)
-
- def display_courses(self, url):
- """Takes a topic url and displays all courses"""
- html = urlread(url)
- courses, lectures = self._get_courses_lectures(html)
- #add listings to UI, courses first, lectures at the bottom.
- self.add_dirs(courses, end=False)
- self.add_videos(lectures)
-
- def display_lectures(self, url):
- """displays the lectures for a given course url"""
- html = urlread(url)
- #get the div which contains all of the <li> lecture tags
- div_tag = BS(html, parseOnlyThese=SS('div', {'class': 'results-list'}))
- #parse the name, url, desc, tn for each lecture
- dirs = [{'name': li.h4.a.text,
- 'htmlurl': self._urljoin(li.h4.a['href']),
- 'info': {'plot': li.p.text, 'title': li.h4.a.text},
- 'tn':self._urljoin(
- li.find('img', {'class': 'thumb-144'})['src'])}
- for li in div_tag('li')]
- #for each dir, download the lecture's html page and parse the video url
- self.dp = DialogProgress(self.getString(30000),
- line1=self.getString(30101),
- num_steps=(len(dirs)))
- urls = [d['htmlurl'] for d in dirs]
- responses = async_urlread(urls, self.dp)
- [d.update({'url': self._get_video_url(response)})
- for d, response in zip(dirs, responses)]
- #filter out lectures that don't have urls, currently a fix for a chem
- #course which contains a bad link to a lecture
- dirs = filter(lambda d: d['url'] != None, dirs)
- self.dp.update(100)
- self.dp.close()
- self.add_videos(dirs)
-
- def display_allresults(self, url):
- """displays all results for a given url, used on a subject page t lis
- all video results without having to drill down into each category"""
- #dp = self.xbmcgui.DialogProgress()
- html = urlread(url)
- #get the div which contains all of the topic <a> tags
- div_topics = BS(html,
- parseOnlyThese=SS('div', {'class': 'results-side'}))
- #create a list of urls for all topics
- topic_urls = [self._urljoin(a['href']) for a in div_topics('a')
- if a.text.startswith('Online') == False and
- 'Credit' not in a.text and not a.text.startswith('All')]
- self.dp = DialogProgress(self.getString(30000),
- line1=self.getString(30102),
- num_steps=(2 * len(topic_urls)))
- topic_htmls = async_urlread(topic_urls, self.dp)
- courses, lectures = self._get_courses_lectures(topic_htmls)
- self.dp.update(100)
- self.dp.close()
- courses = sorted(courses, key=lambda c: c['name'])
- lectures = sorted(lectures, key=lambda l: l['name'])
- self.add_dirs(courses, end=False)
- self.add_videos(lectures)
-
- def _get_courses_lectures(self, htmls):
- """returns a tuple of lists: (courses_list, lectures_list). It takes
- the html source(s) of a topic page and parses all results by visiting
- each page of results"""
- if type(htmls).__name__ == 'str': htmls = [htmls]
- #Each topic page displays only 12 results to a page. So to get all
- #results for a topic, parse all page results urls from the topic page,
- #then download each of the extra pages of results, then parse the video
- #results.
- pagination_urls = [url for html in htmls
- for url in self._get_pagination_urls(html)]
- #Download every pagination page. If a dialog progress box exists,
- #update the step for each increment. Allocate 50% of the bar for
- #downloading the pagination urls. The other 50% is allocated to
- #downloading all of the topic pages when choosing 'View All' for a
- #subject.
- if self.dp and len(pagination_urls) != 0:
- self.dp.step = int(50 / len(pagination_urls))
- page_htmls = async_urlread(pagination_urls, self.dp)
- else:
- page_htmls = async_urlread(pagination_urls)
-
- #extend the list of pagination htmls with the given htmls
- page_htmls.extend(htmls)
- #get a complete list of video results by parsing results from all pages
- results = self._get_video_results(page_htmls)
- #filter courses and lectures so they can be displayed in groups
- courses = filter(lambda r: '/courses/' in r['url'], results)
- lectures = filter(lambda r: '/lectures/' in r['url'], results)
- #add mode argument to courses, lectures don't need it since they will
- #contain a direct url to the video
- [c.update({'mode': 3}) for c in courses]
- #get the actual URL for the video for each lecture, this ensures that
- #the display link plays a video, and doesn't go to another level of
- #directory listings
- [l.update({'url': self._get_video_url(l['url']),
- 'name': self.getString(30103) + l['name']})
- for l in lectures]
- #filter out lectures with no video url. This is a result of bad regex
- #parsing, crappy fix...
- lectures = [l for l in lectures if l['url'] is not None]
- return courses, lectures
-
- def _get_video_url(self, html):
- """Takes html for a video page and returns the url of the video"""
- m = re.search(r'flashVars.flvURL = "(.+?)"', html)
- if m: return m.group(1)
- return None
-
- def _get_pagination_urls(self, html):
- """Returns a list of urls for other results pages for given html."""
- #get the pagination <ul> tags
- ul_tags = BS(html, parseOnlyThese=SS('ul', {'class': 'pagination'}))
- #choose the first pagination <ul> tag since both <ul>s are identical
- ul = ul_tags('ul', limit=1)[0]
- #return the complete url for each link in the <ul>, ignore the last
- #url in the list because it is the next page link, so it is already
- #included
- return [self._urljoin(a['href']) for a in ul('a')[:-1]]
-
- def _get_video_results(self, htmls):
- """takes an html source(s) and a list of video results"""
- video_results = []
- #if htmls is only a single html page, then convert htmls to a list with
- #a single item, the given html string
- if type(htmls).__name__ == 'str': htmls = [htmls]
- for html in htmls:
- div_results = BS(html,
- parseOnlyThese=SS('div', {'class': 'video-results'}))
- #filter out empty <li> tags that only contain ' '
- lis = [li for li in div_results('li')
- if li.get('class') != 'break']
- #build the list of results, a dict for each results
- res = [{'name': li.h3.text,
- 'url': self._urljoin(li.a['href']),
- 'tn': self._urljoin(
- li.find('img', {'class': 'thumb-144'})['src'])}
- for li in lis]
- video_results.extend(res)
- return video_results
-
- def run(self, mode, url):
- #must pass default values for mode and url, mode is '0', url is ''
- mode_functions = {'0': self.display_subjects,
- '1': self.display_topics,
- '2': self.display_courses,
- '3': self.display_lectures,
- '4': self.display_allresults}
- mode_functions[mode](url)
+from urlparse import urljoin
+from resources.lib.getflashvideo import YouTube
+import re
+from resources.lib.favorites import favorites
+from xbmcswift import xbmcgui
+
+__plugin_name__ = 'New Academic Earth'
+__plugin_id__ = 'plugin.video.newacademicearth'
+
+plugin = Plugin(__plugin_name__, __plugin_id__, filepath=__file__)
+plugin.register_module(favorites, '/favorites')
+
+BASE_URL = 'http://academicearth.org'
+def full_url(path):
+ return urljoin(BASE_URL, path)
+
+def htmlify(url):
+ return BS(download_page(url))
+
+def filter_free(items):
+ return filter(lambda item: not item['label'].startswith('Online'), items)
+
[email protected]('/')
+def show_index():
+ items = [
+ {'label': plugin.get_string(30200), 'url':
plugin.url_for('show_subjects')},
+ {'label': plugin.get_string(30201), 'url':
plugin.url_for('show_universities')},
+ {'label': plugin.get_string(30202), 'url':
plugin.url_for('show_instructors')},
+ {'label': plugin.get_string(30203), 'url':
plugin.url_for('show_top_instructors')},
+ {'label': plugin.get_string(30204), 'url':
plugin.url_for('show_playlists')},
+ {'label': plugin.get_string(30205), 'url':
plugin.url_for('favorites.show_favorites')},
+ ]
+ return plugin.add_items(items)
+
[email protected]('/subjects/', url=full_url('subjects'))
+def show_subjects(url):
+ html = htmlify(url)
+ parent_div = html.find('div', {'class': 'institution-list'}).parent
+ subjects = parent_div.findAll('li')
+
+ items = [{
+ 'label': subject.a.string,
+ 'url': plugin.url_for('show_topics', url=full_url(subject.a['href'])),
+ } for subject in subjects]
+
+ # Filter out non-free subjects
+ items = filter(lambda item: not item['label'].startswith('Online'), items)
+
+ return plugin.add_items(items)
+
[email protected]('/universities/', url=full_url('universities'))
+def show_universities(url):
+ html = htmlify(url)
+ parent_div = html.find('div', {'class': 'institution-list'})
+ universities = parent_div.findAll('a')
+
+ items = [{
+ 'label': item.string,
+ 'url': plugin.url_for('show_topics', url=full_url(item['href'])),
+ } for item in universities]
+
+ return plugin.add_items(items)
+
[email protected]('/instructors/', url=full_url('speakers'))
+def show_instructors(url):
+ html = htmlify(url)
+ uls = html.findAll('ul', {'class': 'professors-list'})
+ professors = uls[0].findAll('li') + uls[1].findAll('li')
+
+ items = [{
+ 'label': item.a.string,
+ 'url': plugin.url_for('show_instructor_courses',
url=full_url(item.a['href'])),
+ } for item in professors]
+
+ return plugin.add_items(items)
+
[email protected]('/instructors/top/', url=BASE_URL)
+def show_top_instructors(url):
+ html = htmlify(url)
+ menu = html.find('ul', {'id': 'categories-accordion'})
+ speakers = menu.findAll('a', {'class': 'accordion-item', 'href': lambda h:
'/speakers/' in h})
+
+ items = [{
+ 'label': item.string,
+ 'url': plugin.url_for('show_instructor_courses',
url=full_url(item['href'])),
+ } for item in speakers]
+
+ return plugin.add_items(items)
+
[email protected]('/playlists/', url=full_url('playlists'))
+def show_playlists(url):
+ html = htmlify(url)
+ playlists = html.find('ol', {'class': 'playlist-list'}).findAll('li',
recursive=False)
+
+ items = [{
+ 'label': item.h4.findAll('a')[-1].string,
+ 'url': plugin.url_for('show_lectures', url=full_url(item.a['href'])),
+ 'thumbnail': full_url(item.find('img', {'width': '144'})['src']),
+ } for item in playlists]
+
+ return plugin.add_items(items)
-if __name__ == '__main__':
- #parse command line parameters into a dictionary
- params = parse_qs(sys.argv[2])
-
- #create new app
- app = AcademicEarth(sys.argv[0], sys.argv[1])
-
- #run the app
- app.run(params.get('mode', '0'),
- unquote_plus(params.get('url', app.subjects_url)))
+
[email protected]('/instructors/courses/<url>/')
+def show_instructor_courses(url):
+ html = htmlify(url)
+ parent_div = html.find('div', {'class': 'results-list'})
+ courses_lectures = parent_div.findAll('li')
+
+ courses = filter(lambda item: '/courses/' in item.h4.a['href'],
courses_lectures)
+ lectures = filter(lambda item: '/lectures/' in item.h4.a['href'],
courses_lectures)
+
+ course_items = [{
+ 'label': item.h4.a.string,
+ 'url': plugin.url_for('show_lectures',
url=full_url(item.h4.a['href'])),
+ 'thumbnail': full_url(item.find('img', {'width': '144'})['src']),
+ } for item in courses]
+
+ lecture_items = [{
+ 'label': '%s: %s' % (plugin.get_string(30206), item.h4.a.string),
+ 'url': plugin.url_for('watch_lecture',
url=full_url(item.h4.a['href'])),
+ 'thumbnail': full_url(item.find('img', {'class': 'thumb-144'})['src']),
+ 'is_folder': False,
+ 'is_playable': True,
+ } for item in lectures]
+
+ return plugin.add_items(course_items + lecture_items)
+
[email protected]('/topics/<url>/')
+def show_topics(url):
+ # Filter our topcis taht start with 'Online'
+ # if we only have one topic, redirect to teh courses/lectures page
+ html = htmlify(url)
+ parent_div = html.find('div', {'class': 'results-side'})
+ topics = parent_div.findAll('li')
+
+ items = [{
+ 'label': topic.a.string,
+ 'url': plugin.url_for('show_courses', url=full_url(topic.a['href'])),
+ } for topic in topics]
+
+ # Filter out non free topics
+ items = filter_free(items)
+
+ # If we only have one item, just redirect to the show_topics page,
+ # there's no need to display a single item in the list
+ if len(items) == 1:
+ return plugin.redirect(items[0]['url'])
+
+ return plugin.add_items(items)
+
[email protected]('/courses/<url>/')
+def show_courses(url):
+ def get_pagination(html):
+ items = []
+ pagination = html.find('ul', {'class': 'pagination'})
+ if not pagination:
+ return items
+
+ previous = pagination.find(text='<')
+ if previous:
+ items.append({
+ 'label': '< Previous',
+ 'url': plugin.url_for('show_courses',
url=full_url(previous.parent['href'])),
+ })
+
+ next = pagination.find(text='>')
+ if next:
+ items.append({
+ 'label': 'Next >',
+ 'url': plugin.url_for('show_courses',
url=full_url(next.parent['href'])),
+ })
+ return items
+
+ html = htmlify(url)
+ parent_div = html.find('div', {'class': 'video-results'})
+
+ # Need to filter out <li>'s that are only used for spacing.
+ # Spacing li's look like <li class="break">
+ courses_lectures = parent_div.findAll('li', {'class': lambda c: c !=
'break'})
+
+ # Some of the results can be a standalone lecture, not a link to a course
+ # page. We need to display these separately.
+ courses = filter(lambda item: '/courses/' in item.h3.a['href'],
courses_lectures)
+ lectures = filter(lambda item: '/lectures/' in item.h3.a['href'],
courses_lectures)
+
+ course_items = [{
+ 'label': item.h3.a.string,
+ 'url': plugin.url_for('show_lectures',
url=full_url(item.h3.a['href'])),
+ 'thumbnail': full_url(item.find('img', {'class': 'thumb-144'})['src']),
+ } for item in courses]
+
+ lecture_items = [{
+ 'label': '%s: %s' % (plugin.get_string(30206),item.h3.a.string),
+ 'url': plugin.url_for('watch_lecture',
url=full_url(item.h3.a['href'])),
+ 'thumbnail': full_url(item.find('img', {'class': 'thumb-144'})['src']),
+ 'is_folder': False,
+ 'is_playable': True,
+ } for item in lectures]
+
+ pagination_items = get_pagination(html)
+
+ return plugin.add_items(pagination_items + course_items + lecture_items)
+
[email protected]('/lectures/<url>/')
+def show_lectures(url):
+ def get_plot(item):
+ if item.p:
+ return item.p.string
+ return ''
+
+ def get_add_to_favorites_url(item):
+ path = item.find('a', {'class': 'add'})
+ if path:
+ return (plugin.get_string(30300), # Add to favorites
+ 'XBMC.RunPlugin(%s)' % favorites.url_for(
+ 'favorites.add_lecture',
+ url=full_url(path)['href']
+ ))
+ return
+
+ html = htmlify(url)
+ parent_div = html.find('div', {'class': 'results-list'})
+ lectures = parent_div.findAll('li')
+
+ items = [{
+ 'label': item.h4.a.string,
+ 'url': plugin.url_for('watch_lecture',
url=full_url(item.h4.a['href'])),
+ 'thumbnail': full_url(item.find('img', {'class': 'thumb-144'})['src']),
+ 'is_folder': False,
+ 'is_playable': True,
+ # Call to get_plot is because we are using this view to parse a course
page
+ # and also parse a playlist page. The playlist pages don't contain a
lecture
+ # description.
+ 'info': {'plot': get_plot(item)},
+ 'context_menu': [
+ (plugin.get_string(30300), # Add to favorites
+ 'XBMC.RunPlugin(%s)' % favorites.url_for(
+ 'favorites.add_lecture',
+ url=full_url(item.find('a', {'class': 'add'})['href'])
+ )),
+ ],
+
+ } for item in lectures]
+
+ return plugin.add_items(items)
+
[email protected]('/watch/<url>/')
+def watch_lecture(url):
+ src = download_page(url)
+ # There are 2 different hosts for lectures.
+ # blip.tv and youtube.
+
+ # Attempt to match blip.tv
+ flv_ptn = re.compile(r'flashVars.flvURL = "(.+?)"')
+ m = flv_ptn.search(src)
+ if m:
+ return plugin.set_resolved_url(m.group(1))
+
+ # If we're still here attempt to match youtube
+ #videoid_ptn =
+ ytid_ptn = re.compile(r'flashVars.ytID = "(.+?)"')
+ m = ytid_ptn.search(src)
+ if m:
+ video_url = YouTube.get_flashvideo_url(videoid=m.group(1))
+ return plugin.set_resolved_url(video_url)
+
+ xbmcgui.Dialog().ok(plugin.get_string(30000), plugin.get_string(30400))
+ raise Exception, 'No video url found. Please alert plugin author.'
+
+
+if __name__ == '__main__':
+ plugin.run()
diff --git a/plugin.video.academicearth/addon.xml
b/plugin.video.academicearth/addon.xml
index ec74974..89eed94 100644
--- a/plugin.video.academicearth/addon.xml
+++ b/plugin.video.academicearth/addon.xml
@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
-<addon id="plugin.video.academicearth" name="Academic Earth" version="1.0.4"
provider-name="jbel">
+<addon id="plugin.video.academicearth" name="Academic Earth" version="1.1.1"
provider-name="Jonathan Beluch (jbel)">
<requires>
<import addon="xbmc.python" version="1.0"/>
<import addon="script.module.beautifulsoup" version="3.0.8"/>
+ <import addon="script.module.xbmcswift" version="0.1.3"/>
</requires>
<extension point="xbmc.python.pluginsource" library="addon.py">
<provides>video</provides>
</extension>
<extension point="xbmc.addon.metadata">
<platform>all</platform>
- <summary>Academic Earth video plugin</summary>
- <description>Watch online video lectures from leading
universities.</description>
- <disclaimer>Only free courses/lectures are listed.</disclaimer>
+ <summary>Watch lectures from Academic Earth
(http://academicearth.org)</summary>
+ <description>Browse online courses and lectures from the world's top
scholars.</description>
</extension>
</addon>
diff --git a/plugin.video.academicearth/changelog.txt
b/plugin.video.academicearth/changelog.txt
index 1144507..e80bae2 100644
--- a/plugin.video.academicearth/changelog.txt
+++ b/plugin.video.academicearth/changelog.txt
@@ -1,2 +1,12 @@
+Version 1.1.1
+* Bumped required version of xbmcswift to 0.1.3
+
+Version 1.1.0
+* Fixed problems with certain lectures not playing.
+* Added browsing support for Universities, Playlists, Instructors, Top
+Instructors
+* Added support for viewing favorites from http://academicearth.org. Includes
+support for adding/removing videos from favorites via the context menu.
+
Version 1.0.4
-Fixed BeautifulSoup import error.
+* Fixed BeautifulSoup import error.
diff --git a/plugin.video.academicearth/resources/language/English/strings.xml
b/plugin.video.academicearth/resources/language/English/strings.xml
index 5fa0fd6..5d9ab0e 100644
--- a/plugin.video.academicearth/resources/language/English/strings.xml
+++ b/plugin.video.academicearth/resources/language/English/strings.xml
@@ -1,13 +1,30 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<strings>
- <!-- Plugin name -->
- <string id="30000">Academic Earth</string>
+ <!-- Plugin name -->
+ <string id="30000">New Academic Earth</string>
+ <!-- Settings stuff -->
+ <string id="30100">Account Settings for http://www.academicearth.org</string>
+ <string id="30101">Username:</string>
+ <string id="30102">Password:</string>
- <!-- List item titles and dialog progress strings -->
- <string id="30100">View all results</string>
- <string id="30101">Downloading lecture info...</string>
- <string id="30102">Downloading course/lecture info...</string>
+ <!-- List Item labels -->
+ <string id="30200">Subjects</string>
+ <string id="30201">Universities</string>
+ <string id="30202">Instructors</string>
+ <string id="30203">Top Rated Instructors</string>
+ <string id="30204">Playlists</string>
+ <string id="30205">Your Website Favorites</string>
+ <string id="30206">Lecture</string>
+
+ <!-- Context menu options -->
+ <string id="30300">Add to website favorites</string>
+ <string id="30301">Remove from website favorites</string>
+
+ <!-- Error messages -->
+ <string id="30400">No video url found. Please alert plugin author.</string>
+ <string id="30401">It seems your username/password combination aren't
valid.</string>
+ <string id="30402">There was a problem removing the item from your website
favorites.</string>
+ <string id="30403">There was a problem adding the item to your website
favorites.</string>
+ <string id="30404">You don't have an favorites yet! Add favorites on
http://academicearth.com or through the context menu of a lecture list
item.</string>
- <!-- (L) comes from (L)ecture -->
- <string id="30103">(L)</string>
</strings>
-----------------------------------------------------------------------
Summary of changes:
.../{README.markdown => README.md} | 25 +-
plugin.video.academicearth/addon.py | 515 +++++++++++---------
plugin.video.academicearth/addon.xml | 8 +-
plugin.video.academicearth/changelog.txt | 12 +-
.../resources/language/English/strings.xml | 33 +-
.../resources/lib/favorites.py | 145 ++++++
.../resources/lib/getflashvideo.py | 0
.../resources/lib/xbmcvideoplugin.py | 214 --------
plugin.video.academicearth/resources/settings.xml | 13 +
9 files changed, 502 insertions(+), 463 deletions(-)
rename plugin.video.academicearth/{README.markdown => README.md} (56%)
create mode 100644 plugin.video.academicearth/resources/lib/favorites.py
copy {plugin.video.aljazeera =>
plugin.video.academicearth}/resources/lib/getflashvideo.py (100%)
delete mode 100644 plugin.video.academicearth/resources/lib/xbmcvideoplugin.py
create mode 100644 plugin.video.academicearth/resources/settings.xml
hooks/post-receive
--
Plugins
------------------------------------------------------------------------------
Get a FREE DOWNLOAD! and learn more about uberSVN rich system,
user administration capabilities and model configuration. Take
the hassle out of deploying and managing Subversion and the
tools developers use with it. http://p.sf.net/sfu/wandisco-d2d-2
_______________________________________________
Xbmc-addons mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/xbmc-addons