8
8
9
9
#include <pthread.h>
10
10
#include <stdint.h>
11
+ #include <stdlib.h>
11
12
#include <string.h>
12
13
#include <sys/time.h>
14
+ #include <unistd.h>
13
15
14
16
#include "gamepad.h"
15
17
#include "vanilla.h"
16
18
#include "util.h"
17
19
18
- #pragma pack(push, 1)
19
- typedef struct {
20
- unsigned format : 3 ;
21
- unsigned mono : 1 ;
22
- unsigned vibrate : 1 ;
23
- unsigned type : 1 ;
24
- unsigned seq_id : 10 ;
25
- unsigned payload_size : 16 ;
26
- unsigned timestamp : 32 ;
27
- unsigned char payload [2048 ];
28
- } AudioPacket ;
29
- const static unsigned int TYPE_AUDIO = 0 ;
30
- const static unsigned int TYPE_VIDEO = 1 ;
31
- #pragma pack(pop)
32
-
33
- typedef struct {
34
- uint32_t timestamp ;
35
- uint32_t unknown_freq_0 [2 ];
36
- uint32_t unknown_freq_1 [2 ];
37
- uint32_t video_format ;
38
- } AudioPacketVideoFormat ;
39
-
40
- static unsigned char queued_audio [2048 ];
20
+ static unsigned char queued_audio [8192 ];
41
21
static size_t queued_audio_start = 0 ;
42
22
static size_t queued_audio_end = 0 ;
43
23
static pthread_mutex_t queued_audio_mutex ;
24
+ static pthread_cond_t queued_audio_cond ;
44
25
45
26
int send_audio_packet (const void * data , size_t len )
46
27
{
47
28
pthread_mutex_lock (& queued_audio_mutex );
48
29
49
- for (size_t i = 0 ; i < len ; ) {
30
+ for (size_t i = 0 ; i < len ; ) {
50
31
size_t phys = queued_audio_end % sizeof (queued_audio );
51
32
size_t max_write = MIN (sizeof (queued_audio ) - phys , len - i );
52
33
memcpy (queued_audio + phys , ((const unsigned char * ) data ) + i , max_write );
34
+
53
35
i += max_write ;
54
36
queued_audio_end += max_write ;
37
+
38
+ // Skip start ahead if necessary
39
+ if (queued_audio_end > queued_audio_start + sizeof (queued_audio )) {
40
+ queued_audio_start = queued_audio_end - sizeof (queued_audio );
41
+ }
55
42
}
56
43
44
+ pthread_cond_broadcast (& queued_audio_cond );
45
+
57
46
pthread_mutex_unlock (& queued_audio_mutex );
58
47
59
48
return VANILLA_SUCCESS ;
60
49
}
61
50
62
- static void handle_queued_audio (gamepad_context_t * ctx , int seq_id )
51
+ static void * handle_queued_audio (void * data )
63
52
{
64
- AudioPacket ap ;
53
+ // Mic only ever sends 512 bytes at a time
54
+ const size_t MIC_PAYLOAD_SIZE = 512 ;
65
55
66
- // Initialize payload size to zero
67
- const size_t MIC_PAYLOAD_SIZE = 512 ;
68
- ap .payload_size = 0 ;
56
+ gamepad_context_t * ctx = (gamepad_context_t * ) data ;
69
57
70
- // Lock mutex
71
58
pthread_mutex_lock (& queued_audio_mutex );
72
59
73
- // If available, copy over to our packet
74
- if (queued_audio_end >= (queued_audio_start + MIC_PAYLOAD_SIZE )) {
75
- for (size_t i = 0 ; i < MIC_PAYLOAD_SIZE ; ) {
76
- size_t phys = queued_audio_start % sizeof (queued_audio );
77
- size_t max_write = MIN (sizeof (queued_audio ) - phys , MIC_PAYLOAD_SIZE - i );
78
- memcpy (ap .payload + i , queued_audio + queued_audio_start , max_write );
79
- i += max_write ;
80
- queued_audio_start += max_write ;
81
- }
82
- ap .payload_size = MIC_PAYLOAD_SIZE ;
83
- }
60
+ while (!is_interrupted ()) {
61
+ while (!is_interrupted () && queued_audio_end < (queued_audio_start + MIC_PAYLOAD_SIZE )) {
62
+ // Wait for more data
63
+ pthread_cond_wait (& queued_audio_cond , & queued_audio_mutex );
64
+ }
65
+
66
+ if (is_interrupted ()) {
67
+ break ;
68
+ }
69
+
70
+ AudioPacket ap ;
71
+
72
+ // Copy data into our packet
73
+ for (size_t i = 0 ; i < MIC_PAYLOAD_SIZE ; ) {
74
+ size_t phys = queued_audio_start % sizeof (queued_audio );
75
+ size_t max_write = MIN (sizeof (queued_audio ) - phys , MIC_PAYLOAD_SIZE - i );
76
+ memcpy (ap .payload + i , queued_audio + phys , max_write );
77
+
78
+ i += max_write ;
79
+ queued_audio_start += max_write ;
80
+ }
81
+
82
+ // Don't need access to the buffer while we set up the packet
83
+ pthread_mutex_unlock (& queued_audio_mutex );
84
+
85
+ // Set up remaining default parameters
86
+ ap .format = 6 ;
87
+ ap .mono = 1 ;
88
+ ap .vibrate = 0 ;
89
+ ap .type = TYPE_AUDIO ; // Audio data
90
+ ap .timestamp = 0 ; // Gamepad actually sends no timestamp
91
+ ap .payload_size = MIC_PAYLOAD_SIZE ;
92
+
93
+ static unsigned int seq_id = 0 ;
94
+ ap .seq_id = seq_id ++ ;
95
+
96
+ // Reverse bits on params
97
+ ap .format = reverse_bits (ap .format , 3 );
98
+ ap .seq_id = reverse_bits (ap .seq_id , 10 );
99
+ ap .payload_size = reverse_bits (ap .payload_size , 16 );//ntohs(ap.payload_size);
100
+ // ap.timestamp = reverse_bits(ap.timestamp, 32); // Not necessary because timestamp is 0
101
+
102
+ // Further reverse bits
103
+ unsigned char * bytes = (unsigned char * ) & ap ;
104
+ const size_t header_sz = sizeof (AudioPacket ) - sizeof (ap .payload );
105
+ for (int i = 0 ; i < 4 ; i ++ ) { // 4 instead of 8 because ap.timestamp == 0
106
+ bytes [i ] = (unsigned char ) reverse_bits (bytes [i ], 8 );
107
+ }
108
+
109
+ // Console expects 512 bytes every 16 ms so make sure we achieve that interval
110
+ static struct timeval last ;
111
+ struct timeval now ;
112
+ gettimeofday (& now , 0 );
113
+ long diff = (now .tv_sec - last .tv_sec ) * 1000000 + (now .tv_usec - last .tv_usec );
114
+ static const long target_delta = 16000 ;
115
+ if (diff < target_delta ) {
116
+ usleep (target_delta - diff );
117
+ }
118
+ gettimeofday (& last , 0 );
119
+
120
+ // Send packet to console
121
+ send_to_console (ctx -> socket_aud , & ap , header_sz + MIC_PAYLOAD_SIZE , PORT_AUD );
122
+
123
+ pthread_mutex_lock (& queued_audio_mutex );
124
+ }
84
125
85
- // Unlock
86
126
pthread_mutex_unlock (& queued_audio_mutex );
87
-
88
- // If we didn't get audio, return here
89
- if (!ap .payload_size ) {
90
- return ;
91
- }
92
-
93
- // struct timeval tv;
94
- // gettimeofday(&tv, 0);
95
- // if ((tv.tv_sec % 2) == 1) {
96
- // for (int i = 0; i < ap.payload_size; i++) {
97
- // ap.payload[i] = (rand() % 0xFF);
98
- // }
99
- // vanilla_log("NOISE!");
100
- // } else {
101
- // memset(ap.payload, 0x00, ap.payload_size);
102
- // vanilla_log("...quiet...");
103
- // }
104
-
105
- // Set up remaining default parameters
106
- ap .format = 6 ;
107
- ap .mono = 1 ;
108
- ap .vibrate = 0 ;
109
- ap .type = TYPE_AUDIO ; // Audio data
110
- ap .seq_id = seq_id + 1 ;
111
- ap .timestamp = 0 ;
112
-
113
- // Reverse bits on params
114
- ap .format = reverse_bits (ap .format , 3 );
115
- ap .seq_id = reverse_bits (ap .seq_id , 10 );
116
- ap .payload_size = reverse_bits (ap .payload_size , 16 );//ntohs(ap.payload_size);
117
- // ap.timestamp = reverse_bits(ap.timestamp, 32); // Not necessary because timestamp is 0
118
-
119
- // Further reverse bits
120
- unsigned char * bytes = (unsigned char * ) & ap ;
121
- const size_t header_sz = sizeof (AudioPacket ) - sizeof (ap .payload );
122
- for (int i = 0 ; i < header_sz ; i ++ ) {
123
- bytes [i ] = (unsigned char ) reverse_bits (bytes [i ], 8 );
124
- }
125
-
126
- // Send packet to console
127
- send_to_console (ctx -> socket_aud , & ap , header_sz + ap .payload_size , PORT_AUD );
128
127
}
129
128
130
129
void handle_audio_packet (gamepad_context_t * ctx , unsigned char * data , size_t len )
@@ -162,7 +161,7 @@ void handle_audio_packet(gamepad_context_t *ctx, unsigned char *data, size_t len
162
161
uint8_t vibrate_val = ap -> vibrate ;
163
162
push_event (ctx -> event_loop , VANILLA_EVENT_VIBRATE , & vibrate_val , sizeof (vibrate_val ));
164
163
165
- handle_queued_audio (ctx , ap -> seq_id );
164
+ handle_queued_audio (ctx );
166
165
}
167
166
168
167
void * listen_audio (void * x )
@@ -175,6 +174,14 @@ void *listen_audio(void *x)
175
174
queued_audio_end = 0 ;
176
175
177
176
pthread_mutex_init (& queued_audio_mutex , 0 );
177
+ pthread_cond_init (& queued_audio_cond , 0 );
178
+
179
+ pthread_t mic_thread ;
180
+ int mic_thread_created = 1 ;
181
+ if (pthread_create (& mic_thread , 0 , handle_queued_audio , info ) != 0 ) {
182
+ vanilla_log ("Failed to create mic thread" );
183
+ mic_thread_created = 0 ;
184
+ }
178
185
179
186
do {
180
187
size = recv (info -> socket_aud , data , sizeof (data ), 0 );
@@ -183,7 +190,13 @@ void *listen_audio(void *x)
183
190
}
184
191
} while (!is_interrupted ());
185
192
186
- pthread_mutex_destroy (& queued_audio_mutex );
193
+ if (mic_thread_created ) {
194
+ pthread_cond_broadcast (& queued_audio_cond );
195
+ pthread_join (mic_thread , 0 );
196
+ }
197
+
198
+ pthread_cond_destroy (& queued_audio_cond );
199
+ pthread_mutex_destroy (& queued_audio_mutex );
187
200
188
201
pthread_exit (NULL );
189
202
0 commit comments