|
@@ -0,0 +1,121 @@
|
|
|
+/*
|
|
|
+ * SPDX-FileCopyrightText: 2019 Helmut Pozimski <helmut@pozimski.eu>
|
|
|
+ *
|
|
|
+ * SPDX-License-Identifier: GPL-2.0-only
|
|
|
+ */
|
|
|
+
|
|
|
+#include <stdlib.h>
|
|
|
+#include <stdint.h>
|
|
|
+#include <unistd.h>
|
|
|
+#include <getopt.h>
|
|
|
+#include <stdio.h>
|
|
|
+#include <string.h>
|
|
|
+#include <netinet/in.h>
|
|
|
+#include <time.h>
|
|
|
+
|
|
|
+#include "tcpserver.h"
|
|
|
+#include "wavfile.h"
|
|
|
+
|
|
|
+#define BUF_SIZE 1558
|
|
|
+
|
|
|
+typedef struct {
|
|
|
+ uint32_t sample_rate;
|
|
|
+ uint32_t bits;
|
|
|
+} sync_information;
|
|
|
+
|
|
|
+/*
|
|
|
+ * Function: construct_file_path
|
|
|
+ * ----------------------------------------
|
|
|
+ * Constructs the file path to write a new file to
|
|
|
+ *
|
|
|
+ * directory: directory in which the file should be placed
|
|
|
+ * file_path: pointer to the buffer to write the file path to
|
|
|
+ */
|
|
|
+static void construct_file_path(char * directory, char * file_path) {
|
|
|
+ time_t cur_time;
|
|
|
+ struct tm local_time;
|
|
|
+ char timebuffer[12];
|
|
|
+ cur_time = time(NULL);
|
|
|
+ local_time = (*localtime(&cur_time));
|
|
|
+ strncpy(file_path, "", 1);
|
|
|
+ strncat(file_path, directory, 255);
|
|
|
+ strncat(file_path, "/", 2);
|
|
|
+ sprintf(timebuffer, "%d", local_time.tm_year +1900);
|
|
|
+ strncat(file_path, timebuffer, 12);
|
|
|
+ sprintf(timebuffer, "%d", local_time.tm_mon +1);
|
|
|
+ strncat(file_path, timebuffer, 12);
|
|
|
+ sprintf(timebuffer, "%d", local_time.tm_mday);
|
|
|
+ strncat(file_path, timebuffer, 12);
|
|
|
+ sprintf(timebuffer, "%d", local_time.tm_hour);
|
|
|
+ strncat(file_path, timebuffer, 12);
|
|
|
+ sprintf(timebuffer, "%d", local_time.tm_min);
|
|
|
+ strncat(file_path, timebuffer, 12);
|
|
|
+ sprintf(timebuffer, "%d", local_time.tm_sec);
|
|
|
+ strncat(file_path, timebuffer, 12);
|
|
|
+ strncat(file_path, "-recording.wav", 15);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+int main(int argc, char **argv) {
|
|
|
+ char * ip_address = NULL;
|
|
|
+ char * directory = NULL;
|
|
|
+ uint16_t port = 0;
|
|
|
+ int opt, sock, conn, bytes_received;
|
|
|
+ struct sockaddr_in client;
|
|
|
+ unsigned int namelen;
|
|
|
+ sync_information sync;
|
|
|
+ uint8_t buffer[BUF_SIZE];
|
|
|
+ wavfile * file;
|
|
|
+ char * file_path;
|
|
|
+ while ((opt = getopt(argc, argv, "i:p:d:")) != -1) {
|
|
|
+ switch(opt) {
|
|
|
+ case 'i':
|
|
|
+ ip_address = optarg;
|
|
|
+ break;
|
|
|
+ case 'p':
|
|
|
+ port = strtoul(optarg, NULL, 10);
|
|
|
+ break;
|
|
|
+ case 'd':
|
|
|
+ directory = optarg;
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (port == 0 || ip_address == NULL || directory == NULL) {
|
|
|
+ printf("Usage: %s -i IPV4_ADDRESS -p PORT -d DIRECTORY\n", argv[0]);
|
|
|
+ return EXIT_SUCCESS;
|
|
|
+ }
|
|
|
+ if ((sock = tcpserver_start(ip_address, port)) < 0 ) {
|
|
|
+ printf("Failed to start TCP server\n");
|
|
|
+ return EXIT_FAILURE;
|
|
|
+ }
|
|
|
+ file_path = malloc(strlen(directory) + 1 + 29);
|
|
|
+ if (file_path == NULL) {
|
|
|
+ printf("Error allocating memory for file path\n");
|
|
|
+ return EXIT_FAILURE;
|
|
|
+ }
|
|
|
+ namelen = sizeof(client);
|
|
|
+ while (1) {
|
|
|
+ conn = accept(sock, (struct sockaddr *)&client, &namelen);
|
|
|
+ if (conn == -1) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ recv(conn, &sync, sizeof(sync), 0);
|
|
|
+ if (sync.sample_rate < 8000 || sync.sample_rate > 48000) {
|
|
|
+ printf("Invalid sample rate received\n");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ construct_file_path(directory, file_path);
|
|
|
+ printf("Current file path: %s\n", file_path);
|
|
|
+ file = wavfile_create(file_path, 1, sync.sample_rate, sync.bits);
|
|
|
+ if (file == NULL) {
|
|
|
+ printf("Error creating new file\n");
|
|
|
+ close(conn);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ while ((bytes_received = recv(conn, buffer, BUF_SIZE, 0)) != 0) {
|
|
|
+ wavfile_append_data(file, buffer, bytes_received);
|
|
|
+ }
|
|
|
+ wavfile_close(file);
|
|
|
+ }
|
|
|
+ return EXIT_SUCCESS;
|
|
|
+}
|