From ce92747d8996d1362cf764d7b542cd5bd37d345e Mon Sep 17 00:00:00 2001
From: Eliot Berriot <contact@eliotberriot.com>
Date: Sat, 12 May 2018 12:06:14 +0200
Subject: [PATCH] Fix #157: Can now import and play flac files

If you ever need an empty flac file with metadata again:

1. Get a flac file (like https://archive.org/download/NineInchNailsTheSlip24bit96khz/01999999.flac)
2. Tag it with Musicbrainz Picard
3. Truncate it, keeping only tags with `ffmpeg -i in.flac -ss 0 -to 0.001 out.flac`

Thanks @HgO for the trick!
---
 api/funkwhale_api/music/metadata.py |  40 +++++++++++++++++++++++++++-
 api/funkwhale_api/music/utils.py    |   1 +
 api/tests/music/sample.flac         | Bin 0 -> 9793 bytes
 api/tests/music/test_metadata.py    |  17 ++++++++++++
 changes/changelog.d/157.feature     |   1 +
 front/src/audio/formats.js          |   3 ++-
 6 files changed, 60 insertions(+), 2 deletions(-)
 create mode 100644 api/tests/music/sample.flac
 create mode 100644 changes/changelog.d/157.feature

diff --git a/api/funkwhale_api/music/metadata.py b/api/funkwhale_api/music/metadata.py
index a20069783..494256711 100644
--- a/api/funkwhale_api/music/metadata.py
+++ b/api/funkwhale_api/music/metadata.py
@@ -28,6 +28,13 @@ def get_id3_tag(f, k):
         raise TagNotFound(k)
 
 
+def get_flac_tag(f, k):
+    try:
+        return f.get(k)[0]
+    except (KeyError, IndexError):
+        raise TagNotFound(k)
+
+
 def get_mp3_recording_id(f, k):
     try:
         return [
@@ -121,7 +128,38 @@ CONF = {
                 'getter': get_mp3_recording_id,
             },
         }
-    }
+    },
+    'FLAC': {
+        'getter': get_flac_tag,
+        'fields': {
+            'track_number': {
+                'field': 'tracknumber',
+                'to_application': convert_track_number
+            },
+            'title': {
+                'field': 'title'
+            },
+            'artist': {
+                'field': 'artist'
+            },
+            'album': {
+                'field': 'album'
+            },
+            'date': {
+                'field': 'date',
+                'to_application': lambda v: arrow.get(str(v)).date()
+            },
+            'musicbrainz_albumid': {
+                'field': 'musicbrainz_albumid'
+            },
+            'musicbrainz_artistid': {
+                'field': 'musicbrainz_artistid'
+            },
+            'musicbrainz_recordingid': {
+                'field': 'musicbrainz_trackid'
+            },
+        }
+    },
 }
 
 
diff --git a/api/funkwhale_api/music/utils.py b/api/funkwhale_api/music/utils.py
index 49a639303..329a99bed 100644
--- a/api/funkwhale_api/music/utils.py
+++ b/api/funkwhale_api/music/utils.py
@@ -66,6 +66,7 @@ def compute_status(jobs):
 AUDIO_EXTENSIONS_AND_MIMETYPE = [
     ('ogg', 'audio/ogg'),
     ('mp3', 'audio/mpeg'),
+    ('flac', 'audio/flac'),
 ]
 
 EXTENSION_TO_MIMETYPE = {ext: mt for ext, mt in AUDIO_EXTENSIONS_AND_MIMETYPE}
diff --git a/api/tests/music/sample.flac b/api/tests/music/sample.flac
new file mode 100644
index 0000000000000000000000000000000000000000..6eff1c06e43f6f536c2d810d0d059cc6af319f5e
GIT binary patch
literal 9793
zcmYfENpxmlU{F$EP+(wSILW|pQoMk<fPsM_LB^#$b)8pU@^?|`<quac+{VJd>c-2!
zz~GZumS$?MXKJQrXke(#z`y_!3<+{{_Vx?)b#e`|H56rFU~u;L4e$?k4YCa>O3f=#
z2uiKW%P$fFO9Vs)dAfUq*curaSSaLW=J7KyFt|8|xPk?A4NP?nOxZy~p25z}wuYPx
z3=EO3jzM5qkX0a)J$)QQJpKJ_4fGip7y^R)T|%8*gKQmh67v*%^GkD5Qj4q|OG+}6
zON$kP@{5bDksSdtBg8Yr$JN%-(o)CL(h}rcpU5CjXV2ge6z2*uFfatU`nWm<yE^-a
z`h^5V+D3%)FfcHL_=h<9xOfIT2iqD-fr7-*$<@a;BqLS9uQVq|!8yOEAipTFBr`vc
z52hL%K*6?#26hY#48Ebkp3Y7|j-Gx|@s2)Dp}vkmA)dh@o-VdY=4ojuMu};<CWaPi
zx+Y1fM!HEUDTca6MrjsFCKhIf#wm#)7l15>1vl73pzsGf%hu4q9?c4<AHYuVbg?xy
zG)%KJHAvC5v@|u*H8xF4)3r1(N!B$pHcK>0G%!mxGB*RoiDR&*pRJRDfuXaTe}HeG
zJOcv*l4FDYgF<ZmGV@XuJoAz>6#No1bBe_o7#RG6Jl#G09DUGYl$(KpA=o*{Ga$s)
zC$S{Y1{7+Z&aQsJuC^H^B?VUc`pHG9i6xn3smb}dx%qj;dih1^`Z<}&sd>ez#rjE=
zx_QaE#fkdHdItKX#rhU#UIaVL)5X@%D9O}3#l%cE(a_RJ*Tm8?RX5SnFiqDyCDF{x
z+|nS?FxgNH5v{=?jv=AJw)tsknaP=nInt<JME4#jp*TB+IQsazL&M&~(Z^rG$lQ>D
zfx*?!-P6w%Zz}Z7OwLG5%~1#`&B;kE0woQwv%v``I485f65UgzqzYk>W>*(aM_ZT7
z^vsgP90lLhl*~k=G#nBc;A)$glT?}u%7?z55onGDDTT!zJjXeLGMH<Sn}3k6Ymlv1
zesP9^TTyCiajJDteo|(hf?H-@a<;W&PHJ&+VqQv7J}B{*Waed}WI2$@p20!RwxPix
z&ZY(yW)|jVhM*JyO2*Js3yKv;Hb4({9Ld=|$Uii|)5X@*($XNw$T&^c%*4=0*ElsX
zP1n-GGFdm##KPDx%_PmzG|e16xxll6L7H)zv2m)dMT$YPu1TtyrLKjkv88TuQi{2O
zVTz$envn%4gF_sKE6GD;(cKM7E~$CR`6;PIwkU;WBe<+(7zLvtFd71*Aut*OqaiRF
z0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*Aut*OqaiRF0;3@?8UmvsFd71*
zAut*OqaiRF0z*6m{{P5c!w~P`_y7MN1_tK;|Nk;DF#ZPvh{v86+Xv(@UB8xb=Dew*
zyH|;lV9G;J2WJ+ii-L&?u8XG$b<AXFlGERu7!^Kak;Ip2$3u3no%=79pUdJB`-`CC
ze=S->=J`R4f{+4WiiLrJiGhLX`NM5q=b|+xZ(ROy|Dy!2>q;6og-y&<RaH8dIZH~)
zbe!>dV0f_La6s$SYrb<Hw}?$R<YA)tRFYpx;@*Yjl3qTMDr*!&jLujpv}^|eDgMR!

literal 0
HcmV?d00001

diff --git a/api/tests/music/test_metadata.py b/api/tests/music/test_metadata.py
index 342bc99b8..3f1ea9177 100644
--- a/api/tests/music/test_metadata.py
+++ b/api/tests/music/test_metadata.py
@@ -40,3 +40,20 @@ def test_can_get_metadata_from_id3_mp3_file(field, value):
     data = metadata.Metadata(path)
 
     assert data.get(field) == value
+
+
+@pytest.mark.parametrize('field,value', [
+    ('title', '999,999'),
+    ('artist', 'Nine Inch Nails'),
+    ('album', 'The Slip'),
+    ('date', datetime.date(2008, 5, 5)),
+    ('track_number', 1),
+    ('musicbrainz_albumid', uuid.UUID('12b57d46-a192-499e-a91f-7da66790a1c1')),
+    ('musicbrainz_recordingid', uuid.UUID('30f3f33e-8d0c-4e69-8539-cbd701d18f28')),
+    ('musicbrainz_artistid', uuid.UUID('b7ffd2af-418f-4be2-bdd1-22f8b48613da')),
+])
+def test_can_get_metadata_from_flac_file(field, value):
+    path = os.path.join(DATA_DIR, 'sample.flac')
+    data = metadata.Metadata(path)
+
+    assert data.get(field) == value
diff --git a/changes/changelog.d/157.feature b/changes/changelog.d/157.feature
new file mode 100644
index 000000000..0560541b5
--- /dev/null
+++ b/changes/changelog.d/157.feature
@@ -0,0 +1 @@
+Can now import and play flac files (#157)
diff --git a/front/src/audio/formats.js b/front/src/audio/formats.js
index f6e2157a1..a4c2ecf0e 100644
--- a/front/src/audio/formats.js
+++ b/front/src/audio/formats.js
@@ -5,6 +5,7 @@ export default {
   ],
   formatsMap: {
     'audio/ogg': 'ogg',
-    'audio/mpeg': 'mp3'
+    'audio/mpeg': 'mp3',
+    'audio/flac': 'flac'
   }
 }
-- 
GitLab