diff --git a/plugin.audio.kissfm/LICENSE.txt b/plugin.audio.kissfm/LICENSE.txt
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.audio.kissfm/addon.py b/plugin.audio.kissfm/addon.py
new file mode 100644
index 0000000..cff82de
--- /dev/null
+++ b/plugin.audio.kissfm/addon.py
@@ -0,0 +1,19 @@
+import sys
+import xbmcgui
+import xbmcplugin
+
+addon_handle = int(sys.argv[1])
+
+xbmcplugin.setContent(addon_handle, 'audio')
+
+url = 'http://tx.whatson.com/icecast.php?i=kisstorylow.mp3'
+li = xbmcgui.ListItem('Kisstory', iconImage='http://whitenoisehq.co.uk/kisstory.png', thumbnailImage='http://whitenoisehq.co.uk/kisstory.png')
+li.setProperty('fanart_image', 'http://whitenoisehq.co.uk/kissbg.jpg')
+xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+
+url = 'http://tx.whatson.com/icecast.php?i=kissnationallow.mp3'
+li = xbmcgui.ListItem('Kiss FM UK - National', iconImage='http://whitenoisehq.co.uk/kisslogo.png', thumbnailImage='http://whitenoisehq.co.uk/kisslogo.png')
+li.setProperty('fanart_image', 'http://whitenoisehq.co.uk/kissbg.jpg')
+xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+
+xbmcplugin.endOfDirectory(addon_handle)
\ No newline at end of file
diff --git a/plugin.audio.kissfm/addon.xml b/plugin.audio.kissfm/addon.xml
new file mode 100644
index 0000000..f68caa0
--- /dev/null
+++ b/plugin.audio.kissfm/addon.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ audio
+
+
+ Kiss FM UK - Live Stream
+ KissFMUK.com
+
+ English
+ all
+
+
+ http://www.kissfmuk.com
+ oli@whitenoisehq.co.uk
+
+
+
\ No newline at end of file
diff --git a/plugin.audio.kissfm/changelog.txt b/plugin.audio.kissfm/changelog.txt
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.audio.kissfm/fanart.jpg b/plugin.audio.kissfm/fanart.jpg
new file mode 100644
index 0000000..c666bc7
Binary files /dev/null and b/plugin.audio.kissfm/fanart.jpg differ
diff --git a/plugin.audio.kissfm/icon.PNG b/plugin.audio.kissfm/icon.PNG
new file mode 100644
index 0000000..53ba406
Binary files /dev/null and b/plugin.audio.kissfm/icon.PNG differ
diff --git a/plugin.audio.kissfm/resources/icon.PNG b/plugin.audio.kissfm/resources/icon.PNG
new file mode 100644
index 0000000..53ba406
Binary files /dev/null and b/plugin.audio.kissfm/resources/icon.PNG differ
diff --git a/plugin.audio.kissfm/resources/lib/academicearth/__init__.py b/plugin.audio.kissfm/resources/lib/academicearth/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.audio.kissfm/resources/lib/academicearth/api.py b/plugin.audio.kissfm/resources/lib/academicearth/api.py
new file mode 100644
index 0000000..dc17d6c
--- /dev/null
+++ b/plugin.audio.kissfm/resources/lib/academicearth/api.py
@@ -0,0 +1,141 @@
+'''
+
+ academicearth.api
+ ~~~~~~~~~~~~~~~~~
+
+ This module contains the API classes and method to parse information from
+ the Academic Earth website.
+
+'''
+from scraper import (get_subjects, get_courses, get_subject_metadata,
+ get_course_metadata, get_lecture_metadata)
+
+
+class AcademicEarth(object):
+ '''The main API object. Useful as a starting point to get available
+ subjects.
+ '''
+
+ def __init__(self):
+ pass
+
+ def get_subjects(self):
+ '''Returns a list of subjects available on the website.'''
+ return [Subject(**info) for info in get_subjects()]
+
+
+class Subject(object):
+ '''Object representing an Academic Earth subject.'''
+
+ def __init__(self, url, name=None):
+ self.url = url
+ self._name = name
+ self._courses = None
+ self._lectures = None
+ self._loaded = False
+
+ @classmethod
+ def from_url(cls, url):
+ return cls(url=url)
+
+ def __repr__(self):
+ return u"" % self.name
+
+ def _load_metadata(self):
+ resp = get_subject_metadata(self.url)
+ if not self._name:
+ self._name = resp['name']
+ self._courses = [Course(**info) for info in resp['courses']]
+ self._lectures = [Lecture(**info) for info in resp['lectures']]
+ self._description = resp['description']
+ self._loaded = True
+
+ @property
+ def name(self):
+ '''Subject name'''
+ if not self._name:
+ self._load_metadata()
+ return self._name
+
+ @property
+ def courses(self):
+ '''List of courses available for this subject'''
+ if not self._loaded:
+ self._load_metadata()
+ return self._courses
+
+ @property
+ def lectures(self):
+ '''List of lectures available for this subject'''
+ if not self._loaded:
+ self._load_metadata()
+ return self._lectures
+
+
+class Course(object):
+
+ def __init__(self, url, name=None, **kwargs):
+ self.url = url
+ self._name = name
+ self._loaded = False
+ self._lectures = None
+
+ @classmethod
+ def from_url(cls, url):
+ return cls(url=url)
+
+ def __repr__(self):
+ return u"" % self.name
+
+ def _load_metadata(self):
+ resp = get_course_metadata(self.url)
+ if not self._name:
+ self._name = resp['name']
+ self._lectures = [Lecture(**info) for info in resp['lectures']]
+ self._loaded = True
+
+ @property
+ def name(self):
+ if not self._name:
+ self._load_metadata()
+ return self._name
+
+ @property
+ def lectures(self):
+ if not self._loaded:
+ self._load_metadata()
+ return self._lectures
+
+
+class Lecture(object):
+
+ def __init__(self, url, name=None, **kwargs):
+ self.url = url
+ self._name = name
+ self._loaded = False
+
+ @classmethod
+ def from_url(cls, url):
+ return cls(url=url)
+
+ def __repr__(self):
+ return u"" % self.name
+
+ def _load_metadata(self):
+ resp = get_lecture_metadata(self.url)
+ if not self._name:
+ self._name = resp['name']
+ self._youtube_id = resp['youtube_id']
+ self._loaded = True
+
+ @property
+ def name(self):
+ if not self._name:
+ self._load_metadata()
+ return self._name
+
+ @property
+ def youtube_id(self):
+ if not self._loaded:
+ self._load_metadata()
+ return self._youtube_id
diff --git a/plugin.audio.kissfm/resources/lib/academicearth/scraper.py b/plugin.audio.kissfm/resources/lib/academicearth/scraper.py
new file mode 100644
index 0000000..1e14ec7
--- /dev/null
+++ b/plugin.audio.kissfm/resources/lib/academicearth/scraper.py
@@ -0,0 +1,151 @@
+'''
+ academicearth.scraper
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ This module contains some functions which do the website scraping for the
+ API module. You shouldn't have to use this module directly.
+'''
+import re
+from urllib2 import urlopen
+from urlparse import urljoin
+from BeautifulSoup import BeautifulSoup as BS
+
+
+BASE_URL = 'http://www.academicearth.org'
+def _url(path):
+ '''Returns a full url for the given path'''
+ return urljoin(BASE_URL, path)
+
+
+def get(url):
+ '''Performs a GET request for the given url and returns the response'''
+ conn = urlopen(url)
+ resp = conn.read()
+ conn.close()
+ return resp
+
+
+def _html(url):
+ '''Downloads the resource at the given url and parses via BeautifulSoup'''
+ return BS(get(url), convertEntities=BS.HTML_ENTITIES)
+
+
+def make_showall_url(url):
+ '''Takes an api url and appends info to the path to force the page to
+ return all entries instead of paginating.
+ '''
+ if not url.endswith('/'):
+ url += '/'
+ return url + 'page:1/show:500'
+
+
+def get_subjects():
+ '''Returns a list of subjects for the website. Each subject is a dict with
+ keys of 'name' and 'url'.
+ '''
+ url = _url('subjects')
+ html = _html(url)
+ subjs = html.findAll('a',
+ {'href': lambda attr_value: attr_value.startswith('/subjects/')
+ and len(attr_value) > len('/subjects/')})
+
+ # subjs will contain some duplicates so we will key on url
+ items = []
+ urls = set()
+ for subj in subjs:
+ url = _url(subj['href'])
+ if url not in urls:
+ urls.add(url)
+ items.append({
+ 'name': subj.string,
+ 'url': url,
+ })
+
+ # filter out any items that didn't parse correctly
+ return [item for item in items if item['name'] and item['url']]
+
+
+def get_subject_metadata(subject_url):
+ '''Returns metadata for a subject parsed from the given url'''
+ html = _html(make_showall_url(subject_url))
+ name = get_subject_name(html)
+ courses = get_courses(html)
+ lectures = get_lectures(html)
+ desc = get_subject_description(html)
+
+ return {
+ 'name': name,
+ 'courses': courses,
+ 'lectures': lectures,
+ 'description': desc,
+ }
+
+
+def get_subject_name(html):
+ return html.find('article').h1.text
+
+
+def get_course_name(html):
+ return html.find('section', {'class': 'pagenav'}).span.text
+
+
+def get_lecture_name(html):
+ return html.find('section', {'class': 'pagenav'}).span.text
+
+
+def get_subject_description(html):
+ desc_nodes = html.find('article').findAll('span')
+ return '\n'.join(node.text.strip() for node in desc_nodes)
+
+
+def _get_courses_or_lectures(class_type, html):
+ '''class_type can be 'course' or 'lecture'.'''
+ nodes = html.findAll('div', {'class': class_type})
+
+ items = [{
+ 'name': node.h3.text,
+ 'url': _url(node.a['href']),
+ 'icon': node.img['src'],
+ #'university': '',
+ #'speaker': '',
+ } for node in nodes]
+
+ return items
+
+
+def get_lectures(html):
+ return _get_courses_or_lectures('lecture', html)
+
+
+def get_courses(html):
+ return _get_courses_or_lectures('course', html)
+
+
+def get_course_metadata(course_url):
+ html = _html(make_showall_url(course_url))
+ lectures = get_lectures(html)
+ name = get_course_name(html)
+ return {
+ 'lectures': lectures,
+ 'name': name,
+ }
+
+
+def get_lecture_metadata(lecture_url):
+ html = _html(lecture_url)
+ name = get_lecture_name(html)
+ youtube_id = parse_youtube_id(html)
+ return {
+ 'name': name,
+ 'youtube_id': youtube_id
+ }
+
+
+
+def parse_youtube_id(html):
+ embed = html.find('embed')
+ yt_ptn = re.compile(r'http://www.youtube.com/v/(.+?)\?')
+ match = yt_ptn.search(embed['src'])
+ if match:
+ return match.group(1)
+ return None
diff --git a/plugin.audio.kissfm/resources/settings.xml b/plugin.audio.kissfm/resources/settings.xml
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.audio.rinsefm/LICENSE.txt b/plugin.audio.rinsefm/LICENSE.txt
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.audio.rinsefm/Thumbs.db b/plugin.audio.rinsefm/Thumbs.db
new file mode 100644
index 0000000..7b4a1fe
Binary files /dev/null and b/plugin.audio.rinsefm/Thumbs.db differ
diff --git a/plugin.audio.rinsefm/addon.py b/plugin.audio.rinsefm/addon.py
new file mode 100644
index 0000000..0525373
--- /dev/null
+++ b/plugin.audio.rinsefm/addon.py
@@ -0,0 +1,14 @@
+import sys
+import xbmcgui
+import xbmcplugin
+
+addon_handle = int(sys.argv[1])
+
+xbmcplugin.setContent(addon_handle, 'movies')
+
+url = 'http://podcast.dgen.net:8000/rinseradio.m3u'
+li = xbmcgui.ListItem('Rinse.FM', iconImage='http://in-reach.co.uk/wp-content/uploads/2014/02/rinse-fm-logo-620x400.png', thumbnailImage='http://in-reach.co.uk/wp-content/uploads/2014/02/rinse-fm-logo-620x400.png')
+li.setProperty('fanart_image', 'http://in-reach.co.uk/wp-content/uploads/2014/02/rinse-fm-logo-620x400.png')
+xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+
+xbmcplugin.endOfDirectory(addon_handle)
\ No newline at end of file
diff --git a/plugin.audio.rinsefm/addon.xml b/plugin.audio.rinsefm/addon.xml
new file mode 100644
index 0000000..fed7cfd
--- /dev/null
+++ b/plugin.audio.rinsefm/addon.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ audio
+
+
+ Rinse.FM - Live Stream
+ RinseFM live from Brick Lane, London
+
+ English
+ all
+
+
+ http://rinse.fm
+ oli@whitenoisehq.co.uk
+
+
+
\ No newline at end of file
diff --git a/plugin.audio.rinsefm/changelog.txt b/plugin.audio.rinsefm/changelog.txt
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.audio.rinsefm/fanart.jpg b/plugin.audio.rinsefm/fanart.jpg
new file mode 100644
index 0000000..849eeee
Binary files /dev/null and b/plugin.audio.rinsefm/fanart.jpg differ
diff --git a/plugin.audio.rinsefm/logo.png b/plugin.audio.rinsefm/logo.png
new file mode 100644
index 0000000..496e171
Binary files /dev/null and b/plugin.audio.rinsefm/logo.png differ
diff --git a/plugin.audio.rinsefm/resources/icon.PNG b/plugin.audio.rinsefm/resources/icon.PNG
new file mode 100644
index 0000000..5e8ad88
Binary files /dev/null and b/plugin.audio.rinsefm/resources/icon.PNG differ
diff --git a/plugin.audio.rinsefm/resources/lib/academicearth/__init__.py b/plugin.audio.rinsefm/resources/lib/academicearth/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.audio.rinsefm/resources/lib/academicearth/api.py b/plugin.audio.rinsefm/resources/lib/academicearth/api.py
new file mode 100644
index 0000000..dc17d6c
--- /dev/null
+++ b/plugin.audio.rinsefm/resources/lib/academicearth/api.py
@@ -0,0 +1,141 @@
+'''
+
+ academicearth.api
+ ~~~~~~~~~~~~~~~~~
+
+ This module contains the API classes and method to parse information from
+ the Academic Earth website.
+
+'''
+from scraper import (get_subjects, get_courses, get_subject_metadata,
+ get_course_metadata, get_lecture_metadata)
+
+
+class AcademicEarth(object):
+ '''The main API object. Useful as a starting point to get available
+ subjects.
+ '''
+
+ def __init__(self):
+ pass
+
+ def get_subjects(self):
+ '''Returns a list of subjects available on the website.'''
+ return [Subject(**info) for info in get_subjects()]
+
+
+class Subject(object):
+ '''Object representing an Academic Earth subject.'''
+
+ def __init__(self, url, name=None):
+ self.url = url
+ self._name = name
+ self._courses = None
+ self._lectures = None
+ self._loaded = False
+
+ @classmethod
+ def from_url(cls, url):
+ return cls(url=url)
+
+ def __repr__(self):
+ return u"" % self.name
+
+ def _load_metadata(self):
+ resp = get_subject_metadata(self.url)
+ if not self._name:
+ self._name = resp['name']
+ self._courses = [Course(**info) for info in resp['courses']]
+ self._lectures = [Lecture(**info) for info in resp['lectures']]
+ self._description = resp['description']
+ self._loaded = True
+
+ @property
+ def name(self):
+ '''Subject name'''
+ if not self._name:
+ self._load_metadata()
+ return self._name
+
+ @property
+ def courses(self):
+ '''List of courses available for this subject'''
+ if not self._loaded:
+ self._load_metadata()
+ return self._courses
+
+ @property
+ def lectures(self):
+ '''List of lectures available for this subject'''
+ if not self._loaded:
+ self._load_metadata()
+ return self._lectures
+
+
+class Course(object):
+
+ def __init__(self, url, name=None, **kwargs):
+ self.url = url
+ self._name = name
+ self._loaded = False
+ self._lectures = None
+
+ @classmethod
+ def from_url(cls, url):
+ return cls(url=url)
+
+ def __repr__(self):
+ return u"" % self.name
+
+ def _load_metadata(self):
+ resp = get_course_metadata(self.url)
+ if not self._name:
+ self._name = resp['name']
+ self._lectures = [Lecture(**info) for info in resp['lectures']]
+ self._loaded = True
+
+ @property
+ def name(self):
+ if not self._name:
+ self._load_metadata()
+ return self._name
+
+ @property
+ def lectures(self):
+ if not self._loaded:
+ self._load_metadata()
+ return self._lectures
+
+
+class Lecture(object):
+
+ def __init__(self, url, name=None, **kwargs):
+ self.url = url
+ self._name = name
+ self._loaded = False
+
+ @classmethod
+ def from_url(cls, url):
+ return cls(url=url)
+
+ def __repr__(self):
+ return u"" % self.name
+
+ def _load_metadata(self):
+ resp = get_lecture_metadata(self.url)
+ if not self._name:
+ self._name = resp['name']
+ self._youtube_id = resp['youtube_id']
+ self._loaded = True
+
+ @property
+ def name(self):
+ if not self._name:
+ self._load_metadata()
+ return self._name
+
+ @property
+ def youtube_id(self):
+ if not self._loaded:
+ self._load_metadata()
+ return self._youtube_id
diff --git a/plugin.audio.rinsefm/resources/lib/academicearth/scraper.py b/plugin.audio.rinsefm/resources/lib/academicearth/scraper.py
new file mode 100644
index 0000000..1e14ec7
--- /dev/null
+++ b/plugin.audio.rinsefm/resources/lib/academicearth/scraper.py
@@ -0,0 +1,151 @@
+'''
+ academicearth.scraper
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ This module contains some functions which do the website scraping for the
+ API module. You shouldn't have to use this module directly.
+'''
+import re
+from urllib2 import urlopen
+from urlparse import urljoin
+from BeautifulSoup import BeautifulSoup as BS
+
+
+BASE_URL = 'http://www.academicearth.org'
+def _url(path):
+ '''Returns a full url for the given path'''
+ return urljoin(BASE_URL, path)
+
+
+def get(url):
+ '''Performs a GET request for the given url and returns the response'''
+ conn = urlopen(url)
+ resp = conn.read()
+ conn.close()
+ return resp
+
+
+def _html(url):
+ '''Downloads the resource at the given url and parses via BeautifulSoup'''
+ return BS(get(url), convertEntities=BS.HTML_ENTITIES)
+
+
+def make_showall_url(url):
+ '''Takes an api url and appends info to the path to force the page to
+ return all entries instead of paginating.
+ '''
+ if not url.endswith('/'):
+ url += '/'
+ return url + 'page:1/show:500'
+
+
+def get_subjects():
+ '''Returns a list of subjects for the website. Each subject is a dict with
+ keys of 'name' and 'url'.
+ '''
+ url = _url('subjects')
+ html = _html(url)
+ subjs = html.findAll('a',
+ {'href': lambda attr_value: attr_value.startswith('/subjects/')
+ and len(attr_value) > len('/subjects/')})
+
+ # subjs will contain some duplicates so we will key on url
+ items = []
+ urls = set()
+ for subj in subjs:
+ url = _url(subj['href'])
+ if url not in urls:
+ urls.add(url)
+ items.append({
+ 'name': subj.string,
+ 'url': url,
+ })
+
+ # filter out any items that didn't parse correctly
+ return [item for item in items if item['name'] and item['url']]
+
+
+def get_subject_metadata(subject_url):
+ '''Returns metadata for a subject parsed from the given url'''
+ html = _html(make_showall_url(subject_url))
+ name = get_subject_name(html)
+ courses = get_courses(html)
+ lectures = get_lectures(html)
+ desc = get_subject_description(html)
+
+ return {
+ 'name': name,
+ 'courses': courses,
+ 'lectures': lectures,
+ 'description': desc,
+ }
+
+
+def get_subject_name(html):
+ return html.find('article').h1.text
+
+
+def get_course_name(html):
+ return html.find('section', {'class': 'pagenav'}).span.text
+
+
+def get_lecture_name(html):
+ return html.find('section', {'class': 'pagenav'}).span.text
+
+
+def get_subject_description(html):
+ desc_nodes = html.find('article').findAll('span')
+ return '\n'.join(node.text.strip() for node in desc_nodes)
+
+
+def _get_courses_or_lectures(class_type, html):
+ '''class_type can be 'course' or 'lecture'.'''
+ nodes = html.findAll('div', {'class': class_type})
+
+ items = [{
+ 'name': node.h3.text,
+ 'url': _url(node.a['href']),
+ 'icon': node.img['src'],
+ #'university': '',
+ #'speaker': '',
+ } for node in nodes]
+
+ return items
+
+
+def get_lectures(html):
+ return _get_courses_or_lectures('lecture', html)
+
+
+def get_courses(html):
+ return _get_courses_or_lectures('course', html)
+
+
+def get_course_metadata(course_url):
+ html = _html(make_showall_url(course_url))
+ lectures = get_lectures(html)
+ name = get_course_name(html)
+ return {
+ 'lectures': lectures,
+ 'name': name,
+ }
+
+
+def get_lecture_metadata(lecture_url):
+ html = _html(lecture_url)
+ name = get_lecture_name(html)
+ youtube_id = parse_youtube_id(html)
+ return {
+ 'name': name,
+ 'youtube_id': youtube_id
+ }
+
+
+
+def parse_youtube_id(html):
+ embed = html.find('embed')
+ yt_ptn = re.compile(r'http://www.youtube.com/v/(.+?)\?')
+ match = yt_ptn.search(embed['src'])
+ if match:
+ return match.group(1)
+ return None
diff --git a/plugin.audio.rinsefm/resources/settings.xml b/plugin.audio.rinsefm/resources/settings.xml
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.video.londonlive/LICENSE.txt b/plugin.video.londonlive/LICENSE.txt
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.video.londonlive/addon.py b/plugin.video.londonlive/addon.py
new file mode 100644
index 0000000..d141282
--- /dev/null
+++ b/plugin.video.londonlive/addon.py
@@ -0,0 +1,14 @@
+import sys
+import xbmcgui
+import xbmcplugin
+
+addon_handle = int(sys.argv[1])
+
+xbmcplugin.setContent(addon_handle, 'movies')
+
+url = 'http://bcoveliveios-i.akamaihd.net/hls/live/217434/3083279840001/master.m3u8'
+li = xbmcgui.ListItem('London Live', iconImage='http://whitenoisehq.co.uk/londonlivelogo.png', thumbnailImage='http://whitenoisehq.co.uk/londonlivelogo.png')
+li.setProperty('fanart_image', 'fanart.jpg')
+xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+
+xbmcplugin.endOfDirectory(addon_handle)
\ No newline at end of file
diff --git a/plugin.video.londonlive/addon.xml b/plugin.video.londonlive/addon.xml
new file mode 100644
index 0000000..7e26655
--- /dev/null
+++ b/plugin.video.londonlive/addon.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ video
+
+
+ London Live - Live Stream
+ LondonLive.co.uk
+
+ English
+ all
+
+ http://forum.xbmc.org/showthread.php?tid=190935
+ http://www.londonlive.co.uk
+ oli@whitenoisehq.co.uk
+
+
+
\ No newline at end of file
diff --git a/plugin.video.londonlive/changelog.txt b/plugin.video.londonlive/changelog.txt
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.video.londonlive/fanart.jpg b/plugin.video.londonlive/fanart.jpg
new file mode 100644
index 0000000..849eeee
Binary files /dev/null and b/plugin.video.londonlive/fanart.jpg differ
diff --git a/plugin.video.londonlive/icon.PNG b/plugin.video.londonlive/icon.PNG
new file mode 100644
index 0000000..8caccf5
Binary files /dev/null and b/plugin.video.londonlive/icon.PNG differ
diff --git a/plugin.video.londonlive/resources/icon.PNG b/plugin.video.londonlive/resources/icon.PNG
new file mode 100644
index 0000000..8caccf5
Binary files /dev/null and b/plugin.video.londonlive/resources/icon.PNG differ
diff --git a/plugin.video.londonlive/resources/lib/academicearth/__init__.py b/plugin.video.londonlive/resources/lib/academicearth/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.video.londonlive/resources/lib/academicearth/api.py b/plugin.video.londonlive/resources/lib/academicearth/api.py
new file mode 100644
index 0000000..dc17d6c
--- /dev/null
+++ b/plugin.video.londonlive/resources/lib/academicearth/api.py
@@ -0,0 +1,141 @@
+'''
+
+ academicearth.api
+ ~~~~~~~~~~~~~~~~~
+
+ This module contains the API classes and method to parse information from
+ the Academic Earth website.
+
+'''
+from scraper import (get_subjects, get_courses, get_subject_metadata,
+ get_course_metadata, get_lecture_metadata)
+
+
+class AcademicEarth(object):
+ '''The main API object. Useful as a starting point to get available
+ subjects.
+ '''
+
+ def __init__(self):
+ pass
+
+ def get_subjects(self):
+ '''Returns a list of subjects available on the website.'''
+ return [Subject(**info) for info in get_subjects()]
+
+
+class Subject(object):
+ '''Object representing an Academic Earth subject.'''
+
+ def __init__(self, url, name=None):
+ self.url = url
+ self._name = name
+ self._courses = None
+ self._lectures = None
+ self._loaded = False
+
+ @classmethod
+ def from_url(cls, url):
+ return cls(url=url)
+
+ def __repr__(self):
+ return u"" % self.name
+
+ def _load_metadata(self):
+ resp = get_subject_metadata(self.url)
+ if not self._name:
+ self._name = resp['name']
+ self._courses = [Course(**info) for info in resp['courses']]
+ self._lectures = [Lecture(**info) for info in resp['lectures']]
+ self._description = resp['description']
+ self._loaded = True
+
+ @property
+ def name(self):
+ '''Subject name'''
+ if not self._name:
+ self._load_metadata()
+ return self._name
+
+ @property
+ def courses(self):
+ '''List of courses available for this subject'''
+ if not self._loaded:
+ self._load_metadata()
+ return self._courses
+
+ @property
+ def lectures(self):
+ '''List of lectures available for this subject'''
+ if not self._loaded:
+ self._load_metadata()
+ return self._lectures
+
+
+class Course(object):
+
+ def __init__(self, url, name=None, **kwargs):
+ self.url = url
+ self._name = name
+ self._loaded = False
+ self._lectures = None
+
+ @classmethod
+ def from_url(cls, url):
+ return cls(url=url)
+
+ def __repr__(self):
+ return u"" % self.name
+
+ def _load_metadata(self):
+ resp = get_course_metadata(self.url)
+ if not self._name:
+ self._name = resp['name']
+ self._lectures = [Lecture(**info) for info in resp['lectures']]
+ self._loaded = True
+
+ @property
+ def name(self):
+ if not self._name:
+ self._load_metadata()
+ return self._name
+
+ @property
+ def lectures(self):
+ if not self._loaded:
+ self._load_metadata()
+ return self._lectures
+
+
+class Lecture(object):
+
+ def __init__(self, url, name=None, **kwargs):
+ self.url = url
+ self._name = name
+ self._loaded = False
+
+ @classmethod
+ def from_url(cls, url):
+ return cls(url=url)
+
+ def __repr__(self):
+ return u"" % self.name
+
+ def _load_metadata(self):
+ resp = get_lecture_metadata(self.url)
+ if not self._name:
+ self._name = resp['name']
+ self._youtube_id = resp['youtube_id']
+ self._loaded = True
+
+ @property
+ def name(self):
+ if not self._name:
+ self._load_metadata()
+ return self._name
+
+ @property
+ def youtube_id(self):
+ if not self._loaded:
+ self._load_metadata()
+ return self._youtube_id
diff --git a/plugin.video.londonlive/resources/lib/academicearth/scraper.py b/plugin.video.londonlive/resources/lib/academicearth/scraper.py
new file mode 100644
index 0000000..1e14ec7
--- /dev/null
+++ b/plugin.video.londonlive/resources/lib/academicearth/scraper.py
@@ -0,0 +1,151 @@
+'''
+ academicearth.scraper
+ ~~~~~~~~~~~~~~~~~~~~~
+
+ This module contains some functions which do the website scraping for the
+ API module. You shouldn't have to use this module directly.
+'''
+import re
+from urllib2 import urlopen
+from urlparse import urljoin
+from BeautifulSoup import BeautifulSoup as BS
+
+
+BASE_URL = 'http://www.academicearth.org'
+def _url(path):
+ '''Returns a full url for the given path'''
+ return urljoin(BASE_URL, path)
+
+
+def get(url):
+ '''Performs a GET request for the given url and returns the response'''
+ conn = urlopen(url)
+ resp = conn.read()
+ conn.close()
+ return resp
+
+
+def _html(url):
+ '''Downloads the resource at the given url and parses via BeautifulSoup'''
+ return BS(get(url), convertEntities=BS.HTML_ENTITIES)
+
+
+def make_showall_url(url):
+ '''Takes an api url and appends info to the path to force the page to
+ return all entries instead of paginating.
+ '''
+ if not url.endswith('/'):
+ url += '/'
+ return url + 'page:1/show:500'
+
+
+def get_subjects():
+ '''Returns a list of subjects for the website. Each subject is a dict with
+ keys of 'name' and 'url'.
+ '''
+ url = _url('subjects')
+ html = _html(url)
+ subjs = html.findAll('a',
+ {'href': lambda attr_value: attr_value.startswith('/subjects/')
+ and len(attr_value) > len('/subjects/')})
+
+ # subjs will contain some duplicates so we will key on url
+ items = []
+ urls = set()
+ for subj in subjs:
+ url = _url(subj['href'])
+ if url not in urls:
+ urls.add(url)
+ items.append({
+ 'name': subj.string,
+ 'url': url,
+ })
+
+ # filter out any items that didn't parse correctly
+ return [item for item in items if item['name'] and item['url']]
+
+
+def get_subject_metadata(subject_url):
+ '''Returns metadata for a subject parsed from the given url'''
+ html = _html(make_showall_url(subject_url))
+ name = get_subject_name(html)
+ courses = get_courses(html)
+ lectures = get_lectures(html)
+ desc = get_subject_description(html)
+
+ return {
+ 'name': name,
+ 'courses': courses,
+ 'lectures': lectures,
+ 'description': desc,
+ }
+
+
+def get_subject_name(html):
+ return html.find('article').h1.text
+
+
+def get_course_name(html):
+ return html.find('section', {'class': 'pagenav'}).span.text
+
+
+def get_lecture_name(html):
+ return html.find('section', {'class': 'pagenav'}).span.text
+
+
+def get_subject_description(html):
+ desc_nodes = html.find('article').findAll('span')
+ return '\n'.join(node.text.strip() for node in desc_nodes)
+
+
+def _get_courses_or_lectures(class_type, html):
+ '''class_type can be 'course' or 'lecture'.'''
+ nodes = html.findAll('div', {'class': class_type})
+
+ items = [{
+ 'name': node.h3.text,
+ 'url': _url(node.a['href']),
+ 'icon': node.img['src'],
+ #'university': '',
+ #'speaker': '',
+ } for node in nodes]
+
+ return items
+
+
+def get_lectures(html):
+ return _get_courses_or_lectures('lecture', html)
+
+
+def get_courses(html):
+ return _get_courses_or_lectures('course', html)
+
+
+def get_course_metadata(course_url):
+ html = _html(make_showall_url(course_url))
+ lectures = get_lectures(html)
+ name = get_course_name(html)
+ return {
+ 'lectures': lectures,
+ 'name': name,
+ }
+
+
+def get_lecture_metadata(lecture_url):
+ html = _html(lecture_url)
+ name = get_lecture_name(html)
+ youtube_id = parse_youtube_id(html)
+ return {
+ 'name': name,
+ 'youtube_id': youtube_id
+ }
+
+
+
+def parse_youtube_id(html):
+ embed = html.find('embed')
+ yt_ptn = re.compile(r'http://www.youtube.com/v/(.+?)\?')
+ match = yt_ptn.search(embed['src'])
+ if match:
+ return match.group(1)
+ return None
diff --git a/plugin.video.londonlive/resources/settings.xml b/plugin.video.londonlive/resources/settings.xml
new file mode 100644
index 0000000..e69de29
diff --git a/plugin.video.wnhq/LICENSE.txt b/plugin.video.wnhq/LICENSE.txt
new file mode 100644
index 0000000..9aa03b3
--- /dev/null
+++ b/plugin.video.wnhq/LICENSE.txt
@@ -0,0 +1,12 @@
+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 .
diff --git a/plugin.video.wnhq/README b/plugin.video.wnhq/README
new file mode 100644
index 0000000..5341202
--- /dev/null
+++ b/plugin.video.wnhq/README
@@ -0,0 +1,2 @@
+Simply download the git, zip it as plugin.liveleak.zip and install like a normal zip.
+
diff --git a/plugin.video.wnhq/addon.xml b/plugin.video.wnhq/addon.xml
new file mode 100644
index 0000000..3be34d8
--- /dev/null
+++ b/plugin.video.wnhq/addon.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ video
+
+
+ White Noise HQ live on your TV!
+ en
+ Keep up to date with the latest from everyone at White Noise HQ!
+ all
+
+
diff --git a/plugin.video.wnhq/default.py b/plugin.video.wnhq/default.py
new file mode 100644
index 0000000..bd15e03
--- /dev/null
+++ b/plugin.video.wnhq/default.py
@@ -0,0 +1,175 @@
+import sys
+import urllib
+import urlparse
+import xbmcgui
+import xbmcplugin
+
+base_url = sys.argv[0]
+addon_handle = int(sys.argv[1])
+args = urlparse.parse_qs(sys.argv[2][1:])
+
+xbmcplugin.setContent(addon_handle, 'movies')
+
+def build_url(query):
+ return base_url + '?' + urllib.urlencode(query)
+
+mode = args.get('mode', None)
+
+if mode is None:
+ url = build_url({'mode': 'folder', 'foldername': 'Folder One'})
+ li = xbmcgui.ListItem('Live Radio (Audio)', iconImage='http://cdn.instructables.com/F21/3AKT/FX5571DH/F213AKTFX5571DH.MEDIUM.gif')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url,
+ listitem=li, isFolder=True)
+
+ url = build_url({'mode': 'folder6', 'foldername': 'Folder One'})
+ li = xbmcgui.ListItem('YouTube Live Streams (Audio & Video)', iconImage='http://cdn.instructables.com/F21/3AKT/FX5571DH/F213AKTFX5571DH.MEDIUM.gif')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url,
+ listitem=li, isFolder=True)
+
+ url = build_url({'mode': 'folder1', 'foldername': 'Folder Two'})
+ li = xbmcgui.ListItem('DJ Klass-A Radio Recordings', iconImage='http://static.house-mixes.com/s3/webmixes-images/accounts-410112/artwork/efa00ee9-1270-4820-92b3-0f502a85ced3.jpg/400/45/true')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url,
+ listitem=li, isFolder=True)
+
+ url = build_url({'mode': 'folder2', 'foldername': 'Folder Two'})
+ li = xbmcgui.ListItem('WhiteNoiseHQ Vs Ballistic Beats', iconImage='http://www.whitenoisehq.co.uk/v3/WN&BBFront.jpg')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url,
+ listitem=li, isFolder=True)
+
+ url = build_url({'mode': 'folder3', 'foldername': 'Folder Two'})
+ li = xbmcgui.ListItem('WhiteNoiseHQ - The Freeform Special', iconImage='http://farm5.static.flickr.com/4089/5040817729_d7d6efcb8e_b.jpg')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url,
+ listitem=li, isFolder=True)
+
+ url = build_url({'mode': 'folder4', 'foldername': 'Folder Two'})
+ li = xbmcgui.ListItem('Lady Brock - House Series', iconImage='http://static.house-mixes.com/s3/webmixes-images/accounts-88106/artwork/73c5708c-8276-4545-afd7-b367d8bc760d.jpg/360/45/true')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url,
+ listitem=li, isFolder=True)
+
+ url = build_url({'mode': 'folder5', 'foldername': 'Folder Two'})
+ li = xbmcgui.ListItem('White Noise HQ Recordings', iconImage='http://static.house-mixes.com/s3/webmixes-images/accounts-88106/artwork/73c5708c-8276-4545-afd7-b367d8bc760d.jpg/360/45/true')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url,
+ listitem=li, isFolder=True)
+
+ xbmcplugin.endOfDirectory(addon_handle)
+
+elif mode[0] == 'folder':
+ foldername = args['foldername'][0]
+ url = 'http://whitenoisehq.co.uk/v3/RevoltLive.m3u'
+ li = xbmcgui.ListItem('Revolt Party - Live Stream', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://whitenoisehq.co.uk/v3/RevoltBot.m3u'
+ li = xbmcgui.ListItem('Revolt Party - AutoDJ', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://whitenoisehq.co.uk/v3/PLUR.pls'
+ li = xbmcgui.ListItem('Peace Love Unity Radio', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ xbmcplugin.endOfDirectory(addon_handle)
+
+elif mode[0] == 'folder1':
+ foldername = args['foldername'][0]
+ url = 'http://lnd1.house-mixes.com/m/klass-a/3c081bc2-4404-45f7-8d2a-88f92441d77b.mp3'
+ li = xbmcgui.ListItem('DJ Klass-A - PLURadio 1st November 2014 (Hard House)', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://lnd1.house-mixes.com/m/klass-a/0db80df5-8568-4e87-9d44-20d4ec6ec77b.mp3'
+ li = xbmcgui.ListItem('DJ Klass-A - PLURadio 25th October 2014 (UK Hardcore)', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://lnd1.house-mixes.com/m/klass-a/be09b7e3-989c-4a0d-a7a8-d494096091d7.mp3'
+ li = xbmcgui.ListItem('DJ Klass-A with MC Tom Thumb - PLURadio 18th October 2014 (UK Hardcore)', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://lnd1.house-mixes.com/m/klass-a/f892c47f-e6d9-4e5a-800e-60c88854568a.mp3'
+ li = xbmcgui.ListItem('DJ Klass-A - Revolt Party 19th October 2014 (UK Hardcore)', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://lnd1.house-mixes.com/m/klass-a/11f7b6a5-1c3a-4904-b7ae-77a6a2d91a89.mp3'
+ li = xbmcgui.ListItem('DJ Klass-A - Revolt Party 12th October 2014 *(Gabba)', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ xbmcplugin.endOfDirectory(addon_handle)
+
+elif mode[0] == 'folder2':
+ foldername = args['foldername'][0]
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=29'
+ li = xbmcgui.ListItem('Lady Brock b2b Double T @ White Noise HQ Vs Ballistic Beatz', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=27'
+ li = xbmcgui.ListItem('Klass A b2b Program @ White Noise HQ Vs Ballistic Beatz', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=28'
+ li = xbmcgui.ListItem('Kurt @ White Noise HQ Vs Ballistic Beatz', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=24'
+ li = xbmcgui.ListItem('Darwin @ White Noise HQ Vs Ballistic Beatz', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=26'
+ li = xbmcgui.ListItem('JB-C b2b Clodhopper @ White Noise HQ Vs Ballistic Beatz', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=30'
+ li = xbmcgui.ListItem('Lil Miss Detonate b2b Bernzey @ White Noise HQ Vs Ballistic Beatz', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=25'
+ li = xbmcgui.ListItem('Hoodzie b2b Vapour @ White Noise HQ Vs Ballistic Beatz', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=32'
+ li = xbmcgui.ListItem('Mizel @ White Noise HQ Vs Ballistic Beatz', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=31'
+ li = xbmcgui.ListItem('Hoodzie b2b Distortion @ White Noise HQ Vs Ballistic Beatz', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ xbmcplugin.endOfDirectory(addon_handle)
+
+elif mode[0] == 'folder3':
+ foldername = args['foldername'][0]
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=36'
+ li = xbmcgui.ListItem('Kevin Energy @ White Noise HQ - The Freeform Special', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=39'
+ li = xbmcgui.ListItem('Nick235 @ White Noise HQ - The Freeform Special', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=38'
+ li = xbmcgui.ListItem('Lady Brock @ White Noise HQ - The Freeform Special', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=33'
+ li = xbmcgui.ListItem('Solution @ White Noise HQ - The Freeform Special', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=35'
+ li = xbmcgui.ListItem('Greg Peaks & Pinnacle @ White Noise HQ - The Freeform Special', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=37'
+ li = xbmcgui.ListItem('Klass-A & Program @ White Noise HQ - The Freeform Special', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/?dl_id=34'
+ li = xbmcgui.ListItem('Double T @ White Noise HQ - The Freeform Special', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ xbmcplugin.endOfDirectory(addon_handle)
+
+elif mode[0] == 'folder4':
+ foldername = args['foldername'][0]
+ url = 'http://lnd1.house-mixes.com/m/lady%20brock/dab511e3-c2ae-4418-b658-cb71ec528032.mp3'
+ li = xbmcgui.ListItem('Lady Brock - House Series - 001 Tech & Progressive', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://lnd1.house-mixes.com/m/lady%20brock/54bac03a-a1dc-4e9f-8d37-95581a1c9792.mp3'
+ li = xbmcgui.ListItem('Lady Brock - House Series - 002 Electro', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ xbmcplugin.endOfDirectory(addon_handle)
+
+elif mode[0] == 'folder5':
+ foldername = args['foldername'][0]
+ url = 'http://www.whitenoisehq.co.uk/v3/wnhq001.m3u'
+ li = xbmcgui.ListItem('[WNHQ001] Lady Brock Vs Sc@r - Muppet (UK Hardcore)', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/wnhq002.m3u'
+ li = xbmcgui.ListItem('[WNHQ002] Double T - Lil Fluffy Cloudz (Drum n Bass)', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/wnhq003.m3u'
+ li = xbmcgui.ListItem('[WNHQ003] Force & Styles - Field Of Dreams (Firestrike Drumstep Remix) (Drumstep)', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ xbmcplugin.endOfDirectory(addon_handle)
+
+elif mode[0] == 'folder6':
+ foldername = args['foldername'][0]
+ url = 'http://www.whitenoisehq.co.uk/v3/YouTube2.m3u'
+ li = xbmcgui.ListItem('[WNHQ Live] DJ Klass-A : Miss-Judged : Double T (UK Hardcore)', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ url = 'http://www.whitenoisehq.co.uk/v3/YouTube.m3u'
+ li = xbmcgui.ListItem('[WNHQ Live] DJ Klass-A - Hard House Power Hour (Hard House)', iconImage='DefaultVideo.png')
+ xbmcplugin.addDirectoryItem(handle=addon_handle, url=url, listitem=li)
+ xbmcplugin.endOfDirectory(addon_handle)
\ No newline at end of file
diff --git a/plugin.video.wnhq/dummy.xml b/plugin.video.wnhq/dummy.xml
new file mode 100644
index 0000000..de51110
--- /dev/null
+++ b/plugin.video.wnhq/dummy.xml
@@ -0,0 +1,22 @@
+
+
+
+
+
+
+
+
+
+
+
+
+ Dummyhttp://www.nada.com" dest="8">
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/plugin.video.wnhq/fanart.jpg b/plugin.video.wnhq/fanart.jpg
new file mode 100644
index 0000000..bb56dfa
Binary files /dev/null and b/plugin.video.wnhq/fanart.jpg differ
diff --git a/plugin.video.wnhq/icon.png b/plugin.video.wnhq/icon.png
new file mode 100644
index 0000000..ac1a48a
Binary files /dev/null and b/plugin.video.wnhq/icon.png differ
diff --git a/plugin.video.wnhq/resources/settings.xml b/plugin.video.wnhq/resources/settings.xml
new file mode 100644
index 0000000..e747e0b
--- /dev/null
+++ b/plugin.video.wnhq/resources/settings.xml
@@ -0,0 +1,4 @@
+
+
+
+
\ No newline at end of file
diff --git a/zips/addons.xml b/zips/addons.xml
index 100f11f..756a7c9 100644
--- a/zips/addons.xml
+++ b/zips/addons.xml
@@ -1,5 +1,47 @@
+
+
+
+
+
+ audio
+
+
+ Kiss FM UK - Live Stream
+ KissFMUK.com
+
+ English
+ all
+
+
+ http://www.kissfmuk.com
+ oli@whitenoisehq.co.uk
+
+
+
+
+
+
+
+
+
+ audio
+
+
+ Rinse.FM - Live Stream
+ RinseFM live from Brick Lane, London
+
+ English
+ all
+
+
+ http://rinse.fm
+ oli@whitenoisehq.co.uk
+
+
+
+
@@ -21,6 +63,46 @@
+
+
+
+
+
+ video
+
+
+ London Live - Live Stream
+ LondonLive.co.uk
+
+ English
+ all
+
+ http://forum.xbmc.org/showthread.php?tid=190935
+ http://www.londonlive.co.uk
+ oli@whitenoisehq.co.uk
+
+
+
+
+
+
+
+
+
+ video
+
+
+ White Noise HQ live on your TV!
+ en
+ Keep up to date with the latest from everyone at White Noise HQ!
+ all
+
+
+
diff --git a/zips/addons.xml.md5 b/zips/addons.xml.md5
index 0193eea..f258e1b 100644
--- a/zips/addons.xml.md5
+++ b/zips/addons.xml.md5
@@ -1 +1 @@
-e3d70faa82043b4470f2617931f13613
\ No newline at end of file
+a7bc395704ae09a3cf72205b65f2acfc
\ No newline at end of file
diff --git a/zips/plugin.audio.kissfm/addon.xml b/zips/plugin.audio.kissfm/addon.xml
new file mode 100644
index 0000000..f68caa0
--- /dev/null
+++ b/zips/plugin.audio.kissfm/addon.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ audio
+
+
+ Kiss FM UK - Live Stream
+ KissFMUK.com
+
+ English
+ all
+
+
+ http://www.kissfmuk.com
+ oli@whitenoisehq.co.uk
+
+
+
\ No newline at end of file
diff --git a/zips/plugin.audio.kissfm/fanart.jpg b/zips/plugin.audio.kissfm/fanart.jpg
new file mode 100644
index 0000000..c666bc7
Binary files /dev/null and b/zips/plugin.audio.kissfm/fanart.jpg differ
diff --git a/zips/plugin.audio.kissfm/plugin.audio.kissfm-0.2.zip b/zips/plugin.audio.kissfm/plugin.audio.kissfm-0.2.zip
new file mode 100644
index 0000000..efeefbf
Binary files /dev/null and b/zips/plugin.audio.kissfm/plugin.audio.kissfm-0.2.zip differ
diff --git a/zips/plugin.audio.rinsefm/addon.xml b/zips/plugin.audio.rinsefm/addon.xml
new file mode 100644
index 0000000..fed7cfd
--- /dev/null
+++ b/zips/plugin.audio.rinsefm/addon.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ audio
+
+
+ Rinse.FM - Live Stream
+ RinseFM live from Brick Lane, London
+
+ English
+ all
+
+
+ http://rinse.fm
+ oli@whitenoisehq.co.uk
+
+
+
\ No newline at end of file
diff --git a/zips/plugin.audio.rinsefm/fanart.jpg b/zips/plugin.audio.rinsefm/fanart.jpg
new file mode 100644
index 0000000..849eeee
Binary files /dev/null and b/zips/plugin.audio.rinsefm/fanart.jpg differ
diff --git a/zips/plugin.audio.rinsefm/plugin.audio.rinsefm-0.2.zip b/zips/plugin.audio.rinsefm/plugin.audio.rinsefm-0.2.zip
new file mode 100644
index 0000000..09c8641
Binary files /dev/null and b/zips/plugin.audio.rinsefm/plugin.audio.rinsefm-0.2.zip differ
diff --git a/zips/plugin.video.londonlive/addon.xml b/zips/plugin.video.londonlive/addon.xml
new file mode 100644
index 0000000..7e26655
--- /dev/null
+++ b/zips/plugin.video.londonlive/addon.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+ video
+
+
+ London Live - Live Stream
+ LondonLive.co.uk
+
+ English
+ all
+
+ http://forum.xbmc.org/showthread.php?tid=190935
+ http://www.londonlive.co.uk
+ oli@whitenoisehq.co.uk
+
+
+
\ No newline at end of file
diff --git a/zips/plugin.video.londonlive/fanart.jpg b/zips/plugin.video.londonlive/fanart.jpg
new file mode 100644
index 0000000..849eeee
Binary files /dev/null and b/zips/plugin.video.londonlive/fanart.jpg differ
diff --git a/zips/plugin.video.londonlive/plugin.video.londonlive-0.4.zip b/zips/plugin.video.londonlive/plugin.video.londonlive-0.4.zip
new file mode 100644
index 0000000..a9d4077
Binary files /dev/null and b/zips/plugin.video.londonlive/plugin.video.londonlive-0.4.zip differ
diff --git a/zips/plugin.video.wnhq/addon.xml b/zips/plugin.video.wnhq/addon.xml
new file mode 100644
index 0000000..3be34d8
--- /dev/null
+++ b/zips/plugin.video.wnhq/addon.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+ video
+
+
+ White Noise HQ live on your TV!
+ en
+ Keep up to date with the latest from everyone at White Noise HQ!
+ all
+
+
diff --git a/zips/plugin.video.wnhq/fanart.jpg b/zips/plugin.video.wnhq/fanart.jpg
new file mode 100644
index 0000000..bb56dfa
Binary files /dev/null and b/zips/plugin.video.wnhq/fanart.jpg differ
diff --git a/zips/plugin.video.wnhq/icon.png b/zips/plugin.video.wnhq/icon.png
new file mode 100644
index 0000000..ac1a48a
Binary files /dev/null and b/zips/plugin.video.wnhq/icon.png differ
diff --git a/zips/plugin.video.wnhq/plugin.video.wnhq-0.3.zip b/zips/plugin.video.wnhq/plugin.video.wnhq-0.3.zip
new file mode 100644
index 0000000..5c9e92a
Binary files /dev/null and b/zips/plugin.video.wnhq/plugin.video.wnhq-0.3.zip differ