first commit

This commit is contained in:
MrFry 2023-06-30 01:31:02 +01:00
commit 4fd853f28a
8 changed files with 439 additions and 0 deletions

67
src/curl.c Normal file
View File

@ -0,0 +1,67 @@
/*
The curl part of this program is adapted from Artem's publication on:
https://dev.to/hi_artem/using-libcurl-in-c-c-application-4668
*/
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <curl/curl.h>
#include "curl.h"
int curl(char *request) {
if( request == 0 ) {
printf("error, empty request!\n");
return 1;
}
CURL *curl_handle;
CURLcode res;
struct curlMemoryStruct chunk;
chunk.memory = malloc(1);
chunk.size = 0;
curl_handle = curl_easy_init();
if(curl_handle) {
curl_easy_setopt(curl_handle, CURLOPT_URL, request);
curl_easy_setopt(curl_handle, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, curlCallback);
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
res = curl_easy_perform(curl_handle);
if(res != CURLE_OK) {
fprintf(stderr, "error: %s\n", curl_easy_strerror(res));
} else {
printf("Size: %lu\n", (unsigned long)chunk.size);
printf("Data: %s\n", chunk.memory);
}
curl_easy_cleanup(curl_handle);
free(chunk.memory);
}
return 0;
}
size_t curlCallback(void *contents, size_t size, size_t nmemb, void *userp) {
size_t realsize = size * nmemb;
struct curlMemoryStruct *mem = (struct curlMemoryStruct *)userp;
char *ptr = realloc(mem->memory, mem->size + realsize + 1);
if(ptr == NULL) {
printf("error: not enough memory\n");
return 0;
}
mem->memory = ptr;
memcpy(&(mem->memory[mem->size]), contents, realsize);
mem->size += realsize;
mem->memory[mem->size] = 0;
return realsize;
}

11
src/curl.h Normal file
View File

@ -0,0 +1,11 @@
struct curlMemoryStruct {
char *memory;
size_t size;
};
void md5Compute(char *str, unsigned char digest[16]);
char * md5_output(char *expression, char buf[]);
int curl(char *request);
size_t curlCallback(void *contents, size_t size, size_t nmemb, void *userp);

29
src/md5.c Normal file
View File

@ -0,0 +1,29 @@
/*
The md5 part of this program is adapted from
https://stackoverflow.com/questions/58065208/calculate-md5-in-c-display-output-as-string
*/
#include <stdio.h>
#include <string.h>
#include <openssl/md5.h>
#include "md5.h"
void md5Compute(char *str, unsigned char digest[16]) {
MD5_CTX ctx;
MD5_Init(&ctx);
MD5_Update(&ctx, str, strlen(str));
MD5_Final(digest, &ctx);
}
char * md5Output(char *expression, char buf[]) {
unsigned char digest[16];
md5Compute(expression, digest);
for (int i = 0, j = 0; i < 16; i++, j+=2) {
sprintf(buf+j, "%02x", digest[i]);
}
buf[sizeof digest * 2] = 0;
return buf;
}

3
src/md5.h Normal file
View File

@ -0,0 +1,3 @@
void md5Compute(char *str, unsigned char digest[16]);
char * md5Output(char *expression, char buf[]);

149
src/mpdclient.c Normal file
View File

@ -0,0 +1,149 @@
/* libmpdclient
(c) 2003-2010 The Music Player Daemon Project
This project's homepage is: http://www.musicpd.org
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
- Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
- Neither the name of the Music Player Daemon nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <mpd/client.h>
#include <mpd/status.h>
#include <mpd/entity.h>
#include <mpd/search.h>
#include <mpd/tag.h>
#include <mpd/message.h>
#include "mpdclient.h"
static int handle_error(struct mpd_connection *c) {
assert(mpd_connection_get_error(c) != MPD_ERROR_SUCCESS);
fprintf(stderr, "%s\n", mpd_connection_get_error_message(c));
mpd_connection_free(c);
return EXIT_FAILURE;
}
static void print_tag(const struct mpd_song *song, enum mpd_tag_type type, const char *label) {
unsigned i = 0;
const char *value;
while ((value = mpd_song_get_tag(song, type, i++)) != NULL)
printf("%s: %s\n", label, value);
}
int mpdClient(int argc, char *argv) {
struct mpd_connection *conn;
conn = mpd_connection_new(NULL, 0, 30000);
if(argc==1) {
struct mpd_status * status;
struct mpd_song *song;
const struct mpd_audio_format *audio_format;
mpd_command_list_begin(conn, true);
mpd_send_status(conn);
mpd_send_current_song(conn);
mpd_command_list_end(conn);
status = mpd_recv_status(conn);
if (status == NULL)
return handle_error(conn);
printf("volume: %i\n", mpd_status_get_volume(status));
printf("repeat: %i\n", mpd_status_get_repeat(status));
printf("queue version: %u\n", mpd_status_get_queue_version(status));
printf("queue length: %i\n", mpd_status_get_queue_length(status));
if (mpd_status_get_error(status) != NULL)
printf("error: %s\n", mpd_status_get_error(status));
if (mpd_status_get_state(status) == MPD_STATE_PLAY ||
mpd_status_get_state(status) == MPD_STATE_PAUSE) {
printf("song: %i\n", mpd_status_get_song_pos(status));
printf("elaspedTime: %i\n",mpd_status_get_elapsed_time(status));
printf("elasped_ms: %u\n", mpd_status_get_elapsed_ms(status));
printf("totalTime: %i\n", mpd_status_get_total_time(status));
printf("bitRate: %i\n", mpd_status_get_kbit_rate(status));
}
mpd_status_free(status);
if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS)
return handle_error(conn);
mpd_response_next(conn);
while ((song = mpd_recv_song(conn)) != NULL) {
printf("uri: %s\n", mpd_song_get_uri(song));
print_tag(song, MPD_TAG_ARTIST, "artist");
print_tag(song, MPD_TAG_ALBUM, "album");
print_tag(song, MPD_TAG_TITLE, "title");
print_tag(song, MPD_TAG_TRACK, "track");
print_tag(song, MPD_TAG_NAME, "name");
print_tag(song, MPD_TAG_DATE, "date");
if (mpd_song_get_duration(song) > 0) {
printf("time: %u\n", mpd_song_get_duration(song));
}
printf("pos: %u\n", mpd_song_get_pos(song));
mpd_song_free(song);
}
if (mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS ||
!mpd_response_finish(conn))
return handle_error(conn);
} else if (argc == 2 && strcmp(argv, "idle") == 0) {
enum mpd_idle idle = mpd_run_idle(conn);
if (idle == 0 &&
mpd_connection_get_error(conn) != MPD_ERROR_SUCCESS)
return handle_error(conn);
for (unsigned j = 0;; ++j) {
enum mpd_idle i = 1 << j;
const char *name = mpd_idle_name(i);
if (name == NULL)
break;
if (idle & i)
printf("%s\n", name);
}
}
mpd_connection_free(conn);
return 0;
}

5
src/mpdclient.h Normal file
View File

@ -0,0 +1,5 @@
static int handle_error(struct mpd_connection *c);
static void print_tag(const struct mpd_song *song, enum mpd_tag_type type, const char *label);
int mpdClient(int argc, char *argv);

36
src/npd.c Normal file
View File

@ -0,0 +1,36 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "curl.h"
#include "md5.h"
#include "mpdclient.h"
typedef struct {
char
} blah_t;
int main(int argc, char *argv[]) {
char password[255] = "Thirty5Nrunyos";
char salt[255] = "wildhorses";
char pass_and_salt[512];
strcat(pass_and_salt, password);
strcat(pass_and_salt, salt);
char buf[33];
char rest[512];
md5Output("Thirty5Nrunyoswildhorses", buf);
strcpy(rest, "http://192.168.191.61:4533/rest/search3?query=khruangbin&u=mrfry&t=");
strcat(rest, buf);
strcat(rest, "&s=");
strcat(rest, salt);
strcat(rest, "&v=1.16&c=npd");
mpdClient(2,"idle");
curl(rest);
return 0;
}

139
src/parseJSON.c Normal file
View File

@ -0,0 +1,139 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
char artist[256];
char album[256];
char title[256];
char id[256];
} Song;
char *readXML(char *filename) {
// Reads a file and puts it in a string
//
// https://www.youtube.com/watch?v=CzAgM5bez-g
FILE *xmlResponse; // Create a pointer that will read the file
xmlResponse = fopen(filename, "r");
if (xmlResponse == NULL) return NULL;
fseek(xmlResponse, 0, SEEK_END);
int length = ftell(xmlResponse);
fseek(xmlResponse, 0, SEEK_SET);
char *string = malloc(sizeof(char) * (length+1));
char c;
int i = 0;
while ( (c = fgetc(xmlResponse)) != EOF ) {
string[i] = c;
i++;
}
string[i] = '\0';
fclose(xmlResponse);
return string;
}
void emptyBuffer(char *buffer) {
buffer[0] = '\0';
}
void fillBuffer(char *buffer, char c) {
char string[2] = {c, '\0'};
strcat(buffer, string);
}
Song *parseDiagram(char *XMLContents) {
// Parsing the diagram using a state machine
//
// https://www.youtube.com/watch?v=rauO5qespFc
int state = 0;
Song *current_song = malloc(sizeof(Song) * 1024); // Declaring an array of current_song
// int nodeCount = 0; // Songs index used below in the state machine
// int inputCount = 0; // Inputs index used below in the state machine
char buffer[256]; // Buffer for the parsed data
emptyBuffer(buffer);
//printf("buffer\t\tcurrent_song\t\tinputs\t\tstate\n");
printf("\n--- Parsing json response ---\n\n");
for (const char* c = XMLContents; *c; c++) {
switch (state) {
case 0: // Reading
switch (*c) {
case '<':
// Ladies and gentlement we have a tag
strcpy(song.artist, buffer); // Save name of the artistr
emptyBuffer(buffer);
state = 1; // Parse tag
break;
case '<':
// Ladies and gentlement we have a tag
strcpy(song.artist, buffer); // Save name of the artistr
emptyBuffer(buffer);
state = 1; // Parse tag
break;
default:
// Keep reading
fillBuffer(buffer, *c);
printf("Buffer: %s\n", buffer);
break;
}
break;
case 1: // Parse tag names
switch (*c) {
case ' ': // Done
state = 0;
break;
default:
fillBuffer(buffer, *c);
printf("Buffer: %s\n", buffer);
if (strcmp(buffer, "song") {
state = 2;
}
else {
state = 1;
}
break;
}
break;
case 2: // We found a song tag, let's
switch (*c) {
case '"': // Here comes an attribute
state = 2;
break;
default:
fillBuffer(buffer, *c);
printf("Buffer: %s\n", buffer);
if (strcmp(buffer, "id=\"") {
state = 3;
}
else {
fillBuffer(buffer, *c);
}
break;
}
case 3: // Save an id
switch (*c) {
case '"':
strcpy(buffer, song->id);
}
}
}
totalSongs = nodeCount;
free(XMLContents);
printf("\n--- Yay, all parsed! ---\n\n");
return(current_song);
}