I'm writing a program for my Raspberry Pi, that consists of two main parts:
- A C-Program that uses the Spotify-API "Libspotify" to search for music and for playing it.
- A PHP-program, running on an apache2-Webserver, to control the Spotify-program from a PC or Smartphone in my local network.
The communication between these two separate programs works over a couple of files.
The C-part for receiving the user inputs is being called once a second and works like this:
void get_input() {
int i = 0, c;
FILE *file;
struct stat stat;
char buffer[INPUT_BUFFER_SIZE];
file = fopen(PATH_TO_COMMUNICATION, "r");
if (file == NULL) {
perror("Error opening PATH_TO_COMMUNICATION");
return;
}
fstat(fileno(file), &stat);
if (stat.st_size > 1) {
while((c = fgetc(file)) != EOF && i < INPUT_BUFFER_SIZE) {
buffer[i] = c;
++i;
}
buffer[i] = '\0';
parse_input(buffer);
}
fclose(file);
clear_file(PATH_TO_COMMUNICATION);
}
So, via fwrite()
in PHP, I can send commands to the C-program.
Afterwards, the C-Program parses the input and writes the results in an "results"-file. Once this is done, I write the last contents of the "communication"-file an "last_query"-file, so in PHP i can see, when the entire results are written in the "results":
function search($query) {
write_to_communication("search ".$query);
do { // Wait for results
$file = fopen("../tmp/last_query", "r");
$line = fgets($file);
fclose($file);
time_nanosleep(0, 100000000);
} while($line != $query);
echo get_result_json();
}
It does work already, but I don't like the way at all. There is a lot of polling and unneccessary opening and closing of different files. Also, in the worst case the program needs more than a second until it starts to do something with the user input. Furthermore, there can be race conditions, when the C-program tries to read the file during the PHP-program writes into it.
So, now to my question: What is the "right" way, to achieve a nice and clean communication between the two program parts? Is there some completely different way without the ugly polling and without race conditions? Or can I improve the existing code, so that it gets nicer?