TablePCControl/main.cpp
2024-12-08 15:07:48 +01:00

170 lines
4.0 KiB
C++

#include "secret.h"
#include <alsa/asoundlib.h>
#include <arpa/inet.h>
#include <array>
#include <cerrno>
#include <codecvt>
#include <csignal>
#include <cstdint>
#include <cstdio>
#include <cstdlib>
#include <fcntl.h>
#include <fstream>
#include <iostream>
#include <memory>
#include <netdb.h>
#include <netinet/in.h>
#include <sched.h>
#include <stdexcept>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/wait.h>
#include <unistd.h>
#define PORT 54321
int serverSocket;
void safe_exit(int code) {
std::clog << "Exiting\n";
close(serverSocket);
exit(code);
}
int get_volume(const char *selem_name) {
long min, max, volume;
snd_mixer_t *handle;
snd_mixer_selem_id_t *sid;
// Open mixer
snd_mixer_open(&handle, 0);
snd_mixer_attach(handle,
"default"); // Use "default" for the default sound card
snd_mixer_selem_register(handle, NULL, NULL);
snd_mixer_load(handle);
// Allocate and set mixer element ID
snd_mixer_selem_id_alloca(&sid);
snd_mixer_selem_id_set_name(sid, selem_name);
// Find the mixer element
snd_mixer_elem_t *elem = snd_mixer_find_selem(handle, sid);
int volume_percent;
if (elem) {
// Get the playback volume range
snd_mixer_selem_get_playback_volume_range(elem, &min, &max);
// Get the current playback volume for front left channel
snd_mixer_selem_get_playback_volume(elem, SND_MIXER_SCHN_FRONT_LEFT,
&volume);
// Calculate the volume percentage
volume_percent = (volume - min) * 100 / (max - min);
} else {
std::cerr << "Mixer element not found\n";
snd_mixer_close(handle);
safe_exit(ENODEV);
}
// Clean up
snd_mixer_close(handle);
return volume_percent;
}
int main(int argc, char *argv[]) {
// signal handlers
signal(SIGTERM, safe_exit);
signal(SIGINT, safe_exit);
signal(SIGQUIT, safe_exit);
signal(SIGHUP, safe_exit);
// error signal handlers
signal(SIGSEGV, safe_exit);
// creating socket
serverSocket = socket(AF_INET, SOCK_STREAM, 0);
// specifying the address
sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_port = htons(PORT);
serverAddress.sin_addr.s_addr = INADDR_ANY;
// binding socket.
while (bind(serverSocket, (struct sockaddr *)&serverAddress,
sizeof(serverAddress)) != 0) {
std::cerr << "error binding socket retring\n";
sleep(2);
}
// listening to the assigned socket
listen(serverSocket, 5);
accept_new_connection:
// accepting connection request
int clientSocket = accept(serverSocket, nullptr, nullptr);
pid_t pid;
pid = fork();
if (pid == -1) {
std::cerr << "Fork failed";
safe_exit(-1);
} else if (pid == 0) {
// child process
signal(SIGUSR1, exit);
char bufferSend[1024];
int volume_percent = INTMAX_MIN;
int volume_percent_old;
while (1) {
volume_percent_old = volume_percent;
volume_percent = get_volume("Master");
if (volume_percent != volume_percent_old) {
}
usleep(100000);
sprintf(bufferSend, "Volume: %d%%\n", get_volume("Master"));
if (send(clientSocket, bufferSend, strlen(bufferSend), 0) == -1) {
std::cerr << "send() returned an error code\n";
safe_exit(-1);
}
sleep(1);
}
} else {
// parent process
char bufferRecv[1024];
// recieving data
while (1) {
memset(&bufferRecv, 0, sizeof(bufferRecv));
int RecvRetVal = recv(clientSocket, bufferRecv, sizeof(bufferRecv), 0);
if (RecvRetVal > sizeof(bufferRecv) || RecvRetVal < 0) {
std::cerr << "recv() returned an error code\n";
safe_exit(RecvRetVal);
} else if (RecvRetVal == 0) {
// detect if client disconected
kill(pid, SIGUSR1);
close(clientSocket);
goto accept_new_connection;
}
std::cout << "Message from client: " << bufferRecv << std::endl;
}
// closing the socket.
close(serverSocket);
}
return 0;
}