Mercurial > pidgin
annotate src/mediastreamer/msringplayer.c @ 12662:eb4841fa697c
[gaim-migrate @ 15005]
sf bug #1385691, Text field visible even when status set to "online"
Don't allow available messages for ICQ. The server doesn't support them.
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Mon, 26 Dec 2005 07:43:41 +0000 |
| parents | 1c771536a032 |
| children |
| rev | line source |
|---|---|
| 12024 | 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> | |
|
12029
1c771536a032
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
28 #include <stdlib.h> |
| 12024 | 29 |
| 30 #include "waveheader.h" | |
| 31 | |
| 32 #define WAVE_HEADER_OFFSET sizeof(wave_header_t) | |
| 33 | |
| 34 enum { PLAY_RING, PLAY_SILENCE}; | |
| 35 | |
| 36 static int supported_freq[6]={8000,11025,16000,22050,32000,44100}; | |
| 37 | |
| 38 gint freq_is_supported(gint freq){ | |
| 39 int i; | |
| 40 for (i=0;i<6;i++){ | |
| 41 if (abs(supported_freq[i]-freq)<50) return supported_freq[i]; | |
| 42 } | |
| 43 return 0; | |
| 44 } | |
| 45 | |
| 46 static MSRingPlayerClass *ms_ring_player_class=NULL; | |
| 47 | |
| 48 /** | |
| 49 * ms_ring_player_new: | |
| 50 * @name: The path to the 16-bit 8khz raw file to be played as a ring. | |
| 51 * @seconds: The number of seconds that separates two rings. | |
| 52 * | |
| 53 * Allocates a new MSRingPlayer object. | |
| 54 * | |
| 55 * | |
| 56 * Returns: a pointer the the object, NULL if name could not be open. | |
| 57 */ | |
| 58 MSFilter * ms_ring_player_new(char *name, gint seconds) | |
| 59 { | |
| 60 MSRingPlayer *r; | |
| 61 int fd=-1; | |
| 62 | |
| 63 if ((name!=NULL) && (strlen(name)!=0)) | |
| 64 { | |
| 65 fd=open(name,O_RDONLY); | |
| 66 if (fd<0) | |
| 67 { | |
| 68 g_warning("ms_ring_player_new: failed to open %s.\n",name); | |
| 69 return NULL; | |
| 70 } | |
| 71 | |
| 72 }else { | |
| 73 g_warning("ms_ring_player_new: Bad file name"); | |
| 74 return NULL; | |
| 75 } | |
| 76 | |
| 77 r=g_new(MSRingPlayer,1); | |
| 78 ms_ring_player_init(r); | |
| 79 if (ms_ring_player_class==NULL) | |
| 80 { | |
| 81 ms_ring_player_class=g_new(MSRingPlayerClass,1); | |
| 82 ms_ring_player_class_init(ms_ring_player_class); | |
| 83 } | |
| 84 MS_FILTER(r)->klass=MS_FILTER_CLASS(ms_ring_player_class); | |
| 85 | |
| 86 r->fd=fd; | |
| 87 r->silence=seconds; | |
| 88 r->freq=8000; | |
| 89 if (strstr(name,".wav")!=NULL){ | |
| 90 wave_header_t header; | |
| 91 int freq,freq2; | |
| 92 /* read the header */ | |
| 93 read(fd,&header,sizeof(wave_header_t)); | |
| 94 freq=wave_header_get_rate(&header); | |
| 95 if ((freq2=freq_is_supported(freq))>0){ | |
| 96 r->freq=freq2; | |
| 97 }else { | |
| 98 g_warning("Unsupported sampling rate %i",freq); | |
| 99 r->freq=8000; | |
| 100 } | |
| 101 r->channel=wave_header_get_channel(&header); | |
| 102 lseek(fd,WAVE_HEADER_OFFSET,SEEK_SET); | |
| 103 #ifdef WORDS_BIGENDIAN | |
| 104 r->need_swap=1; | |
| 105 #else | |
| 106 r->need_swap=0; | |
| 107 #endif | |
| 108 } | |
| 109 ms_ring_player_set_property(r, MS_FILTER_PROPERTY_FREQ,&r->freq); | |
| 110 r->state=PLAY_RING; | |
| 111 return(MS_FILTER(r)); | |
| 112 } | |
| 113 | |
| 114 | |
| 115 /* FOR INTERNAL USE*/ | |
| 116 void ms_ring_player_init(MSRingPlayer *r) | |
| 117 { | |
| 118 ms_filter_init(MS_FILTER(r)); | |
| 119 MS_FILTER(r)->outfifos=r->foutputs; | |
| 120 MS_FILTER(r)->outqueues=r->qoutputs; | |
| 121 memset(r->foutputs,0,sizeof(MSFifo*)*MS_RING_PLAYER_MAX_OUTPUTS); | |
| 122 memset(r->qoutputs,0,sizeof(MSQueue*)*MS_RING_PLAYER_MAX_OUTPUTS); | |
| 123 r->fd=-1; | |
| 124 r->current_pos=0; | |
| 125 r->need_swap=0; | |
| 126 r->sync=NULL; | |
| 127 } | |
| 128 | |
| 129 gint ms_ring_player_set_property(MSRingPlayer *f,MSFilterProperty prop, void *value) | |
| 130 { | |
| 131 switch(prop){ | |
| 132 case MS_FILTER_PROPERTY_FREQ: | |
| 133 f->rate=((gint*)value)[0]*2; | |
| 134 f->silence_bytes=f->silence*f->rate; | |
| 135 if (f->sync!=NULL) | |
| 136 f->gran=(f->rate*f->sync->interval/1000)*2; | |
| 137 break; | |
|
12029
1c771536a032
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
138 case MS_FILTER_PROPERTY_BITRATE: |
|
1c771536a032
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
139 case MS_FILTER_PROPERTY_CHANNELS: |
|
1c771536a032
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
140 case MS_FILTER_PROPERTY_FMTP: |
|
1c771536a032
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
141 default: |
|
1c771536a032
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
142 break; |
| 12024 | 143 } |
| 144 return 0; | |
| 145 } | |
| 146 | |
| 147 gint ms_ring_player_get_property(MSRingPlayer *f,MSFilterProperty prop, void *value) | |
| 148 { | |
| 149 switch(prop){ | |
| 150 case MS_FILTER_PROPERTY_FREQ: | |
| 151 ((gint*)value)[0]=f->freq; | |
| 152 | |
| 153 break; | |
| 154 case MS_FILTER_PROPERTY_CHANNELS: | |
| 155 ((gint*)value)[0]=f->channel; | |
| 156 break; | |
|
12029
1c771536a032
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
157 case MS_FILTER_PROPERTY_BITRATE: |
|
1c771536a032
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
158 case MS_FILTER_PROPERTY_FMTP: |
|
1c771536a032
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
159 default: |
|
1c771536a032
[gaim-migrate @ 14322]
Gary Kramlich <grim@reaperworld.com>
parents:
12024
diff
changeset
|
160 break; |
| 12024 | 161 } |
| 162 return 0; | |
| 163 } | |
| 164 | |
| 165 gint ms_ring_player_get_sample_freq(MSRingPlayer *obj){ | |
| 166 return obj->freq; | |
| 167 } | |
| 168 | |
| 169 | |
| 170 void ms_ring_player_class_init(MSRingPlayerClass *klass) | |
| 171 { | |
| 172 ms_filter_class_init(MS_FILTER_CLASS(klass)); | |
| 173 ms_filter_class_set_name(MS_FILTER_CLASS(klass),"ringplay"); | |
| 174 ms_filter_class_set_attr(MS_FILTER_CLASS(klass),FILTER_IS_SOURCE); | |
| 175 MS_FILTER_CLASS(klass)->max_foutputs=MS_RING_PLAYER_MAX_OUTPUTS; | |
| 176 MS_FILTER_CLASS(klass)->max_qoutputs=MS_RING_PLAYER_MAX_OUTPUTS; | |
| 177 MS_FILTER_CLASS(klass)->w_maxgran=MS_RING_PLAYER_DEF_GRAN; | |
| 178 MS_FILTER_CLASS(klass)->setup=(MSFilterSetupFunc)ms_ring_player_setup; | |
| 179 MS_FILTER_CLASS(klass)->destroy=(MSFilterDestroyFunc)ms_ring_player_destroy; | |
| 180 MS_FILTER_CLASS(klass)->process=(MSFilterProcessFunc)ms_ring_player_process; | |
| 181 MS_FILTER_CLASS(klass)->set_property=(MSFilterPropertyFunc)ms_ring_player_set_property; | |
| 182 MS_FILTER_CLASS(klass)->get_property=(MSFilterPropertyFunc)ms_ring_player_get_property; | |
| 183 } | |
| 184 | |
| 185 void ms_ring_player_process(MSRingPlayer *r) | |
| 186 { | |
| 187 MSFifo *f; | |
| 188 gint err; | |
| 189 gint processed=0; | |
| 190 gint gran=r->gran; | |
| 191 char *p; | |
| 192 | |
| 193 g_return_if_fail(gran>0); | |
| 194 /* process output fifos*/ | |
| 195 | |
| 196 f=r->foutputs[0]; | |
| 197 ms_fifo_get_write_ptr(f,gran,(void**)&p); | |
| 198 g_return_if_fail(p!=NULL); | |
| 199 for (processed=0;processed<gran;){ | |
| 200 switch(r->state){ | |
| 201 case PLAY_RING: | |
| 202 err=read(r->fd,&p[processed],gran-processed); | |
| 203 if (err<0) | |
| 204 { | |
| 205 memset(&p[processed],0,gran-processed); | |
| 206 processed=gran; | |
| 207 g_warning("ms_ring_player_process: failed to read: %s.\n",strerror(errno)); | |
| 208 return; | |
| 209 } | |
| 210 else if (err<gran) | |
| 211 {/* end of file */ | |
| 212 | |
| 213 r->current_pos=r->silence_bytes; | |
| 214 lseek(r->fd,WAVE_HEADER_OFFSET,SEEK_SET); | |
| 215 r->state=PLAY_SILENCE; | |
| 216 ms_filter_notify_event(MS_FILTER(r),MS_RING_PLAYER_END_OF_RING_EVENT,NULL); | |
| 217 } | |
| 218 if (r->need_swap) swap_buffer(&p[processed],err); | |
| 219 processed+=err; | |
| 220 break; | |
| 221 case PLAY_SILENCE: | |
| 222 err=gran-processed; | |
| 223 if (r->current_pos>err){ | |
| 224 memset(&p[processed],0,err); | |
| 225 r->current_pos-=gran; | |
| 226 processed=gran; | |
| 227 }else{ | |
| 228 memset(&p[processed],0,r->current_pos); | |
| 229 processed+=r->current_pos; | |
| 230 r->state=PLAY_RING; | |
| 231 } | |
| 232 break; | |
| 233 } | |
| 234 } | |
| 235 } | |
| 236 | |
| 237 /** | |
| 238 * ms_ring_player_destroy: | |
| 239 * @obj: A valid MSRingPlayer object. | |
| 240 * | |
| 241 * Destroy a MSRingPlayer object. | |
| 242 * | |
| 243 * | |
| 244 */ | |
| 245 | |
| 246 void ms_ring_player_destroy( MSRingPlayer *obj) | |
| 247 { | |
| 248 if (obj->fd!=0) close(obj->fd); | |
| 249 g_free(obj); | |
| 250 } | |
| 251 | |
| 252 void ms_ring_player_setup(MSRingPlayer *r,MSSync *sync) | |
| 253 { | |
| 254 r->sync=sync; | |
| 255 r->gran=(r->rate*r->sync->interval/1000)*r->channel; | |
| 256 } |
