first commit
This commit is contained in:
commit
4fd853f28a
|
@ -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;
|
||||
}
|
||||
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
void md5Compute(char *str, unsigned char digest[16]);
|
||||
|
||||
char * md5Output(char *expression, char buf[]);
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue