Alex: Added the new sources for terminatorX 3.5
[terminatorX.git] / src / tX_audiodevice.cc
1 /*
2     terminatorX - realtime audio scratching software
3     Copyright (C) 1999  Alexander K├Ânig
4  
5     This program is free software; you can redistribute it and/or modify
6     it under the terms of the GNU General Public License as published by
7     the Free Software Foundation; either version 2 of the License, or
8     (at your option) any later version.
9  
10     This program is distributed in the hope that it will be useful,
11     but WITHOUT ANY WARRANTY; without even the implied warranty of
12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13     GNU General Public License for more details.
14  
15     You should have received a copy of the GNU General Public License
16     along with this program; if not, write to the Free Software
17     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  
19     File: tX_aduiodevice.cc
20  
21     Description: Implements Audiodevice handling... 
22 */    
23
24 #include "tX_audiodevice.h"
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/ioctl.h>
29 #include <unistd.h>
30 #include <fcntl.h>
31 #include <sys/soundcard.h>
32
33 #ifdef USE_WRITER_THREAD
34
35 void* writer_thread(void *parm)
36 {
37         audiodevice *audio=(audiodevice *) parm;
38         int16_t *buffer;
39
40         puts("writer thread");
41
42         pthread_mutex_lock(&audio->write_mutex);
43         
44         while (pthread_mutex_trylock(&audio->stop_mutex))
45         {
46         
47                 pthread_mutex_lock(&audio->buffer_read_mutex);
48                 pthread_mutex_unlock(&audio->write_mutex);
49                 pthread_mutex_lock(&audio->buffer_ready_mutex);
50                 buffer=audio->current_buffer;
51                 pthread_mutex_unlock(&audio->buffer_read_mutex);
52                 pthread_mutex_unlock(&audio->buffer_ready_mutex);
53                 pthread_mutex_lock(&audio->write_mutex);
54                 
55                 write(audio->fd, buffer, audio->blocksize);     
56         }
57         pthread_mutex_unlock(&audio->stop_mutex);
58         pthread_mutex_unlock(&audio->write_mutex);
59         
60         puts("wt quits");
61         return NULL;
62 }
63
64 int audiodevice :: eat(int16_t *buffer)
65 {
66         if (pthread_mutex_trylock(&stop_mutex))
67         {
68                 pthread_mutex_lock(&write_mutex);
69
70                 current_buffer=buffer;
71                 pthread_mutex_unlock(&buffer_ready_mutex);      
72         
73                 pthread_mutex_lock(&buffer_read_mutex);
74         
75                 pthread_mutex_lock(&buffer_ready_mutex);
76         
77                 pthread_mutex_unlock(&buffer_read_mutex);
78                 pthread_mutex_unlock(&write_mutex);     
79         }
80 }
81
82 #endif
83
84 int audiodevice :: dev_open(int dont_use_rt_buffsize)
85 {
86         int i=0;
87         int p;
88         int buff_cfg;
89
90         if (fd) return (1);
91
92         if (globals.use_stdout)
93         {
94                 fd=STDOUT_FILENO;
95                 blocksize=1 << globals.buff_size;
96                 return(0);
97         }
98
99         fd = open(globals.audio_device, O_WRONLY, 0);
100         
101         /* setting buffer size */       
102         if (dont_use_rt_buffsize)
103         {
104                 buff_cfg=(globals.buff_no<<16) | NON_RT_BUFF;   
105         }       
106         else
107         {
108                 buff_cfg=(globals.buff_no<<16) | globals.buff_size;
109         }
110         
111         p=buff_cfg;
112                 
113         i = ioctl(fd, SNDCTL_DSP_SETFRAGMENT, &p);
114
115         ioctl(fd, SNDCTL_DSP_RESET, 0);         
116
117         /* 16 Bits */
118         
119         p =  16;
120
121         i +=  ioctl(fd, SOUND_PCM_WRITE_BITS, &p);
122
123         /* MONO */
124         
125         p =  1;
126         i += ioctl(fd, SOUND_PCM_WRITE_CHANNELS, &p);
127         
128         /* 44.1 khz */
129
130         p =  44100;
131         i += ioctl(fd, SOUND_PCM_WRITE_RATE, &p);
132                 
133         i += ioctl(fd, SNDCTL_DSP_GETBLKSIZE, &blocksize);
134         
135         ioctl(fd, SNDCTL_DSP_SYNC, 0);
136
137 #ifdef USE_WRITER_THREAD
138         
139         puts("A");
140         pthread_mutex_lock(&stop_mutex);
141         puts("A");
142         pthread_mutex_trylock(&buffer_ready_mutex);
143         puts("A");
144         pthread_create(&writer, NULL, writer_thread, (void *) this);
145 #endif  
146         
147         return(i);      
148 }
149
150 int audiodevice :: getblocksize()
151 {
152         return(blocksize);
153 }
154
155 int audiodevice :: dev_close()
156 {
157         void *dummy;
158
159 #ifdef USE_WRITER_THREAD
160         pthread_mutex_unlock(&buffer_ready_mutex);
161         pthread_mutex_unlock(&stop_mutex);
162         
163         pthread_join(writer, &dummy);   
164         puts("okidoki");
165 #endif  
166
167         if (!fd)
168         {       
169                 return(1);              
170         }
171
172         if (!globals.use_stdout)
173         {
174                 close(fd);
175         }
176         fd=0;
177         blocksize=0;
178         
179         return(0);      
180 }
181
182 audiodevice :: audiodevice()
183 {
184         fd=0;
185         blocksize=0;
186 #ifdef USE_WRITER_THREAD        
187         pthread_mutex_init(&stop_mutex, NULL);
188         pthread_mutex_init(&write_mutex, NULL);
189         pthread_mutex_init(&buffer_read_mutex, NULL);
190         pthread_mutex_init(&buffer_ready_mutex, NULL);
191 #endif  
192 }
193
194 #ifndef USE_WRITER_THREAD
195 int audiodevice :: eat(int16_t *buffer)
196 {
197         write(fd, buffer, blocksize);   
198 }
199 #endif