Support loading of m3u8 playlists.

Unicode is nice, let's support it!
This commit is contained in:
Giorgos Logiotatidis 2015-05-29 20:25:27 +03:00
parent 63fa6849e2
commit 69dc639ab3
3 changed files with 22 additions and 5 deletions

View File

@ -63,7 +63,7 @@ class M3UPlaylistsProvider(backend.PlaylistsProvider):
playlists = {}
encoding = sys.getfilesystemencoding()
for path in glob.glob(os.path.join(self._playlists_dir, b'*.m3u')):
for path in glob.glob(os.path.join(self._playlists_dir, b'*.m3u*')):
relpath = os.path.basename(path)
uri = translator.path_to_playlist_uri(relpath)
name = os.path.splitext(relpath)[0].decode(encoding, 'replace')

View File

@ -74,11 +74,14 @@ def parse_m3u(file_path, media_dir=None):
- Lines starting with # are ignored, except for extended M3U directives.
- Track.name and Track.length are set from extended M3U directives.
- m3u files are latin-1.
- m3u8 files are utf-8
"""
# TODO: uris as bytes
file_encoding = 'utf-8' if file_path.endswith(b'.m3u8') else 'latin1'
tracks = []
try:
with open(file_path) as m3u:
with codecs.open(file_path, 'rb', file_encoding, 'replace') as m3u:
contents = m3u.readlines()
except IOError as error:
logger.warning('Couldn\'t open m3u: %s', locale_decode(error))
@ -87,12 +90,13 @@ def parse_m3u(file_path, media_dir=None):
if not contents:
return tracks
extended = contents[0].decode('latin1').startswith('#EXTM3U')
# Strip newlines left by codecs
contents = [line.strip() for line in contents]
extended = contents[0].startswith('#EXTM3U')
track = Track()
for line in contents:
line = line.strip().decode('latin1')
if line.startswith('#'):
if extended and line.startswith('#EXTINF'):
track = m3u_extinf_to_track(line)

View File

@ -15,12 +15,15 @@ from tests import path_to_data_dir
data_dir = path_to_data_dir('')
song1_path = path_to_data_dir('song1.mp3')
song2_path = path_to_data_dir('song2.mp3')
song3_path = path_to_data_dir('φοο.mp3')
encoded_path = path_to_data_dir('æøå.mp3')
song1_uri = path.path_to_uri(song1_path)
song2_uri = path.path_to_uri(song2_path)
song3_uri = path.path_to_uri(song3_path)
encoded_uri = path.path_to_uri(encoded_path)
song1_track = Track(uri=song1_uri)
song2_track = Track(uri=song2_uri)
song3_track = Track(uri=song3_uri)
encoded_track = Track(uri=encoded_uri)
song1_ext_track = song1_track.copy(name='song1')
song2_ext_track = song2_track.copy(name='song2', length=60000)
@ -115,6 +118,16 @@ class M3UToUriTest(unittest.TestCase):
tracks = self.parse(path_to_data_dir('encoding-ext.m3u'))
self.assertEqual([encoded_ext_track], tracks)
def test_m3u8_file(self):
with tempfile.NamedTemporaryFile(suffix='.m3u8', delete=False) as tmp:
tmp.write(song3_path)
try:
tracks = self.parse(tmp.name)
self.assertEqual([song3_track], tracks)
finally:
if os.path.exists(tmp.name):
os.remove(tmp.name)
class URItoM3UTest(unittest.TestCase):
pass