nims11/IPod-Shuffle-4g

Use default Speaker when voiceover is disabled

Closed this issue · 14 comments

Normally you hear a male speaker if no voiceover was selected via ITunes. Those sound files are still there ./NICO'S IPOD/iPod_Control/Speakable/Messages/.

However I checked my old Ipod backup and it seems the ipod does not generate any database for this "non voiceover" ipod settings from itunes. So there must be a way to use the internal voices without merging the sounds and doing complicated stuff.

If I disable voiceover with your tool I only get "Playlist zero" for ALL playlists. "All Songs" disappeared and is silent.

We should be able to fix this somehow. This also means we do not have to provide the closed source male speaker voiceover, which is great. I will look at the hex output with xxd. But I have nothing more than my backup. Not even a windows PC I could use to regenerate Itunes files.

Partly solved here:
NicoHood@78482c9

The Playlist n is just missing. I tried to set the hex value to the following (with 1 and 2 playlists), but it always outputs "zero"

"\0\0\0\0\0\0\0\1"
"\0\0\0\0\0\0\0\2"
"\0\0\0\1\0\0\0\0"
"\0\0\0\2\0\0\0\0"
"\1\0\0\0\0\0\0\0"
"\2\0\0\0\0\0\0\0"

Information was taken from this section:
https://github.com/nims11/IPod-Shuffle-4g/blob/master/docs/iTunesSD3gen.md#playlistx

If I can get the playlist n to work I will open another PR.

Maybe we can extract more information from here:
https://github.com/GNOME/rhythmbox/tree/master/plugins/ipod

I still cannot find the playlist fake voiceover yet. But we might get additional track field information from this, like stars (rating) and others. However it should be useless anyways for an ipod shuffle.

Here is an extract from a 2 file and 1 file playlist, generated from rythmbox. I marked the voiceover field. No idea why it has to be like this.

00004b0: 0000 0000 0000 0000 0000 0000 6870 6873  ............hphs
00004c0: 2000 0000 0300 0000 0300 0100 0300 0000   ...............
00004d0: dc04 0000 1405 0000 4405 0000 6c70 6873  ........D...lphs
00004e0: 3800 0000 0300 0000 0300 0000|0000 0000| 8...............
00004f0: 0000 0000 0100 0000 0000 0000 0000 0000  ................
0000500: 0000 0000 0000 0000 0000 0000 0100 0000  ................
0000510: 0200 0000 6c70 6873 3000 0000 0100 0000  ....lphs0.......
0000520: 0100 0000|db75 0b15|ccf4 6524 0200 0000  .....u....e$....
0000530: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000540: 0000 0000 6c70 6873 3400 0000 0200 0000  ....lphs4.......
0000550: 0200 0000|5c2a d310|6a0d e823 0200 0000  ....\*..j..#....
0000560: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000570: 0100 0000 0200 0000                      ........

The playlist header format is totally different to the docs:
https://github.com/nims11/IPod-Shuffle-4g/blob/master/docs/iTunesSD3gen.md#playlist-header

The same playlists (form above) now generated with the script gives:

00001c0: 0000 0000 0000 0000 0000 0000 6870 6873  ............hphs
00001d0:|4c00 0000|0200 0000|ffff|ffff|0000|0000| L...............
00001e0: ffff ffff 0000 0000 ffff ffff 0000 0000  ................
00001f0: ffff ffff 0000 0000 ffff ffff 0000 0000  ................
0000200: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000210: 1802 0000 4802 0000 6c70 6873 3000 0000  ....H...lphs0...
0000220: 0100 0000 0100 0000 0000 0000 0000 0000  ................
0000230: 0100 0000 0000 0000 0000 0000 0000 0000  ................
0000240: 0000 0000 0000 0000 6c70 6873 3000 0000  ........lphs0...
0000250: 0100 0000 0100 0000 1db1 7926 8a06 9bec  ..........y&....
0000260: 0200 0000 0000 0000 0000 0000 0000 0000  ................
0000270: 0000 0000 0000 0000                      ........

You can see there is very weird data in it. I think the bytelength is wrong and also the information inside. And thatswhy the ipod outputs zero probably. Not because we have a playlist header problem, I think its more a playlist header header problem.

I found a Rythmbox bug X_x

If you sync 2 playlists with 1 and x songs, it will transmit only 1, x-1 songs as playlist. This first confused me.

I got the header now setup exactly as rythmbox, except the voiceover filename (which i dont know if its random). However my ipod crashes if i hit the playlist button. It keeps playing music, even after turning off. After a while it then goes off luckly. Nice to see it crashing like that. If I dont destroy the aux plugs, then I will do it by software ;D

This confuses me even more. Why does a fixed header not work and this unknown one does!? There must be something wrong still.

See my headers (last playlist misses 1 song as described)

00004b0: 0000 0000 0000 0000 0000 0000 6870 6873  ............hphs
00004c0: 2000 0000 0300 0000 0300 0100 0300 0000   ...............
00004d0: dc04 0000 1405 0000 4405 0000 6c70 6873  ........D...lphs
00004e0: 3800 0000 0300 0000 0300 0000 0000 0000  8...............
00004f0: 0000 0000 0100 0000 0000 0000 0000 0000  ................
0000500: 0000 0000 0000 0000 0000 0000 0100 0000  ................
0000510: 0200 0000 6c70 6873 3000 0000 0100 0000  ....lphs0.......
0000520: 0100 0000 1db1 7926 8a06 9bec 0200 0000  ......y&........
0000530: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000540: 0200 0000 6c70 6873 3000 0000 0100 0000  ....lphs0.......
0000550: 0100 0000 3b43 3a8c 1332 b6ad 0200 0000  ....;C:..2......
0000560: 0000 0000 0000 0000 0000 0000 0000 0000  ................
0000570: 0100 0000                                ....

As reference what i did so far:

IPod-Shuffle-4g$ git diff
diff --git a/shuffle.py b/shuffle.py
index 78c9719..82617d1 100755
--- a/shuffle.py
+++ b/shuffle.py
@@ -281,7 +281,7 @@ class Track(Record):
                            ("track", ("H", 1)),
                            ("disc", ("H", 0)),
                            ("unknown4", ("Q", 0)),
-                           ("dbid", ("8s", 0)),
+                           ("dbid", ("8s", "\x00" * 8)),
                            ("artistid", ("I", 0)),
                            ("unknown5", ("32s", "\x00" * 32)),
                            ])
@@ -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)

Any thoughs appreciated. But I will continue self conversion here, sometimes this helps. And others can pick up the work if I ever give up. But not yet time for it ;)

Ah, quite some work done by you! Will take me some time to look into it and relate to your findings (Weekdays -_-). Give me a day or two to get back to you on this.

I found the bug!!!!

I applied the patch I showed above. I do not know where this weird data is coming from, but it does not apply the ipod shuffle specs we have in our documents. Maybe this is an older ipod shuffle gen 3 format? I do not know. And I do not own such a device, and I also think we should not care. The rythmbox plugin handles it the same way.

The critical difference however is the 2nd 32bit value of the database.

("unknown1", ("I", 0x02010001)),

Also our docs list a different value here (the one I fixed in the PR). I do not know where this also comes from, but its wrong. Maybe a version number? And this makes the ipod not work with the built-in sound files. I do not know why this happens, but can simply fix it.

I still do not have a windows machine to test an itunes setting. Just a little note here:
Windows 10 in vm does not recognize the USB device.
I then tried Windows 7. But it does stop finding updates after SP1. It just searches forever with 100% cpu. I thought this was caused by the vm, but it also happened to someone else in vm and real hardware. See what windows is doing here to break fresh win7 installations to force us use win10?
So no way for me to test itunes.

PR will come soon.

Also see this:
http://sourceforge.net/p/gtkpod/mailman/message/32333835/

It has to be a version number.

I tried syncing 3 files from my itunes in windows. Turns out it generates a completely different database format (mhbd, different from the bdhs we are using). I was able to find some references on this format (http://homepage.ntlworld.com/simon.mason20/ipod_tunes_spec.htm), but it seems incomplete. Will probe and update on it.
iTunesDB.zip

We are looking at the iTunesSD file not iTunesDB file. That might be the difference. Please upload the whole iTunes folder.

Edit:
it seems that rythmbox also generates this file. I i am totally wrong, idk. Too bad I dont have a clean itunes available. My files are just "as is" and I have to live with the things inside. It might be modified by other programs, no reference.

It might be just to stay compatible to other ipods like the nano. Or usage data for the NSA.

Ah, hit me, sorry for that :|
iTunesSD.zip
Here's the one generated by shuffle.py
iTunesSD.zip

Differences:

  • unknown_3 is 1 instead of 0.
  • stop_at_pos_ms seem to differ for 2/3 songs?? (rythmbox doesnt use this at all)
  • dbid is different, but expected.
  • artist id, track number, album id is different, might be some itunes internals, nothing important. But we can read this from id3 tag if we want to. But not all files have this. Probably set the numbers all to zero then.
  • we use a post and pregap of 2 which i was wondering about.

Is the post/pregap important? Is it something like crossfade or a cutoff? We might want to test that. I can manipulate my database.

I am just wondering about unknown_3 value... (2nd row last 2 bytes in xxd dump). It might be some special setting in itunes. Can you just list the options you have in itunes and maybe play with those settings we dont know yet?

You used my PR to generate the 2nd data? Otherwise it must have been different.
If so I think you can merge #24

You disabled voiceover via itunes, but enabled it via script. didnt you?

FYI:
I use xxd to dump the data, meld to compare and bless to manipulate it.

Also see this:
http://sourceforge.net/p/gtkpod/code/ci/master/tree/itunesdb_info.txt

I looked into the other files that were still on my ipod. Looks like it collected a lot of data. My old windows pc hostname is still in there. Multiple times. I guess it records usage data of ALL songs etc. It saves some windows specific data and probably my old itunes id is also in there somewhere. Should not matter for our linux usage though.

I backed up my IPod before the first use. The folder iTunes only has a 0 bye file firsttime. This means all settings and stats must be placed inside this folder. There was a ._.Trashes file and a .Trashes folder as well. The Speakable folder contains the basic "All Songs" sound files and some language xml files (.plist). So i guess we can savely delete (before a backup) the iTunes folder and its content.

It would be also interresting which files are then recreated by the ipod itself. I also think that they made a lot of stuff similar to other apple products so they have the same recognition algorithms for song names, albums, artists and rating etc. Most stuff we dont use, since we dont have itunes. And the ipod hardware gives a shit.

Fixed f7eafd1