]>
Commit | Line | Data |
---|---|---|
526ddb13 GL |
1 | // -------------------------------------------------------------------------- |
2 | // Name: sndesd.cpp | |
3 | // Purpose: | |
4 | // Date: 08/11/1999 | |
5 | // Author: Guilhem Lavaux <lavaux@easynet.fr> (C) 1999 | |
6 | // CVSID: $Id$ | |
7 | // -------------------------------------------------------------------------- | |
8 | #ifdef __GNUG__ | |
9 | #pragma implementation "sndesd.cpp" | |
10 | #endif | |
11 | ||
12 | #include <sys/types.h> | |
13 | #include <sys/stat.h> | |
14 | #include <unistd.h> | |
15 | #include <wx/defs.h> | |
16 | #include <wx/string.h> | |
17 | #include <esd.h> | |
18 | #include "sndbase.h" | |
19 | #include "sndesd.h" | |
20 | #include "sndpcm.h" | |
21 | #ifdef __WXGTK__ | |
22 | #include <gdk/gdk.h> | |
23 | #endif | |
24 | ||
25 | #define MY_ESD_NAME "wxWindows/wxSoundStreamESD" | |
26 | ||
27 | wxSoundStreamESD::wxSoundStreamESD(const wxString& hostname) | |
28 | { | |
29 | wxSoundFormatPcm pcm_default; | |
30 | ||
31 | m_fd = esd_monitor_stream(ESD_MONO | ESD_BITS8 | ESD_RECORD, 22050, | |
32 | hostname.mb_str(), MY_ESD_NAME); | |
33 | ||
34 | if (m_fd == -1) { | |
35 | m_snderror = wxSOUND_INVDEV; | |
36 | return; | |
37 | } | |
38 | ||
39 | esd_close(m_fd); | |
40 | ||
41 | m_hostname = hostname; | |
42 | ||
43 | SetSoundFormat(pcm_default); | |
44 | ||
45 | m_snderror = wxSOUND_NOERR; | |
46 | m_esd_stop = TRUE; | |
47 | } | |
48 | ||
49 | wxSoundStreamESD::~wxSoundStreamESD() | |
50 | { | |
51 | if (m_fd > 0) | |
52 | esd_close(m_fd); | |
53 | } | |
54 | ||
55 | wxSoundStream& wxSoundStreamESD::Read(void *buffer, size_t len) | |
56 | { | |
57 | int ret; | |
58 | ||
59 | m_lastcount = (size_t)ret = read(m_fd, buffer, len); | |
60 | ||
61 | if (ret < 0) | |
62 | m_snderror = wxSOUND_IOERR; | |
63 | else | |
64 | m_snderror = wxSOUND_NOERR; | |
65 | ||
66 | return *this; | |
67 | } | |
68 | ||
69 | wxSoundStream& wxSoundStreamESD::Write(const void *buffer, size_t len) | |
70 | { | |
71 | int ret; | |
72 | ||
73 | m_lastcount = (size_t)ret = write(m_fd, buffer, len); | |
74 | ||
75 | if (ret < 0) | |
76 | m_snderror = wxSOUND_IOERR; | |
77 | else | |
78 | m_snderror = wxSOUND_NOERR; | |
79 | ||
80 | return *this; | |
81 | } | |
82 | ||
83 | bool wxSoundStreamESD::SetSoundFormat(const wxSoundFormatBase& format) | |
84 | { | |
85 | wxSoundFormatPcm *pcm_format; | |
86 | ||
87 | if (format.GetType() != wxSOUND_PCM) { | |
88 | m_snderror = wxSOUND_INVFRMT; | |
89 | return FALSE; | |
90 | } | |
91 | ||
92 | if (m_fd == -1) { | |
93 | m_snderror = wxSOUND_INVDEV; | |
94 | return FALSE; | |
95 | } | |
96 | ||
97 | if (m_sndformat) | |
98 | delete m_sndformat; | |
99 | ||
100 | m_sndformat = format.Clone(); | |
101 | if (!m_sndformat) { | |
102 | m_snderror = wxSOUND_MEMERR; | |
103 | return FALSE; | |
104 | } | |
105 | pcm_format = (wxSoundFormatPcm *)m_sndformat; | |
106 | ||
107 | // Detect the best format | |
108 | DetectBest(pcm_format); | |
109 | ||
110 | m_snderror = wxSOUND_NOERR; | |
111 | if (*pcm_format != format) { | |
112 | m_snderror = wxSOUND_NOTEXACT; | |
113 | return FALSE; | |
114 | } | |
115 | return TRUE; | |
116 | } | |
117 | ||
118 | #ifdef __WXGTK__ | |
119 | static void _wxSound_OSS_CBack(gpointer data, int source, | |
120 | GdkInputCondition condition) | |
121 | { | |
122 | wxSoundStreamESD *esd = (wxSoundStreamESD *)data; | |
123 | ||
124 | switch (condition) { | |
125 | case GDK_INPUT_READ: | |
126 | esd->WakeUpEvt(wxSOUND_INPUT); | |
127 | break; | |
128 | case GDK_INPUT_WRITE: | |
129 | esd->WakeUpEvt(wxSOUND_OUTPUT); | |
130 | break; | |
131 | default: | |
132 | break; | |
133 | } | |
134 | } | |
135 | #endif | |
136 | ||
137 | void wxSoundStreamESD::WakeUpEvt(int evt) | |
138 | { | |
139 | OnSoundEvent(evt); | |
140 | } | |
141 | ||
142 | bool wxSoundStreamESD::StartProduction(int evt) | |
143 | { | |
144 | wxSoundFormatPcm *pcm; | |
145 | int flag = 0; | |
146 | ||
147 | if (!m_esd_stop) | |
148 | StopProduction(); | |
149 | ||
150 | pcm = (wxSoundFormatPcm *)m_sndformat; | |
151 | ||
152 | flag |= (pcm->GetBPS() == 16) ? ESD_BITS16 : ESD_BITS8; | |
153 | flag |= (pcm->GetChannels() == 2) ? ESD_STEREO : ESD_MONO; | |
154 | ||
155 | if (evt == wxSOUND_OUTPUT) { | |
156 | flag |= ESD_PLAY | ESD_STREAM; | |
157 | m_fd = esd_play_stream(flag, pcm->GetSampleRate(), m_hostname.mb_str(), | |
158 | MY_ESD_NAME); | |
159 | } else { | |
160 | flag |= ESD_RECORD | ESD_STREAM; | |
161 | m_fd = esd_record_stream(flag, pcm->GetSampleRate(), m_hostname.mb_str(), | |
162 | MY_ESD_NAME); | |
163 | } | |
164 | ||
165 | #ifdef __WXGTK__ | |
166 | if (evt == wxSOUND_OUTPUT) | |
167 | m_tag = gdk_input_add(m_fd, GDK_INPUT_WRITE, _wxSound_OSS_CBack, (gpointer)this); | |
168 | else | |
169 | m_tag = gdk_input_add(m_fd, GDK_INPUT_READ, _wxSound_OSS_CBack, (gpointer)this); | |
170 | #endif | |
171 | ||
172 | m_esd_stop = FALSE; | |
173 | ||
174 | return TRUE; | |
175 | } | |
176 | ||
177 | bool wxSoundStreamESD::StopProduction() | |
178 | { | |
179 | if (m_esd_stop) | |
180 | return FALSE; | |
181 | ||
182 | gdk_input_remove(m_tag); | |
183 | esd_close(m_fd); | |
184 | m_esd_stop = TRUE; | |
185 | return TRUE; | |
186 | } | |
187 | ||
188 | // | |
189 | // Detect the closest format (The best). | |
190 | // | |
191 | void wxSoundStreamESD::DetectBest(wxSoundFormatPcm *pcm) | |
192 | { | |
193 | wxSoundFormatPcm best_pcm; | |
194 | ||
195 | // We change neither the number of channels nor the sample rate | |
196 | ||
197 | best_pcm.SetSampleRate(pcm->GetSampleRate()); | |
198 | best_pcm.SetChannels(pcm->GetChannels()); | |
199 | ||
200 | // It supports 16 bits | |
201 | if (pcm->GetBPS() == 16) | |
202 | best_pcm.SetBPS(16); | |
203 | ||
204 | best_pcm.SetOrder(wxLITTLE_ENDIAN); | |
205 | best_pcm.Signed(TRUE); | |
206 | ||
207 | // Finally recopy the new format | |
208 | *pcm = best_pcm; | |
209 | } |