gnunet-conversation-test.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254
  1. /*
  2. This file is part of GNUnet.
  3. (C) 2013 Christian Grothoff (and other contributing authors)
  4. GNUnet is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 3, or (at your
  7. option) any later version.
  8. GNUnet is distributed in the hope that it will be useful, but
  9. WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  11. General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with GNUnet; see the file COPYING. If not, write to the
  14. Free Software Foundation, Inc., 59 Temple Place - Suite 330,
  15. Boston, MA 02111-1307, USA.
  16. */
  17. /**
  18. * @file conversation/gnunet-conversation-test.c
  19. * @brief tool to test speaker and microphone (for end users!)
  20. * @author Christian Grothoff
  21. */
  22. #include "platform.h"
  23. #include "gnunet_util_lib.h"
  24. #include "gnunet_speaker_lib.h"
  25. #include "gnunet_microphone_lib.h"
  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. * A recording we made.
  32. */
  33. struct Recording
  34. {
  35. /**
  36. * Kept in a DLL.
  37. */
  38. struct Recording *next;
  39. /**
  40. * Kept in a DLL.
  41. */
  42. struct Recording *prev;
  43. /**
  44. * Number of bytes that follow.
  45. */
  46. size_t size;
  47. };
  48. /**
  49. * Final status code.
  50. */
  51. static int ret;
  52. /**
  53. * Handle to the microphone.
  54. */
  55. static struct GNUNET_MICROPHONE_Handle *microphone;
  56. /**
  57. * Handle to the speaker.
  58. */
  59. static struct GNUNET_SPEAKER_Handle *speaker;
  60. /**
  61. * Task scheduled to switch from recording to playback.
  62. */
  63. static GNUNET_SCHEDULER_TaskIdentifier switch_task;
  64. /**
  65. * The shutdown task.
  66. */
  67. static GNUNET_SCHEDULER_TaskIdentifier st;
  68. /**
  69. * Head of DLL with recorded frames.
  70. */
  71. static struct Recording *rec_head;
  72. /**
  73. * Tail of DLL with recorded frames.
  74. */
  75. static struct Recording *rec_tail;
  76. /**
  77. * Terminate test.
  78. *
  79. * @param cls NULL
  80. * @param tc unused
  81. */
  82. static void
  83. do_shutdown (void *cls,
  84. const struct GNUNET_SCHEDULER_TaskContext *tc)
  85. {
  86. struct Recording *rec;
  87. if (GNUNET_SCHEDULER_NO_TASK != switch_task)
  88. GNUNET_SCHEDULER_cancel (switch_task);
  89. if (NULL != microphone)
  90. GNUNET_MICROPHONE_destroy (microphone);
  91. if (NULL != speaker)
  92. GNUNET_SPEAKER_destroy (speaker);
  93. while (NULL != (rec = rec_head))
  94. {
  95. GNUNET_CONTAINER_DLL_remove (rec_head,
  96. rec_tail,
  97. rec);
  98. GNUNET_free (rec);
  99. }
  100. fprintf (stderr,
  101. _("\nEnd of transmission. Have a GNU day.\n"));
  102. }
  103. /**
  104. * Terminate recording process and switch to playback.
  105. *
  106. * @param cls NULL
  107. * @param tc unused
  108. */
  109. static void
  110. switch_to_speaker (void *cls,
  111. const struct GNUNET_SCHEDULER_TaskContext *tc)
  112. {
  113. struct Recording *rec;
  114. switch_task = GNUNET_SCHEDULER_NO_TASK;
  115. microphone->disable_microphone (microphone->cls);
  116. if (GNUNET_OK !=
  117. speaker->enable_speaker (speaker->cls))
  118. {
  119. fprintf (stderr,
  120. "Failed to enable microphone\n");
  121. ret = 1;
  122. GNUNET_SCHEDULER_shutdown ();
  123. return;
  124. }
  125. fprintf (stderr,
  126. _("\nWe are now playing your recording back. If you can hear it, your audio settings are working..."));
  127. for (rec=rec_head; NULL != rec; rec = rec->next)
  128. {
  129. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  130. "Replaying %u bytes\n",
  131. (unsigned int) rec->size);
  132. speaker->play (speaker->cls,
  133. rec->size,
  134. &rec[1]);
  135. }
  136. GNUNET_SCHEDULER_cancel (st);
  137. st = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
  138. &do_shutdown,
  139. NULL);
  140. }
  141. /**
  142. * Process recorded audio data.
  143. *
  144. * @param cls clsoure
  145. * @param data_size number of bytes in @a data
  146. * @param data audio data to play
  147. */
  148. static void
  149. record (void *cls,
  150. size_t data_size,
  151. const void *data)
  152. {
  153. struct Recording *rec;
  154. GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
  155. "Recorded %u bytes\n",
  156. (unsigned int) data_size);
  157. rec = GNUNET_malloc (sizeof (struct Recording) + data_size);
  158. rec->size = data_size;
  159. memcpy (&rec[1], data, data_size);
  160. GNUNET_CONTAINER_DLL_insert_tail (rec_head,
  161. rec_tail,
  162. rec);
  163. }
  164. /**
  165. * Main function that will be run by the scheduler.
  166. *
  167. * @param cls closure
  168. * @param args remaining command-line arguments
  169. * @param cfgfile name of the configuration file used (for saving, can be NULL!)
  170. * @param cfg configuration
  171. */
  172. static void
  173. run (void *cls, char *const *args, const char *cfgfile,
  174. const struct GNUNET_CONFIGURATION_Handle *cfg)
  175. {
  176. microphone = GNUNET_MICROPHONE_create_from_hardware (cfg);
  177. GNUNET_assert (NULL != microphone);
  178. speaker = GNUNET_SPEAKER_create_from_hardware (cfg);
  179. GNUNET_assert (NULL != speaker);
  180. switch_task = GNUNET_SCHEDULER_add_delayed (TIMEOUT,
  181. &switch_to_speaker,
  182. NULL);
  183. st = GNUNET_SCHEDULER_add_delayed (GNUNET_TIME_UNIT_FOREVER_REL,
  184. &do_shutdown,
  185. NULL);
  186. fprintf (stderr,
  187. _("We will now be recording you for %s. After that time, the recording will be played back to you..."),
  188. GNUNET_STRINGS_relative_time_to_string (TIMEOUT, GNUNET_YES));
  189. if (GNUNET_OK !=
  190. microphone->enable_microphone (microphone->cls,
  191. &record, NULL))
  192. {
  193. fprintf (stderr,
  194. "Failed to enable microphone\n");
  195. ret = 1;
  196. GNUNET_SCHEDULER_shutdown ();
  197. return;
  198. }
  199. }
  200. /**
  201. * The main function of our code to test microphone and speaker.
  202. *
  203. * @param argc number of arguments from the command line
  204. * @param argv command line arguments
  205. * @return 0 ok, 1 on error
  206. */
  207. int
  208. main (int argc, char *const *argv)
  209. {
  210. static const struct GNUNET_GETOPT_CommandLineOption options[] = {
  211. GNUNET_GETOPT_OPTION_END
  212. };
  213. if (GNUNET_OK != GNUNET_STRINGS_get_utf8_args (argc, argv, &argc, &argv))
  214. return 2;
  215. ret = (GNUNET_OK ==
  216. GNUNET_PROGRAM_run (argc, argv, "gnunet-conversation-test",
  217. gettext_noop ("help text"), options, &run,
  218. NULL)) ? ret : 1;
  219. GNUNET_free ((void*) argv);
  220. return ret;
  221. }
  222. /* end of gnunet-conversation-test.c */