|
6 | 6 | import base64
|
7 | 7 | import mimetypes
|
8 | 8 | import os
|
| 9 | +import posixpath |
9 | 10 | import xml.etree.cElementTree as ET
|
10 | 11 | from math import ceil
|
11 | 12 | from xml.dom import minidom
|
12 | 13 |
|
| 14 | +EXTENSION_TO_MIME_TYPE_FALLBACK = { |
| 15 | + '.aac' : 'audio/aac', |
| 16 | + '.flac' : 'audio/flac', |
| 17 | + '.mp3' : 'audio/mpeg', |
| 18 | + '.ogg' : 'audio/ogg', |
| 19 | +} |
| 20 | + |
13 | 21 | def strip_accents(s):
|
14 | 22 | return ''.join(c for c in unicodedata.normalize('NFD', s) if unicodedata.category(c) != 'Mn')
|
15 | 23 |
|
@@ -140,7 +148,7 @@ def map_song(song):
|
140 | 148 | "genre": song["genre"],
|
141 | 149 | "coverArt": album_beetid_to_subid(str(song["album_id"])) or "",
|
142 | 150 | "size": os.path.getsize(path),
|
143 |
| - "contentType": mimetypes.guess_type(path)[0], |
| 151 | + "contentType": path_to_content_type(path), |
144 | 152 | "suffix": song["format"].lower(),
|
145 | 153 | "duration": ceil(song["length"]),
|
146 | 154 | "bitRate": ceil(song["bitrate"]/1000),
|
@@ -168,7 +176,7 @@ def map_song_xml(xml, song):
|
168 | 176 | xml.set("genre", song["genre"])
|
169 | 177 | xml.set("coverArt", album_beetid_to_subid(str(song["album_id"])) or "")
|
170 | 178 | xml.set("size", str(os.path.getsize(path)))
|
171 |
| - xml.set("contentType", mimetypes.guess_type(path)[0]) |
| 179 | + xml.set("contentType", path_to_content_type(path)) |
172 | 180 | xml.set("suffix", song["format"].lower())
|
173 | 181 | xml.set("duration", str(ceil(song["length"])))
|
174 | 182 | xml.set("bitRate", str(ceil(song["bitrate"]/1000)))
|
@@ -217,6 +225,21 @@ def song_beetid_to_subid(id):
|
217 | 225 | def song_subid_to_beetid(id):
|
218 | 226 | return id[len(SONG_ID_PREFIX):]
|
219 | 227 |
|
| 228 | +def path_to_content_type(path): |
| 229 | + result = mimetypes.guess_type(path)[0] |
| 230 | + |
| 231 | + if result: |
| 232 | + return result |
| 233 | + |
| 234 | + # our mimetype database didn't have information about this file extension. |
| 235 | + base, ext = posixpath.splitext(path) |
| 236 | + result = EXTENSION_TO_MIME_TYPE_FALLBACK.get(ext) |
| 237 | + |
| 238 | + if result: |
| 239 | + return result |
| 240 | + |
| 241 | + raise RuntimeError(f"Unable to determine content type for {path}") |
| 242 | + |
220 | 243 | def handleSizeAndOffset(collection, size, offset):
|
221 | 244 | if size is not None:
|
222 | 245 | if offset is not None:
|
|
0 commit comments