Initial community commit

This commit is contained in:
Jef 2024-09-24 14:54:57 +02:00
parent 537bcbc862
commit fc06254474
16440 changed files with 4239995 additions and 2 deletions

View file

@ -0,0 +1,71 @@
#pragma once
#include "foundation/dispatch.h"
#include "foundation/error.h"
#include "types.h"
#include "svc_output.h"
#include "ifc_playback_parameters.h"
/* Note that since a typical ifc_playback implementation
is running on another thread, most functions will always succeed (except for out of memory or thread creation problems)
but might report an error later to the ifc_player object that was passed
when creating the playback object */
class NOVTABLE ifc_playback : public Wasabi2::Dispatchable
{
protected:
ifc_playback() : Dispatchable(NUM_DISPATCH_CODES) {}
~ifc_playback() {}
public:
/* optionally call Cue before calling Play to set the start and end positions
in a cuesheet situation, these will might also get called after
you indicate that cue end position has been reached */
int Cue(Agave_PositionType position_type, Agave_Position start, Agave_Position end) { return Playback_Cue(position_type, start, end); }
// start only version of Cue
int CueStart(Agave_PositionType position_type, Agave_Position start) { return Playback_CueStart(position_type, start); }
// begins playback.
int Play(svc_output *output, ifc_playback_parameters *secondary_parameters) { return Playback_Play(output, secondary_parameters); }
int SeekSeconds(double seconds) { return Playback_SeekSeconds(seconds); }
// called on user-initiated stop. not called if the playback object indiciated a stop (e.g. EOF)
int Stop() { return Playback_Stop(); }
int Pause() { return Playback_Pause(); }
int Unpause() { return Playback_Unpause(); }
/* called to shut things down.
note that if your playback object is in a 'stopped' state,
it should be prepared to receive Cue/Play call until Close() is called */
int Close() { return Playback_Close(); }
/* most of the time, you'll pass SetVolume and SetPan on to the output object
but some special-use playback objects (e.g. analog CD playback) might have to implement this */
// 0 to 1.0
int SetVolume(float volume) { return Playback_SetVolume(volume); }
// -1.0 to 1.0
int SetPan(float pan) { return Playback_SetPan(pan); }
/* most of the time, you'll ignore SetEQ
but some special-use playback objects (e.g. analog CD playback) might have to implement this */
int SetEQ(float preamp, int num_bands, float *bands) { return Playback_SetEQ(preamp, num_bands, bands); }
enum
{
NUM_DISPATCH_CODES,
};
protected:
virtual int WASABICALL Playback_Cue(Agave_PositionType position_type, Agave_Position start, Agave_Position end) { return NErr_NotImplemented; }
virtual int WASABICALL Playback_CueStart(Agave_PositionType position_type, Agave_Position start) { return NErr_NotImplemented; }
virtual int WASABICALL Playback_Play(svc_output *output, ifc_playback_parameters *secondary_parameters)=0;
virtual int WASABICALL Playback_SeekSeconds(double seconds)=0;
virtual int WASABICALL Playback_Stop()=0;
virtual int WASABICALL Playback_Pause()=0;
virtual int WASABICALL Playback_Unpause()=0;
virtual int WASABICALL Playback_Close()=0;
virtual int WASABICALL Playback_SetVolume(float volume) { return NErr_NotImplemented; }
virtual int WASABICALL Playback_SetPan(float pan) { return NErr_NotImplemented; }
virtual int WASABICALL Playback_SetEQ(float preamp, int num_bands, float *bands) { return NErr_NotImplemented; }
};

View file

@ -0,0 +1,20 @@
#pragma once
#include "foundation/dispatch.h"
/* ifc_output_parameters abstracts output parameters that are passed to an input plugin
it is things that an input plugin wouldn't necessary know about
for example, is a playback object is being used for track preview,
it might be configured to play out of a different output device
and there's no way an input plugin would know that
*/
class NOVTABLE ifc_playback_parameters : public Wasabi2::Dispatchable
{
protected:
ifc_playback_parameters() : Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_playback_parameters() {}
enum
{
DISPATCHABLE_VERSION=0,
};
};

View file

@ -0,0 +1,93 @@
#pragma once
#include "foundation/dispatch.h"
#include "foundation/error.h"
#include "foundation/types.h"
#include "metadata/ifc_metadata.h"
#include "audio/ifc_equalizer.h"
#include "nx/nxuri.h"
/* implemented by Winamp (or whatever application)
your ifc_playback implementation should call this with events
TODO: benski> should we require the ifc_playback object to get passed in to each function?
*/
class NOVTABLE ifc_player : public Wasabi2::Dispatchable
{
protected:
ifc_player() : Dispatchable(DISPATCHABLE_VERSION) {}
~ifc_player() {}
public:
/* When your playback object has read enough of the file to provide metadata
it should call this method.
It will be called for both song metadata (artist, album, etc) and codec metadata (bitrate, samplerate, etc).
so make sure you can provide both - this might mean you have to wait until the first frame is decoded.
The player object will add a reference in the function, and release whenever it is no longer needed (usually on start of next track)
*/
void SetMetadata(ifc_metadata *metadata) { Player_SetMetadata(metadata); }
/* Call this just once (with timestamp=0) for CBR files or update continuously for VBR
bitrate should be in bits per second, e.g. 128000 (not 128!)
*/
void SetBitrate(uint64_t bitrate, double timestamp) { Player_SetBitrate(bitrate, timestamp); }
/* Playback plugin should call this when it knows the length
can be updated if necessary (e.g. for VBR files w/o header)
If this is not called, it assumed to be a stream (radio)
*/
void SetLength(double length) { Player_SetLength(length); }
/* Output plugin should call this every once in a while,
if your input plugin does its own audio output (e.g. analog CD) you should call this yourself
*/
void SetPosition(double timestamp) { Player_SetPosition(timestamp); }
void OnLoaded(nx_uri_t filename) { Player_OnLoaded(filename); }
/* Input plugin should call this when playback ends at the end of the file
Do not call if playback stopped because of an error */
void OnEndOfFile() { Player_OnEndOfFile(); }
void OnError(NError code) { Player_OnError(code); }
void OnStopped() { Player_OnStopped(); }
void SetEqualizer(ifc_equalizer *equalizer) { return Player_SetEqualizer(equalizer); }
/* percent is 0-100. setting to 100 implies that buffering has finished */
void SetBufferStatus(int percent) { return Player_SetBufferStatus(percent); }
void OnSeekComplete(int error_code, double new_position) { return Player_OnSeekComplete(error_code, new_position); }
/* seekable is 0 (false) or 1 (true) */
void SetSeekable(int seekable) { return Player_SetSeekable(seekable); }
void AsynchronousFunctionCall(void (*function)(void *, void *, double), void *param1, void *param2, double real_param) { Player_AsynchronousFunctionCall(function, param1, param2, real_param); }
/* Call this after you've successfully opened and parsed the playback file, and are attempting to start playback */
void OnReady() { Player_OnReady(); };
/* Call this after EndOfFile() when either 1) You process an ifc_playback::Close() call or 2) ifc_audioout::IsPlaying() returns NErr_False while waiting for a Close() call */
void OnClosed() { Player_OnClosed(); };
enum
{
DISPATCHABLE_VERSION,
};
protected:
virtual void WASABICALL Player_SetMetadata(ifc_metadata *metadata) = 0;
virtual void WASABICALL Player_SetBitrate(uint64_t bitrate, double timestamp) = 0;
virtual void WASABICALL Player_SetLength(double length) = 0;
virtual void WASABICALL Player_SetPosition(double timestamp) = 0;
virtual void WASABICALL Player_OnLoaded(nx_uri_t filename) = 0;
virtual void WASABICALL Player_OnEndOfFile() = 0;
virtual void WASABICALL Player_OnError(NError code) = 0;
virtual void WASABICALL Player_OnStopped()=0;
virtual void WASABICALL Player_SetEqualizer(ifc_equalizer *equalizer)=0;
virtual void WASABICALL Player_SetBufferStatus(int percent)=0;
virtual void WASABICALL Player_OnSeekComplete(int error_code, double new_position)=0;
virtual void WASABICALL Player_SetSeekable(int seekable)=0;
virtual void WASABICALL Player_AsynchronousFunctionCall(void (*function)(void *, void *, double), void *param1, void *param2, double real_param)=0;
virtual void WASABICALL Player_OnReady()=0;
virtual void WASABICALL Player_OnClosed()=0;
};

View file

@ -0,0 +1,40 @@
#pragma once
#include "foundation/dispatch.h"
#include "audio/ifc_audioout.h"
#include "player/ifc_playback_parameters.h"
class ifc_player;
// {FB5E9AE3-E033-407C-942B-6C1BFAF52A5C}
static const GUID output_service_guid =
{ 0xfb5e9ae3, 0xe033, 0x407c, { 0x94, 0x2b, 0x6c, 0x1b, 0xfa, 0xf5, 0x2a, 0x5c } };
class NOVTABLE svc_output : public Wasabi2::Dispatchable
{
protected:
svc_output() : Dispatchable(DISPATCHABLE_VERSION) {}
~svc_output() {}
public:
static GUID GetServiceType() { return output_service_guid; }
/* ----- Audio Output ----- */
// Opens winamp2-style Audio Output - good for audio-only streams (buffered, push, output-plugin-defined buffersize)
int AudioOpen(const ifc_audioout::Parameters *format, ifc_player *player, ifc_playback_parameters *secondary_parameters, ifc_audioout **out_output) { return OutputService_AudioOpen(format, player, secondary_parameters, out_output); }
/* ----- Video Output ----- */
int VideoOpen();
/* ----- Text Output ----- */
// Opens a subtitle stream
int TextOpenSubtitle();
// Opens a video info text stream
int TextOpenInfo();
// Opens a lyrics text stream
int TextOpenLyrics();
enum
{
DISPATCHABLE_VERSION,
};
protected:
virtual int WASABICALL OutputService_AudioOpen(const ifc_audioout::Parameters *format, ifc_player *player, ifc_playback_parameters *secondary_parameters, ifc_audioout **out_output) = 0;
};

View file

@ -0,0 +1,44 @@
#pragma once
#include "foundation/types.h"
enum Agave_PositionType
{
AGAVE_PLAYPOSITION_100NANOECONDS = 0,
AGAVE_PLAYPOSITION_MILLISECONDS = 1,
AGAVE_PLAYPOSITION_SECONDS = 2,
AGAVE_PLAYPOSITION_HMSF= 3,
AGAVE_PLAYPOSITION_SAMPLE_FRAMES = 4,
AGAVE_PLAYPOSITION_BYTES = 5,
AGAVE_PLAYPOSITION_PACKETS = 6,
};
struct Agave_HMSF
{
uint8_t hours;
uint8_t minutes;
uint8_t seconds;
uint8_t frames;
};
union Agave_Position
{
uint64_t nanoseconds100; // in increments of 100 nanoseconds (microsoft style)
uint64_t milliseconds;
double seconds;
Agave_HMSF hmsf;
uint64_t sample_frames;
uint64_t bytes;
uint64_t packets;
};
struct Agave_Seek
{
Agave_PositionType position_type;
Agave_Position position;
};
static void Agave_Seek_SetBytes(Agave_Seek *seek, uint64_t bytes)
{
seek->position_type=AGAVE_PLAYPOSITION_BYTES;
seek->position.bytes = bytes;
}