mirror of
https://github.com/clangen/musikcube.git
synced 2024-10-02 13:02:35 +00:00
Fixed WaveOut to actually use both channels, instead of just the left one. Also fixed a few bugs related to closing WaveOut.
This commit is contained in:
parent
fe1b2827e4
commit
a0f7a7670c
@ -1,233 +0,0 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright © 2007, mC2 team
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of the author nor the names of other contributors may
|
||||
// be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
#include "StdAfx.h"
|
||||
#include "OGGDecoder.h"
|
||||
|
||||
OGGDecoder::OGGDecoder()
|
||||
{
|
||||
// Set the callbacks to handle all file io
|
||||
this->oggCallbacks.read_func = &OggRead;
|
||||
this->oggCallbacks.seek_func = &OggSeek;
|
||||
this->oggCallbacks.tell_func = &OggTell;
|
||||
this->oggCallbacks.close_func = &OggClose;
|
||||
|
||||
|
||||
}
|
||||
|
||||
size_t OGGDecoder::OggRead(void *buffer, size_t nofParts, size_t partSize, void *datasource){
|
||||
return (size_t)((OGGDecoder*)datasource)->fileStream->Read(buffer,(long)(nofParts*partSize));
|
||||
}
|
||||
|
||||
int OGGDecoder::OggSeek(void *datasource, ogg_int64_t offset, int whence){
|
||||
switch(whence){
|
||||
case SEEK_CUR:
|
||||
{
|
||||
long currentPosition = ((OGGDecoder*)datasource)->fileStream->Position();
|
||||
if( ((OGGDecoder*)datasource)->fileStream->SetPosition(currentPosition+(long)offset)){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SEEK_END:
|
||||
{
|
||||
long fileSize = ((OGGDecoder*)datasource)->fileStream->Filesize();
|
||||
if( ((OGGDecoder*)datasource)->fileStream->SetPosition(fileSize)){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if( ((OGGDecoder*)datasource)->fileStream->SetPosition((long)offset)){
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Unsuccessfull
|
||||
return -1;
|
||||
}
|
||||
|
||||
long OGGDecoder::OggTell(void *datasource){
|
||||
return ((OGGDecoder*)datasource)->fileStream->Position();
|
||||
}
|
||||
|
||||
int OGGDecoder::OggClose(void *datasource){
|
||||
if( ((OGGDecoder*)datasource)->fileStream->Close() ){
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
OGGDecoder::~OGGDecoder()
|
||||
{
|
||||
}
|
||||
|
||||
bool OGGDecoder::Open(musik::core::filestreams::IFileStream *fileStream)
|
||||
{
|
||||
this->fileStream = fileStream;
|
||||
|
||||
if(ov_open_callbacks(this,&this->oggFile,NULL,0,this->oggCallbacks)!=0){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void OGGDecoder::Destroy(void){
|
||||
|
||||
ov_clear(&this->oggFile);
|
||||
|
||||
delete this;
|
||||
}
|
||||
/*
|
||||
bool OGGDecoder::GetFormat(unsigned long * SampleRate, unsigned long * Channels){
|
||||
vorbis_info *info = ov_info(&this->oggFile,-1);
|
||||
if(info){
|
||||
*SampleRate = info->rate;
|
||||
*Channels = info->channels;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool OGGDecoder::GetLength(unsigned long * MS){
|
||||
double time = ov_time_total(&this->oggFile, 0);
|
||||
if( time!=OV_EINVAL ){
|
||||
*MS = (unsigned long)(time * 1000.0);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
double OGGDecoder::SetPosition(double second,double totalLength){
|
||||
|
||||
if(ov_seekable(&this->oggFile)){
|
||||
if(!ov_time_seek(&this->oggFile, second)){
|
||||
return ov_time_tell(&this->oggFile);
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool OGGDecoder::GetBuffer(IBuffer *buffer){
|
||||
vorbis_info *info = ov_info(&this->oggFile, -1);
|
||||
|
||||
long nofSamplesMax = 1024*2;
|
||||
int currentSelection;
|
||||
|
||||
buffer->SetChannels(info->channels);
|
||||
buffer->SetSampleRate(info->rate);
|
||||
buffer->SetSamples(nofSamplesMax);
|
||||
|
||||
float ** pcm;
|
||||
unsigned long samplesRead = ov_read_float(&this->oggFile, &pcm, nofSamplesMax, ¤tSelection);
|
||||
if(samplesRead == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
buffer->SetSamples(samplesRead);
|
||||
|
||||
/* MUSIKCUBE EXPECTS
|
||||
SPEAKER_FRONT_LEFT 0x1
|
||||
SPEAKER_FRONT_RIGHT 0x2
|
||||
SPEAKER_FRONT_CENTER 0x4
|
||||
SPEAKER_LOW_FREQUENCY 0x8
|
||||
SPEAKER_BACK_LEFT 0x10
|
||||
SPEAKER_BACK_RIGHT 0x20
|
||||
*/
|
||||
|
||||
/* OGG DOES
|
||||
|
||||
One channel: the stream is monophonic
|
||||
Two channels: the stream is stereo. channel order: left, right.
|
||||
Three channels: the stream is a 1d-surround encoding. channel order: left, center, right
|
||||
Four channels: the stream is quadraphonic surround. channel order: front left, front right, rear left, rear right
|
||||
Five channels: the stream is five-channel surround. channel order: front left, front center, front right, rear left, rear right
|
||||
Six channels: (used in Dolby Digital/AC3) the stream is 5,1 surround. channel order: front left, front center, front right, rear left, rear right, LFE (the sixth channel is entirely bass).
|
||||
*/
|
||||
|
||||
// so we need to REORDER
|
||||
float *pDataBuffer = buffer->BufferPointer();
|
||||
|
||||
if(info->channels == 3){
|
||||
float *pDataBuffer = buffer->BufferPointer();
|
||||
for(unsigned long x=0; x<samplesRead; ++x){
|
||||
*pDataBuffer = pcm[0][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[2][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[1][x];
|
||||
++pDataBuffer;
|
||||
}
|
||||
}else if(info->channels == 5){
|
||||
for(unsigned long x=0; x<samplesRead; ++x){
|
||||
*pDataBuffer = pcm[0][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[2][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[1][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[3][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[4][x];
|
||||
++pDataBuffer;
|
||||
}
|
||||
}else if(info->channels == 6){
|
||||
for(unsigned long x=0; x<samplesRead; ++x){
|
||||
*pDataBuffer = pcm[0][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[2][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[1][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[5][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[3][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[4][x];
|
||||
++pDataBuffer;
|
||||
}
|
||||
}else{
|
||||
for(unsigned long x=0; x<samplesRead; ++x){
|
||||
for(int channel(0); channel<info->channels; ++channel){
|
||||
*pDataBuffer = pcm[channel][x];
|
||||
++pDataBuffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -32,47 +32,41 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "stdafx.h"
|
||||
|
||||
#include <cctype>
|
||||
#include "OggDecoderFactory.h"
|
||||
#include "VorbisDecoder.h"
|
||||
|
||||
#include "OggSourceSupplier.h"
|
||||
|
||||
#include "OggDecoder.h"
|
||||
|
||||
OggSourceSupplier::OggSourceSupplier()
|
||||
{
|
||||
OggDecoderFactory::OggDecoderFactory() {
|
||||
}
|
||||
|
||||
OggSourceSupplier::~OggSourceSupplier()
|
||||
{
|
||||
OggDecoderFactory::~OggDecoderFactory() {
|
||||
}
|
||||
|
||||
void OggSourceSupplier::Destroy()
|
||||
{
|
||||
void OggDecoderFactory::Destroy() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
IDecoder* OggSourceSupplier::CreateDecoder()
|
||||
{
|
||||
return new OGGDecoder();
|
||||
IDecoder* OggDecoderFactory::CreateDecoder() {
|
||||
return new VorbisDecoder();
|
||||
}
|
||||
|
||||
bool OggSourceSupplier::CanHandle(const utfchar* type) const
|
||||
{
|
||||
if(type){
|
||||
bool OggDecoderFactory::CanHandle(const utfchar* type) const {
|
||||
if (type) {
|
||||
utfstring typeString(type);
|
||||
if(typeString.find(UTF("ogg"))!=utfstring::npos){
|
||||
|
||||
if (typeString.find(UTF("ogg")) != utfstring::npos) {
|
||||
return true;
|
||||
}
|
||||
if(typeString.find(UTF("oga"))!=utfstring::npos){
|
||||
if (typeString.find(UTF("oga")) != utfstring::npos) {
|
||||
return true;
|
||||
}
|
||||
if(typeString.find(UTF("audio/ogg"))!=utfstring::npos){
|
||||
if (typeString.find(UTF("audio/ogg")) != utfstring::npos) {
|
||||
return true;
|
||||
}
|
||||
if(typeString.find(UTF("audio/vorbis"))!=utfstring::npos){
|
||||
if (typeString.find(UTF("audio/vorbis")) != utfstring::npos) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
@ -37,10 +37,10 @@
|
||||
|
||||
using namespace musik::core::audio;
|
||||
|
||||
class OggSourceSupplier : public IDecoderFactory {
|
||||
class OggDecoderFactory : public IDecoderFactory {
|
||||
public:
|
||||
OggSourceSupplier();
|
||||
~OggSourceSupplier();
|
||||
OggDecoderFactory();
|
||||
~OggDecoderFactory();
|
||||
|
||||
IDecoder* CreateDecoder();
|
||||
void Destroy();
|
214
src/contrib/oggdecoder/VorbisDecoder.cpp
Normal file
214
src/contrib/oggdecoder/VorbisDecoder.cpp
Normal file
@ -0,0 +1,214 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright © 2007, mC2 team
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of the author nor the names of other contributors may
|
||||
// be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "StdAfx.h"
|
||||
#include "VorbisDecoder.h"
|
||||
|
||||
VorbisDecoder::VorbisDecoder() {
|
||||
this->oggCallbacks.read_func = &OggRead;
|
||||
this->oggCallbacks.seek_func = &OggSeek;
|
||||
this->oggCallbacks.tell_func = &OggTell;
|
||||
this->oggCallbacks.close_func = &OggClose;
|
||||
}
|
||||
|
||||
size_t VorbisDecoder::OggRead(void *buffer, size_t nofParts, size_t partSize, void *datasource) {
|
||||
return (size_t)((VorbisDecoder*)datasource)->fileStream->Read(buffer,(long)(nofParts*partSize));
|
||||
}
|
||||
|
||||
int VorbisDecoder::OggSeek(void *datasource, ogg_int64_t offset, int whence) {
|
||||
switch(whence) {
|
||||
case SEEK_CUR:
|
||||
{
|
||||
long currentPosition = ((VorbisDecoder*)datasource)->fileStream->Position();
|
||||
if(((VorbisDecoder*)datasource)->fileStream->SetPosition(currentPosition+(long) offset)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case SEEK_END:
|
||||
{
|
||||
long fileSize = ((VorbisDecoder*) datasource)->fileStream->Filesize();
|
||||
if(((VorbisDecoder*) datasource)->fileStream->SetPosition(fileSize)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
if(((VorbisDecoder*) datasource)->fileStream->SetPosition((long) offset)) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
long VorbisDecoder::OggTell(void *datasource) {
|
||||
return ((VorbisDecoder*)datasource)->fileStream->Position();
|
||||
}
|
||||
|
||||
int VorbisDecoder::OggClose(void *datasource) {
|
||||
if(((VorbisDecoder*)datasource)->fileStream->Close()) {
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
VorbisDecoder::~VorbisDecoder() {
|
||||
}
|
||||
|
||||
bool VorbisDecoder::Open(musik::core::filestreams::IFileStream *fileStream) {
|
||||
this->fileStream = fileStream;
|
||||
|
||||
if (ov_open_callbacks(this, &this->oggFile, NULL, 0, this->oggCallbacks) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void VorbisDecoder::Destroy() {
|
||||
ov_clear(&this->oggFile);
|
||||
delete this;
|
||||
}
|
||||
|
||||
double VorbisDecoder::SetPosition(double second, double totalLength) {
|
||||
if (ov_seekable(&this->oggFile)) {
|
||||
if (!ov_time_seek(&this->oggFile, second)) {
|
||||
return ov_time_tell(&this->oggFile);
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
#define OGG_MAX_SAMPLES 1024
|
||||
|
||||
bool VorbisDecoder::GetBuffer(IBuffer *buffer) {
|
||||
int bitstream;
|
||||
float **pcm;
|
||||
|
||||
unsigned long samplesRead = ov_read_float(&this->oggFile, &pcm, OGG_MAX_SAMPLES, &bitstream);
|
||||
|
||||
if (samplesRead == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
vorbis_info *info = ov_info(&this->oggFile, -1);
|
||||
buffer->SetChannels(info->channels);
|
||||
buffer->SetSampleRate(info->rate);
|
||||
buffer->SetSamples(samplesRead);
|
||||
|
||||
/*
|
||||
The musik audio engine expects:
|
||||
|
||||
SPEAKER_FRONT_LEFT 0x1
|
||||
SPEAKER_FRONT_RIGHT 0x2
|
||||
SPEAKER_FRONT_CENTER 0x4
|
||||
SPEAKER_LOW_FREQUENCY 0x8
|
||||
SPEAKER_BACK_LEFT 0x10
|
||||
SPEAKER_BACK_RIGHT 0x20
|
||||
|
||||
OGG returns:
|
||||
|
||||
One channel: the stream is monophonic
|
||||
Two channels: the stream is stereo. channel order: left, right.
|
||||
Three channels: the stream is a 1d-surround encoding. channel order: left, center, right
|
||||
Four channels: the stream is quadraphonic surround. channel order: front left, front right, rear left, rear right
|
||||
Five channels: the stream is five-channel surround. channel order: front left, front center, front right, rear left, rear right
|
||||
Six channels: (used in Dolby Digital/AC3) the stream is 5,1 surround. channel order: front left, front center, front right, rear left, rear right, LFE (the sixth channel is entirely bass).
|
||||
|
||||
... so let's re-order when writing to our output buffer ...
|
||||
*/
|
||||
|
||||
float *pDataBuffer = buffer->BufferPointer();
|
||||
|
||||
if (info->channels == 2) {
|
||||
for (unsigned long x = 0; x < samplesRead; ++x) {
|
||||
pDataBuffer[0] = pcm[0][x];
|
||||
pDataBuffer[1] = pcm[1][x];
|
||||
pDataBuffer += 2;
|
||||
}
|
||||
}
|
||||
else if (info->channels == 3) {
|
||||
for (unsigned long x=0; x < samplesRead; ++x) {
|
||||
*pDataBuffer = pcm[0][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[2][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[1][x];
|
||||
++pDataBuffer;
|
||||
}
|
||||
}
|
||||
else if (info->channels == 5) {
|
||||
for (unsigned long x = 0; x < samplesRead; ++x) {
|
||||
*pDataBuffer = pcm[0][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[2][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[1][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[3][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[4][x];
|
||||
++pDataBuffer;
|
||||
}
|
||||
}
|
||||
else if (info->channels == 6) {
|
||||
for (unsigned long x = 0; x < samplesRead; ++x) {
|
||||
*pDataBuffer = pcm[0][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[2][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[1][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[5][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[3][x];
|
||||
++pDataBuffer;
|
||||
*pDataBuffer = pcm[4][x];
|
||||
++pDataBuffer;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (unsigned long x = 0; x < samplesRead; ++x) {
|
||||
for (int channel(0); channel < info->channels; ++channel) {
|
||||
*pDataBuffer = pcm[channel][x];
|
||||
++pDataBuffer;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
@ -39,29 +39,28 @@
|
||||
|
||||
using namespace musik::core::audio;
|
||||
|
||||
class OGGDecoder : public IDecoder
|
||||
class VorbisDecoder : public IDecoder
|
||||
{
|
||||
|
||||
public:
|
||||
OGGDecoder();
|
||||
~OGGDecoder();
|
||||
VorbisDecoder();
|
||||
~VorbisDecoder();
|
||||
|
||||
public:
|
||||
virtual void Destroy();
|
||||
virtual double SetPosition(double second,double totalLength);
|
||||
virtual bool GetBuffer(IBuffer *buffer);
|
||||
virtual bool Open(musik::core::filestreams::IFileStream *fileStream);
|
||||
virtual void Destroy();
|
||||
virtual double SetPosition(double second, double totalLength);
|
||||
virtual bool GetBuffer(IBuffer *buffer);
|
||||
virtual bool Open(musik::core::filestreams::IFileStream *fileStream);
|
||||
|
||||
public:
|
||||
// OGG callbacks
|
||||
static size_t OggRead(void *buffer, size_t nofParts, size_t partSize, void *datasource);
|
||||
static int OggSeek(void *datasource, ogg_int64_t offset, int whence);
|
||||
static long OggTell(void *datasource);
|
||||
static int OggClose(void *datasource);
|
||||
/* libvorbis callbacks */
|
||||
static size_t OggRead(void *buffer, size_t nofParts, size_t partSize, void *datasource);
|
||||
static int OggSeek(void *datasource, ogg_int64_t offset, int whence);
|
||||
static long OggTell(void *datasource);
|
||||
static int OggClose(void *datasource);
|
||||
|
||||
protected:
|
||||
musik::core::filestreams::IFileStream *fileStream;
|
||||
OggVorbis_File oggFile;
|
||||
ov_callbacks oggCallbacks;
|
||||
|
||||
OggVorbis_File oggFile;
|
||||
ov_callbacks oggCallbacks;
|
||||
};
|
@ -93,14 +93,14 @@
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="OGGDecoder.cpp" />
|
||||
<ClCompile Include="VorbisDecoder.cpp" />
|
||||
<ClCompile Include="oggdecoder_plugin.cpp" />
|
||||
<ClCompile Include="OggSourceSupplier.cpp" />
|
||||
<ClCompile Include="OggDecoderFactory.cpp" />
|
||||
<ClCompile Include="stdafx.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="OGGDecoder.h" />
|
||||
<ClInclude Include="OggSourceSupplier.h" />
|
||||
<ClInclude Include="VorbisDecoder.h" />
|
||||
<ClInclude Include="OggDecoderFactory.h" />
|
||||
<ClInclude Include="stdafx.h" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
|
@ -38,7 +38,7 @@
|
||||
|
||||
#include <core/sdk/IPlugin.h>
|
||||
|
||||
#include "OggSourceSupplier.h"
|
||||
#include "OggDecoderFactory.h"
|
||||
|
||||
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
|
||||
return true;
|
||||
@ -57,5 +57,5 @@ extern "C" __declspec(dllexport) musik::core::IPlugin* GetPlugin() {
|
||||
}
|
||||
|
||||
extern "C" __declspec(dllexport) IDecoderFactory* GetDecoderFactory() {
|
||||
return new OggSourceSupplier();
|
||||
return new OggDecoderFactory();
|
||||
}
|
||||
|
@ -33,7 +33,7 @@
|
||||
|
||||
#include "WaveOut.h"
|
||||
|
||||
#define MAX_VOLUME 65535.0
|
||||
#define MAX_VOLUME 0xFFFF
|
||||
|
||||
WaveOut::WaveOut()
|
||||
: waveHandle(NULL)
|
||||
@ -51,7 +51,7 @@ WaveOut::~WaveOut(){
|
||||
}
|
||||
}
|
||||
|
||||
void WaveOut::Destroy(){
|
||||
void WaveOut::Destroy() {
|
||||
delete this;
|
||||
}
|
||||
|
||||
@ -66,7 +66,8 @@ void WaveOut::Resume() {
|
||||
void WaveOut::SetVolume(double volume) {
|
||||
if (this->waveHandle) {
|
||||
DWORD newVolume = (DWORD)(volume * MAX_VOLUME);
|
||||
waveOutSetVolume(this->waveHandle,newVolume);
|
||||
DWORD leftAndRight = (newVolume << 16) | newVolume;
|
||||
waveOutSetVolume(this->waveHandle, leftAndRight);
|
||||
}
|
||||
|
||||
this->currentVolume = volume;
|
||||
@ -148,7 +149,7 @@ void WaveOut::SetFormat(IBuffer *buffer) {
|
||||
this->currentSampleRate = buffer->SampleRate();
|
||||
|
||||
/* format changed, kill the old output device */
|
||||
if(this->waveHandle!=NULL) {
|
||||
if (this->waveHandle != NULL) {
|
||||
waveOutClose(this->waveHandle);
|
||||
this->waveHandle = NULL;
|
||||
}
|
||||
@ -156,44 +157,41 @@ void WaveOut::SetFormat(IBuffer *buffer) {
|
||||
/* reset, and configure speaker output */
|
||||
ZeroMemory(&this->waveFormat, sizeof(this->waveFormat));
|
||||
|
||||
DWORD speakerconfig = 0;
|
||||
DWORD speakerConfig = 0;
|
||||
|
||||
switch (buffer->Channels()) {
|
||||
case 1:
|
||||
speakerconfig = KSAUDIO_SPEAKER_MONO;
|
||||
speakerConfig = KSAUDIO_SPEAKER_MONO;
|
||||
break;
|
||||
case 2:
|
||||
speakerconfig = KSAUDIO_SPEAKER_STEREO;
|
||||
speakerConfig = KSAUDIO_SPEAKER_STEREO;
|
||||
break;
|
||||
case 4:
|
||||
speakerconfig = KSAUDIO_SPEAKER_QUAD;
|
||||
speakerConfig = KSAUDIO_SPEAKER_QUAD;
|
||||
break;
|
||||
case 5:
|
||||
speakerconfig = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT);
|
||||
speakerConfig = (SPEAKER_FRONT_LEFT | SPEAKER_FRONT_RIGHT | SPEAKER_FRONT_CENTER | SPEAKER_BACK_LEFT | SPEAKER_BACK_RIGHT);
|
||||
break;
|
||||
case 6:
|
||||
speakerconfig = KSAUDIO_SPEAKER_5POINT1;
|
||||
speakerConfig = KSAUDIO_SPEAKER_5POINT1;
|
||||
break;
|
||||
}
|
||||
|
||||
this->waveFormat.Format.cbSize = 22;
|
||||
this->waveFormat.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX);
|
||||
this->waveFormat.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE;
|
||||
this->waveFormat.Format.nChannels = (WORD) buffer->Channels();
|
||||
this->waveFormat.Format.wBitsPerSample = sizeof(float) * 8;
|
||||
this->waveFormat.Format.nSamplesPerSec = (DWORD) buffer->SampleRate();
|
||||
this->waveFormat.Format.wBitsPerSample = 32;
|
||||
|
||||
this->waveFormat.Format.nBlockAlign =
|
||||
(this->waveFormat.Format.wBitsPerSample / 8) * this->waveFormat.Format.nChannels;
|
||||
int bytesPerSample = this->waveFormat.Format.wBitsPerSample / 8;
|
||||
this->waveFormat.Format.nBlockAlign = bytesPerSample * this->waveFormat.Format.nChannels;
|
||||
|
||||
this->waveFormat.Format.nAvgBytesPerSec =
|
||||
((this->waveFormat.Format.wBitsPerSample/8) *
|
||||
this->waveFormat.Format.nChannels) *
|
||||
this->waveFormat.Format.nSamplesPerSec; /* Compute using nBlkAlign * nSamp/Sec */
|
||||
this->waveFormat.Format.nBlockAlign * this->waveFormat.Format.nSamplesPerSec;
|
||||
|
||||
/* IMPORTANT NOTE: wValidBitsPerSample/wReserved/wSamplesPerBlock are a union,
|
||||
so don't set wReserved or wSamplesPerBlock to 0 after assigning wValidBitsPerSample. */
|
||||
this->waveFormat.Samples.wValidBitsPerSample = 32;
|
||||
this->waveFormat.dwChannelMask = speakerconfig;
|
||||
/* NOTE: wValidBitsPerSample/wReserved/wSamplesPerBlock are a union */
|
||||
this->waveFormat.Samples.wValidBitsPerSample = this->waveFormat.Format.wBitsPerSample;
|
||||
this->waveFormat.dwChannelMask = speakerConfig;
|
||||
this->waveFormat.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;
|
||||
|
||||
/* create the output device */
|
||||
|
@ -34,6 +34,8 @@
|
||||
#include "WaveOutBuffer.h"
|
||||
#include "WaveOut.h"
|
||||
|
||||
#include <iostream>
|
||||
|
||||
WaveOutBuffer::WaveOutBuffer(WaveOut *waveOut, IBuffer *buffer, IPlayer *player)
|
||||
: waveOut(waveOut)
|
||||
, buffer(buffer)
|
||||
@ -44,9 +46,9 @@ WaveOutBuffer::WaveOutBuffer(WaveOut *waveOut, IBuffer *buffer, IPlayer *player)
|
||||
}
|
||||
|
||||
void WaveOutBuffer::Initialize() {
|
||||
this->header.dwBufferLength = this->buffer->Samples() * this->buffer->Channels()*sizeof(float);
|
||||
this->header.lpData = (LPSTR)this->buffer->BufferPointer();
|
||||
this->header.dwUser = (DWORD_PTR)this;
|
||||
this->header.dwBufferLength = this->buffer->Samples() * this->buffer->Channels() * sizeof(float);
|
||||
this->header.lpData = (LPSTR) this->buffer->BufferPointer();
|
||||
this->header.dwUser = (DWORD_PTR) this;
|
||||
this->header.dwBytesRecorded = 0;
|
||||
this->header.dwFlags = 0;
|
||||
this->header.dwLoops = 0;
|
||||
@ -57,14 +59,13 @@ void WaveOutBuffer::Initialize() {
|
||||
if (result != MMSYSERR_NOERROR) {
|
||||
throw;
|
||||
}
|
||||
|
||||
this->header.dwFlags |= WHDR_DONE;
|
||||
}
|
||||
|
||||
void WaveOutBuffer::Destroy() {
|
||||
if (!this->destroyed) {
|
||||
if (this->waveOut->waveHandle && this->header.dwFlags & WHDR_PREPARED) {
|
||||
waveOutUnprepareHeader(this->waveOut->waveHandle, &this->header, sizeof(WAVEHDR));
|
||||
this->header.dwFlags = WHDR_DONE;
|
||||
}
|
||||
|
||||
this->player->Notify();
|
||||
|
@ -186,7 +186,9 @@ void Player::ThreadLoop() {
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: why do we release buffers from the output here?? */
|
||||
/* TODO: why do we release buffers from the output here?? this appears to be
|
||||
an old hack to fix up some WaveOut issues where pending buffers need to be
|
||||
released before the device can be closed. we can probably remove this now. */
|
||||
this->output->ReleaseBuffers();
|
||||
|
||||
BufferPtr buffer;
|
||||
@ -207,6 +209,8 @@ void Player::ThreadLoop() {
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO CLEAN UP AND DOCUMENT */
|
||||
|
||||
/* if we have a buffer available, let's try to send it to the output device */
|
||||
if (buffer) {
|
||||
{
|
||||
@ -232,7 +236,7 @@ void Player::ThreadLoop() {
|
||||
}
|
||||
}
|
||||
}
|
||||
else{
|
||||
else {
|
||||
// Buffer send to output
|
||||
boost::mutex::scoped_lock lock(this->mutex);
|
||||
if(!this->bufferQueue.empty()) {
|
||||
@ -246,6 +250,8 @@ void Player::ThreadLoop() {
|
||||
}
|
||||
}
|
||||
|
||||
/* END TODO CLEAN UP AND DOCUMENT */
|
||||
|
||||
/* if we're unable to obtain a buffer, it means we're out of data and the
|
||||
player is finished. terminate the thread. */
|
||||
else {
|
||||
|
@ -38,6 +38,7 @@
|
||||
#include <core/PluginFactory.h>
|
||||
|
||||
using namespace musik::core::audio;
|
||||
using musik::core::PluginFactory;
|
||||
|
||||
Stream::Stream(unsigned int options)
|
||||
:preferedBufferSampleSize(4096)
|
||||
@ -45,12 +46,9 @@ Stream::Stream(unsigned int options)
|
||||
,decoderSampleRate(0)
|
||||
,decoderSamplePosition(0)
|
||||
{
|
||||
// Get all DSPs
|
||||
// TODO: fixing PluginFactory
|
||||
if( (this->options&NoDSP)==0){
|
||||
this->dsps = musik::core::PluginFactory::Instance().QueryInterface<
|
||||
IDSP,
|
||||
musik::core::PluginFactory::DestroyDeleter<IDSP> >("GetDSP");
|
||||
if((this->options&NoDSP) == 0){
|
||||
typedef PluginFactory::DestroyDeleter<IDSP> Deleter;
|
||||
this->dsps = PluginFactory::Instance().QueryInterface<IDSP, Deleter>("GetDSP");
|
||||
}
|
||||
}
|
||||
|
||||
@ -62,9 +60,7 @@ StreamPtr Stream::Create(unsigned int options){
|
||||
return StreamPtr(new Stream(options));
|
||||
}
|
||||
|
||||
BufferPtr Stream::NextBuffer(){
|
||||
|
||||
// Decode a new buffer
|
||||
BufferPtr Stream::NextBuffer() {
|
||||
return this->GetNextBuffer();
|
||||
}
|
||||
|
||||
@ -82,110 +78,104 @@ double Stream::SetPosition(double seconds){
|
||||
}
|
||||
return newPosition;
|
||||
}
|
||||
/*
|
||||
void Stream::SetMaxCacheLength(double seconds){
|
||||
}
|
||||
|
||||
void Stream::SetPreferedBufferSampleSize(long samples){
|
||||
}
|
||||
*/
|
||||
bool Stream::OpenStream(utfstring uri){
|
||||
|
||||
// Open the filestream
|
||||
this->fileStream = musik::core::filestreams::Factory::OpenFile(uri.c_str());
|
||||
if(!this->fileStream){
|
||||
bool Stream::OpenStream(utfstring uri) {
|
||||
/* use our file stream abstraction to open the data at the
|
||||
specified URI */
|
||||
this->fileStream = musik::core::filestreams::Factory::OpenFile(uri.c_str());
|
||||
if (!this->fileStream) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Look up what DecoderFactory to use
|
||||
/* find a DecoderFactory we can use for this type of data*/
|
||||
StreamHelper::DecoderFactoryPtr decoderFactory;
|
||||
for(StreamHelper::DecoderFactories::iterator decoderFactoryIt=Stream::Helper()->decoderFactories.begin();decoderFactoryIt!=Stream::Helper()->decoderFactories.end() && !decoderFactory;++decoderFactoryIt){
|
||||
if( (*decoderFactoryIt)->CanHandle(this->fileStream->Type())){
|
||||
decoderFactory = (*decoderFactoryIt);
|
||||
StreamHelper::DecoderFactories::iterator factories = Stream::Helper()->decoderFactories.begin();
|
||||
StreamHelper::DecoderFactories::iterator end = Stream::Helper()->decoderFactories.end();
|
||||
|
||||
for( ; factories != end && !decoderFactory; ++factories) {
|
||||
if((*factories)->CanHandle(this->fileStream->Type())){
|
||||
decoderFactory = (*factories);
|
||||
}
|
||||
}
|
||||
|
||||
if(!decoderFactory){
|
||||
// We have failed to get a working decoderFactory
|
||||
if (!decoderFactory) {
|
||||
/* nothing can decode this type of file */
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// Create the decoder
|
||||
IDecoder *decoderPtr = decoderFactory->CreateDecoder();
|
||||
if(!decoderPtr){
|
||||
IDecoder *decoder = decoderFactory->CreateDecoder();
|
||||
if (!decoder) {
|
||||
/* shouldn't ever happen, the factory said it can handle this file */
|
||||
return false;
|
||||
}
|
||||
|
||||
typedef PluginFactory::DestroyDeleter<IDecoder> Deleter;
|
||||
|
||||
// Open the decoder
|
||||
typedef musik::core::PluginFactory::DestroyDeleter<IDecoder> IDecoderDeleter;
|
||||
this->decoder.reset(decoderPtr,IDecoderDeleter());
|
||||
if( !this->decoder->Open(this->fileStream.get()) ){
|
||||
/* ask the decoder to open the data stream. if it returns true we're
|
||||
good to start pulling data out of it! */
|
||||
this->decoder.reset(decoder, Deleter());
|
||||
if (!this->decoder->Open(this->fileStream.get())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
BufferPtr Stream::GetNextDecoderBuffer(){
|
||||
// First get a buffer
|
||||
BufferPtr Stream::GetNextDecoderBuffer() {
|
||||
/* get a spare buffer, then ask the decoder for some data */
|
||||
BufferPtr buffer = this->NewBuffer();
|
||||
|
||||
// Get the buffer from the decoder
|
||||
if(!this->decoder->GetBuffer(buffer.get())){
|
||||
// Nothing to decode left, return a empty buffer
|
||||
if(!this->decoder->GetBuffer(buffer.get())) {
|
||||
return BufferPtr();
|
||||
}
|
||||
|
||||
// We need to save the decoders samplerate to be able to calculate the current time-position
|
||||
/* remember the samplerate so we can calculate the current time-position */
|
||||
if(!this->decoderSampleRate){
|
||||
this->decoderSampleRate = buffer->SampleRate();
|
||||
}
|
||||
|
||||
// Calculate the current sample position
|
||||
/* calculate the current offset, in samples */
|
||||
this->decoderSamplePosition += buffer->Samples();
|
||||
|
||||
// Save the position (seconds) in the buffer
|
||||
buffer->position = ((double)this->decoderSamplePosition)/((double)this->decoderSampleRate);
|
||||
/* calculate the position (seconds) in the buffer */
|
||||
buffer->position = ((double)this->decoderSamplePosition) / ((double)this->decoderSampleRate);
|
||||
|
||||
return buffer;
|
||||
|
||||
}
|
||||
|
||||
BufferPtr Stream::GetNextBuffer(){
|
||||
// First get the next decoded buffer
|
||||
BufferPtr Stream::GetNextBuffer() {
|
||||
/* ask the decoder for the next buffer */
|
||||
BufferPtr currentBuffer = this->GetNextDecoderBuffer();
|
||||
|
||||
if(currentBuffer){
|
||||
/////////////////////////////////////////////
|
||||
// Lets check if the buffer is too small
|
||||
bool moreBuffers(true);
|
||||
while(currentBuffer->Samples()<this->preferedBufferSampleSize && moreBuffers){
|
||||
BufferPtr appendBuffer = this->GetNextDecoderBuffer();
|
||||
if(appendBuffer){
|
||||
currentBuffer->Append(appendBuffer);
|
||||
this->DeleteBuffer(appendBuffer);
|
||||
}else{
|
||||
if(currentBuffer) {
|
||||
/* try to fill the buffer to its optimal size; if the decoder didn't return
|
||||
a full buffer, ask it for some more data. */
|
||||
bool moreBuffers = true;
|
||||
while (currentBuffer->Samples() < this->preferedBufferSampleSize && moreBuffers) {
|
||||
BufferPtr bufferToAppend = this->GetNextDecoderBuffer();
|
||||
if (bufferToAppend) {
|
||||
currentBuffer->Append(bufferToAppend);
|
||||
this->DeleteBuffer(bufferToAppend);
|
||||
}
|
||||
else {
|
||||
moreBuffers = false;
|
||||
}
|
||||
}
|
||||
/////////////////////////////////////////////
|
||||
|
||||
BufferPtr oldBuffer = this->NewBuffer();
|
||||
/* let DSP plugins process the buffer */
|
||||
if (this->dsps.size() > 0) {
|
||||
BufferPtr oldBuffer = this->NewBuffer();
|
||||
|
||||
// Now lets loop through all DSP plugins
|
||||
for(Dsps::iterator dsp=this->dsps.begin();dsp!=this->dsps.end();++dsp){
|
||||
oldBuffer->CopyFormat(currentBuffer);
|
||||
oldBuffer->position = currentBuffer->position;
|
||||
for (Dsps::iterator dsp = this->dsps.begin(); dsp != this->dsps.end(); ++dsp) {
|
||||
oldBuffer->CopyFormat(currentBuffer);
|
||||
oldBuffer->position = currentBuffer->position;
|
||||
|
||||
if( (*dsp)->ProcessBuffers(currentBuffer.get(),oldBuffer.get()) ){
|
||||
// Success in processing DSP, swap the buffers
|
||||
currentBuffer.swap(oldBuffer);
|
||||
if ((*dsp)->ProcessBuffers(currentBuffer.get(), oldBuffer.get())) {
|
||||
currentBuffer.swap(oldBuffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this->DeleteBuffer(oldBuffer);
|
||||
this->DeleteBuffer(oldBuffer);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -203,7 +193,7 @@ BufferPtr Stream::NewBuffer(){
|
||||
return buffer;
|
||||
}
|
||||
|
||||
void Stream::DeleteBuffer(BufferPtr oldBuffer){
|
||||
void Stream::DeleteBuffer(BufferPtr oldBuffer) {
|
||||
this->availableBuffers.push_back(oldBuffer);
|
||||
}
|
||||
|
||||
@ -215,20 +205,22 @@ Stream::StreamHelperPtr Stream::Helper(){
|
||||
return helper;
|
||||
}
|
||||
|
||||
Stream::StreamHelper::StreamHelper(){
|
||||
// Look up all DecoderFactories
|
||||
this->decoderFactories = musik::core::PluginFactory::Instance().QueryInterface<
|
||||
IDecoderFactory,
|
||||
musik::core::PluginFactory::DestroyDeleter<IDecoderFactory> >("GetDecoderFactory");
|
||||
Stream::StreamHelper::StreamHelper() {
|
||||
PluginFactory::DestroyDeleter<IDecoderFactory> typedef Deleter;
|
||||
|
||||
this->decoderFactories = PluginFactory::Instance()
|
||||
.QueryInterface<IDecoderFactory, Deleter>("GetDecoderFactory");
|
||||
}
|
||||
|
||||
double Stream::DecoderProgress(){
|
||||
if(this->fileStream){
|
||||
long fileSize = this->fileStream->Filesize();
|
||||
long filePosition = this->fileStream->Position();
|
||||
if(fileSize && filePosition){
|
||||
return ((double)filePosition)/((double)fileSize);
|
||||
double Stream::DecoderProgress() {
|
||||
if (this->fileStream) {
|
||||
long fileSize = this->fileStream->Filesize();
|
||||
long filePosition = this->fileStream->Position();
|
||||
|
||||
if (fileSize && filePosition) {
|
||||
return ((double) filePosition) / ((double) fileSize);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -41,8 +41,6 @@
|
||||
#include <core/Common.h>
|
||||
#include <core/config_filesystem.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#ifdef UTF_WIDECHAR
|
||||
#define UTFFopen _wfopen
|
||||
typedef fpos_t stdioPositionType;
|
||||
@ -51,11 +49,8 @@ typedef fpos_t stdioPositionType;
|
||||
typedef fpos_t stdioPositionType;
|
||||
#endif
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
using namespace musik::core::filestreams;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
LocalFileStream::LocalFileStream()
|
||||
: file(NULL)
|
||||
, filesize(-1)
|
||||
@ -82,10 +77,10 @@ bool LocalFileStream::Open(const utfchar *filename,unsigned int options){
|
||||
std::cerr << "File not a regular file" << std::endl;
|
||||
}
|
||||
|
||||
this->filesize = (long)boost::filesystem::file_size(file);
|
||||
this->filesize = (long)boost::filesystem::file_size(file);
|
||||
this->extension = file.extension().wstring();
|
||||
this->file = UTFFopen(filename,UTF("rb"));
|
||||
this->fd = new boost::iostreams::file_descriptor(file);
|
||||
this->fd = new boost::iostreams::file_descriptor(file);
|
||||
this->fileStream = new boost::iostreams::stream<boost::iostreams::file_descriptor>(*this->fd);
|
||||
this->fileStream->exceptions(std::ios_base::eofbit | std::ios_base::failbit | std::ios_base::badbit);
|
||||
|
||||
@ -128,8 +123,6 @@ PositionType LocalFileStream::Read(void* buffer,PositionType readBytes) {
|
||||
}
|
||||
|
||||
bool LocalFileStream::SetPosition(PositionType position) {
|
||||
/*stdioPositionType newPosition = (stdioPositionType)position;
|
||||
return fsetpos(this->file,&newPosition)==0;*/
|
||||
try {
|
||||
this->fileStream->clear();
|
||||
this->fileStream->seekg(position);
|
||||
@ -142,16 +135,10 @@ bool LocalFileStream::SetPosition(PositionType position) {
|
||||
}
|
||||
|
||||
PositionType LocalFileStream::Position() {
|
||||
/*stdioPositionType currentPosition(0);
|
||||
if(fgetpos(this->file,¤tPosition)==0){
|
||||
return (PositionType)currentPosition;
|
||||
}
|
||||
return -1;*/
|
||||
return this->fileStream->tellg();
|
||||
}
|
||||
|
||||
bool LocalFileStream::Eof() {
|
||||
//return feof(this->file)!=0;
|
||||
return this->fileStream->eof();
|
||||
}
|
||||
|
||||
|
@ -37,17 +37,12 @@
|
||||
#pragma once
|
||||
|
||||
namespace musik { namespace core {
|
||||
|
||||
class IPlugin{
|
||||
protected:
|
||||
virtual ~IPlugin() {};
|
||||
class IPlugin{
|
||||
public:
|
||||
virtual void Destroy() =0;
|
||||
|
||||
virtual const utfchar* Name()=0;
|
||||
virtual const utfchar* Version()=0;
|
||||
virtual const utfchar* Author()=0;
|
||||
virtual void Destroy() = 0;
|
||||
virtual const utfchar* Name() = 0;
|
||||
virtual const utfchar* Version() = 0;
|
||||
virtual const utfchar* Author() = 0;
|
||||
};
|
||||
|
||||
} }
|
||||
|
||||
|
58
src/core/sdk/IRequestParser.h
Normal file
58
src/core/sdk/IRequestParser.h
Normal file
@ -0,0 +1,58 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// License Agreement:
|
||||
//
|
||||
// The following are Copyright © 2008, Daniel Önnerby
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of the author nor the names of other contributors may
|
||||
// be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <core/config.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace musik{ namespace core{ namespace http{
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class IRequestParser{
|
||||
public:
|
||||
virtual const char* Attribute(const char* key)=0;
|
||||
virtual const char* Path()=0;
|
||||
virtual const char* SubPath(int position)=0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
} } } // musik::core:http
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
61
src/core/sdk/IRequestPlugin.h
Normal file
61
src/core/sdk/IRequestPlugin.h
Normal file
@ -0,0 +1,61 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// License Agreement:
|
||||
//
|
||||
// The following are Copyright © 2008, Daniel Önnerby
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of the author nor the names of other contributors may
|
||||
// be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <core/config.h>
|
||||
#include "IResponder.h"
|
||||
#include "IRequestParser.h"
|
||||
#include "ITrack.h"
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace musik{ namespace core{ namespace http{
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class IRequestPlugin{
|
||||
public:
|
||||
virtual void Destroy()=0;
|
||||
virtual const char* WatchPath()=0;
|
||||
virtual void Execute(musik::core::http::IResponder* responder,musik::core::http::IRequestParser* request,musik::core::ITrack* track)=0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
} } }
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
58
src/core/sdk/IResponder.h
Normal file
58
src/core/sdk/IResponder.h
Normal file
@ -0,0 +1,58 @@
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// License Agreement:
|
||||
//
|
||||
// The following are Copyright © 2008, Daniel Önnerby
|
||||
//
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// * Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// * Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// * Neither the name of the author nor the names of other contributors may
|
||||
// be used to endorse or promote products derived from this software
|
||||
// without specific prior written permission.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <core/config.h>
|
||||
#include <stddef.h>
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
namespace musik{ namespace core{ namespace http{
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class IResponder{
|
||||
public:
|
||||
virtual void SendContent(const char* buffer,const std::size_t bufferSize)=0;
|
||||
virtual bool Exited()=0;
|
||||
};
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
} } }
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user