5ab115c1f90fe57e85ede3390f431537f8328f91
[oweals/gnunet.git] / src / conversation / microphone.c
1 /*
2    This file is part of GNUnet
3    Copyright (C) 2013 GNUnet e.V.
4
5    GNUnet is free software: you can redistribute it and/or modify it
6    under the terms of the GNU Affero General Public License as published
7    by the Free Software Foundation, either version 3 of the License,
8    or (at your option) any later version.
9
10    GNUnet is distributed in the hope that it will be useful, but
11    WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Affero General Public License for more details.
14
15    You should have received a copy of the GNU Affero General Public License
16    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19  */
20
21 /**
22  * @file conversation/microphone.c
23  * @brief API to access an audio microphone; provides access to hardware microphones;
24  *        actually just wraps the gnunet-helper-audio-record
25  * @author Simon Dieterle
26  * @author Andreas Fuchs
27  * @author Christian Grothoff
28  */
29 #include "platform.h"
30 #include "gnunet_microphone_lib.h"
31 #include "conversation.h"
32
33
34 /**
35  * Internal data structures for the microphone.
36  */
37 struct Microphone
38 {
39   /**
40    * Our configuration.
41    */
42   const struct GNUNET_CONFIGURATION_Handle *cfg;
43
44   /**
45    * Handle for the record helper
46    */
47   struct GNUNET_HELPER_Handle *record_helper;
48
49   /**
50    * Function to call with audio data (if we are enabled).
51    */
52   GNUNET_MICROPHONE_RecordedDataCallback rdc;
53
54   /**
55    * Closure for @e rdc.
56    */
57   void *rdc_cls;
58 };
59
60
61 /**
62  * Function to process the audio from the record helper
63  *
64  * @param cls clsoure with our `struct Microphone`
65  * @param msg the message from the helper
66  * @return #GNUNET_OK on success,
67  *    #GNUNET_NO to stop further processing (no error)
68  *    #GNUNET_SYSERR to stop further processing with error
69  */
70 static int
71 process_record_messages (void *cls,
72                          const struct GNUNET_MessageHeader *msg)
73 {
74   struct Microphone *mic = cls;
75   const struct AudioMessage *am;
76
77   if (ntohs (msg->type) != GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO)
78   {
79     GNUNET_break (0);
80     return GNUNET_SYSERR;
81   }
82   am = (const struct AudioMessage *) msg;
83   mic->rdc (mic->rdc_cls,
84             ntohs (msg->size) - sizeof(struct AudioMessage),
85             &am[1]);
86   return GNUNET_OK;
87 }
88
89
90 /**
91  * Enable a microphone.
92  *
93  * @param cls clsoure with our `struct Microphone`
94  * @param rdc function to call with recorded data
95  * @param rdc_cls closure for @a dc
96  */
97 static int
98 enable (void *cls,
99         GNUNET_MICROPHONE_RecordedDataCallback rdc,
100         void *rdc_cls)
101 {
102   struct Microphone *mic = cls;
103   static char *const record_helper_argv[] = {
104     "gnunet-helper-audio-record",
105     NULL
106   };
107
108   mic->rdc = rdc;
109   mic->rdc_cls = rdc_cls;
110   mic->record_helper = GNUNET_HELPER_start (GNUNET_NO,
111                                             "gnunet-helper-audio-record",
112                                             record_helper_argv,
113                                             &process_record_messages,
114                                             NULL, mic);
115   if (NULL == mic->record_helper)
116   {
117     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
118                 _ ("Could not start record audio helper\n"));
119     return GNUNET_SYSERR;
120   }
121   return GNUNET_OK;
122 }
123
124
125 /**
126  * Function that disables a microphone.
127  *
128  * @param cls clsoure
129  */
130 static void
131 disable (void *cls)
132 {
133   struct Microphone *mic = cls;
134
135   if (NULL == mic->record_helper)
136   {
137     GNUNET_break (0);
138     return;
139   }
140   GNUNET_break (GNUNET_OK ==
141                 GNUNET_HELPER_kill (mic->record_helper, GNUNET_NO));
142   GNUNET_HELPER_destroy (mic->record_helper);
143   mic->record_helper = NULL;
144 }
145
146
147 /**
148  * Function to destroy a microphone.
149  *
150  * @param cls clsoure
151  */
152 static void
153 destroy (void *cls)
154 {
155   struct Microphone *mic = cls;
156
157   if (NULL != mic->record_helper)
158     disable (mic);
159 }
160
161
162 /**
163  * Create a microphone that corresponds to the microphone hardware
164  * of our system.
165  *
166  * @param cfg configuration to use
167  * @return NULL on error
168  */
169 struct GNUNET_MICROPHONE_Handle *
170 GNUNET_MICROPHONE_create_from_hardware (const struct
171                                         GNUNET_CONFIGURATION_Handle *cfg)
172 {
173   struct GNUNET_MICROPHONE_Handle *microphone;
174   struct Microphone *mic;
175
176   mic = GNUNET_new (struct Microphone);
177   mic->cfg = cfg;
178   microphone = GNUNET_new (struct GNUNET_MICROPHONE_Handle);
179   microphone->cls = mic;
180   microphone->enable_microphone = &enable;
181   microphone->disable_microphone = &disable;
182   microphone->destroy_microphone = &destroy;
183   return microphone;
184 }
185
186
187 /**
188  * Destroy a microphone.
189  *
190  * @param microphone microphone to destroy
191  */
192 void
193 GNUNET_MICROPHONE_destroy (struct GNUNET_MICROPHONE_Handle *microphone)
194 {
195   microphone->destroy_microphone (microphone->cls);
196   GNUNET_free (microphone);
197 }
198
199 /* end of microphone.c */