-remove trailing whitespace
[oweals/gnunet.git] / src / conversation / speaker.c
1 /*
2   This file is part of GNUnet
3   (C) 2013 Christian Grothoff (and other contributing authors)
4
5   GNUnet is free software; you can redistribute it and/or modify
6   it under the terms of the GNU General Public License as published
7   by the Free Software Foundation; either version 3, or (at your
8   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   General Public License for more details.
14
15   You should have received a copy of the GNU General Public License
16   along with GNUnet; see the file COPYING.  If not, write to the
17   Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18   Boston, MA 02111-1307, USA.
19  */
20
21 /**
22  * @file conversation/speaker.c
23  * @brief API to access an audio speaker; provides access to hardware speakers
24  * @author Simon Dieterle
25  * @author Andreas Fuchs
26  * @author Christian Grothoff
27  */
28 #include "platform.h"
29 #include "gnunet_speaker_lib.h"
30 #include "conversation.h"
31
32
33 /**
34  * Internal data structures for the speaker.
35  */
36 struct Speaker
37 {
38   /**
39    * Our configuration.
40    */
41   const struct GNUNET_CONFIGURATION_Handle *cfg;
42
43   /**
44    * Handle for the playback helper
45    */
46   struct GNUNET_HELPER_Handle *playback_helper;
47
48 };
49
50
51 /**
52  * Function that enables a speaker.
53  *
54  * @param cls closure with the `struct Speaker`
55  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
56  */
57 static int
58 enable (void *cls)
59 {
60   struct Speaker *spe = cls;
61   static char *playback_helper_argv[] =
62   {
63     "gnunet-helper-audio-playback",
64     NULL
65   };
66
67   spe->playback_helper = GNUNET_HELPER_start (GNUNET_NO,
68                                               "gnunet-helper-audio-playback",
69                                               playback_helper_argv,
70                                               NULL,
71                                               NULL, spe);
72   if (NULL == spe->playback_helper)
73   {
74     GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
75                 _("Could not start playback audio helper.\n"));
76     return GNUNET_SYSERR;
77   }
78   return GNUNET_OK;
79 }
80
81
82 /**
83  * Function that disables a speaker.
84  *
85  * @param cls closure with the `struct Speaker`
86  */
87 static void
88 disable (void *cls)
89 {
90   struct Speaker *spe = cls;
91
92   if (NULL == spe->playback_helper)
93   {
94     GNUNET_break (0);
95     return;
96   }
97   GNUNET_break (GNUNET_OK ==
98                 GNUNET_HELPER_kill (spe->playback_helper, GNUNET_NO));
99   GNUNET_HELPER_destroy (spe->playback_helper);
100   spe->playback_helper = NULL;
101 }
102
103
104 /**
105  * Function to destroy a speaker.
106  *
107  * @param cls closure with the `struct Speaker`
108  */
109 static void
110 destroy (void *cls)
111 {
112   struct Speaker *spe = cls;
113
114   if (NULL != spe->playback_helper)
115     disable (spe);
116 }
117
118
119 /**
120  * Function to cause a speaker to play audio data.
121  *
122  * @param cls clsoure with the `struct Speaker`
123  * @param data_size number of bytes in @a data
124  * @param data audio data to play, format is
125  *        opaque to the API but should be OPUS.
126  */
127 static void
128 play (void *cls,
129       size_t data_size,
130       const void *data)
131 {
132   struct Speaker *spe = cls;
133   char buf[sizeof (struct AudioMessage) + data_size];
134   struct AudioMessage *am;
135
136   if (NULL == spe->playback_helper)
137   {
138     GNUNET_break (0);
139     return;
140   }
141   am = (struct AudioMessage *) buf;
142   am->header.size = htons (sizeof (struct AudioMessage) + data_size);
143   am->header.type = htons (GNUNET_MESSAGE_TYPE_CONVERSATION_AUDIO);
144   memcpy (&am[1], data, data_size);
145   (void) GNUNET_HELPER_send (spe->playback_helper,
146                              &am->header,
147                              GNUNET_NO,
148                              NULL, NULL);
149 }
150
151
152 /**
153  * Create a speaker that corresponds to the speaker hardware
154  * of our system.
155  *
156  * @param cfg configuration to use
157  * @return NULL on error
158  */
159 struct GNUNET_SPEAKER_Handle *
160 GNUNET_SPEAKER_create_from_hardware (const struct GNUNET_CONFIGURATION_Handle *cfg)
161 {
162   struct GNUNET_SPEAKER_Handle *speaker;
163   struct Speaker *spe;
164
165   spe = GNUNET_new (struct Speaker);
166   spe->cfg = cfg;
167   speaker = GNUNET_new (struct GNUNET_SPEAKER_Handle);
168   speaker->cls = spe;
169   speaker->enable_speaker = &enable;
170   speaker->play = &play;
171   speaker->disable_speaker = &disable;
172   speaker->destroy_speaker = &destroy;
173   return speaker;
174 }
175
176
177 /**
178  * Destroy a speaker.
179  *
180  * @param speaker speaker to destroy
181  */
182 void
183 GNUNET_SPEAKER_destroy (struct GNUNET_SPEAKER_Handle *speaker)
184 {
185   speaker->destroy_speaker (speaker->cls);
186   GNUNET_free (speaker);
187 }
188
189 /* end of speaker.c */