Main Page   Class Hierarchy   Alphabetical List   Compound List   File List   Compound Members   File Members  

output_oss.cpp

Go to the documentation of this file.
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";  // default device
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   // attempt to open output device
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     // unsupported format
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     // unsupported channel number
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     // unsupported sampling rate
00083     return false;
00084   }
00085 
00086   return true;
00087 }
00088 
00090 
00091 void
00092 OSSOutputContext::Update()
00093 {
00094   // find out how much data we can write to the device before it blocks
00095   audio_buf_info info;
00096   if (ioctl(m_output_device, SNDCTL_DSP_GETOSPACE, &info) == -1) {
00097     return;
00098   }
00099 
00100   // how many samples is that?
00101   int sample_count = info.bytes / 4;
00102 
00103   // write to the OSS device, 1024 samples at a time
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);  // 5 milliseconds
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

Generated at Mon Jun 10 02:55:12 2002 for audiere by doxygen1.2.8.1 written by Dimitri van Heesch, © 1997-2001