diff --git a/.gitignore b/.gitignore index cd4c22c..470c1ea 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ *__pycache__* +*.ogg diff --git a/Makefile b/Makefile index e881626..226efc2 100644 --- a/Makefile +++ b/Makefile @@ -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/ diff --git a/curds/test_track.py b/curds/test_track.py new file mode 100644 index 0000000..42a5d47 --- /dev/null +++ b/curds/test_track.py @@ -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() diff --git a/curds/track.py b/curds/track.py new file mode 100644 index 0000000..6ee5e27 --- /dev/null +++ b/curds/track.py @@ -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())) diff --git a/trier/generate_tracks.py b/trier/generate_tracks.py new file mode 100644 index 0000000..eca9ec3 --- /dev/null +++ b/trier/generate_tracks.py @@ -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}" })