00001 #ifdef WITH_OSS
00002
00003 #include <algorithm>
00004 #include <string>
00005 #include <stdio.h>
00006 #include <unistd.h>
00007 #include <fcntl.h>
00008 #include <sys/ioctl.h>
00009 #include <sys/soundcard.h>
00010 #include "output_oss.hpp"
00011 #include "debug.hpp"
00012
00013
00015
00016 OSSOutputContext::OSSOutputContext()
00017 {
00018 m_output_device = -1;
00019 }
00020
00022
00023 OSSOutputContext::~OSSOutputContext()
00024 {
00025 ADR_GUARD("OSSOutputContext::~OSSOutputContext");
00026
00027 if (m_output_device != -1) {
00028 close(m_output_device);
00029 }
00030 }
00031
00033
00034 bool
00035 OSSOutputContext::Initialize(const char* parameters)
00036 {
00037 ParameterList pl;
00038 ParseParameters(parameters, pl);
00039
00040 std::string device = "/dev/dsp";
00041
00042 ParameterList::iterator i;
00043 for (i = pl.begin(); i != pl.end(); ++i) {
00044 if (i->first == "device") {
00045 device = i->second;
00046 }
00047 }
00048
00049
00050 m_output_device = open(device.c_str(), O_WRONLY);
00051 if (m_output_device == -1) {
00052 perror(device.c_str());
00053 return false;
00054 }
00055
00056 int format = AFMT_S16_LE;
00057 if (ioctl(m_output_device, SNDCTL_DSP_SETFMT, &format) == -1) {
00058 perror("SNDCTL_DSP_SETFMT");
00059 return false;
00060 }
00061 if (format != AFMT_S16_LE) {
00062
00063 return false;
00064 }
00065
00066 int stereo = 1;
00067 if (ioctl(m_output_device, SNDCTL_DSP_STEREO, &stereo) == -1) {
00068 perror("SNDCTL_DSP_STEREO");
00069 return false;
00070 }
00071 if (stereo != 1) {
00072
00073 return false;
00074 }
00075
00076 int speed = 44100;
00077 if (ioctl(m_output_device, SNDCTL_DSP_SPEED, &speed) == -1) {
00078 perror("SNDCTL_DSP_SPEED");
00079 return false;
00080 }
00081 if (abs(44100 - speed) > 2205) {
00082
00083 return false;
00084 }
00085
00086 return true;
00087 }
00088
00090
00091 void
00092 OSSOutputContext::Update()
00093 {
00094
00095 audio_buf_info info;
00096 if (ioctl(m_output_device, SNDCTL_DSP_GETOSPACE, &info) == -1) {
00097 return;
00098 }
00099
00100
00101 int sample_count = info.bytes / 4;
00102
00103
00104 static const int BUFFER_SIZE = 1024;
00105 char buffer[BUFFER_SIZE * 4];
00106 while (sample_count > 0) {
00107 int transfer_count = std::min(sample_count, BUFFER_SIZE);
00108
00109 m_mixer.Read(transfer_count, buffer);
00110 write(m_output_device, buffer, transfer_count * 4);
00111
00112 sample_count -= transfer_count;
00113 }
00114
00115 usleep(50000);
00116 }
00117
00119
00120 IOutputStream*
00121 OSSOutputContext::OpenStream(ISampleSource* source)
00122 {
00123 return new OSSOutputStream(&m_mixer, source);
00124 }
00125
00127
00128 OSSOutputStream::OSSOutputStream(Mixer* mixer, ISampleSource* source)
00129 {
00130 m_mixer = mixer;
00131 m_source = source;
00132
00133 m_mixer->AddSource(source);
00134 }
00135
00137
00138 OSSOutputStream::~OSSOutputStream()
00139 {
00140 m_mixer->RemoveSource(m_source);
00141 }
00142
00144
00145 void
00146 OSSOutputStream::Play()
00147 {
00148 m_mixer->SetPlaying(m_source, true);
00149 }
00150
00152
00153 void
00154 OSSOutputStream::Stop()
00155 {
00156 m_mixer->SetPlaying(m_source, false);
00157 }
00158
00160
00161 void
00162 OSSOutputStream::Reset()
00163 {
00164 m_source->Reset();
00165 }
00166
00168
00169 bool
00170 OSSOutputStream::IsPlaying()
00171 {
00172 return m_mixer->IsPlaying(m_source);
00173 }
00174
00176
00177 void
00178 OSSOutputStream::SetVolume(int volume)
00179 {
00180 m_volume = volume;
00181 m_mixer->SetVolume(m_source, m_volume);
00182 }
00183
00185
00186 int
00187 OSSOutputStream::GetVolume()
00188 {
00189 return m_volume;
00190 }
00191
00193
00194 #endif