Wed Jan 8 2020 09:49:53

Asterisk developer's documentation


app_jack.c File Reference

Jack Application. More...

#include "asterisk.h"
#include <limits.h>
#include <jack/jack.h>
#include <jack/ringbuffer.h>
#include <libresample.h>
#include "asterisk/module.h"
#include "asterisk/channel.h"
#include "asterisk/strings.h"
#include "asterisk/lock.h"
#include "asterisk/app.h"
#include "asterisk/pbx.h"
#include "asterisk/audiohook.h"

Go to the source code of this file.

Data Structures

struct  jack_data
 

Macros

#define COMMON_OPTIONS
 Common options between the Jack() app and JACK_HOOK() function. More...
 
#define RESAMPLE_QUALITY   1
 
#define RINGBUFFER_SIZE   16384
 

Enumerations

enum  {
  OPT_SERVER_NAME = (1 << 0), OPT_INPUT_PORT = (1 << 1), OPT_OUTPUT_PORT = (1 << 2), OPT_NOSTART_SERVER = (1 << 3),
  OPT_CLIENT_NAME = (1 << 4)
}
 
enum  {
  OPT_ARG_SERVER_NAME, OPT_ARG_INPUT_PORT, OPT_ARG_OUTPUT_PORT, OPT_ARG_CLIENT_NAME,
  OPT_ARG_ARRAY_SIZE
}
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int alloc_resampler (struct jack_data *jack_data, int input)
 
static struct jack_datadestroy_jack_data (struct jack_data *jack_data)
 
static int disable_jack_hook (struct ast_channel *chan)
 
static int enable_jack_hook (struct ast_channel *chan, char *data)
 
static void handle_input (void *buf, jack_nframes_t nframes, struct jack_data *jack_data)
 Handle jack input port. More...
 
static void handle_jack_audio (struct ast_channel *chan, struct jack_data *jack_data, struct ast_frame *out_frame)
 handle jack audio More...
 
static int handle_options (struct jack_data *jack_data, const char *__options_str)
 
static void handle_output (void *buf, jack_nframes_t nframes, struct jack_data *jack_data)
 Handle jack output port. More...
 
static int init_jack_data (struct ast_channel *chan, struct jack_data *jack_data)
 
static struct jack_datajack_data_alloc (void)
 
static int jack_exec (struct ast_channel *chan, const char *data)
 
static int jack_hook_callback (struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
 
static void jack_hook_ds_destroy (void *data)
 
static int jack_hook_write (struct ast_channel *chan, const char *cmd, char *data, const char *value)
 
static int jack_process (jack_nframes_t nframes, void *arg)
 
static void jack_shutdown (void *arg)
 
static const char * jack_status_to_str (jack_status_t status)
 
static int load_module (void)
 
static void log_jack_status (const char *prefix, jack_status_t status)
 
static int queue_voice_frame (struct jack_data *jack_data, struct ast_frame *f)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "JACK Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
static struct ast_module_infoast_module_info = &__mod_info
 
static const char jack_app [] = "JACK"
 
static struct ast_app_option jack_exec_options [128] = { [ 's' ] = { .flag = OPT_SERVER_NAME , .arg_index = OPT_ARG_SERVER_NAME + 1 }, [ 'i' ] = { .flag = OPT_INPUT_PORT , .arg_index = OPT_ARG_INPUT_PORT + 1 }, [ 'o' ] = { .flag = OPT_OUTPUT_PORT , .arg_index = OPT_ARG_OUTPUT_PORT + 1 }, [ 'n' ] = { .flag = OPT_NOSTART_SERVER }, [ 'c' ] = { .flag = OPT_CLIENT_NAME , .arg_index = OPT_ARG_CLIENT_NAME + 1 }, }
 
static struct ast_datastore_info jack_hook_ds_info
 
static struct ast_custom_function jack_hook_function
 
struct {
   jack_status_t   status
 
   const char *   str
 
jack_status_table []
 

Detailed Description

Jack Application.

Author
Russell Bryant russe.nosp@m.ll@d.nosp@m.igium.nosp@m..com

This is an application to connect an Asterisk channel to an input and output jack port so that the audio can be processed through another application, or to play audio from another application.

ExtRef:
http://www.jackaudio.org/
Note
To install libresample, check it out of the following repository: $ svn co http://svn.digium.com/svn/thirdparty/libresample/trunk

Definition in file app_jack.c.

Macro Definition Documentation

#define COMMON_OPTIONS

Common options between the Jack() app and JACK_HOOK() function.

Definition at line 67 of file app_jack.c.

#define RESAMPLE_QUALITY   1

Definition at line 62 of file app_jack.c.

Referenced by alloc_resampler().

#define RINGBUFFER_SIZE   16384

Definition at line 64 of file app_jack.c.

Referenced by init_jack_data().

Enumeration Type Documentation

anonymous enum
Enumerator
OPT_SERVER_NAME 
OPT_INPUT_PORT 
OPT_OUTPUT_PORT 
OPT_NOSTART_SERVER 
OPT_CLIENT_NAME 

Definition at line 650 of file app_jack.c.

650  {
651  OPT_SERVER_NAME = (1 << 0),
652  OPT_INPUT_PORT = (1 << 1),
653  OPT_OUTPUT_PORT = (1 << 2),
654  OPT_NOSTART_SERVER = (1 << 3),
655  OPT_CLIENT_NAME = (1 << 4),
656 };
anonymous enum
Enumerator
OPT_ARG_SERVER_NAME 
OPT_ARG_INPUT_PORT 
OPT_ARG_OUTPUT_PORT 
OPT_ARG_CLIENT_NAME 
OPT_ARG_ARRAY_SIZE 

Definition at line 658 of file app_jack.c.

Function Documentation

static void __reg_module ( void  )
static

Definition at line 1031 of file app_jack.c.

static void __unreg_module ( void  )
static

Definition at line 1031 of file app_jack.c.

static int alloc_resampler ( struct jack_data jack_data,
int  input 
)
static

Definition at line 190 of file app_jack.c.

References ast_log(), jack_data::client, jack_data::input_resample_factor, jack_data::input_resampler, LOG_ERROR, jack_data::output_resample_factor, jack_data::output_resampler, and RESAMPLE_QUALITY.

Referenced by jack_process(), and queue_voice_frame().

191 {
192  double from_srate, to_srate, jack_srate;
193  void **resampler;
194  double *resample_factor;
195 
196  if (input && jack_data->input_resampler)
197  return 0;
198 
199  if (!input && jack_data->output_resampler)
200  return 0;
201 
202  jack_srate = jack_get_sample_rate(jack_data->client);
203 
204  /* XXX Hard coded 8 kHz */
205 
206  to_srate = input ? 8000.0 : jack_srate;
207  from_srate = input ? jack_srate : 8000.0;
208 
209  resample_factor = input ? &jack_data->input_resample_factor :
210  &jack_data->output_resample_factor;
211 
212  if (from_srate == to_srate) {
213  /* Awesome! The jack sample rate is the same as ours.
214  * Resampling isn't needed. */
215  *resample_factor = 1.0;
216  return 0;
217  }
218 
219  *resample_factor = to_srate / from_srate;
220 
221  resampler = input ? &jack_data->input_resampler :
222  &jack_data->output_resampler;
223 
224  if (!(*resampler = resample_open(RESAMPLE_QUALITY,
225  *resample_factor, *resample_factor))) {
226  ast_log(LOG_ERROR, "Failed to open %s resampler\n",
227  input ? "input" : "output");
228  return -1;
229  }
230 
231  return 0;
232 }
void * output_resampler
Definition: app_jack.c:131
#define RESAMPLE_QUALITY
Definition: app_jack.c:62
static int input(yyscan_t yyscanner)
Definition: ast_expr2f.c:1575
void * input_resampler
Definition: app_jack.c:133
jack_client_t * client
Definition: app_jack.c:126
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
double input_resample_factor
Definition: app_jack.c:134
double output_resample_factor
Definition: app_jack.c:132
static struct jack_data* destroy_jack_data ( struct jack_data jack_data)
static

Definition at line 342 of file app_jack.c.

References ast_audiohook_destroy(), ast_free, ast_string_field_free_memory, jack_data::audiohook, jack_data::client, jack_data::has_audiohook, jack_data::input_port, jack_data::input_rb, jack_data::input_resampler, jack_data::output_port, jack_data::output_rb, and jack_data::output_resampler.

Referenced by enable_jack_hook(), jack_exec(), and jack_hook_ds_destroy().

343 {
344  if (jack_data->input_port) {
345  jack_port_unregister(jack_data->client, jack_data->input_port);
346  jack_data->input_port = NULL;
347  }
348 
349  if (jack_data->output_port) {
350  jack_port_unregister(jack_data->client, jack_data->output_port);
351  jack_data->output_port = NULL;
352  }
353 
354  if (jack_data->client) {
355  jack_client_close(jack_data->client);
356  jack_data->client = NULL;
357  }
358 
359  if (jack_data->input_rb) {
360  jack_ringbuffer_free(jack_data->input_rb);
361  jack_data->input_rb = NULL;
362  }
363 
364  if (jack_data->output_rb) {
365  jack_ringbuffer_free(jack_data->output_rb);
366  jack_data->output_rb = NULL;
367  }
368 
369  if (jack_data->output_resampler) {
370  resample_close(jack_data->output_resampler);
371  jack_data->output_resampler = NULL;
372  }
373 
374  if (jack_data->input_resampler) {
375  resample_close(jack_data->input_resampler);
376  jack_data->input_resampler = NULL;
377  }
378 
379  if (jack_data->has_audiohook)
380  ast_audiohook_destroy(&jack_data->audiohook);
381 
382  ast_string_field_free_memory(jack_data);
383 
384  ast_free(jack_data);
385 
386  return NULL;
387 }
unsigned int has_audiohook
Definition: app_jack.c:136
void * output_resampler
Definition: app_jack.c:131
int ast_audiohook_destroy(struct ast_audiohook *audiohook)
Destroys an audiohook structure.
Definition: audiohook.c:96
jack_port_t * output_port
Definition: app_jack.c:128
jack_port_t * input_port
Definition: app_jack.c:127
void * input_resampler
Definition: app_jack.c:133
jack_client_t * client
Definition: app_jack.c:126
jack_ringbuffer_t * input_rb
Definition: app_jack.c:129
jack_ringbuffer_t * output_rb
Definition: app_jack.c:130
#define ast_free(a)
Definition: astmm.h:97
struct ast_audiohook audiohook
Definition: app_jack.c:139
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
static int disable_jack_hook ( struct ast_channel chan)
static

Definition at line 921 of file app_jack.c.

References ast_audiohook_detach(), ast_channel_datastore_find(), ast_channel_datastore_remove(), ast_channel_lock, ast_channel_unlock, ast_datastore_free(), ast_log(), jack_data::audiohook, ast_datastore::data, and LOG_WARNING.

Referenced by jack_hook_write().

922 {
923  struct ast_datastore *datastore;
924  struct jack_data *jack_data;
925 
926  ast_channel_lock(chan);
927 
928  if (!(datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
929  ast_channel_unlock(chan);
930  ast_log(LOG_WARNING, "No JACK_HOOK found to disable\n");
931  return -1;
932  }
933 
934  ast_channel_datastore_remove(chan, datastore);
935 
936  jack_data = datastore->data;
937  ast_audiohook_detach(&jack_data->audiohook);
938 
939  /* Keep the channel locked while we destroy the datastore, so that we can
940  * ensure that all of the jack stuff is stopped just in case another frame
941  * tries to come through the audiohook callback. */
942  ast_datastore_free(datastore);
943 
944  ast_channel_unlock(chan);
945 
946  return 0;
947 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define LOG_WARNING
Definition: logger.h:144
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
static struct ast_datastore_info jack_hook_ds_info
Definition: app_jack.c:809
int ast_audiohook_detach(struct ast_audiohook *audiohook)
Detach audiohook from channel.
Definition: audiohook.c:401
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void * data
Definition: datastore.h:56
struct ast_audiohook audiohook
Definition: app_jack.c:139
int ast_channel_datastore_remove(struct ast_channel *chan, struct ast_datastore *datastore)
Remove a datastore from a channel.
Definition: channel.c:2599
static int enable_jack_hook ( struct ast_channel chan,
char *  data 
)
static

Definition at line 854 of file app_jack.c.

References args, AST_APP_ARG, ast_audiohook_attach(), ast_audiohook_init(), AST_AUDIOHOOK_TYPE_MANIPULATE, ast_channel_datastore_add(), ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, ast_datastore_alloc(), ast_datastore_free(), AST_DECLARE_APP_ARGS, ast_log(), AST_STANDARD_APP_ARGS, ast_strlen_zero(), jack_data::audiohook, ast_datastore::data, destroy_jack_data(), handle_options(), jack_data::has_audiohook, init_jack_data(), jack_data_alloc(), jack_hook_callback(), LOG_ERROR, ast_audiohook::manipulate_callback, ast_channel::name, and S_OR.

Referenced by jack_hook_write().

855 {
856  struct ast_datastore *datastore;
857  struct jack_data *jack_data = NULL;
859  AST_APP_ARG(mode);
860  AST_APP_ARG(options);
861  );
862 
864 
865  ast_channel_lock(chan);
866 
867  if ((datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
868  ast_log(LOG_ERROR, "JACK_HOOK already enabled for '%s'\n", chan->name);
869  goto return_error;
870  }
871 
872  if (ast_strlen_zero(args.mode) || strcasecmp(args.mode, "manipulate")) {
873  ast_log(LOG_ERROR, "'%s' is not a supported mode. Only manipulate is supported.\n",
874  S_OR(args.mode, "<none>"));
875  goto return_error;
876  }
877 
878  if (!(jack_data = jack_data_alloc()))
879  goto return_error;
880 
881  if (!ast_strlen_zero(args.options) && handle_options(jack_data, args.options))
882  goto return_error;
883 
884  if (init_jack_data(chan, jack_data))
885  goto return_error;
886 
887  if (!(datastore = ast_datastore_alloc(&jack_hook_ds_info, NULL)))
888  goto return_error;
889 
890  jack_data->has_audiohook = 1;
893 
894  datastore->data = jack_data;
895 
896  if (ast_audiohook_attach(chan, &jack_data->audiohook))
897  goto return_error;
898 
899  if (ast_channel_datastore_add(chan, datastore))
900  goto return_error;
901 
902  ast_channel_unlock(chan);
903 
904  return 0;
905 
906 return_error:
907  ast_channel_unlock(chan);
908 
909  if (jack_data) {
910  destroy_jack_data(jack_data);
911  }
912 
913  if (datastore) {
914  datastore->data = NULL;
915  ast_datastore_free(datastore);
916  }
917 
918  return -1;
919 }
#define ast_channel_lock(chan)
Definition: channel.h:2466
unsigned int has_audiohook
Definition: app_jack.c:136
int ast_audiohook_init(struct ast_audiohook *audiohook, enum ast_audiohook_type type, const char *source)
Initialize an audiohook structure.
Definition: audiohook.c:64
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
static int handle_options(struct jack_data *jack_data, const char *__options_str)
Definition: app_jack.c:690
static int init_jack_data(struct ast_channel *chan, struct jack_data *jack_data)
Definition: app_jack.c:389
int ast_audiohook_attach(struct ast_channel *chan, struct ast_audiohook *audiohook)
Attach audiohook to channel.
Definition: audiohook.c:348
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
ast_audiohook_manipulate_callback manipulate_callback
Definition: audiohook.h:116
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static struct ast_datastore_info jack_hook_ds_info
Definition: app_jack.c:809
#define LOG_ERROR
Definition: logger.h:155
static struct jack_data * destroy_jack_data(struct jack_data *jack_data)
Definition: app_jack.c:342
static struct @350 args
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static int jack_hook_callback(struct ast_audiohook *audiohook, struct ast_channel *chan, struct ast_frame *frame, enum ast_audiohook_direction direction)
Definition: app_jack.c:814
void * data
Definition: datastore.h:56
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
static struct jack_data * jack_data_alloc(void)
Definition: app_jack.c:676
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
struct ast_audiohook audiohook
Definition: app_jack.c:139
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
static void handle_input ( void *  buf,
jack_nframes_t  nframes,
struct jack_data jack_data 
)
static

Handle jack input port.

Read nframes number of samples from the input buffer, resample it if necessary, and write it into the appropriate ringbuffer.

Definition at line 240 of file app_jack.c.

References ARRAY_LEN, ast_debug, ast_log(), jack_data::input_rb, jack_data::input_resample_factor, jack_data::input_resampler, and LOG_ERROR.

Referenced by jack_process().

242 {
243  short s_buf[nframes];
244  float *in_buf = buf;
245  size_t res;
246  int i;
247  size_t write_len = sizeof(s_buf);
248 
249  if (jack_data->input_resampler) {
250  int total_in_buf_used = 0;
251  int total_out_buf_used = 0;
252  float f_buf[nframes + 1];
253 
254  memset(f_buf, 0, sizeof(f_buf));
255 
256  while (total_in_buf_used < nframes) {
257  int in_buf_used;
258  int out_buf_used;
259 
260  out_buf_used = resample_process(jack_data->input_resampler,
261  jack_data->input_resample_factor,
262  &in_buf[total_in_buf_used], nframes - total_in_buf_used,
263  0, &in_buf_used,
264  &f_buf[total_out_buf_used], ARRAY_LEN(f_buf) - total_out_buf_used);
265 
266  if (out_buf_used < 0)
267  break;
268 
269  total_out_buf_used += out_buf_used;
270  total_in_buf_used += in_buf_used;
271 
272  if (total_out_buf_used == ARRAY_LEN(f_buf)) {
273  ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size, "
274  "nframes '%d', total_out_buf_used '%d'\n", nframes, total_out_buf_used);
275  break;
276  }
277  }
278 
279  for (i = 0; i < total_out_buf_used; i++)
280  s_buf[i] = f_buf[i] * (SHRT_MAX / 1.0);
281 
282  write_len = total_out_buf_used * sizeof(int16_t);
283  } else {
284  /* No resampling needed */
285 
286  for (i = 0; i < nframes; i++)
287  s_buf[i] = in_buf[i] * (SHRT_MAX / 1.0);
288  }
289 
290  res = jack_ringbuffer_write(jack_data->input_rb, (const char *) s_buf, write_len);
291  if (res != write_len) {
292  ast_debug(2, "Tried to write %d bytes to the ringbuffer, but only wrote %d\n",
293  (int) sizeof(s_buf), (int) res);
294  }
295 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
void * input_resampler
Definition: app_jack.c:133
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
jack_ringbuffer_t * input_rb
Definition: app_jack.c:129
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
double input_resample_factor
Definition: app_jack.c:134
static void handle_jack_audio ( struct ast_channel chan,
struct jack_data jack_data,
struct ast_frame out_frame 
)
static

handle jack audio

Parameters
[in]chanThe Asterisk channel to write the frames to if no output frame is provided.
[in]jack_dataThis is the jack_data struct that contains the input ringbuffer that audio will be read from.
[out]out_frameIf this argument is non-NULL, then assuming there is enough data avilable in the ringbuffer, the audio in this frame will get replaced with audio from the input buffer. If there is not enough data available to read at this time, then the frame data gets zeroed out.

Read data from the input ringbuffer, which is the properly resampled audio that was read from the jack input port. Write it to the channel in 20 ms frames, or fill up an output frame instead if one is provided.

Returns
Nothing.

Definition at line 602 of file app_jack.c.

References ARRAY_LEN, ast_debug, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_log(), ast_write(), ast_frame::data, ast_frame::datalen, ast_frame::frametype, jack_data::input_rb, LOG_ERROR, ast_frame::ptr, and ast_frame::samples.

Referenced by jack_exec(), and jack_hook_callback().

604 {
605  short buf[160];
606  struct ast_frame f = {
607  .frametype = AST_FRAME_VOICE,
608  .subclass.codec = AST_FORMAT_SLINEAR,
609  .src = "JACK",
610  .data.ptr = buf,
611  .datalen = sizeof(buf),
612  .samples = ARRAY_LEN(buf),
613  };
614 
615  for (;;) {
616  size_t res, read_len;
617  char *read_buf;
618 
619  read_len = out_frame ? out_frame->datalen : sizeof(buf);
620  read_buf = out_frame ? out_frame->data.ptr : buf;
621 
622  res = jack_ringbuffer_read_space(jack_data->input_rb);
623 
624  if (res < read_len) {
625  /* Not enough data ready for another frame, move on ... */
626  if (out_frame) {
627  ast_debug(1, "Sending an empty frame for the JACK_HOOK\n");
628  memset(out_frame->data.ptr, 0, out_frame->datalen);
629  }
630  break;
631  }
632 
633  res = jack_ringbuffer_read(jack_data->input_rb, (char *) read_buf, read_len);
634 
635  if (res < read_len) {
636  ast_log(LOG_ERROR, "Error reading from ringbuffer, even though it said there was enough data\n");
637  break;
638  }
639 
640  if (out_frame) {
641  /* If an output frame was provided, then we just want to fill up the
642  * buffer in that frame and return. */
643  break;
644  }
645 
646  ast_write(chan, &f);
647  }
648 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
void * ptr
Definition: frame.h:160
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int datalen
Definition: frame.h:148
jack_ringbuffer_t * input_rb
Definition: app_jack.c:129
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static struct ast_format f[]
Definition: format_g726.c:181
int ast_write(struct ast_channel *chan, struct ast_frame *frame)
Write a frame to a channel This function writes the given frame to the indicated channel.
Definition: channel.c:4916
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
Data structure associated with a single frame of data.
Definition: frame.h:142
union ast_frame::@172 data
int samples
Definition: frame.h:150
static int handle_options ( struct jack_data jack_data,
const char *  __options_str 
)
static
Note
This must be done before calling init_jack_data().

Definition at line 690 of file app_jack.c.

References ast_app_parse_options(), ast_log(), ast_strdupa, ast_string_field_set, ast_strlen_zero(), ast_test_flag, jack_exec_options, LOG_ERROR, jack_data::no_start_server, OPT_ARG_ARRAY_SIZE, OPT_ARG_CLIENT_NAME, OPT_ARG_INPUT_PORT, OPT_ARG_OUTPUT_PORT, OPT_ARG_SERVER_NAME, OPT_CLIENT_NAME, OPT_INPUT_PORT, OPT_NOSTART_SERVER, OPT_OUTPUT_PORT, and OPT_SERVER_NAME.

Referenced by enable_jack_hook(), and jack_exec().

691 {
692  struct ast_flags options = { 0, };
694  char *options_str;
695 
696  options_str = ast_strdupa(__options_str);
697 
698  ast_app_parse_options(jack_exec_options, &options, option_args, options_str);
699 
700  if (ast_test_flag(&options, OPT_SERVER_NAME)) {
701  if (!ast_strlen_zero(option_args[OPT_ARG_SERVER_NAME]))
702  ast_string_field_set(jack_data, server_name, option_args[OPT_ARG_SERVER_NAME]);
703  else {
704  ast_log(LOG_ERROR, "A server name must be provided with the s() option\n");
705  return -1;
706  }
707  }
708 
709  if (ast_test_flag(&options, OPT_CLIENT_NAME)) {
710  if (!ast_strlen_zero(option_args[OPT_ARG_CLIENT_NAME]))
711  ast_string_field_set(jack_data, client_name, option_args[OPT_ARG_CLIENT_NAME]);
712  else {
713  ast_log(LOG_ERROR, "A client name must be provided with the c() option\n");
714  return -1;
715  }
716  }
717 
718  if (ast_test_flag(&options, OPT_INPUT_PORT)) {
719  if (!ast_strlen_zero(option_args[OPT_ARG_INPUT_PORT]))
720  ast_string_field_set(jack_data, connect_input_port, option_args[OPT_ARG_INPUT_PORT]);
721  else {
722  ast_log(LOG_ERROR, "A name must be provided with the i() option\n");
723  return -1;
724  }
725  }
726 
727  if (ast_test_flag(&options, OPT_OUTPUT_PORT)) {
728  if (!ast_strlen_zero(option_args[OPT_ARG_OUTPUT_PORT]))
729  ast_string_field_set(jack_data, connect_output_port, option_args[OPT_ARG_OUTPUT_PORT]);
730  else {
731  ast_log(LOG_ERROR, "A name must be provided with the o() option\n");
732  return -1;
733  }
734  }
735 
736  jack_data->no_start_server = ast_test_flag(&options, OPT_NOSTART_SERVER) ? 1 : 0;
737 
738  return 0;
739 }
#define ast_test_flag(p, flag)
Definition: utils.h:63
unsigned int no_start_server
Definition: app_jack.c:137
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
static struct ast_app_option jack_exec_options[128]
Definition: app_jack.c:674
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
Structure used to handle boolean flags.
Definition: utils.h:200
option_args
Definition: app_skel.c:84
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static void handle_output ( void *  buf,
jack_nframes_t  nframes,
struct jack_data jack_data 
)
static

Handle jack output port.

Read nframes number of samples from the ringbuffer and write it out to the output port buffer.

Definition at line 303 of file app_jack.c.

References ast_debug, len(), and jack_data::output_rb.

Referenced by jack_process().

305 {
306  size_t res, len;
307 
308  len = nframes * sizeof(float);
309 
310  res = jack_ringbuffer_read(jack_data->output_rb, buf, len);
311 
312  if (len != res) {
313  ast_debug(2, "Wanted %d bytes to send to the output port, "
314  "but only got %d\n", (int) len, (int) res);
315  }
316 }
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
jack_ringbuffer_t * output_rb
Definition: app_jack.c:130
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
static int init_jack_data ( struct ast_channel chan,
struct jack_data jack_data 
)
static

Definition at line 389 of file app_jack.c.

References ast_channel_lock, ast_channel_unlock, ast_debug, ast_log(), ast_strdupa, ast_strlen_zero(), jack_data::client, jack_data::client_name, jack_data::connect_input_port, jack_data::connect_output_port, free, jack_data::input_port, jack_data::input_rb, jack_process(), jack_shutdown(), LOG_ERROR, log_jack_status(), ast_channel::name, jack_data::no_start_server, jack_data::output_port, jack_data::output_rb, RINGBUFFER_SIZE, jack_data::server_name, and status.

Referenced by enable_jack_hook(), and jack_exec().

390 {
391  const char *client_name;
392  jack_status_t status = 0;
393  jack_options_t jack_options = JackNullOption;
394 
395  if (!ast_strlen_zero(jack_data->client_name)) {
396  client_name = jack_data->client_name;
397  } else {
398  ast_channel_lock(chan);
399  client_name = ast_strdupa(chan->name);
400  ast_channel_unlock(chan);
401  }
402 
403  if (!(jack_data->output_rb = jack_ringbuffer_create(RINGBUFFER_SIZE)))
404  return -1;
405 
406  if (!(jack_data->input_rb = jack_ringbuffer_create(RINGBUFFER_SIZE)))
407  return -1;
408 
409  if (jack_data->no_start_server)
410  jack_options |= JackNoStartServer;
411 
412  if (!ast_strlen_zero(jack_data->server_name)) {
413  jack_options |= JackServerName;
414  jack_data->client = jack_client_open(client_name, jack_options, &status,
415  jack_data->server_name);
416  } else {
417  jack_data->client = jack_client_open(client_name, jack_options, &status);
418  }
419 
420  if (status)
421  log_jack_status("Client Open Status", status);
422 
423  if (!jack_data->client)
424  return -1;
425 
426  jack_data->input_port = jack_port_register(jack_data->client, "input",
427  JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput | JackPortIsTerminal, 0);
428  if (!jack_data->input_port) {
429  ast_log(LOG_ERROR, "Failed to create input port for jack port\n");
430  return -1;
431  }
432 
433  jack_data->output_port = jack_port_register(jack_data->client, "output",
434  JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0);
435  if (!jack_data->output_port) {
436  ast_log(LOG_ERROR, "Failed to create output port for jack port\n");
437  return -1;
438  }
439 
440  if (jack_set_process_callback(jack_data->client, jack_process, jack_data)) {
441  ast_log(LOG_ERROR, "Failed to register process callback with jack client\n");
442  return -1;
443  }
444 
445  jack_on_shutdown(jack_data->client, jack_shutdown, jack_data);
446 
447  if (jack_activate(jack_data->client)) {
448  ast_log(LOG_ERROR, "Unable to activate jack client\n");
449  return -1;
450  }
451 
452  while (!ast_strlen_zero(jack_data->connect_input_port)) {
453  const char **ports;
454  int i;
455 
456  ports = jack_get_ports(jack_data->client, jack_data->connect_input_port,
457  NULL, JackPortIsInput);
458 
459  if (!ports) {
460  ast_log(LOG_ERROR, "No input port matching '%s' was found\n",
461  jack_data->connect_input_port);
462  break;
463  }
464 
465  for (i = 0; ports[i]; i++) {
466  ast_debug(1, "Found port '%s' that matched specified input port '%s'\n",
467  ports[i], jack_data->connect_input_port);
468  }
469 
470  if (jack_connect(jack_data->client, jack_port_name(jack_data->output_port), ports[0])) {
471  ast_log(LOG_ERROR, "Failed to connect '%s' to '%s'\n", ports[0],
472  jack_port_name(jack_data->output_port));
473  } else {
474  ast_debug(1, "Connected '%s' to '%s'\n", ports[0],
475  jack_port_name(jack_data->output_port));
476  }
477 
478  free((void *) ports);
479 
480  break;
481  }
482 
483  while (!ast_strlen_zero(jack_data->connect_output_port)) {
484  const char **ports;
485  int i;
486 
487  ports = jack_get_ports(jack_data->client, jack_data->connect_output_port,
488  NULL, JackPortIsOutput);
489 
490  if (!ports) {
491  ast_log(LOG_ERROR, "No output port matching '%s' was found\n",
492  jack_data->connect_output_port);
493  break;
494  }
495 
496  for (i = 0; ports[i]; i++) {
497  ast_debug(1, "Found port '%s' that matched specified output port '%s'\n",
498  ports[i], jack_data->connect_output_port);
499  }
500 
501  if (jack_connect(jack_data->client, ports[0], jack_port_name(jack_data->input_port))) {
502  ast_log(LOG_ERROR, "Failed to connect '%s' to '%s'\n", ports[0],
503  jack_port_name(jack_data->input_port));
504  } else {
505  ast_debug(1, "Connected '%s' to '%s'\n", ports[0],
506  jack_port_name(jack_data->input_port));
507  }
508 
509  free((void *) ports);
510 
511  break;
512  }
513 
514  return 0;
515 }
const ast_string_field connect_input_port
Definition: app_jack.c:125
#define ast_channel_lock(chan)
Definition: channel.h:2466
static void log_jack_status(const char *prefix, jack_status_t status)
Definition: app_jack.c:171
unsigned int no_start_server
Definition: app_jack.c:137
static void jack_shutdown(void *arg)
Definition: app_jack.c:335
jack_port_t * output_port
Definition: app_jack.c:128
jack_port_t * input_port
Definition: app_jack.c:127
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
jack_client_t * client
Definition: app_jack.c:126
jack_ringbuffer_t * input_rb
Definition: app_jack.c:129
jack_ringbuffer_t * output_rb
Definition: app_jack.c:130
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
const ast_string_field server_name
Definition: app_jack.c:125
#define LOG_ERROR
Definition: logger.h:155
#define free(a)
Definition: astmm.h:94
const ast_string_field client_name
Definition: app_jack.c:125
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_channel_unlock(chan)
Definition: channel.h:2467
static int jack_process(jack_nframes_t nframes, void *arg)
Definition: app_jack.c:318
#define RINGBUFFER_SIZE
Definition: app_jack.c:64
const ast_string_field connect_output_port
Definition: app_jack.c:125
jack_status_t status
Definition: app_jack.c:143
static struct jack_data* jack_data_alloc ( void  )
static

Definition at line 676 of file app_jack.c.

References ast_calloc_with_stringfields.

Referenced by enable_jack_hook(), and jack_exec().

677 {
678  struct jack_data *jack_data;
679 
680  if (!(jack_data = ast_calloc_with_stringfields(1, struct jack_data, 32))) {
681  return NULL;
682  }
683 
684  return jack_data;
685 }
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:275
static int jack_exec ( struct ast_channel chan,
const char *  data 
)
static

Definition at line 741 of file app_jack.c.

References AST_CONTROL_HANGUP, AST_FORMAT_SLINEAR, AST_FRAME_CONTROL, AST_FRAME_VOICE, ast_frfree, ast_read(), ast_set_read_format(), ast_set_write_format(), ast_strlen_zero(), ast_waitfor(), destroy_jack_data(), f, ast_frame::frametype, handle_jack_audio(), handle_options(), init_jack_data(), ast_frame_subclass::integer, jack_data_alloc(), queue_voice_frame(), jack_data::stop, and ast_frame::subclass.

Referenced by load_module().

742 {
743  struct jack_data *jack_data;
744 
745  if (!(jack_data = jack_data_alloc()))
746  return -1;
747 
748  if (!ast_strlen_zero(data) && handle_options(jack_data, data)) {
749  destroy_jack_data(jack_data);
750  return -1;
751  }
752 
753  if (init_jack_data(chan, jack_data)) {
754  destroy_jack_data(jack_data);
755  return -1;
756  }
757 
759  destroy_jack_data(jack_data);
760  return -1;
761  }
762 
764  destroy_jack_data(jack_data);
765  return -1;
766  }
767 
768  while (!jack_data->stop) {
769  struct ast_frame *f;
770 
771  if (ast_waitfor(chan, -1) < 0) {
772  break;
773  }
774 
775  f = ast_read(chan);
776  if (!f) {
777  jack_data->stop = 1;
778  continue;
779  }
780 
781  switch (f->frametype) {
782  case AST_FRAME_CONTROL:
784  jack_data->stop = 1;
785  break;
786  case AST_FRAME_VOICE:
787  queue_voice_frame(jack_data, f);
788  default:
789  break;
790  }
791 
792  ast_frfree(f);
793 
794  handle_jack_audio(chan, jack_data, NULL);
795  }
796 
797  jack_data = destroy_jack_data(jack_data);
798 
799  return 0;
800 }
union ast_frame_subclass subclass
Definition: frame.h:146
static int handle_options(struct jack_data *jack_data, const char *__options_str)
Definition: app_jack.c:690
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
unsigned int stop
Definition: app_jack.c:135
static int init_jack_data(struct ast_channel *chan, struct jack_data *jack_data)
Definition: app_jack.c:389
int ast_set_write_format(struct ast_channel *chan, format_t format)
Sets write format on channel chan Set write format for channel to whichever component of &quot;format&quot; is ...
Definition: channel.c:5307
int ast_set_read_format(struct ast_channel *chan, format_t format)
Sets read format on channel chan Set read format for channel to whichever component of &quot;format&quot; is be...
Definition: channel.c:5301
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_data, struct ast_frame *out_frame)
handle jack audio
Definition: app_jack.c:602
static struct jack_data * destroy_jack_data(struct jack_data *jack_data)
Definition: app_jack.c:342
static struct ast_format f[]
Definition: format_g726.c:181
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
Data structure associated with a single frame of data.
Definition: frame.h:142
static struct jack_data * jack_data_alloc(void)
Definition: app_jack.c:676
static int queue_voice_frame(struct jack_data *jack_data, struct ast_frame *f)
Definition: app_jack.c:517
enum ast_frame_type frametype
Definition: frame.h:144
#define ast_frfree(fr)
Definition: frame.h:583
static int jack_hook_callback ( struct ast_audiohook audiohook,
struct ast_channel chan,
struct ast_frame frame,
enum ast_audiohook_direction  direction 
)
static

Definition at line 814 of file app_jack.c.

References AST_AUDIOHOOK_DIRECTION_READ, AST_AUDIOHOOK_STATUS_DONE, ast_channel_datastore_find(), ast_channel_lock, ast_channel_unlock, AST_FORMAT_SLINEAR, AST_FRAME_VOICE, ast_getformatname(), ast_log(), ast_frame_subclass::codec, ast_datastore::data, ast_frame::frametype, handle_jack_audio(), LOG_ERROR, LOG_WARNING, ast_channel::name, queue_voice_frame(), ast_audiohook::status, and ast_frame::subclass.

Referenced by enable_jack_hook().

816 {
817  struct ast_datastore *datastore;
818  struct jack_data *jack_data;
819 
820  if (audiohook->status == AST_AUDIOHOOK_STATUS_DONE)
821  return 0;
822 
823  if (direction != AST_AUDIOHOOK_DIRECTION_READ)
824  return 0;
825 
826  if (frame->frametype != AST_FRAME_VOICE)
827  return 0;
828 
829  if (frame->subclass.codec != AST_FORMAT_SLINEAR) {
830  ast_log(LOG_WARNING, "Expected frame in SLINEAR for the audiohook, but got format %s\n",
832  return 0;
833  }
834 
835  ast_channel_lock(chan);
836 
837  if (!(datastore = ast_channel_datastore_find(chan, &jack_hook_ds_info, NULL))) {
838  ast_log(LOG_ERROR, "JACK_HOOK datastore not found for '%s'\n", chan->name);
839  ast_channel_unlock(chan);
840  return -1;
841  }
842 
843  jack_data = datastore->data;
844 
845  queue_voice_frame(jack_data, frame);
846 
847  handle_jack_audio(chan, jack_data, frame);
848 
849  ast_channel_unlock(chan);
850 
851  return 0;
852 }
union ast_frame_subclass subclass
Definition: frame.h:146
#define ast_channel_lock(chan)
Definition: channel.h:2466
#define LOG_WARNING
Definition: logger.h:144
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
format_t codec
Definition: frame.h:137
static void handle_jack_audio(struct ast_channel *chan, struct jack_data *jack_data, struct ast_frame *out_frame)
handle jack audio
Definition: app_jack.c:602
static struct ast_datastore_info jack_hook_ds_info
Definition: app_jack.c:809
char * ast_getformatname(format_t format)
Get the name of a format.
Definition: frame.c:578
#define LOG_ERROR
Definition: logger.h:155
const ast_string_field name
Definition: channel.h:787
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define ast_channel_unlock(chan)
Definition: channel.h:2467
void * data
Definition: datastore.h:56
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
static int queue_voice_frame(struct jack_data *jack_data, struct ast_frame *f)
Definition: app_jack.c:517
enum ast_audiohook_status status
Definition: audiohook.h:107
enum ast_frame_type frametype
Definition: frame.h:144
static void jack_hook_ds_destroy ( void *  data)
static

Definition at line 802 of file app_jack.c.

References destroy_jack_data().

803 {
804  struct jack_data *jack_data = data;
805 
806  destroy_jack_data(jack_data);
807 }
static struct jack_data * destroy_jack_data(struct jack_data *jack_data)
Definition: app_jack.c:342
static int jack_hook_write ( struct ast_channel chan,
const char *  cmd,
char *  data,
const char *  value 
)
static

Definition at line 949 of file app_jack.c.

References ast_log(), disable_jack_hook(), enable_jack_hook(), LOG_ERROR, and LOG_WARNING.

951 {
952  int res;
953 
954  if (!chan) {
955  ast_log(LOG_WARNING, "No channel was provided to %s function.\n", cmd);
956  return -1;
957  }
958 
959  if (!strcasecmp(value, "on"))
960  res = enable_jack_hook(chan, data);
961  else if (!strcasecmp(value, "off"))
962  res = disable_jack_hook(chan);
963  else {
964  ast_log(LOG_ERROR, "'%s' is not a valid value for JACK_HOOK()\n", value);
965  res = -1;
966  }
967 
968  return res;
969 }
#define LOG_WARNING
Definition: logger.h:144
int value
Definition: syslog.c:39
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
static int disable_jack_hook(struct ast_channel *chan)
Definition: app_jack.c:921
static int enable_jack_hook(struct ast_channel *chan, char *data)
Definition: app_jack.c:854
static int jack_process ( jack_nframes_t  nframes,
void *  arg 
)
static

Definition at line 318 of file app_jack.c.

References alloc_resampler(), handle_input(), handle_output(), jack_data::input_port, jack_data::input_resample_factor, and jack_data::output_port.

Referenced by init_jack_data().

319 {
320  struct jack_data *jack_data = arg;
321  void *input_port_buf, *output_port_buf;
322 
323  if (!jack_data->input_resample_factor)
324  alloc_resampler(jack_data, 1);
325 
326  input_port_buf = jack_port_get_buffer(jack_data->input_port, nframes);
327  handle_input(input_port_buf, nframes, jack_data);
328 
329  output_port_buf = jack_port_get_buffer(jack_data->output_port, nframes);
330  handle_output(output_port_buf, nframes, jack_data);
331 
332  return 0;
333 }
static void handle_input(void *buf, jack_nframes_t nframes, struct jack_data *jack_data)
Handle jack input port.
Definition: app_jack.c:240
static void handle_output(void *buf, jack_nframes_t nframes, struct jack_data *jack_data)
Handle jack output port.
Definition: app_jack.c:303
jack_port_t * output_port
Definition: app_jack.c:128
jack_port_t * input_port
Definition: app_jack.c:127
static int alloc_resampler(struct jack_data *jack_data, int input)
Definition: app_jack.c:190
double input_resample_factor
Definition: app_jack.c:134
static void jack_shutdown ( void *  arg)
static

Definition at line 335 of file app_jack.c.

References jack_data::stop.

Referenced by init_jack_data().

336 {
337  struct jack_data *jack_data = arg;
338 
339  jack_data->stop = 1;
340 }
unsigned int stop
Definition: app_jack.c:135
static const char* jack_status_to_str ( jack_status_t  status)
static

Definition at line 159 of file app_jack.c.

References ARRAY_LEN, and jack_status_table.

Referenced by log_jack_status().

160 {
161  int i;
162 
163  for (i = 0; i < ARRAY_LEN(jack_status_table); i++) {
164  if (jack_status_table[i].status == status)
165  return jack_status_table[i].str;
166  }
167 
168  return "Unknown Error";
169 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
static struct @22 jack_status_table[]
jack_status_t status
Definition: app_jack.c:143
static int load_module ( void  )
static

Definition at line 1017 of file app_jack.c.

References ast_custom_function_register, AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_SUCCESS, ast_register_application_xml, ast_unregister_application(), and jack_exec().

1018 {
1020  return AST_MODULE_LOAD_DECLINE;
1021  }
1022 
1025  return AST_MODULE_LOAD_DECLINE;
1026  }
1027 
1028  return AST_MODULE_LOAD_SUCCESS;
1029 }
static const char jack_app[]
Definition: app_jack.c:117
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
static int jack_exec(struct ast_channel *chan, const char *data)
Definition: app_jack.c:741
static struct ast_custom_function jack_hook_function
Definition: app_jack.c:971
#define ast_custom_function_register(acf)
Register a custom function.
Definition: pbx.h:1164
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:437
static void log_jack_status ( const char *  prefix,
jack_status_t  status 
)
static

Definition at line 171 of file app_jack.c.

References ast_log(), ast_str_alloca, ast_str_append(), ast_str_buffer(), ast_str_set(), first, jack_status_to_str(), LOG_NOTICE, status, and str.

Referenced by init_jack_data().

172 {
173  struct ast_str *str = ast_str_alloca(512);
174  int i, first = 0;
175 
176  for (i = 0; i < (sizeof(status) * 8); i++) {
177  if (!(status & (1 << i)))
178  continue;
179 
180  if (!first) {
181  ast_str_set(&str, 0, "%s", jack_status_to_str((1 << i)));
182  first = 1;
183  } else
184  ast_str_append(&str, 0, ", %s", jack_status_to_str((1 << i)));
185  }
186 
187  ast_log(LOG_NOTICE, "%s: %s\n", prefix, ast_str_buffer(str));
188 }
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:900
static const char * jack_status_to_str(jack_status_t status)
Definition: app_jack.c:159
#define ast_str_alloca(init_len)
Definition: strings.h:608
const char * str
Definition: app_jack.c:144
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
struct sla_ringing_trunk * first
Definition: app_meetme.c:965
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
#define LOG_NOTICE
Definition: logger.h:133
jack_status_t status
Definition: app_jack.c:143
static char prefix[MAX_PREFIX]
Definition: http.c:107
static int queue_voice_frame ( struct jack_data jack_data,
struct ast_frame f 
)
static

Definition at line 517 of file app_jack.c.

References alloc_resampler(), ARRAY_LEN, ast_debug, ast_log(), ast_frame::data, LOG_ERROR, jack_data::output_rb, jack_data::output_resample_factor, jack_data::output_resampler, ast_frame::ptr, and ast_frame::samples.

Referenced by jack_exec(), and jack_hook_callback().

518 {
519  float f_buf[f->samples * 8];
520  size_t f_buf_used = 0;
521  int i;
522  int16_t *s_buf = f->data.ptr;
523  size_t res;
524 
525  memset(f_buf, 0, sizeof(f_buf));
526 
527  if (!jack_data->output_resample_factor)
528  alloc_resampler(jack_data, 0);
529 
530  if (jack_data->output_resampler) {
531  float in_buf[f->samples];
532  int total_in_buf_used = 0;
533  int total_out_buf_used = 0;
534 
535  memset(in_buf, 0, sizeof(in_buf));
536 
537  for (i = 0; i < f->samples; i++)
538  in_buf[i] = s_buf[i] * (1.0 / SHRT_MAX);
539 
540  while (total_in_buf_used < ARRAY_LEN(in_buf)) {
541  int in_buf_used;
542  int out_buf_used;
543 
544  out_buf_used = resample_process(jack_data->output_resampler,
545  jack_data->output_resample_factor,
546  &in_buf[total_in_buf_used], ARRAY_LEN(in_buf) - total_in_buf_used,
547  0, &in_buf_used,
548  &f_buf[total_out_buf_used], ARRAY_LEN(f_buf) - total_out_buf_used);
549 
550  if (out_buf_used < 0)
551  break;
552 
553  total_out_buf_used += out_buf_used;
554  total_in_buf_used += in_buf_used;
555 
556  if (total_out_buf_used == ARRAY_LEN(f_buf)) {
557  ast_log(LOG_ERROR, "Output buffer filled ... need to increase its size\n");
558  break;
559  }
560  }
561 
562  f_buf_used = total_out_buf_used;
563  if (f_buf_used > ARRAY_LEN(f_buf))
564  f_buf_used = ARRAY_LEN(f_buf);
565  } else {
566  /* No resampling needed */
567 
568  for (i = 0; i < f->samples; i++)
569  f_buf[i] = s_buf[i] * (1.0 / SHRT_MAX);
570 
571  f_buf_used = f->samples;
572  }
573 
574  res = jack_ringbuffer_write(jack_data->output_rb, (const char *) f_buf, f_buf_used * sizeof(float));
575  if (res != (f_buf_used * sizeof(float))) {
576  ast_debug(2, "Tried to write %d bytes to the ringbuffer, but only wrote %d\n",
577  (int) (f_buf_used * sizeof(float)), (int) res);
578  }
579 
580  return 0;
581 }
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
void * output_resampler
Definition: app_jack.c:131
void * ptr
Definition: frame.h:160
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int alloc_resampler(struct jack_data *jack_data, int input)
Definition: app_jack.c:190
jack_ringbuffer_t * output_rb
Definition: app_jack.c:130
#define LOG_ERROR
Definition: logger.h:155
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
double output_resample_factor
Definition: app_jack.c:132
union ast_frame::@172 data
int samples
Definition: frame.h:150
static int unload_module ( void  )
static

Definition at line 1007 of file app_jack.c.

References ast_custom_function_unregister(), and ast_unregister_application().

1008 {
1009  int res;
1010 
1013 
1014  return res;
1015 }
static const char jack_app[]
Definition: app_jack.c:117
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
static struct ast_custom_function jack_hook_function
Definition: app_jack.c:971

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "JACK Interface" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 1031 of file app_jack.c.

Definition at line 1031 of file app_jack.c.

const char jack_app[] = "JACK"
static

Definition at line 117 of file app_jack.c.

struct ast_app_option jack_exec_options[128] = { [ 's' ] = { .flag = OPT_SERVER_NAME , .arg_index = OPT_ARG_SERVER_NAME + 1 }, [ 'i' ] = { .flag = OPT_INPUT_PORT , .arg_index = OPT_ARG_INPUT_PORT + 1 }, [ 'o' ] = { .flag = OPT_OUTPUT_PORT , .arg_index = OPT_ARG_OUTPUT_PORT + 1 }, [ 'n' ] = { .flag = OPT_NOSTART_SERVER }, [ 'c' ] = { .flag = OPT_CLIENT_NAME , .arg_index = OPT_ARG_CLIENT_NAME + 1 }, }
static

Definition at line 674 of file app_jack.c.

Referenced by handle_options().

struct ast_datastore_info jack_hook_ds_info
static
Initial value:
= {
.type = "JACK_HOOK",
}
static void jack_hook_ds_destroy(void *data)
Definition: app_jack.c:802

Definition at line 809 of file app_jack.c.

struct ast_custom_function jack_hook_function
static

Definition at line 971 of file app_jack.c.

struct { ... } jack_status_table[]

Referenced by jack_status_to_str().

jack_status_t status

Definition at line 143 of file app_jack.c.

Referenced by __ast_pbx_run(), __iax2_show_peers(), _child_handler(), _sip_show_peer(), _sip_show_peers_one(), acf_odbc_read(), acf_odbc_write(), action_agents(), action_extensionstate(), agi_exec_full(), aji_handle_presence(), aji_handle_subscribe(), aji_show_clients(), aji_status_exec(), ast_audiohook_update_status(), ast_safe_system(), ast_srtp_change_source(), build_dialplan_useage_map(), callerid_read(), callerid_write(), chanavail_exec(), change_favorite_icon(), complete_dpreply(), connectedline_read(), connectedline_write(), dundi_show_peers(), filestream_destructor(), function_agent(), handle_cc_notify(), handle_cli_iax2_show_peer(), handle_cli_realtime_pgsql_status(), handle_open_receive_channel_ack_message(), init_jack_data(), join_queue(), local_hangup(), log_jack_status(), manager_iax2_show_peer_list(), ospauth_exec(), ospfinished_exec(), osplookup_exec(), ospnext_exec(), parse_status(), party_id_read(), party_id_write(), party_name_read(), party_name_write(), party_number_read(), party_number_write(), party_subaddress_read(), party_subaddress_write(), peers_data_provider_get(), queue_exec(), read_exec(), readexten_exec(), realtime_ldap_status(), redirecting_read(), redirecting_write(), ring_entry(), run_ras(), send_favorite(), Sendicon(), sendtext_exec(), sendurl_exec(), shaun_of_the_dead(), show_entry_history(), sig_pri_cc_agent_req_rsp(), sig_pri_cli_show_span(), sig_pri_cli_show_spans(), transfer_exec(), update_status(), wait_for_answer(), and wait_our_turn().

const char* str

Definition at line 144 of file app_jack.c.

Referenced by _free_port_cfg(), acf_curl_helper(), acf_cut_exec(), action_status(), add_ie(), add_ipv4_ie(), add_publish_event(), add_required_respheader(), add_subscribe_event(), add_timeval_ie(), alloc_event(), anti_injection(), aoc_charge_type_str(), aoc_charged_item_str(), aoc_rate_type_str(), aoc_scale_str(), aoc_type_of_totaling_str(), aoc_volume_unit_str(), aocmessage_get_unit_entry(), ast_cc_agent_set_interfaces_chanvar(), ast_event_subscribe(), ast_func_read(), ast_hashtab_hash_string(), ast_hashtab_hash_string_nocase(), ast_hashtab_hash_string_sax(), ast_include_rename(), ast_set_cc_interfaces_chanvar(), ast_skip_blanks(), ast_sockaddr_split_hostport(), ast_sockaddr_stringify_fmt(), ast_trim_blanks(), cc_extension_monitor_init(), cc_generic_agent_start_monitoring(), check_mime(), custom_log(), dial_handle_playtones(), do_magic_pickup(), ext_cmp_exten_strlen(), find_realtime(), frame_trace_helper(), function_fieldnum_helper(), function_fieldqty_helper(), get_pidf_body(), handle_cli_core_show_translation(), handle_getvariablefull(), handle_playtones(), handle_tcptls_connection(), hash_string(), iax_parse_ies(), init_appendbuf(), jingle_new(), log_jack_status(), mansession_cmp_fn(), match_ie_val(), misdn_cfg_get(), misdn_cfg_get_config_string(), misdn_cfg_get_next_port(), misdn_cfg_get_ports_string(), misdn_cfg_is_group_method(), misdn_cfg_is_port_valid(), misdn_to_str_plan(), misdn_to_str_pres(), misdn_to_str_screen(), misdn_to_str_ton(), new_find_extension(), parse_cdata(), pbx_retrieve_variable(), process_text_line(), pvalWordSetString(), regex(), remove_spaces_before_equals(), replace(), sdp_crypto_process(), security_event_cb(), sendtext_exec(), string_replace(), switch(), syslog_log(), transmit_info_with_aoc(), variable_count_cmp_fn(), and write_html_escaped().