- Fixed plugins to match on case-insensitive filenames

- Added musik::sdk::endsWith (but now having seconds thoughts...)
- Fixed mpg123 decoder to work in windows, in favor of the old Tuniac
  one.
This commit is contained in:
casey 2016-05-29 11:38:15 -07:00
parent 4f8294169d
commit d312932210
18 changed files with 2332 additions and 27 deletions

View File

@ -24,6 +24,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "waveout", "src\contrib\wave
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "flacdecoder", "src\contrib\flacdecoder\flacdecoder.vcxproj", "{465EF178-91C1-4068-BE1D-F9616ECCB6DE}"
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "mpg123decoder", "src\contrib\mpg123decoder\mpg123decoder.vcxproj", "{04118CC2-DE10-4627-A695-2219428C7D59}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
@ -74,6 +76,10 @@ Global
{465EF178-91C1-4068-BE1D-F9616ECCB6DE}.Debug|Win32.Build.0 = Debug|Win32
{465EF178-91C1-4068-BE1D-F9616ECCB6DE}.Release|Win32.ActiveCfg = Release|Win32
{465EF178-91C1-4068-BE1D-F9616ECCB6DE}.Release|Win32.Build.0 = Release|Win32
{04118CC2-DE10-4627-A695-2219428C7D59}.Debug|Win32.ActiveCfg = Debug|Win32
{04118CC2-DE10-4627-A695-2219428C7D59}.Debug|Win32.Build.0 = Debug|Win32
{04118CC2-DE10-4627-A695-2219428C7D59}.Release|Win32.ActiveCfg = Release|Win32
{04118CC2-DE10-4627-A695-2219428C7D59}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -60,6 +60,6 @@ bool FlacDecoderFactory::CanHandle(const char* type) const {
std::transform(str.begin(), str.end(), str.begin(), tolower);
return
str.find(".flac") != std::string::npos ||
musik::sdk::endsWith(type, ".flac") ||
str.find("audio/flag") != std::string::npos;
}

View File

@ -56,9 +56,10 @@ IDecoder* Mp3DecoderFactory::CreateDecoder() {
}
bool Mp3DecoderFactory::CanHandle(const char* source) const {
std::string str(source);
std::string str(type);
std::transform(str.begin(), str.end(), str.begin(), tolower);
if (str.find(".mp3") != std::string::npos ||
if (musik::sdk::endsWith(str, ".mp3") ||
str.find("audio/mpeg3") != std::string::npos ||
str.find("audio/x-mpeg-3") != std::string::npos ||
str.find("audio/mp3") != std::string::npos)

View File

@ -2,6 +2,11 @@
#include <core/sdk/IDecoder.h>
#include <core/sdk/IDataStream.h>
#ifdef _MSC_VER /* ehh */
typedef long ssize_t;
#endif
#include <mpg123.h>
class Mpg123Decoder : public musik::core::audio::IDecoder {

View File

@ -1,6 +1,7 @@
#include "stdafx.h"
#include <string>
#include <algorithm>
#include "Mpg123DecoderFactory.h"
#include "Mpg123Decoder.h"
#include "mpg123.h"
@ -25,8 +26,9 @@ IDecoder* Mpg123DecoderFactory::CreateDecoder() {
bool Mpg123DecoderFactory::CanHandle(const char* type) const {
std::string str(type);
std::transform(str.begin(), str.end(), str.begin(), tolower);
if (str.find(".mp3") != std::string::npos ||
if (musik::sdk::endsWith(str, ".mp3") ||
str.find("audio/mpeg3") != std::string::npos ||
str.find("audio/x-mpeg-3") != std::string::npos ||
str.find("audio/mp3") != std::string::npos)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,135 @@
/*
libmpg123: MPEG Audio Decoder library
separate header just for audio format definitions not tied to
library code
copyright 1995-2015 by the mpg123 project
free software under the terms of the LGPL 2.1
see COPYING and AUTHORS files in distribution or http://mpg123.org
*/
#ifndef MPG123_ENC_H
#define MPG123_ENC_H
/** \file fmt123.h Audio format definitions. */
/** \defgroup mpg123_enc mpg123 PCM sample encodings
* These are definitions for audio formats used by libmpg123 and
* libout123.
*
* @{
*/
/** An enum over all sample types possibly known to mpg123.
* The values are designed as bit flags to allow bitmasking for encoding
* families.
* This is also why the enum is not used as type for actual encoding variables,
* plain integers (at least 16 bit, 15 bit being used) cover the possible
* combinations of these flags.
*
* Note that (your build of) libmpg123 does not necessarily support all these.
* Usually, you can expect the 8bit encodings and signed 16 bit.
* Also 32bit float will be usual beginning with mpg123-1.7.0 .
* What you should bear in mind is that (SSE, etc) optimized routines may be
* absent for some formats. We do have SSE for 16, 32 bit and float, though.
* 24 bit integer is done via postprocessing of 32 bit output -- just cutting
* the last byte, no rounding, even. If you want better, do it yourself.
*
* All formats are in native byte order. If you need different endinaness, you
* can simply postprocess the output buffers (libmpg123 wouldn't do anything
* else). The macro MPG123_SAMPLESIZE() can be helpful there.
*/
enum mpg123_enc_enum
{
/* 0000 0000 0000 1111 Some 8 bit integer encoding. */
MPG123_ENC_8 = 0x00f
/* 0000 0000 0100 0000 Some 16 bit integer encoding. */
, MPG123_ENC_16 = 0x040
/* 0100 0000 0000 0000 Some 24 bit integer encoding. */
, MPG123_ENC_24 = 0x4000
/* 0000 0001 0000 0000 Some 32 bit integer encoding. */
, MPG123_ENC_32 = 0x100
/* 0000 0000 1000 0000 Some signed integer encoding. */
, MPG123_ENC_SIGNED = 0x080
/* 0000 1110 0000 0000 Some float encoding. */
, MPG123_ENC_FLOAT = 0xe00
/* 0000 0000 1101 0000 signed 16 bit */
, MPG123_ENC_SIGNED_16 = (MPG123_ENC_16|MPG123_ENC_SIGNED|0x10)
/* 0000 0000 0110 0000 unsigned 16 bit */
, MPG123_ENC_UNSIGNED_16 = (MPG123_ENC_16|0x20)
/* 0000 0000 0000 0001 unsigned 8 bit */
, MPG123_ENC_UNSIGNED_8 = 0x01
/* 0000 0000 1000 0010 signed 8 bit */
, MPG123_ENC_SIGNED_8 = (MPG123_ENC_SIGNED|0x02)
/* 0000 0000 0000 0100 ulaw 8 bit */
, MPG123_ENC_ULAW_8 = 0x04
/* 0000 0000 0000 1000 alaw 8 bit */
, MPG123_ENC_ALAW_8 = 0x08
/* 0001 0001 1000 0000 signed 32 bit */
, MPG123_ENC_SIGNED_32 = MPG123_ENC_32|MPG123_ENC_SIGNED|0x1000
/* 0010 0001 0000 0000 unsigned 32 bit */
, MPG123_ENC_UNSIGNED_32 = MPG123_ENC_32|0x2000
/* 0101 0000 1000 0000 signed 24 bit */
, MPG123_ENC_SIGNED_24 = MPG123_ENC_24|MPG123_ENC_SIGNED|0x1000
/* 0110 0000 0000 0000 unsigned 24 bit */
, MPG123_ENC_UNSIGNED_24 = MPG123_ENC_24|0x2000
/* 0000 0010 0000 0000 32bit float */
, MPG123_ENC_FLOAT_32 = 0x200
/* 0000 0100 0000 0000 64bit float */
, MPG123_ENC_FLOAT_64 = 0x400
/* Any possibly known encoding from the list above. */
, MPG123_ENC_ANY = ( MPG123_ENC_SIGNED_16 | MPG123_ENC_UNSIGNED_16
| MPG123_ENC_UNSIGNED_8 | MPG123_ENC_SIGNED_8
| MPG123_ENC_ULAW_8 | MPG123_ENC_ALAW_8
| MPG123_ENC_SIGNED_32 | MPG123_ENC_UNSIGNED_32
| MPG123_ENC_SIGNED_24 | MPG123_ENC_UNSIGNED_24
| MPG123_ENC_FLOAT_32 | MPG123_ENC_FLOAT_64 )
};
/** Get size of one PCM sample with given encoding.
* This is included both in libmpg123 and libout123. Both offer
* an API function to provide the macro results from library
* compile-time, not that of you application. This most likely
* does not matter as I do not expect any fresh PCM sample
* encoding to appear. But who knows? Perhaps the encoding type
* will be abused for funny things in future, not even plain PCM.
* And, by the way: Thomas really likes the ?: operator.
* \param enc the encoding (mpg123_enc_enum value)
* \return size of one sample in bytes
*/
#define MPG123_SAMPLESIZE(enc) ( \
(enc) & MPG123_ENC_8 \
? 1 \
: ( (enc) & MPG123_ENC_16 \
? 2 \
: ( (enc) & MPG123_ENC_24 \
? 3 \
: ( ( (enc) & MPG123_ENC_32 \
|| (enc) == MPG123_ENC_FLOAT_32 ) \
? 4 \
: ( (enc) == MPG123_ENC_FLOAT_64 \
? 8 \
: 0 \
) ) ) ) )
/** Structure defining an audio format.
* Providing the members as individual function arguments to define a certain
* output format is easy enough. This struct makes is more comfortable to deal
* with a list of formats.
* Negative values for the members might be used to communicate use of default
* values.
*/
struct mpg123_fmt
{
long rate; /**< sampling rate in Hz */
int channels; /**< channel count */
/** encoding code, can be single value or bitwise or of members of
* mpg123_enc_enum */
int encoding;
};
/* @} */
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,580 @@
/*
out123: audio output interface
copyright 1995-2016 by the mpg123 project,
free software under the terms of the LGPL 2.1
see COPYING and AUTHORS files in distribution or http://mpg123.org
initially written as audio.h by Michael Hipp, reworked into out123 API
by Thomas Orgis
*/
#ifndef _OUT123_H_
#define _OUT123_H_
/** \file out123.h The header file for the libout123 audio output facility. */
/* We only need size_t definition. */
#include <stddef.h>
/* Common audio encoding specification, including a macro for getting
* size of encodined samples in bytes. Said macro is still hardcoded
* into out123_encsize(). Relying on this one may help an old program
* know sizes of encodings added to fmt123.h later on.
* If you don't care, just use the macro.
*/
#include <fmt123.h>
/** A macro to check at compile time which set of API functions to expect.
* This should be incremented at least each time a new symbol is added
* to the header.
*/
#define OUT123_API_VERSION 1
/** Defines needed for MS Visual Studio(tm) DLL builds.
* Every public function must be prefixed with MPG123_EXPORT. When building
* the DLL ensure to define BUILD_MPG123_DLL. This makes the function accessible
* for clients and includes it in the import library which is created together
* with the DLL. When consuming the DLL ensure to define LINK_MPG123_DLL which
* imports the functions from the DLL.
*/
#ifdef BUILD_MPG123_DLL
/* The dll exports. */
#define MPG123_EXPORT __declspec(dllexport)
#else
#ifdef LINK_MPG123_DLL
/* The exe imports. */
#define MPG123_EXPORT __declspec(dllimport)
#else
/* Nothing on normal/UNIX builds */
#define MPG123_EXPORT
#endif
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** \defgroup out123_api out123 library API
* This is out123, a library focused on continuous playback of audio streams
* via various platform-specific output methods. It glosses over details of
* the native APIs to give an interface close to simply writing data to a
* file. There might be the option to tune details like buffer (period) sizes
* and the number of them on the device side in future, but the focus of the
* library is to ease the use case of just getting that raw audio data out
* there, without interruptions.
*
* The basic idea is to create a handle with out123_new() and open a certain
* output device (using a certain driver module, possibly build-time defaults)
* with out123_open(). Now, you can query the output device for supported
* encodings for given rate and channel count with out123_get_encodings() and
* decide what to use for actually starting playback with out123_start().
*
* Then, you just need to provide (interleaved pcm) data for playback with
* out123_play(), which will block when the device's buffers are full. You get
* your timing from that (instead of callbacks). If your program does the
* production of the audio data just a little bit faster than the playback,
* causing out123_play() to block ever so briefly, you're fine.
*
* You stop playback with out123_stop(), or just close the device and driver
* via out123_close(), or even just decide to drop it all and do out123_del()
* right away when you're done.
*
* There are other functions for specific needs, but the basic idea should be
* covered by the above.
@{
*/
/** Opaque structure for the libout123 handle. */
struct out123_struct;
/** Typedef shortcut as preferrend name for the handle type. */
typedef struct out123_struct out123_handle;
/** Enumeration of codes for the parameters that it is possible to set/get. */
enum out123_parms
{
OUT123_FLAGS = 1 /**< integer, various flags, see enum out123_flags */
, OUT123_PRELOAD /**< float, fraction of buffer to fill before playback */
, OUT123_GAIN /**< integer, output device gain (module-specific) */
, OUT123_VERBOSE /**< integer, verbosity to stderr, >= 0 */
, OUT123_DEVICEBUFFER /**<
* float, length of device buffer in seconds;
* This might be ignored, might have only a loose relation to actual
* buffer sizes and latency, depending on output driver. Try to tune
* this before opening a device if you want to influcence latency or reduce
* dropouts. Value <= 0 uses some default, usually favouring stable playback
* over low latency. Values above 0.5 are probably too much.
*/
, OUT123_PROPFLAGS /**< integer, query driver/device property flags (r/o) */
, OUT123_NAME /**< string, name of this instance (NULL restores default);
* The value returned by out123_getparam() might be different if the audio
* backend changed it (to be unique among clients, p.ex.).
* TODO: The name provided here is used as prefix in diagnostic messages. */
};
/** Flags to tune out123 behaviour */
enum out123_flags
{
OUT123_HEADPHONES = 0x01 /**< output to headphones (if supported) */
, OUT123_INTERNAL_SPEAKER = 0x02 /**< output to speaker (if supported) */
, OUT123_LINE_OUT = 0x04 /**< output to line out (if supported) */
, OUT123_QUIET = 0x08 /**< no printouts to stdandard error */
, OUT123_KEEP_PLAYING = 0x10 /**<
* When this is set (default), playback continues in a loop when the device
* does not consume all given data at once. This happens when encountering
* signals (like SIGSTOP, SIGCONT) that cause interruption of the underlying
* functions.
* Note that this flag is meaningless when the optional buffer is employed,
* There, your program will always block until the buffer completely took
* over the data given to it via out123_play(), unless a communcation error
* arises.
*/
};
/** Read-only output driver/device property flags (OUT123_PROPFLAGS). */
enum out123_propflags
{
OUT123_PROP_LIVE = 0x01 /**< This is a live output, meaning that
* special care might be needed for pauses in playback (p.ex. stream
* of silence instead of interruption), as opposed to files on disk.
*/
, OUT123_PROP_PERSISTENT = 0x02 /**< This (live) output does not need
* special care for pauses (continues with silence itself),
* out123_pause() does nothing to the device.
*/
};
/** Create a new output handle.
* This only allocates and initializes memory, so the only possible
* error condition is running out of memory.
* \return pointer to new handle or NULL on error
*/
MPG123_EXPORT
out123_handle *out123_new(void);
/** Delete output handle.
* This implies out123_close().
*/
MPG123_EXPORT
void out123_del(out123_handle *ao);
/** Error code enumeration
* API calls return a useful (positve) value or zero (OUT123_OK) on simple
* success. A negative value (-1 == OUT123_ERR) usually indicates that some
* error occured. Which one, that can be queried using out123_errcode()
* and friends.
*/
enum out123_error
{
OUT123_ERR = -1 /**< generic alias for verbosity, always == -1 */
, OUT123_OK = 0 /**< just a name for zero, not going to change */
, OUT123_DOOM /**< dazzled, out of memory */
, OUT123_BAD_DRIVER_NAME /**< bad driver name given */
, OUT123_BAD_DRIVER /**< unspecified issue loading a driver */
, OUT123_NO_DRIVER /**< no driver loaded */
, OUT123_NOT_LIVE /**< no active audio device */
, OUT123_DEV_PLAY /**< some device playback error */
, OUT123_DEV_OPEN /**< error opening device */
, OUT123_BUFFER_ERROR /**<
* Some (really unexpected) error in buffer infrastructure.
*/
, OUT123_MODULE_ERROR /**< basic failure in module loading */
, OUT123_ARG_ERROR /**< some bad function arguments supplied */
, OUT123_BAD_PARAM /**< unknown parameter code */
, OUT123_SET_RO_PARAM /**< attempt to set read-only parameter */
, OUT123_ERRCOUNT /**< placeholder for shaping arrays */
};
/** Get string representation of last encountered error in the
* context of given handle.
* \param ao handle
* \return error string
*/
MPG123_EXPORT
const char* out123_strerror(out123_handle *ao);
/** Get the plain errcode intead of a string.
* \param ao handle
* \return error code recorded in handle or OUT123_BAD_HANDLE
*/
MPG123_EXPORT
int out123_errcode(out123_handle *ao);
/** Return the error string for a given error code.
* \param errcode the integer error code
* \return error string
*/
MPG123_EXPORT
const char* out123_plain_strerror(int errcode);
/** Set a desired output buffer size.
* This starts a separate process that handles the audio output, decoupling
* the latter from the main process with a memory buffer and saving you the
* burden to ensure sparing CPU cycles for actual playback.
* This is for applicatons that prefer continuous playback over small latency.
* In other words: The kind of applications that out123 is designed for.
* This routine always kills off any currently active audio output module /
* device, even if you just disable the buffer when there is no buffer.
*
* Keep this in mind for memory-constrainted systems: Activating the
* buffer causes a fork of the calling process, doubling the virtual memory
* use. Depending on your operating system kernel's behaviour regarding
* memory overcommit, it might be wise to call out123_set_buffer() very
* early in your program before allocating lots of memory.
*
* There _might_ be a change to threads in future, but for now this is
* classic fork with shared memory, working without any threading library.
* If your platform or build does not support that, you will always get an
* error on trying to set up a non-zero buffer (but the API call will be
* present).
*
* Also, if you do intend to use this from a multithreaded program, think
* twice and make sure that your setup is happy with forking full-blown
* processes off threaded programs. Probably you are better off spawning a
* buffer thread yourself.
*
* \param ao handle
* \param buffer_bytes size (bytes) of a memory buffer for decoded audio,
* a value of zero disables the buffer.
* \return 0 on success, OUT123_ERR on error
*/
MPG123_EXPORT
int out123_set_buffer(out123_handle *ao, size_t buffer_bytes);
/** Set a specific parameter, for a specific out123_handle, using a parameter
* code chosen from the out123_parms enumeration, to the specified value.
* The parameters usually only change what happens on next out123_open, not
* incfluencing running operation.
* \param ao handle
* \param code parameter code
* \param value input value for integer parameters
* \param fvalue input value for floating point parameters
* \param svalue input value for string parameters (contens are copied)
* \return 0 on success, OUT123_ERR on error.
*/
MPG123_EXPORT
int out123_param( out123_handle *ao, enum out123_parms code
, long value, double fvalue, const char *svalue );
#define out123_param_int(ao, code, value) \
out123_param((ao), (code), (value), 0., NULL)
#define out123_param_float(ao, code, value) \
out123_param((ao), (code), 0, (value), NULL)
#define out123_param_string(ao, code, value) \
out123_param((ao), (code), 0, 0., (value))
/** Get a specific parameter, for a specific out123_handle, using a parameter
* code chosen from the out123_parms enumeration, to the specified value.
* \param ao handle
* \param code parameter code
* \param ret_value output address for integer parameters
* \param ret_fvalue output address for floating point parameters
* \param ret_svalue output address for string parameters (pointer to
* internal memory, so no messing around, please)
* \return 0 on success, OUT123_ERR on error (bad parameter name or bad handle).
*/
MPG123_EXPORT
int out123_getparam( out123_handle *ao, enum out123_parms code
, long *ret_value, double *ret_fvalue, char* *ret_svalue );
#define out123_getparam_int(ao, code, value) \
out123_getparam((ao), (code), (value), NULL, NULL)
#define out123_getparam_float(ao, code, value) \
out123_getparam((ao), (code), NULL, (value), NULL)
#define out123_getparam_string(ao, code, value) \
out123_getparam((ao), (code), NULL, NULL, (value))
/** Copy parameters from another out123_handle.
* \param ao handle
* \param from_ao the handle to copy parameters from
* \return 0 in success, -1 on error
*/
MPG123_EXPORT
int out123_param_from(out123_handle *ao, out123_handle* from_ao);
/** Get list of driver modules reachable in system in C argv-style format.
* The client is responsible for freeing the memory of both the individual
* strings and the lists themselves.
* A module that is not loadable because of missing libraries is simply
* skipped. You will get stderr messages about that unless OUT123_QUIET was
* was set, though. Failure to open the module directory is a serious error,
* resulting in negative return value.
* \param ao handle
* \param names address for storing list of names
* \param descr address for storing list of descriptions
* \return number of drivers found, -1 on error
*/
MPG123_EXPORT
int out123_drivers(out123_handle *ao, char ***names, char ***descr);
/** Open an output device with a certain driver
* Note: Opening means that the driver code is loaded and the desired
* device name recorded, possibly tested for availability or tentatively
* opened. After out123_open(), you can ask for supported encodings
* and then really open the device for playback with out123_start().
* \param ao handle
* \param driver (comma-separated list of) output driver name(s to try),
* NULL for default (stdout for file-based drivers)
* \param device device name to open, NULL for default
* \return 0 on success, -1 on error.
*/
MPG123_EXPORT
int out123_open(out123_handle *ao, const char* driver, const char* device);
/** Give info about currently loaded driver and device
* Any of the return addresses can be NULL if you are not interested in
* everything. You get pointers to internal storage. They are valid
* as long as the driver/device combination is opened.
* The device may be NULL indicating some unnamed default.
* TODO: Make the driver modules return names for such defaults.
* \param ao handle
* \param driver return address for driver name
* \param device return address for device name
* \return 0 on success, -1 on error (i.e. no driver loaded)
*/
MPG123_EXPORT
int out123_driver_info(out123_handle *ao, char **driver, char **device);
/** Close the current output device and driver.
* This implies out123_drain() to ensure no data is lost.
* With a buffer, that might cause considerable delay during
* which your main application is blocked waiting.
* Call out123_drop() beforehand if you want to end things
* quickly.
* \param ao handle
*/
MPG123_EXPORT
void out123_close(out123_handle *ao);
/** Get supported audio encodings for given rate and channel count,
* for the currently openend audio device.
* TODO: Reopening the underlying audio device for each query
* is dumb, at least when dealing with JACK. It takes
* a long time and is just a waste. Reconsider that.
* Make sure that all output modules are fine with it, though!
* Usually, a wider range of rates is supported, but the number
* of sample encodings is limited, as is the number of channels.
* So you can call this with some standard rate and hope that the
* returned encodings work also for others, with the tested channel
* count.
* The return value of -1 on some encountered error conveniently also
* does not match any defined format (only 15 bits used for encodings,
* so this would even work with 16 bit integers).
* This implies out123_stop() to enter query mode.
* \param ao handle
* \param rate sampling rate
* \param channels number of channels
* \return supported encodings combined with bitwise or, to be checked
* against your favourite bitmask, -1 on error
*/
MPG123_EXPORT
int out123_encodings(out123_handle *ao, long rate, int channels);
/** Return the size (in bytes) of one mono sample of the named encoding.
* \param encoding The encoding value to analyze.
* \return positive size of encoding in bytes, 0 on invalid encoding. */
MPG123_EXPORT int out123_encsize(int encoding);
/** Get list of supported formats for currently opened audio device.
* Given a list of sampling rates and minimal/maximal channel count,
* this quickly checks what formats are supported with these
* constraints. The first entry is always reserved for a default
* format for the output device. If there is no such default,
* all values of the format are -1.
* For each requested combination of rate and channels, a format entry is
* created, possible with encoding value 0 to indicate that this combination
* has been tested and rejected. So, when there is no basic error, the
* number of returned format entries should be
* (ratecount*(maxchannels-minchannels+1)+1)
* . But instead of forcing you to guess, this will be allocated by
* successful run.
* For the first entry, the encoding member is supposed to be a definite
* encoding, for the others it is a bitwise combination of all possible
* encodings.
* This function is more efficient than many calls to out123_encodings().
* \param ao handle
* \param rates pointer to an array of sampling rates, may be NULL for none
* \param ratecount number of provided sampling rates
* \param minchannels minimal channel count
* \param maxchannels maximal channel count
* \param fmtlist return address for array of supported formats
* the encoding field of each entry is a combination of all
* supported encodings at this rate and channel count;
* Memory shall be freed by user.
* \return number of returned format enries, -1 on error
*/
MPG123_EXPORT
int out123_formats( out123_handle *ao, const long *rates, int ratecount
, int minchannels, int maxchannels
, struct mpg123_fmt **fmtlist );
/** Get list of encodings known to the library.
* You are responsible for freeing the allocated array.
* \param enclist return address for allocated array of encoding codes
* \return number of encodings, -1 on error
*/
MPG123_EXPORT
int out123_enc_list(int **enclist);
/** Find encoding code by name.
* \param name short or long name to find encoding code for
* \return encoding if found (enum mpg123_enc_enum), else 0
*/
MPG123_EXPORT
int out123_enc_byname(const char *name);
/** Get name of encoding.
* \param encoding code (enum mpg123_enc_enum)
* \return short name for valid encodings, NULL otherwise
*/
MPG123_EXPORT
const char* out123_enc_name(int encoding);
/** Get long name of encoding.
* \param encoding code (enum mpg123_enc_enum)
* \return long name for valid encodings, NULL otherwise
*/
MPG123_EXPORT
const char* out123_enc_longname(int encoding);
/** Start playback with a certain output format
* It might be a good idea to have audio data handy to feed after this
* returns with success.
* Rationale for not taking a pointer to struct mpg123_fmt: This would
* always force you to deal with that type and needlessly enlarge the
* shortest possible program.
* \param ao handle
* \param encoding sample encoding (values matching libmpg123 API)
* \param channels number of channels (1 or 2, usually)
* \param rate sampling rate
* \return 0 on success, negative on error (bad format, usually)
*/
MPG123_EXPORT
int out123_start( out123_handle *ao
, long rate, int channels, int encoding );
/** Pause playback
* Interrupt playback, holding any data in the optional buffer.
*
* This closes the audio device if it is a live sink, ready to be re-opened
* by out123_continue() or out123_play() with the existing parameters.
* \param ao handle
*/
MPG123_EXPORT
void out123_pause(out123_handle *ao);
/** Continue playback
* The counterpart to out123_pause(). Announce to the driver that playback
* shall continue.
*
* Playback might not resume immediately if the optional buffer is configured
* to wait for a minimum fill and close to being empty. You can force playback
* of the last scrap with out123_drain(), or just by feeding more data with
* out123_play(), which will trigger out123_continue() for you, too.
* \param ao handle
*/
MPG123_EXPORT
void out123_continue(out123_handle *ao);
/** Stop playback.
* This waits for pending audio data to drain to the speakers.
* You might want to call out123_drop() before stopping if you want
* to end things right away.
* \param ao handle
*/
MPG123_EXPORT
void out123_stop(out123_handle *ao);
/** Hand over data for playback and wait in case audio device is busy.
* This survives non-fatal signals like SIGSTOP/SIGCONT and keeps on
* playing until the buffer is done with if the flag
* OUT123_KEEP_PLAYING ist set (default). So, per default, if
* you provided a byte count divisible by the PCM frame size, it is an
* error when less bytes than given are played.
* To be sure if an error occured, check out123_errcode().
* Also note that it is no accident that the buffer parameter is not marked
* as constant. Some output drivers might need to do things like swap
* byte order. This is done in-place instead of wasting memory on yet
* another copy.
* \param ao handle
* \param buffer pointer to raw audio data to be played
* \param bytes number of bytes to read from the buffer
* \return number of bytes played (might be less than given, even zero)
*/
MPG123_EXPORT
size_t out123_play( out123_handle *ao
, void *buffer, size_t bytes );
/** Drop any buffered data, making next provided data play right away.
* This does not imply an actual pause in playback.
* You are expected to play something, unless you called out123_pause().
* Feel free to call out123_stop() afterwards instead for a quicker
* exit than the implied out123_drain().
* For live sinks, this may include dropping data from their buffers.
* For others (files), this only concerns data in the optional buffer.
* \param ao handle
*/
MPG123_EXPORT
void out123_drop(out123_handle *ao);
/** Drain the output, waiting until all data went to the hardware.
* This does imply out123_continue() before and out123_pause()
* after draining.
* This might involve only the optional buffer process, or the
* buffers on the audio driver side, too.
* \param ao handle
*/
MPG123_EXPORT
void out123_drain(out123_handle *ao);
/** Drain the output, but only partially up to the given number of
* bytes. This gives you the opportunity to do something while
* the optional buffer is writing remaining data instead of having
* one atomic API call for it all.
*
* It is wholly expected that the return value of out123_buffered()
* before and after calling this has a bigger difference than the
* provided limit, as the buffer is writing all the time in the
* background.
*
* This is just a plain out123_drain() if the optional buffer is not
* in use. Also triggers out123_continue(), but only out123_pause()
* if there is no buffered data anymore.
* \param ao handle
* \param bytes limit of buffered bytes to drain
* \return number of bytes drained from buffer
*/
MPG123_EXPORT
void out123_ndrain(out123_handle *ao, size_t bytes);
/** Get an indication of how many bytes reside in the optional buffer.
* This might get extended to tell the number of bytes queued up in the
* audio backend, too.
* \param ao handle
* \return number of bytes in out123 library buffer
*/
MPG123_EXPORT
size_t out123_buffered(out123_handle *ao);
/** Extract currently used audio format from handle.
* matching mpg123_getformat().
* Given return addresses may be NULL to indicate no interest.
* \param ao handle
* \param rate address for sample rate
* \param channels address for channel count
* \param encoding address for encoding
* \param framesize size of a full PCM frame (for convenience)
* \return 0 on success, -1 on error
*/
MPG123_EXPORT
int out123_getformat( out123_handle *ao
, long *rate, int *channels, int *encoding, int *framesize );
/* @} */
#ifdef __cplusplus
}
#endif
#undef MPG123_EXPORT
#endif

View File

@ -0,0 +1,117 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{04118CC2-DE10-4627-A695-2219428C7D59}</ProjectGuid>
<RootNamespace>mpg123decoder</RootNamespace>
<Keyword>Win32Proj</Keyword>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<PlatformToolset>v140</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<_ProjectFileVersion>14.0.25123.0</_ProjectFileVersion>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<OutDir>$(SolutionDir)\bin\$(Configuration)\plugins\</OutDir>
<IntDir>$(SolutionDir)/obj/$(Configuration)\</IntDir>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)\bin\$(Configuration)\plugins\</OutDir>
<IntDir>$(SolutionDir)/obj/$(Configuration)\</IntDir>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<CodeAnalysisRules />
<CodeAnalysisRuleAssemblies />
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<Optimization>Disabled</Optimization>
<AdditionalIncludeDirectories>.;../..;../../3rdparty/include;./include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;_DEBUG;DEBUG;_WINDOWS;OPT_GENERIC;_LIB;FLOATOUT;REAL_IS_FLOAT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<MinimalRebuild>false</MinimalRebuild>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;libmpg123.dll.a;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>./bin;../../3rdparty/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
<PostBuildEvent>
<Command>xcopy /Y $(ProjectDir)bin\*.dll $(OutDir)</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<AdditionalIncludeDirectories>.;../..;../../3rdparty/include;./include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;REAL_IS_FLOAT;OPT_GENERIC;_LIB;FLOATOUT;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<PrecompiledHeader />
<WarningLevel>Level3</WarningLevel>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
</ClCompile>
<Link>
<AdditionalDependencies>shlwapi.lib;libmpg123.dll.a;%(AdditionalDependencies)</AdditionalDependencies>
<AdditionalLibraryDirectories>./bin;../../3rdparty/lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
<PostBuildEvent>
<Command>xcopy /Y $(ProjectDir)bin\*.dll $(OutDir)</Command>
</PostBuildEvent>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="Mpg123Decoder.cpp" />
<ClCompile Include="Mpg123DecoderFactory.cpp" />
<ClCompile Include="mpg123decoder_plugin.cpp" />
<ClCompile Include="stdafx.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="Mpg123Decoder.h" />
<ClInclude Include="Mpg123DecoderFactory.h" />
<ClInclude Include="mpg123\src\config.h" />
<ClInclude Include="mpg123\src\libmpg123\mpg123.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="stdafx.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,40 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav</Extensions>
</Filter>
<Filter Include="plugin">
<UniqueIdentifier>{25ee4e18-20e5-4c49-a9e3-578acf41d396}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>plugin</Filter>
</ClCompile>
<ClCompile Include="Mpg123DecoderFactory.cpp">
<Filter>plugin</Filter>
</ClCompile>
<ClCompile Include="Mpg123Decoder.cpp">
<Filter>plugin</Filter>
</ClCompile>
<ClCompile Include="mpg123decoder_plugin.cpp">
<Filter>plugin</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>plugin</Filter>
</ClInclude>
<ClInclude Include="mpg123\src\config.h" />
<ClInclude Include="mpg123\src\libmpg123\mpg123.h" />
<ClInclude Include="resource.h" />
<ClInclude Include="Mpg123DecoderFactory.h">
<Filter>plugin</Filter>
</ClInclude>
<ClInclude Include="Mpg123Decoder.h">
<Filter>plugin</Filter>
</ClInclude>
</ItemGroup>
</Project>

View File

@ -51,23 +51,12 @@ IDecoder* OggDecoderFactory::CreateDecoder() {
}
bool OggDecoderFactory::CanHandle(const char* type) const {
std::string typeString(type);
std::string str(type);
std::transform(str.begin(), str.end(), str.begin(), tolower);
if (typeString.find("ogg") != std::string::npos) {
return true;
}
if (typeString.find("oga") != std::string::npos) {
return true;
}
if (typeString.find("audio/ogg") != std::string::npos) {
return true;
}
if (typeString.find("audio/vorbis") != std::string::npos) {
return true;
}
return false;
return
musik::sdk::endsWith(str, ".ogg") ||
musik::sdk::endsWith(str, ".oga") ||
str.find("audio/ogg") != std::string::npos ||
str.find("audio/vorbis") != std::string::npos;
}

View File

@ -34,7 +34,7 @@
#include "WaveOut.h"
#define MAX_VOLUME 0xFFFF
#define MAX_BUFFERS 32
#define MAX_BUFFERS 8
static void notifyBufferProcessed(WaveOutBuffer *buffer) {
/* let the provider know the output device is done with the buffer; the

View File

@ -38,7 +38,7 @@
#include <core/plugin/PluginFactory.h>
#include <algorithm>
#define MAX_PREBUFFER_QUEUE_COUNT 16
#define MAX_PREBUFFER_QUEUE_COUNT 8
using namespace musik::core::audio;
using std::min;

View File

@ -84,6 +84,13 @@ PluginFactory::~PluginFactory(void){
void PluginFactory::LoadPlugins(){
boost::mutex::scoped_lock lock(this->mutex);
#ifdef WIN32
{
std::wstring wpath = u8to16(GetPluginDirectory());
SetDllDirectory(wpath.c_str());
}
#endif
std::string pluginDir(GetPluginDirectory());
boost::filesystem::path dir(pluginDir);
@ -95,7 +102,6 @@ void PluginFactory::LoadPlugins(){
#ifdef WIN32
/* if the file ends with ".dll", we'll try to load it*/
if (filename.substr(filename.size() - 4) == ".dll") {
HMODULE dll = LoadLibrary(u8to16(filename).c_str());
if (dll != NULL) {
/* every plugin has a "GetPlugin" method. */

View File

@ -38,8 +38,8 @@
#ifdef WIN32
#define WIN32_LEAN_AND_MEAN
#define WINVER 0x0501
#define _WIN32_WINNT 0x0501
#define WINVER 0x0502
#define _WIN32_WINNT 0x0502
#define NOMINMAX
#include <windows.h>
@ -60,3 +60,18 @@
#endif
#define _ASSERT assert
#endif
#include <string>
/* a super small collection of inlined tools that most plugins will
need to use. these should be header only, and have no dependencies
other than STL */
namespace musik {
namespace sdk {
inline bool endsWith(const std::string& s, const std::string& suffix) {
return
s.size() >= suffix.size() &&
s.rfind(suffix) == (s.size() - suffix.size());
}
}
}