mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-07-29 05:52:58 +00:00
no message
This was SVN commit r789.
This commit is contained in:
Executable
+358
@@ -0,0 +1,358 @@
|
||||
#include "CMusicPlayer.h"
|
||||
|
||||
size_t VorbisRead(void *ptr, size_t byteSize, size_t sizeToRead, void *datasource)
|
||||
{
|
||||
size_t spaceToEOF;
|
||||
size_t actualSizeToRead;
|
||||
SOggFile* vorbisData;
|
||||
|
||||
vorbisData = (SOggFile*)datasource;
|
||||
|
||||
spaceToEOF = vorbisData->dataSize - vorbisData->dataRead;
|
||||
if ((sizeToRead*byteSize) < spaceToEOF)
|
||||
actualSizeToRead = (sizeToRead*byteSize);
|
||||
else
|
||||
actualSizeToRead = spaceToEOF;
|
||||
|
||||
if (actualSizeToRead)
|
||||
{
|
||||
memcpy(ptr, (char*)vorbisData->dataPtr + vorbisData->dataRead, actualSizeToRead);
|
||||
vorbisData->dataRead += (actualSizeToRead);
|
||||
}
|
||||
|
||||
return actualSizeToRead;
|
||||
}
|
||||
|
||||
int VorbisSeek(void *datasource, ogg_int64_t offset, int fromWhere)
|
||||
{
|
||||
size_t spaceToEOF;
|
||||
ogg_int64_t actualOffset;
|
||||
SOggFile* vorbisData;
|
||||
|
||||
vorbisData = (SOggFile*)datasource;
|
||||
|
||||
switch (fromWhere)
|
||||
{
|
||||
case SEEK_SET:
|
||||
|
||||
if (vorbisData->dataSize >= offset)
|
||||
actualOffset = offset;
|
||||
else
|
||||
actualOffset = vorbisData->dataSize;
|
||||
|
||||
vorbisData->dataRead = (int)actualOffset;
|
||||
break;
|
||||
case SEEK_CUR: // Seek from where we are
|
||||
spaceToEOF = vorbisData->dataSize - vorbisData->dataRead;
|
||||
if (offset < spaceToEOF)
|
||||
actualOffset = (offset);
|
||||
else
|
||||
actualOffset = spaceToEOF;
|
||||
vorbisData->dataRead += actualOffset;
|
||||
break;
|
||||
case SEEK_END:
|
||||
vorbisData->dataRead = vorbisData->dataSize+1;
|
||||
break;
|
||||
default:
|
||||
printf("*** ERROR *** Unknown seek command in VorbisSeek\n");
|
||||
break;
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int VorbisClose(void *datasource)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
long VorbisTell(void *datasource)
|
||||
{
|
||||
SOggFile* vorbisData;
|
||||
vorbisData = (SOggFile*)datasource;
|
||||
|
||||
return vorbisData->dataRead;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Class implementation
|
||||
CMusicPlayer::CMusicPlayer(void)
|
||||
{
|
||||
info = NULL;
|
||||
source = NULL;
|
||||
format = NULL;
|
||||
|
||||
for(int i = 0; i < 2; i++)
|
||||
{
|
||||
buffers[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
CMusicPlayer::~CMusicPlayer(void)
|
||||
{
|
||||
release();
|
||||
}
|
||||
|
||||
void CMusicPlayer::open(char *filename)
|
||||
{
|
||||
int ret = 0;
|
||||
format = NULL;
|
||||
info = NULL;
|
||||
|
||||
FILE* tempOggFile;
|
||||
int sizeOfFile;
|
||||
char tempChar;
|
||||
int tempArray;
|
||||
|
||||
if(!(tempOggFile = fopen(filename, "rb")))
|
||||
{
|
||||
printf("Unable to open Ogg file\n");
|
||||
exit(1);
|
||||
}
|
||||
sizeOfFile = 0;
|
||||
while (!feof(tempOggFile))
|
||||
{
|
||||
tempChar = getc(tempOggFile);
|
||||
sizeOfFile++;
|
||||
}
|
||||
|
||||
memFile.dataPtr = new char[sizeOfFile];
|
||||
rewind(tempOggFile);
|
||||
tempArray = 0;
|
||||
while (!feof(tempOggFile))
|
||||
{
|
||||
memFile.dataPtr[tempArray] = getc(tempOggFile);
|
||||
tempArray++;
|
||||
}
|
||||
|
||||
fclose(tempOggFile);
|
||||
|
||||
memFile.dataRead = 0;
|
||||
memFile.dataSize = sizeOfFile;
|
||||
|
||||
|
||||
//set up callbacks
|
||||
vorbisCallbacks.read_func = VorbisRead;
|
||||
vorbisCallbacks.close_func = VorbisClose;
|
||||
vorbisCallbacks.seek_func = VorbisSeek;
|
||||
vorbisCallbacks.tell_func = VorbisTell;
|
||||
|
||||
//start file to from memory
|
||||
if (ov_open_callbacks(&memFile, &oggStream, NULL, 0, vorbisCallbacks) != 0)
|
||||
{
|
||||
printf("Could not decode ogg into memory\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
info = ov_info(&oggStream, -1);
|
||||
|
||||
if(info->channels == 1)
|
||||
{
|
||||
//hopefully not mono
|
||||
format = AL_FORMAT_MONO16;
|
||||
}
|
||||
else
|
||||
{
|
||||
format = AL_FORMAT_STEREO16;
|
||||
}
|
||||
|
||||
alGenBuffers(2,buffers);
|
||||
//printf("Gen buffers calling check()\n");
|
||||
check();
|
||||
//printf("Gen sources calling check()\n");
|
||||
alGenSources(1,&source);
|
||||
check();
|
||||
//printf("check returned from sources\n");
|
||||
|
||||
alSource3f(source,AL_POSITION,0.0,0.0,0.0);
|
||||
check();
|
||||
//printf("returned from POSITION\n");
|
||||
alSource3f(source,AL_VELOCITY,0.0,0.0,0.0);
|
||||
check();
|
||||
//printf("returned from VELOCITY\n");
|
||||
alSource3f(source,AL_DIRECTION,0.0,0.0,0.0);
|
||||
check();
|
||||
//printf("returned from DIRECTION\n");
|
||||
alSourcef(source,AL_ROLLOFF_FACTOR,0.0);
|
||||
check();
|
||||
//printf("returned from ROLLOFF\n");
|
||||
alSourcei(source,AL_SOURCE_RELATIVE,AL_TRUE);
|
||||
check();
|
||||
//printf("returned from S RELATIVE\n");
|
||||
|
||||
}
|
||||
|
||||
void CMusicPlayer::release()
|
||||
{
|
||||
alSourceStop(source);
|
||||
empty();
|
||||
alDeleteSources(1,&source);
|
||||
check();
|
||||
alDeleteBuffers(1,buffers);
|
||||
check();
|
||||
ov_clear(&oggStream);
|
||||
delete[] memFile.dataPtr;
|
||||
memFile.dataPtr = NULL;
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool CMusicPlayer::play()
|
||||
{
|
||||
check();
|
||||
//printf("returned from check at start of isPlaying()\n");
|
||||
//check if already playing
|
||||
if(isPlaying())
|
||||
return true;
|
||||
|
||||
//printf("calling stream on first buffer\n");
|
||||
//load data into 1st buffer
|
||||
if(!stream(buffers[0]))
|
||||
return false;
|
||||
|
||||
//printf("calling stream on second buffer\n");
|
||||
//load data into 2nd buffer
|
||||
if(!stream(buffers[1]))
|
||||
return false;
|
||||
|
||||
//bind the 2 buffers to the source
|
||||
alSourceQueueBuffers(source,2,buffers);
|
||||
check();
|
||||
//printf("check returned from Queuebuffers\n");
|
||||
alSourcePlay(source);
|
||||
check();
|
||||
//printf("check returned from SourcePlay\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool CMusicPlayer::isPlaying()
|
||||
{
|
||||
ALenum state = NULL;
|
||||
|
||||
alGetSourcei(source,AL_SOURCE_STATE,&state);
|
||||
check();
|
||||
//printf("returning from isPlaying.\n");
|
||||
return (state == AL_PLAYING);
|
||||
}
|
||||
|
||||
|
||||
bool CMusicPlayer::update()
|
||||
{
|
||||
int processed;
|
||||
bool active = true;
|
||||
|
||||
//check which buffers have already been played
|
||||
alGetSourcei(source,AL_BUFFERS_PROCESSED, &processed);
|
||||
//printf("checking() buffers processed\n");
|
||||
check();
|
||||
//printf("check returned\n");
|
||||
|
||||
while(processed-- && processed >= 0)
|
||||
{
|
||||
ALuint buffer;
|
||||
|
||||
//remove buffer from queue
|
||||
alSourceUnqueueBuffers(source,1,&buffer);
|
||||
check();
|
||||
|
||||
//fill buffer with new data if false is returned the there is no more data
|
||||
active = stream(buffer);
|
||||
|
||||
//attach buffer to end of queue
|
||||
alSourceQueueBuffers(source,1,&buffer);
|
||||
check();
|
||||
}
|
||||
|
||||
return active;
|
||||
}
|
||||
|
||||
void CMusicPlayer::check()
|
||||
{
|
||||
int error = alGetError();
|
||||
|
||||
if(error != AL_NO_ERROR)
|
||||
{
|
||||
std::cout << "OpenAL error " << error << std::endl;
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void CMusicPlayer::empty()
|
||||
{
|
||||
int queued;
|
||||
alGetSourcei(source,AL_BUFFERS_QUEUED,&queued);
|
||||
|
||||
while(queued--)
|
||||
{
|
||||
ALuint buffer;
|
||||
|
||||
alSourceUnqueueBuffers(source,1,&buffer);
|
||||
check();
|
||||
}
|
||||
}
|
||||
|
||||
bool CMusicPlayer::stream(ALuint buffer)
|
||||
{
|
||||
char data[BUFFER_SIZE];
|
||||
int size = 0;
|
||||
int section, ret;
|
||||
|
||||
|
||||
|
||||
while(size < BUFFER_SIZE)
|
||||
{
|
||||
ret = ov_read(&oggStream, data + size, BUFFER_SIZE - size,0,2,1,§ion);
|
||||
|
||||
if(ret > 0)
|
||||
{
|
||||
size += ret;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(ret < 0)
|
||||
{
|
||||
printf("Error reading from ogg file\n");
|
||||
exit(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(size == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
alBufferData(buffer,format,data,size,info->rate);
|
||||
//printf("calling check in stream()\n");
|
||||
check();
|
||||
//printf("check returned\n");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string CMusicPlayer::errorString(int errorcode)
|
||||
{
|
||||
switch(errorcode)
|
||||
{
|
||||
case OV_EREAD:
|
||||
return std::string("Read from media.");
|
||||
case OV_ENOTVORBIS:
|
||||
return std::string("Not Vorbis data.");
|
||||
case OV_EVERSION:
|
||||
return std::string("Vorbis version mismatch.");
|
||||
case OV_EBADHEADER:
|
||||
return std::string("Invalid Vorbis header.");
|
||||
case OV_EFAULT:
|
||||
return std::string("Internal logic fault (bug or heap/stack corruption.");
|
||||
default:
|
||||
return std::string("Unknown Ogg error.");
|
||||
}
|
||||
}
|
||||
Executable
+50
@@ -0,0 +1,50 @@
|
||||
#ifndef CMUSICPLAYER_H
|
||||
#define CMUSICPLAYER_H
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <al.h>
|
||||
#include <alut.h>
|
||||
#include <ogg/ogg.h>
|
||||
#include <vorbis/codec.h>
|
||||
#include <vorbis/vorbisfile.h>
|
||||
|
||||
#define BUFFER_SIZE (64*1024)
|
||||
|
||||
struct SOggFile
|
||||
{
|
||||
char *dataPtr;
|
||||
int dataSize;
|
||||
int dataRead;
|
||||
};
|
||||
|
||||
class CMusicPlayer
|
||||
{
|
||||
public:
|
||||
CMusicPlayer(void);
|
||||
~CMusicPlayer(void);
|
||||
void open(char *filename);
|
||||
void release();
|
||||
bool play();
|
||||
bool isPlaying();
|
||||
bool update();
|
||||
|
||||
protected:
|
||||
bool stream(ALuint buffer);
|
||||
void check();
|
||||
void empty();
|
||||
std::string errorString(int errorcode);
|
||||
|
||||
private:
|
||||
SOggFile memFile;
|
||||
ov_callbacks vorbisCallbacks;
|
||||
OggVorbis_File oggStream;
|
||||
vorbis_info *info;
|
||||
ALuint buffers[2]; //the 2 buffers, one will be filled whilst the other is being played
|
||||
ALuint source;
|
||||
ALenum format;
|
||||
};
|
||||
|
||||
#endif
|
||||
Executable
+53
@@ -0,0 +1,53 @@
|
||||
#include "CPlayList.h"
|
||||
#include <iostream>
|
||||
|
||||
CPlayList::CPlayList(void)
|
||||
{
|
||||
tracks.clear();
|
||||
}
|
||||
|
||||
CPlayList::CPlayList(char *file)
|
||||
{
|
||||
load(file);
|
||||
}
|
||||
|
||||
CPlayList::~CPlayList(void)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void CPlayList::load(char *file)
|
||||
{
|
||||
std::ifstream input(file);
|
||||
|
||||
tracks.clear();
|
||||
|
||||
if(input.is_open())
|
||||
{
|
||||
std::string temp;
|
||||
|
||||
while(getline(input,temp))
|
||||
{
|
||||
tracks.push_back(temp);
|
||||
}
|
||||
input.close();
|
||||
}
|
||||
else
|
||||
{
|
||||
std::cout << "Error opening file.";
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CPlayList::list()
|
||||
{
|
||||
for(unsigned int i = 0; i < tracks.size(); i++)
|
||||
{
|
||||
std::cout << tracks.at(i) << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
void CPlayList::add(std::string name)
|
||||
{
|
||||
tracks.push_back(name);
|
||||
}
|
||||
Executable
+22
@@ -0,0 +1,22 @@
|
||||
#ifndef CPLAYLIST_H
|
||||
#define CPLAYLIST_H
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
|
||||
class CPlayList
|
||||
{
|
||||
public:
|
||||
CPlayList(void);
|
||||
CPlayList(char *file);
|
||||
~CPlayList(void);
|
||||
void load(char *file);
|
||||
void list();
|
||||
void add(std::string name);
|
||||
|
||||
private:
|
||||
std::vector<std::string> tracks;
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user