owntone / owntone-server

Linux/FreeBSD DAAP (iTunes) and MPD media server with support for AirPlay 1 and 2 speakers (multiroom), Apple Remote (and compatibles), Chromecast, Spotify and internet radio.
https://owntone.github.io/owntone-server
GNU General Public License v2.0
2.01k stars 232 forks source link

Support for other file formats #787

Open niekvlessert opened 4 years ago

niekvlessert commented 4 years ago

I would like to be able to play several chiptunes formats with forked-daapd. I'm thinking about VGM (VGMPlay), KSS (libkss) and MOD like formats like S3M, XM, IT and MOD (the dumb library). I'm aware I can use the fifo thing, but the lag is pretty long.

Would it be a good idea to execute the available command line programs that can output wav data from forked-daapd? Or should the actual generation of audio be integrated in the code so the mentioned programs will be actual libraries? Or is there some other good way? In any case some pointers how to achieve this are very welcome.

ejurgensen commented 4 years ago

Sounds good to add that support, the more the merrier. I'm not so well acquainted with those formats, and what implementations exist to decode them. The simplest way to get the working in forked-daapd would be if ffmpeg has support for them, but I suppose that is not the case? Otherwise the way to go would be to make add one or more input modules to forked-daapd.

In principle, you could probably make an input module that used a command line program, but I'm not sure about the implications of that. It would be much better to base it on libraries, and preferably open source ones. Have you looked into what is available?

niekvlessert commented 4 years ago

No ffmpeg support afaik. Yeah, I looked into them, I've created my own Android based player with those libraries for playback. They all share the obvious function to generate some amount of audio to an array which can be inserted in the audio device. I already found out about the input modules, but I don't see stuff like that happening in there. So could you give me some pointers on how to implement this in an input module? Like some example c file that shows me how to fill the right buffers and stuff, I can then add the actual generation of audio. I can also look into it myself, but since you know everything about this project it's a lot more efficient I'd say. :)

https://github.com/vgmrips/vgmplay https://github.com/kode54/dumb https://github.com/digital-sound-antiques/libkss

ejurgensen commented 4 years ago

No problem, your questions are very welcome. Here is how you could go about it (using kss as an example):

  1. In db.h, add a DATA_KIND_KSS. This will be used to identify this type of source in the different parts of forked-daapd.
  2. In library/filescanner.c, modify file_type_get() so that it returns FILE_KSS (and add the type, of course)
  3. Make a library/filescanner_kss.c file that implements scan_kss(). This function must put the file metadata into a struct media_file_info and then call library_add_media(). This will add the kss files to the library.
  4. Make a inputs/kss.c file that implements an input definition called input_kss. You must define a setup, play and stop function. setup() must open the file and prepare it for reading. play() must demux+decode, and then deliver the audio to the player as PCM using input_write(), stop() must close the file. From a quick look at it, this implementation will do very much what this https://github.com/digital-sound-antiques/libkss/blob/master/src/kss2wav.c does, so perhaps you can use that as a starting point.
  5. In input.c, modify map_data_kind() so that it returns INPUT_TYPE_KSS (and add that type in input.h). Also add input definitions for input_kss (see the top of input.c)

I think that should do it, but I probably forgot some things.

niekvlessert commented 4 years ago

I think I'll start with the VGM format. The files can have the extension vgz or vgm. The issue with KSS files is that 1 file contains all tracks and the format does not specify which to play in the file, what the titles are and how many seconds to play, those things have to be manually specified in for example an m3u file.

niekvlessert commented 4 years ago

What about this. The fifo thing is slow as we all know. But why is this? Because the auto detection of data coming in is slow or is there some other reason? What if a rest call is added that makes it possible to force playback of a certain fifo file? Will this make things quicker?

ejurgensen commented 4 years ago

I don't remember the details of the pipe input, but my guess would be that the autostart and read is actually pretty quick. I think it is the setup of the outputs (especially Airplay) that makes it slow.

There is already a rest call to start playback of pipe, it is just the normal play command. You can also start playback of the pipe via the web ui (or any other client), you will normally find it listed as "Unknown artist"/"Unknown album". You can give it a try, I think it will start everything, also the outputs, but note that some outputs will hang up if no data arrives within a short window (like 10-20 sec).