SID Plugin

I made a SID-Tune plugin for MOC (2.5.0-alpha1).
This was a bit tricky but I think it works quite well...

Depends on libsidplay2 and libsidutils (and on the existence of the ReSID-Builder from that libraries).

Features :
ReSID-Builder for SID-Playback
HVSC-Database support for songlengths
...some more

I hope this opens MOC to an even wider public... :-)

There might be some bugs although I tried to catch most of them - feedback appreciated...

Patch : http://www.tzi.de/~hiben/darcsrep/linux/gentoo/portage/media-sound/moc/files/2.5.0-sidplay2.patch

More info : http://www.tzi.de/~hiben/moc/

Wow, it's your third plugin, thanks for that! Playing SID is on of the oldest items on the TODO list for MOC. I'll take a deeper look at it at weekend and merge it. Once again big thanks!

--
Damian Pietras - MOC developer

I just keep making the plugins for the things I listen too...
There is just no other player that fits my habits better... ;-)

Maybe I released this plugin too soon into the public... I've enountered some thread-related problems I did not see before because they just appear sporadic...
I hope to be able to fix them in a few days because I can't enjoy the ~32000 tunes from the HVSC with random crashes... :-|

There is a global variable player. Could it be the problem? MOC opens up to two files at a time. Try setting Precache = no in the config file to turn it off, this might help.

--
Damian Pietras - MOC developer

You are right.
But I fixed it the other way round (patch updated). Each tune gets a fresh player/builder now (I think this is a good idea anyway).

The only thing left now is that the decoder crashes on (very) rapid song changing (e.g. holding down n)...

I'am currently trying to get after that...

*edit*
I did some tests and improved the plugin a bit but it seems that the crashes originate from memory-leaks in sidplay2... I could just start to not free the structures anymore but this would be wasting a lot of memory...

Okay, I did some further testing, thinking and modified the patch again...

Now this is pretty hard to kill by skipping but it still can happen (but not easy to reproduce).

The downside of this is that now sometimes moc crashes on exit (when calling destroy as now only then objects are freed).

I don't know if I should just leave the C++-Objects in memory (constant count of objects) as they will be cleaned anyway when the process dies... any suggestions if that would be ok ?

*edit*
I'am such an idiot... really...
The only good thing about all this is that this plugin has a lot better performance now...

The real problem was that I created a memory corruption because of an 'off-by-one'-error...

Patch is updated and should be really stable now...

Plugin merged.

Two changes were required to compile it on my Ubuntu system:
Remove static declarations from sidplay2.h, gcc 4.1 treats them as errors.
Searching for libresid-builder.la in $s2lib/libresid-builder.la in addition to $s2lib/sidplay/builders/libresid-builder.la

I hope I didn't break anything.

One again thanks!

--
Damian Pietras - MOC developer

Just compiled the sources from SVN. Still works for me.

I tried to make the functions static as this is done in the other plugins...
I read about that this is actually wrong to do in c++ (and support was removed from newer compilers) so if it does not break the API it should be OK to remove that attribute on any system.

Your Makefile handles the dependencies in a more sane way than what I had come up with... ;-)

How about using the sidplay2_seek() function for changing subtunes? It could be something like in this patch.

The patch stores subtune ending times instead of subtune lengths in the sidplay2_data structure, so that we can put the progress bar in correct position when changing subtunes.

The patch always selects the next subtune on seek. Maybe it would be good to also allow selecting the previous subtune, but I don't know how to detect reliably if the seek was backwards or forwards.

The patch also removes two assignment statements from sidplay2_decode() function, which I think have no effect.

<br /> Index: sidplay2.cc<br /> ===================================================================<br /> --- sidplay2.cc (revision 2094)<br /> +++ sidplay2.cc (working copy)<br /> @@ -34,6 +34,23 @@</p> <p> static int playSubTunes;</p> <p>+namespace<br /> +{<br /> + int get_current_subtune_begin_time(sidplay2_data *data)<br /> + {<br /> + if(data->currentSong == data->timeStart)<br /> + return 0;<br /> +<br /> + return data->subtune_end_times[data->currentSong-2];<br /> + }<br /> +<br /> + int get_current_subtune_length(sidplay2_data *data)<br /> + {<br /> + return data->subtune_end_times[data->currentSong-1]<br /> + - get_current_subtune_begin_time(data);<br /> + }<br /> +}<br /> +<br /> static sidplay2_data * make_data()<br /> {<br /> pthread_mutex_lock(&amp;player_select_mutex);<br /> @@ -240,7 +257,7 @@</p> <p> s2d->songs = st->getInfo().songs;</p> <p>- s2d->sublengths = new int [s2d->songs];<br /> + s2d->subtune_end_times = new int [s2d->songs];</p> <p> s2d->startSong = st->getInfo().startSong;</p> <p>@@ -276,12 +293,12 @@<br /> dl = minLength;</p> <p> s2d->length += dl;<br /> - s2d->sublengths[s-1] = dl;<br /> + s2d->subtune_end_times[s-1] = s2d->length;<br /> }<br /> else<br /> {<br /> s2d->length += defaultLength;<br /> - s2d->sublengths[s-1] = defaultLength;<br /> + s2d->subtune_end_times[s-1] = s2d->length;<br /> }<br /> }</p> <p>@@ -324,8 +341,8 @@<br /> if(data->tune!=NULL)<br /> delete data->tune;</p> <p>- if(data->sublengths!=NULL)<br /> - delete data->sublengths;<br /> + if(data->subtune_end_times!=NULL)<br /> + delete data->subtune_end_times;</p> <p> free(data);<br /> }<br /> @@ -435,9 +452,20 @@<br /> * generic seeking can't be done because the tune has to<br /> * be played until the position (needs CPU)...<br /> * */<br /> -extern "C" int sidplay2_seek (void *void_data ATTR_UNUSED, int sec ATTR_UNUSED)<br /> +extern "C" int sidplay2_seek (void *void_data, int sec)<br /> {<br /> - return -1;<br /> + struct sidplay2_data *data = (struct sidplay2_data *)void_data;<br /> +<br /> + if (data->currentSong >= data->timeEnd)<br /> + {<br /> + return -1;<br /> + }<br /> +<br /> + data->player->stop();<br /> + data->currentSong++;<br /> + data->tune->selectSong(data->currentSong);<br /> + data->player->load(data->tune);<br /> + return get_current_subtune_begin_time(data);<br /> }</p> <p> extern "C" int sidplay2_decode (void *void_data, char *buf, int buf_len,<br /> @@ -447,7 +475,7 @@</p> <p> int seconds = data->player->time() / data->player->timebase();</p> <p>- int currentLength = data->sublengths[data->currentSong-1];<br /> + int currentLength = get_current_subtune_length(data);</p> <p> if(seconds >= currentLength)<br /> {<br /> @@ -458,9 +486,6 @@<br /> data->currentSong++;<br /> data->tune->selectSong(data->currentSong);<br /> data->player->load(data->tune);<br /> -<br /> - currentLength = data->sublengths[data->currentSong-1];<br /> - seconds = 0;<br /> }</p> <p> sound_params->channels = data->channels;<br /> Index: sidplay2.h<br /> ===================================================================<br /> --- sidplay2.h (revision 2094)<br /> +++ sidplay2.h (working copy)<br /> @@ -67,7 +67,7 @@<br /> sid2_config_t cfg;<br /> ReSIDBuilder *builder;<br /> int length;<br /> - int *sublengths;<br /> + int *subtune_end_times;<br /> int songs;<br /> int startSong;<br /> int currentSong;<br />

At the very early stages when I developed the decoder I played around with using seek to change subtunes but removed it. The reason was the same you are experiencing: there is no *easy* way of detecting the direction of the seek. I thought that seeking would then be not very user friendly and in the end I decided to not use it.

I would rather like to modify the whole plugin API to allow more sophisticated controls / runtime-configuration but then again this nice, fast and usable application might turn into 'just another overloaded player'.

But I would very much like to hear about your experiences with users of the plugin; I have to admit that I have not been talking to anybody about how (if) they like to listen to SIDs with MOC (I do :-) ).
If there are users who like the seeking option I have no problem if it gets incorporated.

About the 'effectless assignments': I am very sure they have a purpose - although I would not guarantee it. While hunting bugs I found a lot of special cases when the plugin would crash on certain sequences of events. You basically removed some assignments that try to maintain a sane state of the plugin - they might be not needed most the time but make sure there is really no case when they could be used. But it is of course also possible that they are just some relics from previous design stages... :-)

First, excuse me for the bad english. I use Moc under GoboLinux, and I am not a "Linux-Guru". The Moc like me too, it is me preferred music-player, but I am very beginner in the Linux, and only now can I install the Sid and Midi playing-possibility to under Moc. (Can you create a possibility - patch - to backward playing?).

As I see, the sid-plugin now not 100% perfect. I fund a few sid music, what the moc cannot playing.

But thanks the Moc and the sid- and other plugins!

Can you tell me were to find that particular SID-file ? I would like to find out why I does not work.

SID, MIDI and MOD (XM,S3M,IT...) files cannot (easily) be played backwards without decoding the whole file first as the sound is either synthesized by an emulated microcontroler (for SID) or created by processing a stream of commands with respect to a clocking (MOD, MIDI). As you can imagine, these processes cannot be reverted (easily).

If you really need backwards playing of this kind of music you should just save the output of a suitable decoder to a 'normal' sample based audio format - MOC cannot play these backwards either but other players might be able to do it.

I still do not understand the need for having an option to play backward ? Are you looking for secret messages in the files ? ;-)

Hm, excuse me, as I see, the not playable sid files are errored, or have too much pause in the begin of the music. Now succeeded me to have the good releases...

About the backward playing I think as first not to the sid and midi files, only for the wav, mp3 and ogg files. I not have in the files any "secret messages", only I search new music-idees, new rhythms, and the backward playing is simple a new curious game... interest... And, the AlsaPlayer prog have this feature, but I like the Moc. I think, my preferred music player should know all feature.