curds: Add basic track class

We account for some fallback values, and also attempt to detect
discnumbers from the album name.

Signed-off-by: Anna Schumaker <Anna@NoWheyCreamery.com>
This commit is contained in:
Anna Schumaker 2019-01-29 12:28:30 -05:00
parent a26e8867fe
commit c66405bd80
5 changed files with 127 additions and 3 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
*__pycache__*
*.ogg

View File

@ -1,7 +1,10 @@
# Copyright 2019 (c) Anna Schumaker.
clean:
rm -rv $(find -name __pycache__ -type d)
find . -type d -name __pycache__ -exec rm -r {} \+
find trier -type d -name "Test Album" -exec rm -r {} \+
tests:
python -m unittest discover curds/
.PHONY: trier
trier:
python trier/generate_tracks.py
python -m unittest discover -v curds/

50
curds/test_track.py Normal file
View File

@ -0,0 +1,50 @@
# Copyright 2019 (c) Anna Schumaker.
import unittest
import os
import track
test_tracks = os.path.abspath("./trier/Test Album")
class TestTrackClass(unittest.TestCase):
def test_init_basic(self):
p = [ test_tracks, "01 - Test Track.ogg" ]
t = track.Track(os.path.join(*p))
self.assertEqual(t.path, os.path.join(*p))
self.assertEqual(t.title, "Test Track")
self.assertEqual(t.artist, "Test Artist")
self.assertEqual(t.tracknumber, 1)
self.assertEqual(t.length, 10)
self.assertEqual(t.discnumber, 1)
self.assertEqual(t.album.album, "Test Album")
self.assertEqual(t.album.date, 2019)
self.assertEqual(t.album.genre, "Test")
self.assertEqual(t.album.albumartist, "Test Artist")
def test_init_empty(self):
p = [ test_tracks, "00 - Empty Track.ogg" ]
t = track.Track(os.path.join(*p))
self.assertEqual(t.path, os.path.join(*p))
self.assertEqual(t.title, "00 - Empty Track.ogg")
self.assertEqual(t.artist, "Unknown Artist")
self.assertEqual(t.tracknumber , 0)
self.assertEqual(t.length, 0)
self.assertEqual(t.discnumber, 1)
self.assertEqual(t.album.album, "Unknown Album")
self.assertEqual(t.album.date, 0)
self.assertEqual(t.album.genre, "Unknown")
self.assertEqual(t.album.albumartist, "Unknown Artist")
def test_init_discno_detect(self):
join = os.path.join
self.assertEqual(track.Track(join(test_tracks, "02 - Test {Disc 2}.ogg")).discnumber, 2)
self.assertEqual(track.Track(join(test_tracks, "03 - Test [Disk One].ogg")).discnumber, 1)
self.assertEqual(track.Track(join(test_tracks, "04 - Test (Disc Two).ogg")).discnumber, 2)
self.assertEqual(track.Track(join(test_tracks, "05 - Test - Disc Three.ogg")).discnumber, 3)
self.assertEqual(track.Track(join(test_tracks, "06 - Test;CD Four.ogg")).discnumber, 4)
self.assertEqual(track.Track(join(test_tracks, "07 - Test;CdFive.ogg")).discnumber, 5)
self.assertEqual(track.Track(join(test_tracks, "08 - Test CD 6/10.ogg")).discnumber, 6)
self.assertEqual(track.Track(join(test_tracks, "09 - Test {Disc 02}.ogg")).discnumber, 2)
self.assertEqual(track.Track(join(test_tracks, "10 - Test {Disc 20}.ogg")).discnumber, 20)
if __name__ == '__main--':
unittest.main()

25
curds/track.py Normal file
View File

@ -0,0 +1,25 @@
# Copyright 2019 (c) Anna Schumaker.
import album
import mutagen
import os
import re
discno_map = { "one" : "1", "two" : "2", "three" : "3", "four" : "4", "five" : "5" }
class Track:
def __init__(self, path):
fileinfo = mutagen.File(path)
self.path = path
self.title = fileinfo.get("title", [os.path.basename(path)])[0]
self.artist = fileinfo.get("artist", ["Unknown Artist"])[0]
self.tracknumber = int(fileinfo.get("tracknumber", ["0"])[0])
self.length = fileinfo.info.length
self.album = album.lookup(fileinfo)
self.discnumber = int(fileinfo.get("discnumber", ["1"])[0])
# Try to detect discnumbers that are embedded in the album name
discno = fileinfo.get("album", ["Unknown Album"])[0][len(self.album.album):]
match = re.search("([1-9][0-9]*)|one|two|three|four|five", discno.lower())
if match:
self.discnumber = int(discno_map.get(match.group(), match.group()))

45
trier/generate_tracks.py Normal file
View File

@ -0,0 +1,45 @@
# Copyright 2019 (c) Anna Schumaker.
import mutagen
import os
import subprocess
trier = os.path.abspath("trier")
ffmpeg = "ffmpeg -hide_banner -nostdin -f s16le -i /dev/zero -codec libvorbis -loglevel warning".split()
def generate_track(length, filename, tags={}):
path = os.path.join(trier, filename)
os.makedirs(os.path.dirname(path), exist_ok=True)
subprocess.run(ffmpeg + [ "-t", str(length), path ])
fileinfo = mutagen.File(path)
for (key, value) in tags.items():
fileinfo[key] = value
fileinfo.save()
generate_track( 0, "Test Album/00 - Empty Track.ogg")
generate_track(10, "Test Album/01 - Test Track.ogg", { "title" : "Test Track",
"artist" : "Test Artist",
"album" : "Test Album",
"genre" : "Test",
"date" : "2019",
"tracknumber" : "1",
"discnumber" : "1" })
generate_track(15, "Test Album/02 - Test {Disc 2}.ogg", { "Title" : "Test {Disc 2}",
"album" : "Test Album {Disc 2}" })
generate_track(20, "Test Album/03 - Test [Disk One].ogg", { "Title" : "Test [Disk One]",
"album" : "Test Album [Disk One]",
"discnumber" : "2"})
generate_track(25, "Test Album/04 - Test (Disc Two).ogg", { "Title" : "Test (Disc Two)",
"album" : "Test Album (Disc Two)" })
generate_track(30, "Test Album/05 - Test - Disc Three.ogg", { "Title" : "Test - Disc Three",
"album" : "Test - Disc Three" })
generate_track(35, "Test Album/06 - Test;CD Four.ogg", { "Title" : "Test;CD Four",
"album" : "Test;CD Four" })
generate_track(40, "Test Album/07 - Test;CdFive.ogg", { "Title" : "Test;CdFive",
"album" : "Test;CdFive" })
generate_track(45, "Test Album/08 - Test CD 6/10.ogg", { "Title" : "Test CD 6/10",
"album" : "Test CD 6/10" })
generate_track(50, "Test Album/09 - Test {Disc 02}.ogg", { "Title" : "Test {Disc 02}",
"album" : "Test Album {Disc 02}" })
generate_track(55, "Test Album/10 - Test {Disc 20}.ogg", { "Title" : "Test {Disc 20}",
"album" : "Test Album {Disc 20}" })