~ubuntu-branches/ubuntu/vivid/linphone/vivid

« back to all changes in this revision

Viewing changes to mediastreamer/msringplayer.c

  • Committer: Bazaar Package Importer
  • Author(s): Samuel Mimram
  • Date: 2006-11-15 10:34:50 UTC
  • mfrom: (1.2.1 upstream) (2.1.8 feisty)
  • Revision ID: james.westby@ubuntu.com-20061115103450-qgafwcks2lkhctlj
* New upstream release.
* Enable video support.
* Fix mismatched #endif in mscommon.h, closes: #398307.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
  The mediastreamer library aims at providing modular media processing and I/O
3
 
        for linphone, but also for any telephony application.
4
 
  Copyright (C) 2001  Simon MORLAT simon.morlat@linphone.org
5
 
                                                                                
6
 
  This library is free software; you can redistribute it and/or
7
 
  modify it under the terms of the GNU Lesser General Public
8
 
  License as published by the Free Software Foundation; either
9
 
  version 2.1 of the License, or (at your option) any later version.
10
 
 
11
 
  This library is distributed in the hope that it will be useful,
12
 
  but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 
  Lesser General Public License for more details.
15
 
 
16
 
  You should have received a copy of the GNU Lesser General Public
17
 
  License along with this library; if not, write to the Free Software
18
 
  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19
 
*/
20
 
 
21
 
#include "msringplayer.h"
22
 
#include "mssync.h"
23
 
#include <unistd.h>
24
 
#include <fcntl.h>
25
 
#include <sys/types.h>
26
 
#include <string.h>
27
 
#include <errno.h>
28
 
 
29
 
#include "waveheader.h"
30
 
 
31
 
#define WAVE_HEADER_OFFSET sizeof(wave_header_t)
32
 
 
33
 
enum { PLAY_RING, PLAY_SILENCE};
34
 
 
35
 
static int supported_freq[6]={8000,11025,16000,22050,32000,44100};
36
 
 
37
 
gint freq_is_supported(gint freq){
38
 
        int i;
39
 
        for (i=0;i<6;i++){
40
 
                if (abs(supported_freq[i]-freq)<50) return supported_freq[i];
41
 
        }
42
 
        return 0;
43
 
}
44
 
 
45
 
static MSRingPlayerClass *ms_ring_player_class=NULL;
46
 
 
47
 
/**
48
 
 * ms_ring_player_new:
49
 
 * @name:  The path to the 16-bit 8khz raw file to be played as a ring.
50
 
 * @seconds: The number of seconds that separates two rings.
51
 
 *
52
 
 * Allocates a new MSRingPlayer object.
53
 
 *
54
 
 *
55
 
 * Returns: a pointer the the object, NULL if name could not be open.
56
 
 */
57
 
MSFilter * ms_ring_player_new(char *name, gint seconds)
58
 
{
59
 
        MSRingPlayer *r;
60
 
        int fd=-1;
61
 
        
62
 
        if ((name!=NULL) && (strlen(name)!=0))
63
 
        {
64
 
                fd=open(name,O_RDONLY);
65
 
                if (fd<0) 
66
 
                {
67
 
                        g_warning("ms_ring_player_new: failed to open %s.\n",name);
68
 
                        return NULL;
69
 
                }
70
 
                
71
 
        }else {
72
 
                g_warning("ms_ring_player_new: Bad file name");
73
 
                return NULL;
74
 
        }
75
 
        
76
 
        r=g_new(MSRingPlayer,1);
77
 
        ms_ring_player_init(r);
78
 
        if (ms_ring_player_class==NULL)
79
 
        {
80
 
                ms_ring_player_class=g_new(MSRingPlayerClass,1);
81
 
                ms_ring_player_class_init(ms_ring_player_class);
82
 
        }
83
 
        MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ring_player_class);
84
 
        
85
 
        r->fd=fd;
86
 
        r->silence=seconds;
87
 
        r->freq=8000;
88
 
        if (strstr(name,".wav")!=NULL){
89
 
                wave_header_t header;
90
 
                int freq,freq2;
91
 
                /* read the header */
92
 
                read(fd,&header,sizeof(wave_header_t));
93
 
                freq=wave_header_get_rate(&header);
94
 
                if ((freq2=freq_is_supported(freq))>0){
95
 
                        r->freq=freq2;
96
 
                }else {
97
 
                        g_warning("Unsupported sampling rate %i",freq);
98
 
                        r->freq=8000;
99
 
                }
100
 
                r->channel=wave_header_get_channel(&header);
101
 
                lseek(fd,WAVE_HEADER_OFFSET,SEEK_SET);
102
 
#ifdef WORDS_BIGENDIAN
103
 
                r->need_swap=1; 
104
 
#else
105
 
                r->need_swap=0;
106
 
#endif
107
 
        }
108
 
        ms_ring_player_set_property(r, MS_FILTER_PROPERTY_FREQ,&r->freq);
109
 
        r->state=PLAY_RING;
110
 
        return(MS_FILTER(r));
111
 
}
112
 
        
113
 
 
114
 
/* FOR INTERNAL USE*/
115
 
void ms_ring_player_init(MSRingPlayer *r)
116
 
{
117
 
        ms_filter_init(MS_FILTER(r));
118
 
        MS_FILTER(r)->outfifos=r->foutputs;
119
 
        MS_FILTER(r)->outqueues=r->qoutputs;
120
 
        memset(r->foutputs,0,sizeof(MSFifo*)*MS_RING_PLAYER_MAX_OUTPUTS);
121
 
        memset(r->qoutputs,0,sizeof(MSQueue*)*MS_RING_PLAYER_MAX_OUTPUTS);
122
 
        r->fd=-1;
123
 
        r->current_pos=0;
124
 
        r->need_swap=0;
125
 
        r->sync=NULL;
126
 
}
127
 
 
128
 
gint ms_ring_player_set_property(MSRingPlayer *f,MSFilterProperty prop, void *value)
129
 
{
130
 
        switch(prop){
131
 
                case MS_FILTER_PROPERTY_FREQ:
132
 
                        f->rate=((gint*)value)[0]*2;
133
 
                        f->silence_bytes=f->silence*f->rate;
134
 
                        if (f->sync!=NULL)
135
 
                                f->gran=(f->rate*f->sync->interval/1000)*2;
136
 
                break;
137
 
        }
138
 
        return 0;
139
 
}
140
 
 
141
 
gint ms_ring_player_get_property(MSRingPlayer *f,MSFilterProperty prop, void *value)
142
 
{
143
 
        switch(prop){
144
 
                case MS_FILTER_PROPERTY_FREQ:
145
 
                        ((gint*)value)[0]=f->freq;
146
 
                        
147
 
                break;
148
 
                case MS_FILTER_PROPERTY_CHANNELS:
149
 
                        ((gint*)value)[0]=f->channel;
150
 
                break;
151
 
        }
152
 
        return 0;
153
 
}
154
 
 
155
 
gint ms_ring_player_get_sample_freq(MSRingPlayer *obj){
156
 
        return obj->freq;
157
 
}
158
 
 
159
 
 
160
 
void ms_ring_player_class_init(MSRingPlayerClass *klass)
161
 
{
162
 
        ms_filter_class_init(MS_FILTER_CLASS(klass));
163
 
        ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ringplay");
164
 
        ms_filter_class_set_attr(MS_FILTER_CLASS(klass),FILTER_IS_SOURCE);
165
 
        MS_FILTER_CLASS(klass)->max_foutputs=MS_RING_PLAYER_MAX_OUTPUTS;
166
 
        MS_FILTER_CLASS(klass)->max_qoutputs=MS_RING_PLAYER_MAX_OUTPUTS;
167
 
        MS_FILTER_CLASS(klass)->w_maxgran=MS_RING_PLAYER_DEF_GRAN;
168
 
        MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_ring_player_setup;
169
 
        MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ring_player_destroy;
170
 
        MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ring_player_process;
171
 
        MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_ring_player_set_property;
172
 
        MS_FILTER_CLASS(klass)->get_property=(MSFilterPropertyFunc)ms_ring_player_get_property;
173
 
}
174
 
        
175
 
void ms_ring_player_process(MSRingPlayer *r)
176
 
{
177
 
        MSFifo *f;
178
 
        gint err;
179
 
        gint processed=0;
180
 
        gint gran=r->gran;
181
 
        char *p;
182
 
        
183
 
        g_return_if_fail(gran>0);
184
 
        /* process output fifos*/
185
 
        
186
 
        f=r->foutputs[0];
187
 
        ms_fifo_get_write_ptr(f,gran,(void**)&p);
188
 
        g_return_if_fail(p!=NULL);
189
 
        for (processed=0;processed<gran;){
190
 
                switch(r->state){
191
 
                        case PLAY_RING:
192
 
                                err=read(r->fd,&p[processed],gran-processed);
193
 
                                if (err<0)
194
 
                                {
195
 
                                        memset(&p[processed],0,gran-processed);
196
 
                                        processed=gran;
197
 
                                        g_warning("ms_ring_player_process: failed to read: %s.\n",strerror(errno));
198
 
                                        return;
199
 
                                }
200
 
                                else if (err<gran)
201
 
                                {/* end of file */
202
 
                                        
203
 
                                        r->current_pos=r->silence_bytes;
204
 
                                        lseek(r->fd,WAVE_HEADER_OFFSET,SEEK_SET);
205
 
                                        r->state=PLAY_SILENCE;
206
 
          ms_filter_notify_event(MS_FILTER(r),MS_RING_PLAYER_END_OF_RING_EVENT,NULL);
207
 
                                }
208
 
                                if (r->need_swap) swap_buffer(&p[processed],err);
209
 
                                processed+=err;
210
 
                        break;
211
 
                        case PLAY_SILENCE:
212
 
                                err=gran-processed;
213
 
                                if  (r->current_pos>err){
214
 
                                        memset(&p[processed],0,err);
215
 
                                        r->current_pos-=gran;
216
 
                                        processed=gran;
217
 
                                }else{
218
 
                                        memset(&p[processed],0,r->current_pos);
219
 
                                        processed+=r->current_pos;
220
 
                                        r->state=PLAY_RING;
221
 
                                }
222
 
                        break;
223
 
                }
224
 
        }
225
 
}
226
 
 
227
 
/**
228
 
 * ms_ring_player_destroy:
229
 
 * @obj: A valid MSRingPlayer object.
230
 
 *
231
 
 * Destroy a MSRingPlayer object.
232
 
 *
233
 
 *
234
 
 */
235
 
 
236
 
void ms_ring_player_destroy( MSRingPlayer *obj)
237
 
{
238
 
        if (obj->fd!=0) close(obj->fd);
239
 
        g_free(obj);
240
 
}
241
 
 
242
 
void ms_ring_player_setup(MSRingPlayer *r,MSSync *sync)
243
 
{
244
 
        r->sync=sync;
245
 
        r->gran=(r->rate*r->sync->interval/1000)*r->channel;
246
 
}