1 /******************************************************************************
2 *                            recordMyDesktop                                  *
3 *******************************************************************************
4 *                                                                             *
5 *            Copyright (C) 2006,2007,2008 John Varouhakis                     *
6 *                                                                             *
7 *                                                                             *
8 *   This program is free software; you can redistribute it and/or modify      *
9 *   it under the terms of the GNU General Public License as published by      *
10 *   the Free Software Foundation; either version 2 of the License, or         *
11 *   (at your option) any later version.                                       *
12 *                                                                             *
13 *   This program is distributed in the hope that it will be useful,           *
14 *   but WITHOUT ANY WARRANTY; without even the implied warranty of            *
15 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the             *
16 *   GNU General Public License for more details.                              *
17 *                                                                             *
18 *   You should have received a copy of the GNU General Public License         *
19 *   along with this program; if not, write to the Free Software               *
20 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA  *
21 *                                                                             *
22 *                                                                             *
23 *                                                                             *
24 *   For further information contact me at johnvarouhakis@gmail.com            *
25 ******************************************************************************/
26 
27 #include "config.h"
28 #include "rmd_capture_sound.h"
29 
30 #include "rmd_jack.h"
31 #include "rmd_opendev.h"
32 #include "rmd_types.h"
33 
34 #include <pthread.h>
35 #include <string.h>
36 #include <errno.h>
37 #include <sys/types.h>
38 #include <sys/uio.h>
39 #include <unistd.h>
40 #include <stdlib.h>
41 
42 
CaptureSound(ProgData * pdata)43 void *CaptureSound(ProgData *pdata){
44 
45 #ifdef HAVE_LIBASOUND
46     int frames=pdata->periodsize;
47 #endif
48     //start capturing only after first frame is taken
49     usleep(pdata->frametime);
50 
51     while(pdata->running){
52         int sret=0;
53         SndBuffer *newbuf,*tmp;
54         if (pdata->paused) {
55 #ifdef HAVE_LIBASOUND
56             if(!pdata->hard_pause){
57                 snd_pcm_pause(pdata->sound_handle,1);
58                 pthread_mutex_lock(&pdata->pause_mutex);
59                 pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex);
60                 pthread_mutex_unlock(&pdata->pause_mutex);
61                 snd_pcm_pause(pdata->sound_handle,0);
62             }
63             else{//device doesn't support pause(is this the norm?mine doesn't)
64                 snd_pcm_close(pdata->sound_handle);
65                 pthread_mutex_lock(&pdata->pause_mutex);
66                 pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex);
67                 pthread_mutex_unlock(&pdata->pause_mutex);
68                 pdata->sound_handle=
69                     OpenDev(pdata->args.device,
70                             &pdata->args.channels,
71                             &pdata->args.frequency,
72                             &pdata->args.buffsize,
73                             NULL,
74                             NULL,
75                             NULL//let's hope that the device capabilities
76                                 //didn't magically change
77                             );
78                 if(pdata->sound_handle==NULL){
79                     fprintf(stderr,"Couldn't reopen sound device.Exiting\n");
80                     pdata->running = FALSE;
81                     errno=3;
82                     pthread_exit(&errno);
83                 }
84             }
85 #else
86             close(pdata->sound_handle);
87             pthread_mutex_lock(&pdata->pause_mutex);
88             pthread_cond_wait(&pdata->pause_cond, &pdata->pause_mutex);
89             pthread_mutex_unlock(&pdata->pause_mutex);
90             pdata->sound_handle=
91                 OpenDev(pdata->args.device,
92                         pdata->args.channels,
93                         pdata->args.frequency);
94             if(pdata->sound_handle<0){
95                 fprintf(stderr,"Couldn't reopen sound device.Exiting\n");
96                 pdata->running = FALSE;
97                 errno=3;
98                 pthread_exit(&errno);
99             }
100 #endif
101         }
102 
103         //create new buffer
104         newbuf=(SndBuffer *)malloc(sizeof(SndBuffer));
105 #ifdef HAVE_LIBASOUND
106         newbuf->data=(signed char *)malloc(frames*pdata->sound_framesize);
107 #else
108         newbuf->data=(signed char *)malloc(((pdata->args.buffsize<<1)*
109                                             pdata->args.channels));
110 #endif
111         newbuf->next=NULL;
112 
113         //read data into new buffer
114 #ifdef HAVE_LIBASOUND
115         while(sret<frames){
116             int temp_sret=snd_pcm_readi(pdata->sound_handle,
117                                 newbuf->data+pdata->sound_framesize*sret,
118                                 frames-sret);
119             if(temp_sret==-EPIPE){
120                 fprintf(stderr,"%s: Overrun occurred.\n",
121                                snd_strerror(temp_sret));
122                 snd_pcm_prepare(pdata->sound_handle);
123             }
124             else if (temp_sret<0){
125                 fprintf(stderr,"An error occured while reading sound data:\n"
126                                " %s\n",
127                                snd_strerror(temp_sret));
128                 snd_pcm_prepare(pdata->sound_handle);
129             }
130             else
131                 sret+=temp_sret;
132         }
133 #else
134         sret=0;
135         //oss recording loop
136         do{
137             int temp_sret=read(pdata->sound_handle,
138                                &newbuf->data[sret],
139                                ((pdata->args.buffsize<<1)*
140                                 pdata->args.channels)-sret);
141             if(temp_sret<0){
142                 fprintf(stderr,"An error occured while reading from soundcard"
143                                "%s\n"
144                                "Error description:\n"
145                                "%s\n",pdata->args.device,strerror(errno));
146             }
147             else
148                 sret+=temp_sret;
149         }while(sret<((pdata->args.buffsize<<1)*
150                      pdata->args.channels));
151 #endif
152         //queue the new buffer
153         pthread_mutex_lock(&pdata->sound_buffer_mutex);
154         tmp=pdata->sound_buffer;
155         if(pdata->sound_buffer==NULL)
156                 pdata->sound_buffer=newbuf;
157         else{
158             while(tmp->next!=NULL)
159                 tmp=tmp->next;
160             tmp->next=newbuf;
161         }
162         pthread_mutex_unlock(&pdata->sound_buffer_mutex);
163 
164 
165         //signal that there are data to be proccessed
166         pthread_mutex_lock(&pdata->snd_buff_ready_mutex);
167         pthread_cond_signal(&pdata->sound_data_read);
168         pthread_mutex_unlock(&pdata->snd_buff_ready_mutex);
169     }
170 #ifdef HAVE_LIBASOUND
171     snd_pcm_close(pdata->sound_handle);
172 #else
173     close(pdata->sound_handle);
174 #endif
175     pthread_exit(&errno);
176 }
177 
178 
179 
180