From fa160cee18f131d5dab56239cfe339b4f368ad3d Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 17 Jan 2016 12:26:07 +0100 Subject: [PATCH 1/8] Added 'path' help entry --- shuffle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shuffle.py b/shuffle.py index e1fa0e9..7aac187 100755 --- a/shuffle.py +++ b/shuffle.py @@ -552,7 +552,7 @@ if __name__ == '__main__': parser.add_argument('--disable-voiceover', action='store_true', help='Disable Voiceover Feature') parser.add_argument('--rename-unicode', action='store_true', help='Rename Files Causing Unicode Errors, will do minimal required renaming') parser.add_argument('--track-gain', type=nonnegative_int, default=0, help='Specify volume gain (0-99) for all tracks; 0 (default) means no gain and is usually fine; e.g. 60 is very loud even on minimal player volume') - parser.add_argument('path') + parser.add_argument('path', help='Path to the IPod\'s root directory') result = parser.parse_args() if not os.path.isdir(result.path): From 594ca8f964b0492a7784ac3267c51959c0de4482 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 17 Jan 2016 12:33:21 +0100 Subject: [PATCH 2/8] Made help message lower case --- shuffle.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shuffle.py b/shuffle.py index 7aac187..8193cbe 100755 --- a/shuffle.py +++ b/shuffle.py @@ -549,8 +549,8 @@ def nonnegative_int(string): if __name__ == '__main__': parser = argparse.ArgumentParser() - parser.add_argument('--disable-voiceover', action='store_true', help='Disable Voiceover Feature') - parser.add_argument('--rename-unicode', action='store_true', help='Rename Files Causing Unicode Errors, will do minimal required renaming') + parser.add_argument('--disable-voiceover', action='store_true', help='Disable voiceover feature') + parser.add_argument('--rename-unicode', action='store_true', help='Rename files causing unicode errors, will do minimal required renaming') parser.add_argument('--track-gain', type=nonnegative_int, default=0, help='Specify volume gain (0-99) for all tracks; 0 (default) means no gain and is usually fine; e.g. 60 is very loud even on minimal player volume') parser.add_argument('path', help='Path to the IPod\'s root directory') result = parser.parse_args() From 255bd8931b0022106cf13247f94552492a2c8650 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 17 Jan 2016 14:04:46 +0100 Subject: [PATCH 3/8] Added default "All Songs" male voice if voiceover is disabled --- shuffle.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/shuffle.py b/shuffle.py index 8193cbe..7480934 100755 --- a/shuffle.py +++ b/shuffle.py @@ -378,9 +378,12 @@ class Playlist(Record): ]) def set_master(self, tracks): - self["dbid"] = hashlib.md5("masterlist").digest()[:8] #pylint: disable-msg=E1101 + # By default use "All Songs" builtin voiceover (dbid all zero) + # Else generate alternative "All Songs" to fit the speaker voice of other playlists + if self.voiceover: + self["dbid"] = hashlib.md5("masterlist").digest()[:8] #pylint: disable-msg=E1101 + self.text_to_speech("All songs", self["dbid"], True) self["listtype"] = 1 - self.text_to_speech("All songs", self["dbid"], True) self.listtracks = tracks def populate_m3u(self, data): From 0acb957993fbc84bb373324ca40203366b8a66ea Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 17 Jan 2016 20:44:30 +0100 Subject: [PATCH 4/8] Additional voiceover doc info --- docs/iTunesSD3gen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/iTunesSD3gen.md b/docs/iTunesSD3gen.md index 913189c..9e1900b 100644 --- a/docs/iTunesSD3gen.md +++ b/docs/iTunesSD3gen.md @@ -115,7 +115,7 @@ Here's the general layout of an iTunesSD file:
1
-
+ Only applies for tracks, not for playlists.
1
From c7a2ed164082d5e4f73e72ac236fbae6777cc581 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 17 Jan 2016 20:45:58 +0100 Subject: [PATCH 5/8] Skip existing voiceover files, add proper return value --- shuffle.py | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/shuffle.py b/shuffle.py index 7480934..8bdd58d 100755 --- a/shuffle.py +++ b/shuffle.py @@ -69,14 +69,20 @@ class Text2Speech(object): @staticmethod def text2speech(out_wav_path, text): + # Skip voiceover geneartion if a track with the same name is used. + # This might happen with "Track001" or "01. Intro" names for example. + if os.path.isfile(out_wav_path): + print "Using eExisting", out_wav_path + return + # ensure we deal with unicode later if not isinstance(text, unicode): text = unicode(text, 'utf-8') lang = Text2Speech.guess_lang(text) if lang == "ru-RU": - Text2Speech.rhvoice(out_wav_path, text) + return Text2Speech.rhvoice(out_wav_path, text) else: - Text2Speech.pico2wave(out_wav_path, text) + return Text2Speech.pico2wave(out_wav_path, text) # guess-language seems like an overkill for now @staticmethod @@ -91,6 +97,7 @@ class Text2Speech(object): if not Text2Speech.valid_tts['pico2wave']: return False subprocess.call(["pico2wave", "-l", "en-GB", "-w", out_wav_path, unicodetext]) + return True @staticmethod def rhvoice(out_wav_path, unicodetext): @@ -106,6 +113,7 @@ class Text2Speech(object): subprocess.call(["sox", tmp_file.name, out_wav_path, "norm"]) os.remove(tmp_file.name) + return True class Record(object): @@ -140,7 +148,8 @@ class Record(object): # Create the voiceover wav file fn = "".join(["{0:02X}".format(ord(x)) for x in reversed(dbid)]) path = os.path.join(self.base, "iPod_Control", "Speakable", "Tracks" if not playlist else "Playlists", fn + ".wav") - Text2Speech.text2speech(path, text) + return Text2Speech.text2speech(path, text) + return False def path_to_ipod(self, filename): if os.path.commonprefix([os.path.abspath(filename), self.base]) != self.base: From 69f3b87b6edcd69f659757c9f34bbb56b316af7a Mon Sep 17 00:00:00 2001 From: NicoHood Date: Mon, 18 Jan 2016 18:33:13 +0100 Subject: [PATCH 6/8] Skip already generated voiceover files --- shuffle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shuffle.py b/shuffle.py index 8bdd58d..78c9719 100755 --- a/shuffle.py +++ b/shuffle.py @@ -73,7 +73,7 @@ class Text2Speech(object): # This might happen with "Track001" or "01. Intro" names for example. if os.path.isfile(out_wav_path): print "Using eExisting", out_wav_path - return + return True # ensure we deal with unicode later if not isinstance(text, unicode): From a07873497d8c4b50fca88ea2128d4aeafec03b36 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 24 Jan 2016 12:14:14 +0100 Subject: [PATCH 7/8] Use default speaker when voiceover is disabled #17 --- shuffle.py | 19 ++++++------------- 1 file changed, 6 insertions(+), 13 deletions(-) diff --git a/shuffle.py b/shuffle.py index 78c9719..6d53afd 100755 --- a/shuffle.py +++ b/shuffle.py @@ -197,7 +197,7 @@ class TunesSD(Record): self.play_header = PlaylistHeader(self) self._struct = collections.OrderedDict([ ("header_id", ("4s", "shdb")), - ("unknown1", ("I", 0x02010001)), + ("unknown1", ("I", 0x02000003)), ("total_length", ("I", 64)), ("total_number_of_tracks", ("I", 0)), ("total_number_of_playlists", ("I", 0)), @@ -328,16 +328,10 @@ class PlaylistHeader(Record): ("header_id", ("4s", "shph")), ("total_length", ("I", 0)), ("number_of_playlists", ("I", 0)), - ("number_of_podcast_lists", ("I", 0xffffffff)), - ("number_of_master_lists", ("I", 0)), - ("number_of_audiobook_lists", ("I", 0xffffffff)), - ("unknown1", ("I", 0)), - ("unknown2", ("I", 0xffffffff)), - ("unknown3", ("I", 0)), - ("unknown4", ("I", 0xffffffff)), - ("unknown5", ("I", 0)), - ("unknown6", ("I", 0xffffffff)), - ("unknown7", ("20s", "\x00" * 20)), + ("number_of_non_podcast_lists", ("2s", "\x03\x00")), #TODO check if really ffff is okay + ("number_of_master_lists", ("2s", "\x01\x00")), + ("number_of_non_audiobook_lists", ("2s", "\x03\x00")), #TODO as above + ("unknown2", ("2s", "\x00" * 2)), ]) def construct(self, tracks): #pylint: disable-msg=W0221 @@ -359,8 +353,7 @@ class PlaylistHeader(Record): chunks += [construction] self["number_of_playlists"] = playlistcount - self["number_of_master_lists"] = 0 - self["total_length"] = 0x44 + (self["number_of_playlists"] * 4) + self["total_length"] = 0x14 + (self["number_of_playlists"] * 4) # Start the header output = Record.construct(self) From cab4d83fea5165a5cdd9e5e76cd5bd61957aa7f5 Mon Sep 17 00:00:00 2001 From: NicoHood Date: Sun, 24 Jan 2016 12:18:56 +0100 Subject: [PATCH 8/8] Typo --- shuffle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shuffle.py b/shuffle.py index 6d53afd..90522ce 100755 --- a/shuffle.py +++ b/shuffle.py @@ -72,7 +72,7 @@ class Text2Speech(object): # Skip voiceover geneartion if a track with the same name is used. # This might happen with "Track001" or "01. Intro" names for example. if os.path.isfile(out_wav_path): - print "Using eExisting", out_wav_path + print "Using existing", out_wav_path return True # ensure we deal with unicode later