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