Asterisk - The Open Source Telephony Project  18.5.0
app_ices.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <[email protected]>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18 
19 /*! \file
20  *
21  * \brief Stream to an icecast server via ICES (see contrib/asterisk-ices.xml)
22  *
23  * \author Mark Spencer <[email protected]>
24  *
25  * ICES - http://www.icecast.org/ices.php
26  *
27  * \ingroup applications
28  */
29 
30 /*** MODULEINFO
31  <support_level>deprecated</support_level>
32  ***/
33 
34 #include "asterisk.h"
35 
36 #include <signal.h>
37 #include <fcntl.h>
38 #include <sys/time.h>
39 
40 #include "asterisk/paths.h" /* use ast_config_AST_CONFIG_DIR */
41 #include "asterisk/lock.h"
42 #include "asterisk/file.h"
43 #include "asterisk/channel.h"
44 #include "asterisk/frame.h"
45 #include "asterisk/pbx.h"
46 #include "asterisk/module.h"
47 #include "asterisk/translate.h"
48 #include "asterisk/app.h"
49 #include "asterisk/format_cache.h"
50 
51 /*** DOCUMENTATION
52  <application name="ICES" language="en_US">
53  <synopsis>
54  Encode and stream using 'ices'.
55  </synopsis>
56  <syntax>
57  <parameter name="config" required="true">
58  <para>ICES configuration file.</para>
59  </parameter>
60  </syntax>
61  <description>
62  <para>Streams to an icecast server using ices (available separately).
63  A configuration file must be supplied for ices (see contrib/asterisk-ices.xml).</para>
64  <note><para>ICES version 2 client and server required.</para></note>
65  </description>
66  </application>
67 
68  ***/
69 
70 #define path_BIN "/usr/bin/"
71 #define path_LOCAL "/usr/local/bin/"
72 
73 static char *app = "ICES";
74 
75 static int icesencode(char *filename, int fd)
76 {
77  int res;
78 
79  res = ast_safe_fork(0);
80  if (res < 0)
81  ast_log(LOG_WARNING, "Fork failed\n");
82  if (res) {
83  return res;
84  }
85 
88  dup2(fd, STDIN_FILENO);
89  ast_close_fds_above_n(STDERR_FILENO);
90 
91  /* Most commonly installed in /usr/local/bin
92  * But many places has it in /usr/bin
93  * As a last-ditch effort, try to use PATH
94  */
95  execl(path_LOCAL "ices2", "ices", filename, SENTINEL);
96  execl(path_BIN "ices2", "ices", filename, SENTINEL);
97  execlp("ices2", "ices", filename, SENTINEL);
98 
99  ast_debug(1, "Couldn't find ices version 2, attempting to use ices version 1.\n");
100 
101  execl(path_LOCAL "ices", "ices", filename, SENTINEL);
102  execl(path_BIN "ices", "ices", filename, SENTINEL);
103  execlp("ices", "ices", filename, SENTINEL);
104 
105  ast_log(LOG_WARNING, "Execute of ices failed, could not find command.\n");
106  close(fd);
107  _exit(0);
108 }
109 
110 static int ices_exec(struct ast_channel *chan, const char *data)
111 {
112  int res = 0;
113  int fds[2];
114  int ms = -1;
115  int pid = -1;
116  struct ast_format *oreadformat;
117  struct ast_frame *f;
118  char filename[256]="";
119  char *c;
120 
121  if (ast_strlen_zero(data)) {
122  ast_log(LOG_WARNING, "ICES requires an argument (configfile.xml)\n");
123  return -1;
124  }
125 
126  if (pipe(fds)) {
127  ast_log(LOG_WARNING, "Unable to create pipe\n");
128  return -1;
129  }
130  ast_fd_set_flags(fds[1], O_NONBLOCK);
131 
132  ast_stopstream(chan);
133 
134  if (ast_channel_state(chan) != AST_STATE_UP)
135  res = ast_answer(chan);
136 
137  if (res) {
138  close(fds[0]);
139  close(fds[1]);
140  ast_log(LOG_WARNING, "Answer failed!\n");
141  return -1;
142  }
143 
144  oreadformat = ao2_bump(ast_channel_readformat(chan));
146  if (res < 0) {
147  close(fds[0]);
148  close(fds[1]);
149  ast_log(LOG_WARNING, "Unable to set write format to signed linear\n");
150  ao2_cleanup(oreadformat);
151  return -1;
152  }
153  if (((char *)data)[0] == '/')
154  ast_copy_string(filename, (char *) data, sizeof(filename));
155  else
156  snprintf(filename, sizeof(filename), "%s/%s", ast_config_AST_CONFIG_DIR, (char *)data);
157  /* Placeholder for options */
158  c = strchr(filename, '|');
159  if (c)
160  *c = '\0';
161  res = icesencode(filename, fds[0]);
162  if (res >= 0) {
163  pid = res;
164  for (;;) {
165  /* Wait for audio, and stream */
166  ms = ast_waitfor(chan, -1);
167  if (ms < 0) {
168  ast_debug(1, "Hangup detected\n");
169  res = -1;
170  break;
171  }
172  f = ast_read(chan);
173  if (!f) {
174  ast_debug(1, "Null frame == hangup() detected\n");
175  res = -1;
176  break;
177  }
178  if (f->frametype == AST_FRAME_VOICE) {
179  res = write(fds[1], f->data.ptr, f->datalen);
180  if (res < 0) {
181  if (errno != EAGAIN) {
182  ast_log(LOG_WARNING, "Write failed to pipe: %s\n", strerror(errno));
183  res = -1;
184  ast_frfree(f);
185  break;
186  }
187  }
188  }
189  ast_frfree(f);
190  }
191  }
192  close(fds[0]);
193  close(fds[1]);
194 
195  if (pid > -1)
196  kill(pid, SIGKILL);
197  if (!res && oreadformat)
198  ast_set_read_format(chan, oreadformat);
199  ao2_cleanup(oreadformat);
200 
201  return res;
202 }
203 
204 static int unload_module(void)
205 {
207 }
208 
209 static int load_module(void)
210 {
212 }
213 
214 AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Encode and Stream via icecast and ices");
Main Channel structure associated with a channel.
static int ices_exec(struct ast_channel *chan, const char *data)
Definition: app_ices.c:110
Asterisk locking-related definitions:
Asterisk main include file. File version handling, generic pbx functions.
#define path_BIN
Definition: app_ices.c:70
Support for translation of data formats. translate.c.
#define LOG_WARNING
Definition: logger.h:274
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: main/app.c:3042
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4302
ast_channel_state
ast_channel states
Definition: channelstate.h:35
Definition of a media format.
Definition: format.c:43
static int icesencode(char *filename, int fd)
Definition: app_ices.c:75
static struct test_val c
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static int unload_module(void)
Definition: app_ices.c:204
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx_app.c:392
static char * app
Definition: app_ices.c:73
#define ast_strlen_zero(foo)
Definition: strings.h:52
struct ast_format * ast_channel_readformat(struct ast_channel *chan)
#define ao2_bump(obj)
Definition: astobj2.h:491
static int load_module(void)
Definition: app_ices.c:209
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
Definition: utils.h:1009
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:452
#define ast_log
Definition: astobj2.c:42
#define SENTINEL
Definition: compiler.h:87
General Asterisk PBX channel definitions.
Asterisk file paths, configured in asterisk.conf.
int ast_set_read_format(struct ast_channel *chan, struct ast_format *format)
Sets read format on channel chan.
Definition: channel.c:5849
Asterisk internal frame definitions.
Core PBX routines and definitions.
int ast_set_priority(int)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
Definition: asterisk.c:1799
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:151
int errno
int ast_safe_fork(int stop_reaper)
Common routine to safely fork without a chance of a signal handler firing badly in the child...
Definition: main/app.c:3047
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3171
#define ao2_cleanup(obj)
Definition: astobj2.h:1958
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:401
#define ast_frfree(fr)
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:2814
Data structure associated with a single frame of data.
union ast_frame::@263 data
enum ast_frame_type frametype
#define path_LOCAL
Definition: app_ices.c:71
#define ASTERISK_GPL_KEY
The text the key() function should return.
Definition: module.h:46
struct ast_format * ast_format_slin
Built-in cached signed linear 8kHz format.
Definition: format_cache.c:41
Asterisk module definitions.
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
AST_MODULE_INFO_STANDARD_DEPRECATED(ASTERISK_GPL_KEY, "Encode and Stream via icecast and ices")
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:187
#define ast_register_application_xml(app, execute)
Register an application using XML documentation.
Definition: module.h:626
#define ast_opt_high_priority
Definition: options.h:110
Media Format Cache API.