uncrustify as demanded.
[oweals/gnunet.git] / src / conversation / gnunet-conversation-test.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/gnunet-conversation-test.c
23  * @brief tool to test speaker and microphone (for end users!)
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_util_lib.h"
28 #include "gnunet_speaker_lib.h"
29 #include "gnunet_microphone_lib.h"
30
31 /**
32  * How long do we record before we replay?
33  */
34 #define TIMEOUT GNUNET_TIME_relative_multiply(GNUNET_TIME_UNIT_SECONDS, 5)
35
36
37 /**
38  * A recording we made.
39  */
40 struct Recording {
41   /**
42    * Kept in a DLL.
43    */
44   struct Recording *next;
45
46   /**
47    * Kept in a DLL.
48    */
49   struct Recording *prev;
50
51   /**
52    * Number of bytes that follow.
53    */
54   size_t size;
55 };
56
57
58 /**
59  * Final status code.
60  */
61 static int ret;
62
63 /**
64  * Handle to the microphone.
65  */
66 static struct GNUNET_MICROPHONE_Handle *microphone;
67
68 /**
69  * Handle to the speaker.
70  */
71 static struct GNUNET_SPEAKER_Handle *speaker;
72
73 /**
74  * Task scheduled to switch from recording to playback.
75  */
76 static struct GNUNET_SCHEDULER_Task * switch_task;
77
78 /**
79  * The shutdown task.
80  */
81 static struct GNUNET_SCHEDULER_Task * st;
82
83 /**
84  * Head of DLL with recorded frames.
85  */
86 static struct Recording *rec_head;
87
88 /**
89  * Tail of DLL with recorded frames.
90  */
91 static struct Recording *rec_tail;
92
93
94 /**
95  * Terminate test.
96  *
97  * @param cls NULL
98  */
99 static void
100 do_shutdown(void *cls)
101 {
102   struct Recording *rec;
103
104   (void)cls;
105   if (NULL != switch_task)
106     GNUNET_SCHEDULER_cancel(switch_task);
107   if (NULL != microphone)
108     GNUNET_MICROPHONE_destroy(microphone);
109   if (NULL != speaker)
110     GNUNET_SPEAKER_destroy(speaker);
111   while (NULL != (rec = rec_head))
112     {
113       GNUNET_CONTAINER_DLL_remove(rec_head,
114                                   rec_tail,
115                                   rec);
116       GNUNET_free(rec);
117     }
118   fprintf(stderr,
119           _("\nEnd of transmission.  Have a GNU day.\n"));
120 }
121
122
123 /**
124  * Terminate recording process and switch to playback.
125  *
126  * @param cls NULL
127  */
128 static void
129 switch_to_speaker(void *cls)
130 {
131   (void)cls;
132   switch_task = NULL;
133   microphone->disable_microphone(microphone->cls);
134   if (GNUNET_OK !=
135       speaker->enable_speaker(speaker->cls))
136     {
137       fprintf(stderr,
138               "Failed to enable microphone\n");
139       ret = 1;
140       GNUNET_SCHEDULER_shutdown();
141       return;
142     }
143   fprintf(stderr,
144           _("\nWe are now playing your recording back.  If you can hear it, your audio settings are working..."));
145   for (struct Recording *rec = rec_head; NULL != rec; rec = rec->next)
146     {
147       GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
148                  "Replaying %u bytes\n",
149                  (unsigned int)rec->size);
150       speaker->play(speaker->cls,
151                     rec->size,
152                     &rec[1]);
153     }
154   GNUNET_SCHEDULER_cancel(st);
155   st = GNUNET_SCHEDULER_add_delayed(TIMEOUT,
156                                     &do_shutdown,
157                                     NULL);
158 }
159
160
161 /**
162  * Process recorded audio data.
163  *
164  * @param cls clsoure
165  * @param data_size number of bytes in @a data
166  * @param data audio data to play
167  */
168 static void
169 record(void *cls,
170        size_t data_size,
171        const void *data)
172 {
173   struct Recording *rec;
174
175   (void)cls;
176   GNUNET_log(GNUNET_ERROR_TYPE_DEBUG,
177              "Recorded %u bytes\n",
178              (unsigned int)data_size);
179   rec = GNUNET_malloc(sizeof(struct Recording) + data_size);
180   rec->size = data_size;
181   GNUNET_memcpy(&rec[1], data, data_size);
182   GNUNET_CONTAINER_DLL_insert_tail(rec_head,
183                                    rec_tail,
184                                    rec);
185 }
186
187
188 /**
189  * Main function that will be run by the scheduler.
190  *
191  * @param cls closure
192  * @param args remaining command-line arguments
193  * @param cfgfile name of the configuration file used (for saving, can be NULL!)
194  * @param cfg configuration
195  */
196 static void
197 run(void *cls,
198     char *const *args,
199     const char *cfgfile,
200     const struct GNUNET_CONFIGURATION_Handle *cfg)
201 {
202   (void)cls;
203   (void)args;
204   (void)cfgfile;
205   microphone = GNUNET_MICROPHONE_create_from_hardware(cfg);
206   GNUNET_assert(NULL != microphone);
207   speaker = GNUNET_SPEAKER_create_from_hardware(cfg);
208   GNUNET_assert(NULL != speaker);
209   switch_task = GNUNET_SCHEDULER_add_delayed(TIMEOUT,
210                                              &switch_to_speaker,
211                                              NULL);
212   st = GNUNET_SCHEDULER_add_shutdown(&do_shutdown,
213                                      NULL);
214   fprintf(stderr,
215           _("We will now be recording you for %s. After that time, the recording will be played back to you..."),
216           GNUNET_STRINGS_relative_time_to_string(TIMEOUT, GNUNET_YES));
217   if (GNUNET_OK !=
218       microphone->enable_microphone(microphone->cls,
219                                     &record, NULL))
220     {
221       fprintf(stderr,
222               "Failed to enable microphone\n");
223       ret = 1;
224       GNUNET_SCHEDULER_shutdown();
225       return;
226     }
227 }
228
229
230 /**
231  * The main function of our code to test microphone and speaker.
232  *
233  * @param argc number of arguments from the command line
234  * @param argv command line arguments
235  * @return 0 ok, 1 on error
236  */
237 int
238 main(int argc,
239      char *const *argv)
240 {
241   static const struct GNUNET_GETOPT_CommandLineOption options[] = {
242     GNUNET_GETOPT_OPTION_END
243   };
244
245   if (GNUNET_OK !=
246       GNUNET_STRINGS_get_utf8_args(argc, argv,
247                                    &argc, &argv))
248     return 2;
249
250   ret = (GNUNET_OK ==
251          GNUNET_PROGRAM_run(argc, argv,
252                             "gnunet-conversation-test",
253                             gettext_noop("help text"),
254                             options,
255                             &run,
256                             NULL)) ? ret : 1;
257   GNUNET_free((void*)argv);
258   return ret;
259 }
260
261 /* end of gnunet-conversation-test.c */