Merge lp:~ahayzen/cappella/cappella10_play_stream_2 into lp:cappella

Proposed by Andrew Hayzen
Status: Merged
Approved by: Andrew Hayzen
Approved revision: 99
Merged at revision: 99
Proposed branch: lp:~ahayzen/cappella/cappella10_play_stream_2
Merge into: lp:cappella
Diff against target: 314 lines (+145/-28)
8 files modified
cappella/data/default/format.js (+2/-0)
cappella/data/glade/open_file_dialogs.ui (+1/-1)
cappella/gui/widget/play_queue.py (+3/-3)
cappella/library/podcast_web.py (+1/-13)
cappella/library/stream.py (+90/-6)
cappella/management/media.py (+3/-3)
cappella/tool/media.py (+8/-2)
cappella/tool/parser.py (+37/-0)
To merge this branch: bzr merge lp:~ahayzen/cappella/cappella10_play_stream_2
Reviewer Review Type Date Requested Status
Andrew Hayzen Approve
Review via email: mp+161356@code.launchpad.net

Description of the change

* Added basic support for .asx and .m3u formats

To post a comment you must log in.
Revision history for this message
Andrew Hayzen (ahayzen) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'cappella/data/default/format.js'
--- cappella/data/default/format.js 2013-04-28 18:40:19 +0000
+++ cappella/data/default/format.js 2013-04-29 03:13:27 +0000
@@ -1,8 +1,10 @@
1{1{
2 "aac": {"audio": true, "video": false},2 "aac": {"audio": true, "video": false},
3 "asx": {"audio": true, "video": false},
3 "avi": {"audio": false, "video": true},4 "avi": {"audio": false, "video": true},
4 "flac": {"audio": true, "video": false},5 "flac": {"audio": true, "video": false},
5 "flv": {"audio": false, "video": true},6 "flv": {"audio": false, "video": true},
7 "m3u": {"audio": true, "video": false},
6 "m4a": {"audio": true, "video": false},8 "m4a": {"audio": true, "video": false},
7 "mp3": {"audio": true, "video": false},9 "mp3": {"audio": true, "video": false},
8 "mp4": {"audio": false, "video": true},10 "mp4": {"audio": false, "video": true},
911
=== modified file 'cappella/data/glade/open_file_dialogs.ui'
--- cappella/data/glade/open_file_dialogs.ui 2013-04-28 19:00:58 +0000
+++ cappella/data/glade/open_file_dialogs.ui 2013-04-29 03:13:27 +0000
@@ -188,7 +188,7 @@
188 <property name="skip_taskbar_hint">True</property>188 <property name="skip_taskbar_hint">True</property>
189 <property name="buttons">ok-cancel</property>189 <property name="buttons">ok-cancel</property>
190 <property name="text" translatable="yes">Please enter the address of the stream</property>190 <property name="text" translatable="yes">Please enter the address of the stream</property>
191 <property name="secondary_text" translatable="yes">This should either be a .pls file or a direct stream</property>191 <property name="secondary_text" translatable="yes">This should either be a .asx, .m3u, .pls or a direct stream</property>
192 <child internal-child="vbox">192 <child internal-child="vbox">
193 <object class="GtkBox" id="messagedialog-vbox">193 <object class="GtkBox" id="messagedialog-vbox">
194 <property name="can_focus">False</property>194 <property name="can_focus">False</property>
195195
=== modified file 'cappella/gui/widget/play_queue.py'
--- cappella/gui/widget/play_queue.py 2013-04-28 18:40:19 +0000
+++ cappella/gui/widget/play_queue.py 2013-04-29 03:13:27 +0000
@@ -22,7 +22,7 @@
22from ...config.cappella import settings22from ...config.cappella import settings
23from ...signalhandler import signal23from ...signalhandler import signal
24from ...tool import skipx, thread_safe24from ...tool import skipx, thread_safe
25from ...tool.media import process_pls25from ...tool.media import is_playlist, process_playlist
2626
2727
28class PlayQueue():28class PlayQueue():
@@ -129,8 +129,8 @@
129129
130 @thread_safe130 @thread_safe
131 def on_playqueue_add_int(self, uri, library, view):131 def on_playqueue_add_int(self, uri, library, view):
132 if uri.endswith(".pls"):132 if is_playlist(uri):
133 uri = process_pls(uri)133 uri = process_playlist(uri)
134134
135 if type(uri) is list:135 if type(uri) is list:
136 # Add uris to play queue136 # Add uris to play queue
137137
=== modified file 'cappella/library/podcast_web.py'
--- cappella/library/podcast_web.py 2013-04-02 22:48:35 +0000
+++ cappella/library/podcast_web.py 2013-04-29 03:13:27 +0000
@@ -20,7 +20,6 @@
2020
21from gi.repository import GdkPixbuf21from gi.repository import GdkPixbuf
22from html.parser import HTMLParser22from html.parser import HTMLParser
23from xml.dom import minidom
24from xml.etree import ElementTree23from xml.etree import ElementTree
25from urllib.request import urlopen24from urllib.request import urlopen
2625
@@ -28,21 +27,10 @@
28from ..management.library import (LibraryType, LibraryPurpose, LibraryMode,27from ..management.library import (LibraryType, LibraryPurpose, LibraryMode,
29 LibraryFileType)28 LibraryFileType)
30from ..tool.metatag import MetaParser29from ..tool.metatag import MetaParser
30from ..tool.parser import FeedToXml
3131
3232
33#-------------------------------------- Helper classes for RSS->Dict Conversion33#-------------------------------------- Helper classes for RSS->Dict Conversion
34class FeedToXml():
35 """ Read XML and parse from URL """
36 def __init__(self, url):
37 self.stream = urlopen(url)
38
39 self.obj = minidom.parse(self.stream)
40
41 *proc, dom = self.obj.childNodes
42
43 self.xml = dom.toprettyxml()
44
45
46class XmlToInfo():34class XmlToInfo():
47 def __init__(self, xml_stream, uri):35 def __init__(self, xml_stream, uri):
48 self.root = ElementTree.fromstring(xml_stream)36 self.root = ElementTree.fromstring(xml_stream)
4937
=== modified file 'cappella/library/stream.py'
--- cappella/library/stream.py 2013-04-28 18:49:59 +0000
+++ cappella/library/stream.py 2013-04-29 03:13:27 +0000
@@ -20,7 +20,10 @@
2020
21from ..management.library import LibraryType, LibraryPurpose, LibraryMode21from ..management.library import LibraryType, LibraryPurpose, LibraryMode
22from ..signalhandler import signal22from ..signalhandler import signal
23from ..tool.media import is_playlist
24from ..tool.parser import FeedToXml
23from urllib.request import urlopen25from urllib.request import urlopen
26from xml.etree import ElementTree
2427
2528
26class StreamLibrary():29class StreamLibrary():
@@ -53,9 +56,10 @@
53 def copy(self, uri):56 def copy(self, uri):
54 """ Get a stream for the uri in the library (name) specified """57 """ Get a stream for the uri in the library (name) specified """
5558
56 if (not uri.startswith("http://") and59 if (not uri.startswith("http://") and not uri.startswith("mms://") and
57 (not uri.startswith("file://") and not ".pls" not in uri)):60 (not uri.startswith("file://") and is_playlist(uri))):
58 raise ValueError("URI should start with http:// or ends with .pls")61 raise ValueError("URI should start with http:// or contains .pls, "
62 ".asx, .m3u")
5963
60 f = urlopen(uri)64 f = urlopen(uri)
6165
@@ -86,9 +90,10 @@
86 def get(self, uri):90 def get(self, uri):
87 """ Get the info about a uri in the library (name) specified """91 """ Get the info about a uri in the library (name) specified """
8892
89 if (not uri.startswith("http://") and93 if (not uri.startswith("http://") and not uri.startswith("mms://") and
90 (not uri.startswith("file://") and ".pls" not in uri)):94 (not uri.startswith("file://") and is_playlist(uri))):
91 raise ValueError("URI should start with http:// or ends with .pls")95 raise ValueError("URI should start with http:// or contains .pls, "
96 ".asx, .m3u")
9297
93 files = {}98 files = {}
9499
@@ -134,6 +139,85 @@
134 return {"title": uri, "uri": uri}139 return {"title": uri, "uri": uri}
135 else:140 else:
136 return output141 return output
142 elif ".asx" in uri:
143 # Read .asx file
144 if uri.startswith("http://"):
145 stream = urlopen(uri)
146 else:
147 stream = open(uri[7:])
148
149 xml_stream = FeedToXml(data=stream).xml
150
151 root = ElementTree.fromstring(xml_stream)
152
153 try:
154 title = root.find("TITLE").text
155 except AttributeError:
156 title = None
157
158 try:
159 artist = root.find("AUTHOR").text
160 except AttributeError:
161 artist = None
162
163 output = []
164
165 for item in root.findall("Entry"):
166 info = {"title": title, "artist": artist}
167
168 try:
169 ref = item.find("ref")
170
171 try:
172 info["uri"] = ref.attrib["href"]
173 except KeyError:
174 continue
175 except AttributeError:
176 continue
177
178 output.append(info)
179
180 self.cache[info["uri"]] = {"raw_uri": uri, "title": title,
181 "artist": artist}
182
183 if len(output) > 0:
184 return output
185 elif ".m3u" in uri:
186 # Read .pls file
187 if uri.startswith("http://"):
188 data = urlopen(uri).read().decode("utf")
189 else:
190 data = open(uri[7:]).read()
191
192 # Read data from the .pls file
193 title, artist = None, None
194 output = []
195
196 for line in data.split("\n"):
197 if line.startswith("#EXTINF"):
198 value = line.split(",")[1].split("-")
199
200 if len(value) == 2:
201 artist, title = value
202 else:
203 title = value[0]
204 elif line.startswith("#"):
205 continue
206 elif line.strip() == "":
207 continue
208 else:
209 info = {"title": title or uri, "artist": artist,
210 "uri": line}
211
212 output.append(info)
213 self.cache[line] = {"title": title or uri,
214 "artist": artist,
215 "raw_uri": uri}
216
217 title, artist = None, None
218
219 if len(output) > 0:
220 return output
137221
138 if uri in self.cache:222 if uri in self.cache:
139 info = self.cache[uri]223 info = self.cache[uri]
140224
=== modified file 'cappella/management/media.py'
--- cappella/management/media.py 2013-04-28 18:56:14 +0000
+++ cappella/management/media.py 2013-04-29 03:13:27 +0000
@@ -21,7 +21,7 @@
21from ..config.cappella import settings21from ..config.cappella import settings
22from ..signalhandler import signal22from ..signalhandler import signal
23from ..tool import skipx23from ..tool import skipx
24from ..tool.media import process_pls24from ..tool.media import is_playlist, process_playlist
2525
2626
27class Management():27class Management():
@@ -273,8 +273,8 @@
273 signal.emit("_musicengine_stop_") # Stop playing items273 signal.emit("_musicengine_stop_") # Stop playing items
274274
275 # Check is playable file (eg get uri from pls)275 # Check is playable file (eg get uri from pls)
276 if ".pls" in uri:276 if is_playlist(uri):
277 uri = process_pls(uri)277 uri = process_playlist(uri)
278 library = "stream_library"278 library = "stream_library"
279279
280 if type(uri) is list:280 if type(uri) is list:
281281
=== modified file 'cappella/tool/media.py'
--- cappella/tool/media.py 2013-04-28 18:49:59 +0000
+++ cappella/tool/media.py 2013-04-29 03:13:27 +0000
@@ -73,6 +73,12 @@
73 return False73 return False
7474
7575
76def is_playlist(uri):
77 """ Check if the uri is a playlist """
78
79 return ".pls" in uri or ".asx" in uri or ".m3u" in uri
80
81
76def is_video(uri):82def is_video(uri):
77 """ Return True is uri is video """83 """ Return True is uri is video """
7884
@@ -92,12 +98,12 @@
92 return False98 return False
9399
94100
95def process_pls(uri):101def process_playlist(uri):
96 # Get files from .pls102 # Get files from .pls
97 library = "stream_library"103 library = "stream_library"
98 info = signal.get_object("library").get(library, uri)104 info = signal.get_object("library").get(library, uri)
99105
100 if type(info) is list: # Some pls are playlists106 if type(info) is list: # Some multisong
101 return info107 return info
102 else:108 else:
103 uri = info["uri"]109 uri = info["uri"]
104110
=== added file 'cappella/tool/parser.py'
--- cappella/tool/parser.py 1970-01-01 00:00:00 +0000
+++ cappella/tool/parser.py 2013-04-29 03:13:27 +0000
@@ -0,0 +1,37 @@
1#!/usr/bin/env python3
2'''
3 Copyright (C) 2011-2013 Andrew Hayzen and Simon Bull.
4
5 Cappella is a simple media player based on PyGObject for Ubuntu.
6
7 This file is free software: you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published by the
9 Free Software Foundation, either version 3 of the License,
10 or (at your option) any later version.
11
12 This file is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License along with
18 this file. If not, see <http://www.gnu.org/licenses/>.
19'''
20
21from urllib.request import urlopen
22from xml.dom import minidom
23
24
25class FeedToXml():
26 """ Read XML and parse from URL """
27 def __init__(self, url=None, data=None):
28 if url is not None:
29 self.stream = urlopen(url)
30 else:
31 self.stream = data
32
33 self.obj = minidom.parse(self.stream)
34
35 *proc, dom = self.obj.childNodes
36
37 self.xml = dom.toprettyxml()
0\ No newline at end of file38\ No newline at end of file

Subscribers

People subscribed via source and target branches

to all changes: