FreeSWITCH API Documentation  1.7.0
switch_core_file.c
Go to the documentation of this file.
1 /*
2  * FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
3  * Copyright (C) 2005-2014, Anthony Minessale II <anthm@freeswitch.org>
4  *
5  * Version: MPL 1.1
6  *
7  * The contents of this file are subject to the Mozilla Public License Version
8  * 1.1 (the "License"); you may not use this file except in compliance with
9  * the License. You may obtain a copy of the License at
10  * http://www.mozilla.org/MPL/
11  *
12  * Software distributed under the License is distributed on an "AS IS" basis,
13  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
14  * for the specific language governing rights and limitations under the
15  * License.
16  *
17  * The Original Code is FreeSWITCH Modular Media Switching Software Library / Soft-Switch Application
18  *
19  * The Initial Developer of the Original Code is
20  * Anthony Minessale II <anthm@freeswitch.org>
21  * Portions created by the Initial Developer are Copyright (C)
22  * the Initial Developer. All Rights Reserved.
23  *
24  * Contributor(s):
25  *
26  * Anthony Minessale II <anthm@freeswitch.org>
27  * Michael Jerris <mike@jerris.com>
28  * Paul D. Tinsley <pdt at jackhammer.org>
29  * John Wehle <john@feith.com>
30  *
31  *
32  * switch_core_file.c -- Main Core Library (File I/O Functions)
33  *
34  */
35 
36 #include <switch.h>
38 
39 SWITCH_DECLARE(switch_status_t) switch_core_perform_file_open(const char *file, const char *func, int line,
41  const char *file_path,
42  uint32_t channels, uint32_t rate, unsigned int flags, switch_memory_pool_t *pool)
43 {
44  char *ext;
46  char stream_name[128] = "";
47  char *rhs = NULL;
48  const char *spool_path = NULL;
49  int is_stream = 0;
50  char *fp = NULL;
51  int to = 0;
52 
54  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Handle already open\n");
55  return SWITCH_STATUS_FALSE;
56  }
57 
58  fh->samples_in = 0;
59 
60  if (!fh->samplerate) {
61  if (!(fh->samplerate = rate)) {
62  fh->samplerate = 8000;
63  }
64  }
65 
66  if (zstr(file_path)) {
68  return SWITCH_STATUS_FALSE;
69  }
70 
71  fh->flags = flags;
72 
73  if (pool) {
74  fh->memory_pool = pool;
75  } else {
76  if ((status = switch_core_new_memory_pool(&fh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
77  UNPROTECT_INTERFACE(fh->file_interface);
78  return status;
79  }
81  }
82 
83  switch_mutex_init(&fh->flag_mutex, SWITCH_MUTEX_NESTED, fh->memory_pool);
84 
85  fh->mm.samplerate = 44100;
86  fh->mm.channels = 1;
87  fh->mm.keyint = 60;
88  fh->mm.ab = 128;
89  fh->mm.vencspd = SWITCH_VIDEO_ENCODE_SPEED_DEFAULT;
90  fh->mm.vprofile = SWITCH_VIDEO_PROFILE_BASELINE;
91  fh->mm.try_hardware_encoder = 1;
92 
93  if (*file_path == '{') {
94  char *timeout;
95  char *modname;
96  const char *val;
97  int tmp;
98 
99  fp = switch_core_strdup(fh->memory_pool, file_path);
100 
101  while (*fp == '{') {
102  char *parsed = NULL;
103 
104  if (switch_event_create_brackets(fp, '{', '}', ',', &fh->params, &parsed, SWITCH_FALSE) != SWITCH_STATUS_SUCCESS || !parsed) {
106  goto fail;
107  }
108 
109  fp = parsed;
110  }
111 
112  file_path = fp;
113 
114  if ((timeout = switch_event_get_header(fh->params, "timeout"))) {
115  if ((to = atoi(timeout)) < 1) {
116  to = 0;
117  }
118  }
119 
120  if ((modname = switch_event_get_header(fh->params, "modname"))) {
121  fh->modname = switch_core_strdup(fh->memory_pool, modname);
122  }
123 
124  if ((val = switch_event_get_header(fh->params, "samplerate"))) {
125  tmp = atoi(val);
126  if (tmp > 8000) {
127  fh->mm.samplerate = tmp;
128  }
129  }
130 
131  if ((val = switch_event_get_header(fh->params, "channels"))) {
132  tmp = atoi(val);
133  if (tmp == 1 || tmp == 2) {
134  fh->mm.channels = tmp;
135  }
136  }
137 
138  if ((val = switch_event_get_header(fh->params, "ab"))) {
139  tmp = atoi(val);
140  if (tmp > 16) {
141  fh->mm.ab = tmp;
142  }
143  }
144 
145 
146  if ((val = switch_event_get_header(fh->params, "vb"))) {
147  tmp = atoi(val);
148 
149  if (strrchr(val, 'k')) {
150  tmp *= 1024;
151  } else if (strrchr(val, 'm')) {
152  tmp *= 1048576;
153  }
154 
155  fh->mm.vb = tmp;
156  }
157 
158  if ((val = switch_event_get_header(fh->params, "vw"))) {
159  tmp = atoi(val);
160  if (tmp > 0) {
161  fh->mm.vw = tmp;
162  }
163  }
164 
165  if ((val = switch_event_get_header(fh->params, "vh"))) {
166  tmp = atoi(val);
167  if (tmp > 0) {
168  fh->mm.vh = tmp;
169  }
170  }
171 
172  if ((val = switch_event_get_header(fh->params, "try_hardware_encoder"))) {
173  fh->mm.try_hardware_encoder = switch_true(val);
174  }
175 
176  if ((val = switch_event_get_header(fh->params, "fps"))) {
177  float ftmp = atof(val);
178  if (ftmp > 0.0f) {
179  fh->mm.fps = ftmp;
180  }
181  }
182 
183  if ((val = switch_event_get_header(fh->params, "vbuf"))) {
184  tmp = atoi(val);
185 
186  if (strrchr(val, 'k')) {
187  tmp *= 1024;
188  } else if (strrchr(val, 'm')) {
189  tmp *= 1048576;
190  }
191 
192  if (tmp > 0 && tmp < 104857600 /*100mb*/) {
193  fh->mm.vbuf = tmp;
194  } else {
195  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid buffer size: %d\n", tmp);
196  }
197  }
198 
199  if ((val = switch_event_get_header(fh->params, "vencspd"))) {
200  if (!strcasecmp(val, "slow")) {
201  fh->mm.vencspd = SWITCH_VIDEO_ENCODE_SPEED_SLOW;
202  } else if (!strcasecmp(val, "medium")) {
203  fh->mm.vencspd = SWITCH_VIDEO_ENCODE_SPEED_MEDIUM;
204  } else if (!strcasecmp(val, "fast")) {
205  fh->mm.vencspd = SWITCH_VIDEO_ENCODE_SPEED_FAST;
206  } else {
207  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid video encode speed: %s\n", val);
208  }
209  }
210 
211  if ((val = switch_event_get_header(fh->params, "vprofile"))) {
212  if (!strcasecmp(val, "baseline")) {
213  fh->mm.vprofile = SWITCH_VIDEO_PROFILE_BASELINE;
214  } else if (!strcasecmp(val, "main")) {
215  fh->mm.vprofile = SWITCH_VIDEO_PROFILE_MAIN;
216  } else if (!strcasecmp(val, "high")) {
217  fh->mm.vprofile = SWITCH_VIDEO_PROFILE_HIGH;
218  } else {
219  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid video profile: %s\n", val);
220  }
221  }
222  }
223 
224  if (switch_directory_exists(file_path, fh->memory_pool) == SWITCH_STATUS_SUCCESS) {
225  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File [%s] is a directory not a file.\n", file_path);
226  status = SWITCH_STATUS_GENERR;
227  goto fail;
228  }
229 
230  if ((rhs = strstr(file_path, SWITCH_URL_SEPARATOR))) {
231  switch_copy_string(stream_name, file_path, (rhs + 1) - file_path);
232  ext = stream_name;
233  file_path = rhs + 3;
234  fh->stream_name = switch_core_strdup(fh->memory_pool, stream_name);
235  fh->file_path = switch_core_strdup(fh->memory_pool, file_path);
236  is_stream = 1;
237  } else {
238  if ((flags & SWITCH_FILE_FLAG_WRITE)) {
239 
240  if (fh->params) {
241  spool_path = switch_event_get_header(fh->params, "spool_path");
242  }
243 
244  if (!spool_path) {
246  }
247  }
248 
249  if ((ext = strrchr(file_path, '.')) == 0) {
250  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Unknown file Format [%s]\n", file_path);
252  }
253  ext++;
254  fh->file_path = switch_core_strdup(fh->memory_pool, file_path);
255  }
256 
257 
258 
259  if ((fh->file_interface = switch_loadable_module_get_file_interface(ext, fh->modname)) == 0) {
260  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Invalid file format [%s] for [%s]!\n", ext, file_path);
262  }
263 
264  fh->file = file;
265  fh->func = func;
266  fh->line = line;
267 
268  if (switch_test_flag(fh, SWITCH_FILE_FLAG_VIDEO) && !fh->file_interface->file_read_video) {
270  }
271 
272  if (spool_path) {
273  char uuid_str[SWITCH_UUID_FORMATTED_LENGTH + 1];
274  switch_uuid_t uuid;
275  switch_uuid_get(&uuid);
276  switch_uuid_format(uuid_str, &uuid);
277 
278  fh->spool_path = switch_core_sprintf(fh->memory_pool, "%s%s%s.%s", spool_path, SWITCH_PATH_SEPARATOR, uuid_str, ext);
279  } else {
280  fh->spool_path = NULL;
281  }
282 
283  if (rhs) {
284  fh->handler = switch_core_strdup(fh->memory_pool, rhs);
285  } else {
286  fh->handler = NULL;
287  }
288 
289  if (channels) {
290  fh->channels = channels;
291  } else {
292  fh->channels = 1;
293  }
294 
295  file_path = fh->spool_path ? fh->spool_path : fh->file_path;
296 
297  if ((status = fh->file_interface->file_open(fh, file_path)) != SWITCH_STATUS_SUCCESS) {
298  if (fh->spool_path) {
299  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "Spool dir is set. Make sure [%s] is also a valid path\n", fh->spool_path);
300  }
301  UNPROTECT_INTERFACE(fh->file_interface);
302  goto fail;
303  }
304 
305  fh->real_channels = fh->channels;
306 
307  if (channels) {
308  fh->channels = channels;
309  }
310 
311  if ((flags & SWITCH_FILE_FLAG_WRITE) && !is_stream && (status = switch_file_exists(file_path, fh->memory_pool)) != SWITCH_STATUS_SUCCESS) {
312  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "File [%s] not created!\n", file_path);
313  fh->file_interface->file_close(fh);
314  UNPROTECT_INTERFACE(fh->file_interface);
315  goto fail;
316  }
317 
318  if (to) {
319  fh->max_samples = (fh->samplerate / 1000) * to;
320  }
321 
322 
323  if ((flags & SWITCH_FILE_FLAG_READ)) {
324  fh->native_rate = fh->samplerate;
325  } else {
326  fh->native_rate = rate;
327  }
328 
329  if (fh->samplerate && rate && fh->samplerate != rate) {
330  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "File %s sample rate %d doesn't match requested rate %d\n", file_path, fh->samplerate, rate);
331  if ((flags & SWITCH_FILE_FLAG_READ)) {
332  fh->samplerate = rate;
333  }
334  }
335 
337  fh->pre_buffer_datalen = 0;
338  }
339 
340  if (fh->pre_buffer_datalen) {
341  //switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Prebuffering %d bytes\n", (int)fh->pre_buffer_datalen);
342  switch_buffer_create_dynamic(&fh->pre_buffer, fh->pre_buffer_datalen * fh->channels, fh->pre_buffer_datalen * fh->channels, 0);
343  fh->pre_buffer_data = switch_core_alloc(fh->memory_pool, fh->pre_buffer_datalen * fh->channels);
344  }
345 
346 
347  if (fh->real_channels != fh->channels && (flags & SWITCH_FILE_FLAG_READ) && !(fh->flags & SWITCH_FILE_NOMUX)) {
348  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_WARNING, "File has %d channels, muxing to %d channel%s will occur.\n", fh->real_channels, fh->channels, fh->channels == 1 ? "" : "s");
349  }
350 
352  return status;
353 
354  fail:
355 
357 
358  if (fh->params) {
359  switch_event_destroy(&fh->params);
360  }
361 
362  fh->samples_in = 0;
363  fh->max_samples = 0;
364 
366  switch_core_destroy_memory_pool(&fh->memory_pool);
367  }
368 
369  return status;
370 }
371 
373 {
375  switch_size_t want, orig_len = *len;
376 
377  switch_assert(fh != NULL);
378  switch_assert(fh->file_interface != NULL);
379 
381  return SWITCH_STATUS_FALSE;
382  }
383 
384  top:
385 
386  if (fh->max_samples > 0 && fh->samples_in >= (switch_size_t)fh->max_samples) {
387  *len = 0;
388  return SWITCH_STATUS_FALSE;
389  }
390 
391  if (fh->buffer && switch_buffer_inuse(fh->buffer) >= *len * 2 * fh->channels) {
392  *len = switch_buffer_read(fh->buffer, data, orig_len * 2 * fh->channels) / 2 / fh->channels;
393  return *len == 0 ? SWITCH_STATUS_FALSE : SWITCH_STATUS_SUCCESS;
394  }
395 
398  *len = 0;
399  return SWITCH_STATUS_FALSE;
400  }
401 
402  want = *len;
403 
404  more:
405 
406  if (fh->pre_buffer) {
407  switch_size_t rlen;
408  int asis = switch_test_flag(fh, SWITCH_FILE_NATIVE);
409 
411  rlen = asis ? fh->pre_buffer_datalen : fh->pre_buffer_datalen / 2 / fh->real_channels;
412 
413  if (switch_buffer_inuse(fh->pre_buffer) < rlen * 2 * fh->channels) {
414  if ((status = fh->file_interface->file_read(fh, fh->pre_buffer_data, &rlen)) == SWITCH_STATUS_BREAK) {
415  return SWITCH_STATUS_BREAK;
416  }
417 
418 
419  if (status != SWITCH_STATUS_SUCCESS || !rlen) {
421  } else {
422  fh->samples_in += rlen;
423  if (fh->real_channels != fh->channels && !switch_test_flag(fh, SWITCH_FILE_NOMUX)) {
424  switch_mux_channels((int16_t *) fh->pre_buffer_data, rlen, fh->real_channels, fh->channels);
425  }
426  switch_buffer_write(fh->pre_buffer, fh->pre_buffer_data, asis ? rlen : rlen * 2 * fh->channels);
427  }
428  }
429  }
430 
431  rlen = switch_buffer_read(fh->pre_buffer, data, asis ? *len : *len * 2 * fh->channels);
432  *len = asis ? rlen : rlen / 2 / fh->channels;
433 
434  if (*len == 0) {
436  goto top;
437  } else {
438  status = SWITCH_STATUS_SUCCESS;
439  }
440 
441  } else {
442 
443  if ((status = fh->file_interface->file_read(fh, data, len)) == SWITCH_STATUS_BREAK) {
444  return SWITCH_STATUS_BREAK;
445  }
446 
447  if (status != SWITCH_STATUS_SUCCESS || !*len) {
449  goto top;
450  }
451 
452  fh->samples_in += *len;
453 
454  if (fh->real_channels != fh->channels && !switch_test_flag(fh, SWITCH_FILE_NOMUX)) {
455  switch_mux_channels((int16_t *) data, *len, fh->real_channels, fh->channels);
456  }
457  }
458 
459  if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->native_rate != fh->samplerate) {
460  if (!fh->resampler) {
461  if (switch_resample_create(&fh->resampler,
462  fh->native_rate, fh->samplerate, (uint32_t) orig_len, SWITCH_RESAMPLE_QUALITY, fh->channels) != SWITCH_STATUS_SUCCESS) {
463  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n");
464  return SWITCH_STATUS_GENERR;
465  }
466  }
467 
468  switch_resample_process(fh->resampler, data, (uint32_t) *len);
469 
470  if (fh->resampler->to_len < want || fh->resampler->to_len > orig_len) {
471  if (!fh->buffer) {
472  int factor = fh->resampler->to_len * fh->samplerate / 1000;
473  switch_buffer_create_dynamic(&fh->buffer, factor, factor, 0);
474  switch_assert(fh->buffer);
475  }
476  if (!fh->dbuf || fh->dbuflen < fh->resampler->to_len * 2 * fh->channels) {
477  void *mem;
478  fh->dbuflen = fh->resampler->to_len * 2 * fh->channels;
479  mem = realloc(fh->dbuf, fh->dbuflen);
480  switch_assert(mem);
481  fh->dbuf = mem;
482  }
483  switch_assert(fh->resampler->to_len * 2 * fh->channels <= fh->dbuflen);
484  memcpy((int16_t *) fh->dbuf, fh->resampler->to, fh->resampler->to_len * 2 * fh->channels);
485  switch_buffer_write(fh->buffer, fh->dbuf, fh->resampler->to_len * 2 * fh->channels);
486 
487  if (switch_buffer_inuse(fh->buffer) < want * 2 * fh->channels) {
488  *len = want;
489  goto more;
490  }
491  *len = switch_buffer_read(fh->buffer, data, orig_len * 2 * fh->channels) / 2 / fh->channels;
492  } else {
493  memcpy(data, fh->resampler->to, fh->resampler->to_len * 2 * fh->channels);
494  *len = fh->resampler->to_len;
495  }
496 
497 
498  }
499 
500  return status;
501 }
502 
504 {
506 }
507 
509 {
510  switch_size_t orig_len = *len;
511 
512  switch_assert(fh != NULL);
513  switch_assert(fh->file_interface != NULL);
514 
516  return SWITCH_STATUS_FALSE;
517  }
518 
519  if (!fh->file_interface->file_write) {
520  return SWITCH_STATUS_FALSE;
521  }
522 
523  if (!switch_test_flag(fh, SWITCH_FILE_NATIVE) && fh->native_rate != fh->samplerate) {
524  if (!fh->resampler) {
525  if (switch_resample_create(&fh->resampler,
526  fh->native_rate,
527  fh->samplerate,
528  (uint32_t) orig_len * 2 * fh->channels, SWITCH_RESAMPLE_QUALITY, fh->channels) != SWITCH_STATUS_SUCCESS) {
529  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_CRIT, "Unable to create resampler!\n");
530  return SWITCH_STATUS_GENERR;
531  }
532  }
533 
534  switch_resample_process(fh->resampler, data, (uint32_t) * len);
535 
536  if (fh->resampler->to_len > orig_len) {
537  if (!fh->dbuf || (fh->dbuflen < fh->resampler->to_len * 2 * fh->channels)) {
538  void *mem;
539  fh->dbuflen = fh->resampler->to_len * 2 * fh->channels;
540  mem = realloc(fh->dbuf, fh->dbuflen);
541  switch_assert(mem);
542  fh->dbuf = mem;
543  }
544  switch_assert(fh->resampler->to_len * 2 * fh->channels <= fh->dbuflen);
545  memcpy(fh->dbuf, fh->resampler->to, fh->resampler->to_len * 2 * fh->channels);
546  data = fh->dbuf;
547  } else {
548  memcpy(data, fh->resampler->to, fh->resampler->to_len * 2 * fh->channels);
549  }
550 
551  *len = fh->resampler->to_len;
552  }
553 
554  if (!*len) {
555  return SWITCH_STATUS_SUCCESS;
556  }
557 
558  if (fh->pre_buffer) {
559  switch_size_t rlen, blen;
561  int asis = switch_test_flag(fh, SWITCH_FILE_NATIVE);
562 
563  switch_buffer_write(fh->pre_buffer, data, (asis ? *len : *len * 2) * fh->channels);
564 
565  rlen = switch_buffer_inuse(fh->pre_buffer);
566 
567  if (rlen >= fh->pre_buffer_datalen) {
568  if ((blen = switch_buffer_read(fh->pre_buffer, fh->pre_buffer_data, fh->pre_buffer_datalen))) {
569  if (!asis)
570  blen /= 2;
571  if (fh->channels > 1)
572  blen /= fh->channels;
573  if ((status = fh->file_interface->file_write(fh, fh->pre_buffer_data, &blen)) != SWITCH_STATUS_SUCCESS) {
574  *len = 0;
575  }
576  }
577  }
578  fh->samples_out += orig_len;
579  return status;
580  } else {
581  switch_status_t status;
582  if ((status = fh->file_interface->file_write(fh, data, len)) == SWITCH_STATUS_SUCCESS) {
583  fh->samples_out += orig_len;
584  }
585  return status;
586  }
587 }
588 
590 {
591  switch_assert(fh != NULL);
592  switch_assert(fh->file_interface != NULL);
593 
595  return SWITCH_STATUS_GENERR;
596  }
597 
598  if (!fh->file_interface->file_write_video) {
599  return SWITCH_STATUS_FALSE;
600  }
601 
602  return fh->file_interface->file_write_video(fh, frame);
603 
604 }
605 
607 {
608  switch_status_t status;
609 
610  switch_assert(fh != NULL);
611  switch_assert(fh->file_interface != NULL);
612 
614  return SWITCH_STATUS_GENERR;
615  }
616 
617  if (!fh->file_interface->file_read_video) {
618  return SWITCH_STATUS_FALSE;
619  }
620 
621  status = fh->file_interface->file_read_video(fh, frame, flags);
622 
623  if (status == SWITCH_STATUS_FALSE) {
625  }
626 
627  return status;
628 }
629 
630 SWITCH_DECLARE(switch_status_t) switch_core_file_seek(switch_file_handle_t *fh, unsigned int *cur_pos, int64_t samples, int whence)
631 {
632  switch_status_t status;
633  int ok = 1;
634 
635  switch_assert(fh != NULL);
636 
637  if (!switch_test_flag(fh, SWITCH_FILE_OPEN) || !fh->file_interface->file_seek) {
638  ok = 0;
639  } else if (switch_test_flag(fh, SWITCH_FILE_FLAG_WRITE)) {
641  ok = 0;
642  }
643  } else if (!switch_test_flag(fh, SWITCH_FILE_FLAG_READ)) {
644  ok = 0;
645  }
646 
647  if (!ok) {
648  return SWITCH_STATUS_FALSE;
649  }
650 
651  if (fh->buffer) {
652  switch_buffer_zero(fh->buffer);
653  }
654 
655  if (fh->pre_buffer) {
656  switch_buffer_zero(fh->pre_buffer);
657  }
658 
659  if (whence == SWITCH_SEEK_CUR) {
660  unsigned int cur = 0;
661 
663  fh->file_interface->file_seek(fh, &cur, fh->samples_out, SEEK_SET);
664  } else {
665  fh->file_interface->file_seek(fh, &cur, fh->offset_pos, SEEK_SET);
666  }
667  }
668 
670  status = fh->file_interface->file_seek(fh, cur_pos, samples, whence);
671 
672  fh->offset_pos = *cur_pos;
673 
675  fh->samples_out = *cur_pos;
676  }
677 
678  return status;
679 }
680 
682 {
683  switch_assert(fh != NULL);
684  switch_assert(fh->file_interface != NULL);
685 
687  return SWITCH_STATUS_FALSE;
688  }
689 
690  if (!fh->file_interface->file_set_string) {
691  return SWITCH_STATUS_FALSE;
692  }
693 
694  return fh->file_interface->file_set_string(fh, col, string);
695 }
696 
698 {
699  switch_assert(fh != NULL);
700  switch_assert(fh->file_interface != NULL);
701 
703  return SWITCH_STATUS_FALSE;
704  }
705 
706  if (!fh->file_interface->file_get_string) {
707  return SWITCH_STATUS_FALSE;
708  }
709 
710  return fh->file_interface->file_get_string(fh, col, string);
711 }
712 
714 {
715  switch_status_t status;
716 
717  switch_assert(fh != NULL);
718  switch_assert(fh->file_interface != NULL);
719 
721  return SWITCH_STATUS_FALSE;
722  }
723 
724  if (!fh->file_interface->file_truncate) {
725  return SWITCH_STATUS_FALSE;
726  }
727 
728  if ((status = fh->file_interface->file_truncate(fh, offset)) == SWITCH_STATUS_SUCCESS) {
729  if (fh->buffer) {
730  switch_buffer_zero(fh->buffer);
731  }
732  if (fh->pre_buffer) {
733  switch_buffer_zero(fh->pre_buffer);
734  }
735  fh->samples_out = 0;
736  fh->pos = 0;
737  }
738 
739  return status;
740 
741 }
742 
744 {
746 
747  switch_assert(fh != NULL);
748  switch_assert(fh->file_interface != NULL);
749 
751  return SWITCH_STATUS_FALSE;
752  }
753 
754  switch(command) {
755  case SCFC_FLUSH_AUDIO:
756  if (fh->pre_buffer) {
757  switch_buffer_zero(fh->pre_buffer);
758  }
759  break;
760  default:
761  break;
762  }
763 
764  if (fh->file_interface->file_command) {
765  switch_mutex_lock(fh->flag_mutex);
766  status = fh->file_interface->file_command(fh, command);
767  switch_mutex_unlock(fh->flag_mutex);
768  }
769 
770  return status;
771 }
772 
773 
775 {
776  switch_status_t status;
777 
778  switch_assert(fh != NULL);
779  switch_assert(fh->file_interface != NULL);
780 
782  return SWITCH_STATUS_FALSE;
783  }
784 
785  if (fh->pre_buffer) {
787  switch_size_t rlen, blen;
788  int asis = switch_test_flag(fh, SWITCH_FILE_NATIVE);
789 
790  while ((rlen = switch_buffer_inuse(fh->pre_buffer))) {
791  if ((blen = switch_buffer_read(fh->pre_buffer, fh->pre_buffer_data, fh->pre_buffer_datalen))) {
792  if (!asis)
793  blen /= 2;
794  if (fh->channels > 1)
795  blen /= fh->channels;
796 
797  if (fh->file_interface->file_write(fh, fh->pre_buffer_data, &blen) != SWITCH_STATUS_SUCCESS) {
798  break;
799  }
800  }
801  }
802  }
803 
804  switch_buffer_destroy(&fh->pre_buffer);
805  }
806 
808  status = fh->file_interface->file_close(fh);
809 
810  if (fh->params) {
811  switch_event_destroy(&fh->params);
812  }
813 
814  fh->samples_in = 0;
815  fh->max_samples = 0;
816 
817  if (fh->buffer) {
818  switch_buffer_destroy(&fh->buffer);
819  }
820 
821  switch_resample_destroy(&fh->resampler);
822 
824  switch_core_destroy_memory_pool(&fh->memory_pool);
825  }
826 
827  fh->memory_pool = NULL;
828 
829  switch_safe_free(fh->dbuf);
830 
831  if (fh->spool_path) {
832  char *command;
833 
834 #ifdef _MSC_VER
835  command = switch_mprintf("move %s %s", fh->spool_path, fh->file_path);
836 #else
837  command = switch_mprintf("/bin/mv %s %s", fh->spool_path, fh->file_path);
838 #endif
839  if (system(command) == -1) {
840  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_ERROR, "Failed to copy spooled file [%s] to [%s] because of a command error : %s\n", fh->spool_path, fh->file_path, command);
841  } else {
842  switch_log_printf(SWITCH_CHANNEL_LOG, SWITCH_LOG_DEBUG, "Copy spooled file [%s] to [%s]\n", fh->spool_path, fh->file_path);
843  }
844  free(command);
845  }
846 
847  UNPROTECT_INTERFACE(fh->file_interface);
848  fh->file_interface = NULL;
849 
850  return status;
851 }
852 
853 /* For Emacs:
854  * Local Variables:
855  * mode:c
856  * indent-tabs-mode:t
857  * tab-width:4
858  * c-basic-offset:4
859  * End:
860  * For VIM:
861  * vim:set softtabstop=4 shiftwidth=4 tabstop=4 noet:
862  */
switch_status_t switch_core_file_set_string(switch_file_handle_t *fh, switch_audio_col_t col, const char *string)
#define switch_core_new_memory_pool(p)
Create a new sub memory pool from the core's master pool.
Definition: switch_core.h:631
switch_status_t switch_directory_exists(const char *dirname, switch_memory_pool_t *pool)
Definition: switch_apr.c:474
#define switch_set_flag(obj, flag)
Set a flag on an arbitrary object.
Definition: switch_utils.h:631
#define SWITCH_CHANNEL_LOG
switch_size_t switch_buffer_read(_In_ switch_buffer_t *buffer, _In_ void *data, _In_ switch_size_t datalen)
Read data from a switch_buffer_t up to the ammount of datalen if it is available. Remove read data fr...
switch_status_t switch_buffer_create_dynamic(_Out_ switch_buffer_t **buffer, _In_ switch_size_t blocksize, _In_ switch_size_t start_len, _In_ switch_size_t max_len)
Allocate a new dynamic switch_buffer.
switch_status_t switch_core_file_read_video(switch_file_handle_t *fh, switch_frame_t *frame, switch_video_read_flag_t flags)
char * switch_core_get_variable_pdup(_In_z_ const char *varname, switch_memory_pool_t *pool)
switch_bool_t
Definition: switch_types.h:405
switch_status_t switch_event_create_brackets(char *data, char a, char b, char c, switch_event_t **event, char **new_data, switch_bool_t dup)
switch_audio_col_t
Definition: switch_types.h:578
#define switch_core_strdup(_pool, _todup)
Copy a string using memory allocation from a given pool.
Definition: switch_core.h:729
#define SWITCH_URL_SEPARATOR
Definition: switch_types.h:124
switch_status_t switch_core_file_command(switch_file_handle_t *fh, switch_file_command_t command)
#define switch_core_destroy_memory_pool(p)
Returns a subpool back to the main pool.
Definition: switch_core.h:640
switch_memory_pool_t * pool
#define fail()
Definition: tone2wav.c:70
#define SWITCH_AUDIO_SPOOL_PATH_VARIABLE
Definition: switch_types.h:126
#define SWITCH_RESAMPLE_QUALITY
pack cur
void switch_resample_destroy(switch_audio_resampler_t **resampler)
Destroy an existing resampler handle.
switch_size_t switch_buffer_write(_In_ switch_buffer_t *buffer, _In_bytecount_(datalen) const void *data, _In_ switch_size_t datalen)
Write data into a switch_buffer_t up to the length of datalen.
static int switch_true(const char *expr)
Evaluate the truthfullness of a string expression.
Definition: switch_utils.h:450
#define zstr(x)
Definition: switch_utils.h:281
switch_video_read_flag_t
switch_status_t switch_mutex_unlock(switch_mutex_t *lock)
Definition: switch_apr.c:290
switch_status_t switch_core_file_seek(switch_file_handle_t *fh, unsigned int *cur_pos, int64_t samples, int whence)
#define UNPROTECT_INTERFACE(_it)
#define SWITCH_MUTEX_NESTED
Definition: switch_apr.h:318
#define SWITCH_PATH_SEPARATOR
Definition: switch_types.h:122
switch_status_t switch_mutex_lock(switch_mutex_t *lock)
Definition: switch_apr.c:285
#define switch_core_alloc(_pool, _mem)
Allocate memory directly from a memory pool.
Definition: switch_core.h:682
switch_file_interface_t * switch_loadable_module_get_file_interface(const char *name, const char *modname)
Retrieve the file format interface by it's registered name.
#define switch_safe_free(it)
Free a pointer and set it to NULL unless it already is NULL.
Definition: switch_utils.h:789
switch_status_t switch_mutex_init(switch_mutex_t **lock, unsigned int flags, switch_memory_pool_t *pool)
Definition: switch_apr.c:270
#define SWITCH_SEEK_CUR
Definition: switch_apr.h:699
void switch_buffer_zero(_In_ switch_buffer_t *buffer)
Remove all data from the buffer.
An abstraction of a data frame.
Definition: switch_frame.h:43
uintptr_t switch_size_t
#define switch_set_flag_locked(obj, flag)
Set a flag on an arbitrary object while locked.
Definition: switch_utils.h:638
void switch_cond_next(void)
Definition: switch_time.c:638
char * switch_copy_string(_Out_z_cap_(dst_size) char *dst, _In_z_ const char *src, _In_ switch_size_t dst_size)
void switch_mux_channels(int16_t *data, switch_size_t samples, uint32_t orig_channels, uint32_t channels)
switch_status_t switch_file_exists(const char *filename, switch_memory_pool_t *pool)
Definition: switch_apr.c:496
void switch_uuid_format(char *buffer, const switch_uuid_t *uuid)
Definition: switch_apr.c:1055
switch_status_t switch_core_file_close(switch_file_handle_t *fh)
#define switch_clear_flag_locked(obj, flag)
Clear a flag on an arbitrary object.
Definition: switch_utils.h:648
switch_status_t
Common return values.
#define switch_goto_status(_status, _label)
Definition: switch_utils.h:256
switch_file_command_t
Main Library Header.
#define SWITCH_DECLARE(type)
void switch_uuid_get(switch_uuid_t *uuid)
Definition: switch_apr.c:1067
switch_status_t switch_core_file_get_string(switch_file_handle_t *fh, switch_audio_col_t col, const char **string)
switch_status_t switch_core_perform_file_open(const char *file, const char *func, int line, switch_file_handle_t *fh, const char *file_path, uint32_t channels, uint32_t rate, unsigned int flags, switch_memory_pool_t *pool)
#define switch_event_get_header(_e, _h)
Definition: switch_event.h:172
switch_status_t switch_core_file_truncate(switch_file_handle_t *fh, int64_t offset)
switch_bool_t switch_core_file_has_video(switch_file_handle_t *fh, switch_bool_t check_open)
switch_status_t switch_core_file_write_video(switch_file_handle_t *fh, switch_frame_t *frame)
switch_status_t switch_core_file_read(switch_file_handle_t *fh, void *data, switch_size_t *len)
struct apr_pool_t switch_memory_pool_t
#define switch_test_flag(obj, flag)
Test for the existance of a flag on an arbitary object.
Definition: switch_utils.h:624
void switch_log_printf(_In_ switch_text_channel_t channel, _In_z_ const char *file, _In_z_ const char *func, _In_ int line, _In_opt_z_ const char *userdata, _In_ switch_log_level_t level, _In_z_ _Printf_format_string_ const char *fmt,...) PRINTF_FUNCTION(7
Write log data to the logging engine.
switch_status_t switch_core_file_write(switch_file_handle_t *fh, void *data, switch_size_t *len)
void switch_event_destroy(switch_event_t **event)
Destroy an event.
char * switch_core_sprintf(_In_ switch_memory_pool_t *pool, _In_z_ _Printf_format_string_ const char *fmt,...)
printf-style style printing routine. The data is output to a string allocated from the pool ...
#define switch_assert(expr)
switch_size_t switch_buffer_inuse(_In_ switch_buffer_t *buffer)
Get the in use amount of a switch_buffer_t.
void switch_buffer_destroy(switch_buffer_t **buffer)
Destroy the buffer.
SWITCH_BEGIN_EXTERN_C char * switch_mprintf(const char *zFormat,...)
#define switch_resample_create(_n, _fr, _tr, _ts, _q, _c)
#define SWITCH_UUID_FORMATTED_LENGTH
Definition: switch_apr.h:545
uint32_t switch_resample_process(switch_audio_resampler_t *resampler, int16_t *src, uint32_t srclen)
Resample one float buffer into another using specifications of a given handle.