~ubuntu-branches/ubuntu/precise/coherence/precise

« back to all changes in this revision

Viewing changes to coherence/backends/miroguide_storage.py

  • Committer: Bazaar Package Importer
  • Author(s): Charlie Smotherman
  • Date: 2010-01-02 10:57:15 UTC
  • mfrom: (1.1.7 upstream) (3.2.8 sid)
  • Revision ID: james.westby@ubuntu.com-20100102105715-sghzl2nw4lr5b1ob
Tags: 0.6.6.2-1
*  New  upstream release, summary of changes:
    - adding all necessary files to MANIFEST.in, to compensate for the
      gone 'auto-include-all-files-under-version-control' setuptools
      feature.
    - rearranging genre and genres attribute in DIDLLite - thx Caleb  
    - fix face_path typo, fixes #275.   

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Licensed under the MIT license
 
2
# http://opensource.org/licenses/mit-license.php
 
3
 
 
4
# Coherence backend presenting the content of the MIRO Guide catalog for on-line videos
 
5
#
 
6
# The APi is described on page:
 
7
# https://develop.participatoryculture.org/trac/democracy/wiki/MiroGuideApi
 
8
 
 
9
# Copyright 2009, Jean-Michel Sizun
 
10
# Copyright 2009 Frank Scholz <coherence@beebits.net>
 
11
 
 
12
import urllib
 
13
 
 
14
from coherence.upnp.core import utils
 
15
from coherence.upnp.core import DIDLLite
 
16
from coherence.backend import BackendStore, BackendItem, Container, LazyContainer, \
 
17
     AbstractBackendStore
 
18
 
 
19
from coherence.backends.youtube_storage import TestVideoProxy
 
20
 
 
21
class VideoItem(BackendItem):
 
22
 
 
23
    def __init__(self, name, description, url, thumbnail_url, store):
 
24
        self.name = name
 
25
        self.duration = None
 
26
        self.size = None
 
27
        self.mimetype = "video"
 
28
        self.url = None
 
29
        self.video_url = url
 
30
        self.thumbnail_url = thumbnail_url
 
31
        self.description = description
 
32
        self.date = None
 
33
        self.item = None
 
34
 
 
35
        self.location = TestVideoProxy(self.video_url, hash(self.video_url),
 
36
                                   store.proxy_mode,
 
37
                                   store.cache_directory, store.cache_maxsize,store.buffer_size
 
38
                                   )
 
39
 
 
40
    def get_item(self):
 
41
        if self.item == None:
 
42
            upnp_id = self.get_id()
 
43
            upnp_parent_id = self.parent.get_id()
 
44
            self.item = DIDLLite.VideoItem(upnp_id, upnp_parent_id, self.name)
 
45
            self.item.description = self.description
 
46
            self.item.date = self.date
 
47
            if self.thumbnail_url is not None:
 
48
                self.item.icon = self.thumbnail_url
 
49
                self.item.albumArtURI = self.thumbnail_url
 
50
            res = DIDLLite.Resource(self.url, 'http-get:*:%s:*' % self.mimetype)
 
51
            res.duration = self.duration
 
52
            res.size = self.size
 
53
            self.item.res.append(res)
 
54
        return self.item
 
55
 
 
56
    def get_path(self):
 
57
        return self.url
 
58
 
 
59
    def get_id(self):
 
60
        return self.storage_id
 
61
 
 
62
 
 
63
class MiroGuideStore(AbstractBackendStore):
 
64
 
 
65
    logCategory = 'miroguide_store'
 
66
 
 
67
    implements = ['MediaServer']
 
68
 
 
69
    description = ('Miro Guide', 'connects to the MIRO Guide service and exposes the podcasts catalogued by the service. ', None)
 
70
 
 
71
    options = [{'option':'name', 'text':'Server Name:', 'type':'string','default':'my media','help': 'the name under this MediaServer shall show up with on other UPnP clients'},
 
72
       {'option':'version','text':'UPnP Version:','type':'int','default':2,'enum': (2,1),'help': 'the highest UPnP version this MediaServer shall support','level':'advance'},
 
73
       {'option':'uuid','text':'UUID Identifier:','type':'string','help':'the unique (UPnP) identifier for this MediaServer, usually automatically set','level':'advance'},    
 
74
       {'option':'language','text':'Language:','type':'string', 'default':'English'},
 
75
       {'option':'refresh','text':'Refresh period','type':'string'},
 
76
       {'option':'proxy_mode','text':'Proxy mode:','type':'string', 'enum': ('redirect','proxy','cache','buffered')},
 
77
       {'option':'buffer_size','text':'Buffering size:','type':'int'},
 
78
       {'option':'cache_directory','text':'Cache directory:','type':'dir', 'group':'Cache'},
 
79
       {'option':'cache_maxsize','text':'Cache max size:','type':'int', 'group':'Cache'},
 
80
    ]
 
81
 
 
82
    def __init__(self, server, **kwargs):
 
83
        AbstractBackendStore.__init__(self, server, **kwargs)
 
84
 
 
85
        self.name = kwargs.get('name','MiroGuide')
 
86
 
 
87
        self.language = kwargs.get('language','English')
 
88
 
 
89
        self.refresh = int(kwargs.get('refresh',60))*60
 
90
 
 
91
        self.proxy_mode = kwargs.get('proxy_mode', 'redirect')
 
92
        self.cache_directory = kwargs.get('cache_directory', '/tmp/coherence-cache')
 
93
        try:
 
94
            if self.proxy_mode != 'redirect':
 
95
                os.mkdir(self.cache_directory)
 
96
        except:
 
97
            pass
 
98
        self.cache_maxsize = kwargs.get('cache_maxsize', 100000000)
 
99
        self.buffer_size = kwargs.get('buffer_size', 750000)
 
100
 
 
101
        rootItem = Container(None, self.name)
 
102
        self.set_root_item(rootItem)
 
103
 
 
104
        categoriesItem = Container(rootItem, "All by Categories")
 
105
        rootItem.add_child(categoriesItem)
 
106
        languagesItem = Container(rootItem, "All by Languages")
 
107
        rootItem.add_child(languagesItem)
 
108
 
 
109
        self.appendLanguage("Recent Videos", self.language, rootItem, sort='-age', count=15)
 
110
        self.appendLanguage("Top Rated", self.language, rootItem, sort='rating', count=15)
 
111
        self.appendLanguage("Most Popular", self.language, rootItem, sort='-popular', count=15)
 
112
 
 
113
 
 
114
        def gotError(error):
 
115
            print "ERROR: %s" % error
 
116
 
 
117
        def gotCategories(result):
 
118
            if result is None:
 
119
                print "Unable to retrieve list of categories"
 
120
                return
 
121
            data,header = result
 
122
            categories = eval(data) # FIXME add some checks to avoid code injection
 
123
            for category in categories:
 
124
                name = category['name'].encode('ascii', 'strict')
 
125
                category_url = category['url'].encode('ascii', 'strict')
 
126
                self.appendCategory(name, name, categoriesItem)
 
127
 
 
128
        categories_url = "https://www.miroguide.com/api/list_categories"
 
129
        d1 = utils.getPage(categories_url)
 
130
        d1.addCallbacks(gotCategories, gotError)
 
131
 
 
132
        def gotLanguages(result):
 
133
            if result is None:
 
134
                print "Unable to retrieve list of languages"
 
135
                return
 
136
            data,header = result
 
137
            languages = eval(data) # FIXME add some checks to avoid code injection
 
138
            for language in languages:
 
139
                name = language['name'].encode('ascii', 'strict')
 
140
                language_url = language['url'].encode('ascii', 'strict')
 
141
                self.appendLanguage(name, name, languagesItem)
 
142
 
 
143
        languages_url = "https://www.miroguide.com/api/list_languages"
 
144
        d2 = utils.getPage(languages_url)
 
145
        d2.addCallbacks(gotLanguages, gotError)
 
146
 
 
147
        self.init_completed()
 
148
 
 
149
 
 
150
    def __repr__(self):
 
151
        return self.__class__.__name__
 
152
 
 
153
    def appendCategory( self, name, category_id, parent):
 
154
        item = LazyContainer(parent, name, category_id, self.refresh, self.retrieveChannels, filter="category", filter_value=category_id, per_page=100)
 
155
        parent.add_child(item, external_id=category_id)
 
156
 
 
157
    def appendLanguage( self, name, language_id, parent, sort='name', count=0):
 
158
        item = LazyContainer(parent, name, language_id, self.refresh, self.retrieveChannels, filter="language", filter_value=language_id, per_page=100, sort=sort, count=count)
 
159
        parent.add_child(item, external_id=language_id)
 
160
 
 
161
    def appendChannel(self, name, channel_id, parent):
 
162
        item = LazyContainer(parent, name, channel_id, self.refresh, self.retrieveChannelItems, channel_id=channel_id)
 
163
        parent.add_child(item, external_id=channel_id)
 
164
 
 
165
 
 
166
    def upnp_init(self):
 
167
        self.current_connection_id = None
 
168
 
 
169
        if self.server:
 
170
            self.server.connection_manager_server.set_variable(
 
171
               0, 'SourceProtocolInfo',
 
172
               ['http-get:*:%s:*' % 'video/'], #FIXME put list of all possible video mimetypes
 
173
               default=True)
 
174
 
 
175
        self.wmc_mapping = {'15': self.get_root_id()}
 
176
 
 
177
 
 
178
    def retrieveChannels (self, parent, filter, filter_value, per_page=100, offset=0, count=0, sort='name'):
 
179
        filter_value = urllib.quote(filter_value.encode("utf-8"))
 
180
 
 
181
        limit = count
 
182
        if (count == 0):
 
183
            limit = per_page
 
184
        uri = "https://www.miroguide.com/api/get_channels?limit=%d&offset=%d&filter=%s&filter_value=%s&sort=%s" % (limit, offset, filter, filter_value, sort)
 
185
        #print uri
 
186
        d = utils.getPage(uri)
 
187
 
 
188
        def gotChannels(result):
 
189
           if result is None:
 
190
               print "Unable to retrieve channel for category %s" % category_id
 
191
               return
 
192
           data,header = result
 
193
           channels = eval(data)
 
194
           for channel in channels:
 
195
               publisher = channel['publisher']
 
196
               description = channel['description']
 
197
               url = channel['url']
 
198
               hi_def = channel['hi_def']
 
199
               thumbnail_url = channel['thumbnail_url']
 
200
               postal_code = channel['postal_code']
 
201
               id = channel['id']
 
202
               website_url = channel['website_url']
 
203
               name = channel['name']
 
204
               self.appendChannel(name, id, parent)
 
205
           if ((count == 0) and (len(channels) >= per_page)):
 
206
               #print "reached page limit (%d)" % len(channels)
 
207
               parent.childrenRetrievingNeeded = True
 
208
 
 
209
        def gotError(error):
 
210
            print "ERROR: %s" % error
 
211
 
 
212
        d.addCallbacks(gotChannels, gotError)
 
213
        return d
 
214
 
 
215
 
 
216
    def retrieveChannelItems (self, parent, channel_id):
 
217
        uri = "https://www.miroguide.com/api/get_channel?id=%s" % channel_id
 
218
        d = utils.getPage(uri)
 
219
 
 
220
        def gotItems(result):
 
221
           if result is None:
 
222
               print "Unable to retrieve items for channel %s" % channel_id
 
223
               return
 
224
           data,header = result
 
225
           channel = eval(data)
 
226
           items = []
 
227
           if (channel.has_key('item')):
 
228
               items = channel['item']
 
229
           for item in items:
 
230
               #print "item:",item
 
231
               url = item['url']
 
232
               description = item['description']
 
233
               #print "description:", description              
 
234
               name = item['name']
 
235
               thumbnail_url = None
 
236
               if (channel.has_key('thumbnail_url')):
 
237
                   #print "Thumbnail:", channel['thumbnail_url']
 
238
                   thumbnail_url = channel['thumbnail_url']
 
239
               #size = size['size']
 
240
               item = VideoItem(name, description, url, thumbnail_url, self)
 
241
               item.parent = parent
 
242
               parent.add_child(item, external_id=url)
 
243
 
 
244
        def gotError(error):
 
245
            print "ERROR: %s" % error
 
246
 
 
247
        d.addCallbacks(gotItems, gotError)
 
248
        return d