00001
00002
00003
00004
00005
00006
00007
00008 #include "Core/precomp.h"
00009
00010 #ifdef USE_CLANSOUND
00011
00012 #include <unistd.h>
00013 #include <fcntl.h>
00014 #include <sys/ioctl.h>
00015 #include <sys/soundcard.h>
00016 #include <iostream>
00017
00018 #include <API/Core/System/error.h>
00019 #include "API/Core/System/cl_assert.h"
00020 #include "API/Core/System/system.h"
00021 #include <Sound/Sound/ClanSound/oss.h>
00022
00023
00024
00025
00026
00027
00028 bool has_sound = true;
00029
00030 CL_CSOutput::CL_CSOutput()
00031 {
00032 dev_dsp_fd = open("/dev/dsp", O_WRONLY);
00033 if (dev_dsp_fd == -1)
00034 {
00035 has_sound = false;
00036 frag_size = 22050/2;
00037 return;
00038
00039 }
00040
00041 #ifndef USE_DRIVER_FRAGSIZE
00042 int frag_settings = 0x0003000b;
00043
00044
00045 if (ioctl(dev_dsp_fd, SNDCTL_DSP_SETFRAGMENT, &frag_settings))
00046 {
00047 std::cout << "ClanSound: Failed to set soundcard fragment size. Sound may have a long latency." << std::endl;
00048 }
00049
00050 #endif
00051
00052 int format = AFMT_S16_LE;
00053 ioctl(dev_dsp_fd, SNDCTL_DSP_SETFMT, &format);
00054 if (format != AFMT_S16_LE)
00055 {
00056 close(dev_dsp_fd);
00057 throw CL_Error("Requires 16 bit soundcard. No sound will be available.");
00058 }
00059
00060 int stereo = 1;
00061 ioctl(dev_dsp_fd, SNDCTL_DSP_STEREO, &stereo);
00062 if (stereo != 1)
00063 {
00064 close(dev_dsp_fd);
00065 throw CL_Error("ClanSound: Requires 16 bit stereo capable soundcard. No sound will be available.");
00066 }
00067
00068 int speed = 22050;
00069 ioctl(dev_dsp_fd, SNDCTL_DSP_SPEED, &speed);
00070
00071 float percent_wrong = speed / (float) 22050;
00072 if (percent_wrong < 0.90 || percent_wrong > 1.10)
00073 {
00074 close(dev_dsp_fd);
00075 throw CL_Error("ClanSound: Mixing rate (22.05 kHz) not supported by soundcard.");
00076 }
00077
00078
00079
00080 int err = ioctl(dev_dsp_fd, SNDCTL_DSP_GETBLKSIZE, &frag_size);
00081 if (err == -1)
00082 {
00083 std::cout << "ClanSound: Warning, Couldn't get sound device blocksize. Using 0.25 sec mixing buffer." << std::endl;
00084 frag_size = 22050/2;
00085 }
00086
00087 audio_buf_info info;
00088 ioctl(dev_dsp_fd, SNDCTL_DSP_GETOSPACE, &info);
00089 }
00090
00091 CL_CSOutput::~CL_CSOutput()
00092 {
00093 if (dev_dsp_fd != -1) close(dev_dsp_fd);
00094 }
00095
00096 void CL_CSOutput::silence()
00097
00098
00099 {
00100 ioctl(dev_dsp_fd, SNDCTL_DSP_POST, 0);
00101 }
00102
00103 bool CL_CSOutput::is_full()
00104
00105 {
00106 if (!has_sound) return false;
00107 audio_buf_info info;
00108 int err = ioctl(dev_dsp_fd, SNDCTL_DSP_GETOSPACE, &info);
00109 if (err == -1)
00110 {
00111 std::cout << "ClanSound: fragments free not supported by device!?" << std::endl;
00112 return false;
00113 }
00114
00115 if (info.fragments == 0) return true;
00116 return false;
00117 }
00118
00119 int CL_CSOutput::get_frag_size()
00120
00121 {
00122 return frag_size/4;
00123 }
00124
00125 void CL_CSOutput::write_fragment(short *data)
00126
00127 {
00128 write(dev_dsp_fd, data, frag_size);
00129 }
00130
00131 void CL_CSOutput::wait()
00132 {
00133 if(!has_sound)
00134 {
00135 CL_System::sleep(100);
00136 return;
00137 }
00138
00139 fd_set wfds;
00140
00141 FD_ZERO(&wfds);
00142 FD_SET(dev_dsp_fd, &wfds);
00143
00144 select(dev_dsp_fd+1, NULL, &wfds, NULL, NULL);
00145
00146 }
00147
00148 #endif