diff options
-rwxr-xr-x | build.sh | 2 | ||||
-rw-r--r-- | main.c | 34 | ||||
-rw-r--r-- | program.c | 7 | ||||
-rw-r--r-- | program.h | 2 | ||||
-rw-r--r-- | transmission.c | 87 | ||||
-rw-r--r-- | transmission.h | 14 |
6 files changed, 123 insertions, 23 deletions
@@ -5,4 +5,4 @@ CFLAGS="-O0 -g3 -Wall -Wextra -Werror" #LIBS="-lcurl" LIBS="" #gcc -musl-gcc -static main.c program.c alloc.c buffer.c fileutils.c -o automedia $CFLAGS $LIBS +musl-gcc -static main.c program.c alloc.c buffer.c fileutils.c transmission.c -o automedia $CFLAGS $LIBS @@ -1,23 +1,15 @@ -#include "program.h" #include "buffer.h" #include "fileutils.h" +#include "transmission.h" #include "json.h" #include <stdio.h> #include <stdlib.h> #include <string.h> #include <limits.h> -#include <stdbool.h> #include <dirent.h> -/* -static int program_buffer_write_callback(char *data, int size, void *userdata) { - Buffer *buffer = userdata; - buffer_append(buffer, data, size); - return 0; -} -*/ static void usage(void) { fprintf(stderr, "usage: automedia COMMAND\n"); fprintf(stderr, "\n"); @@ -64,7 +56,7 @@ static struct json_value_s* json_object_get_field_by_name(struct json_object_s * typedef void (*DownloadedListCallback)(const char *title, double timestamp, void *userdata); -static void data_file_get_downloaded(const char *dir_name, const char *data_filepath, bool is_html, DownloadedListCallback callback, void *userdata) { +static void data_file_get_downloaded(const char *dir_name, const char *data_filepath, int is_html, DownloadedListCallback callback, void *userdata) { char *file_data; long file_size; if(file_get_content(data_filepath, &file_data, &file_size) != 0) { @@ -158,7 +150,7 @@ static void downloaded_list_callback(const char *title, double timestamp, void * buffer_append(buffer, &list_data, sizeof(list_data)); } -static void get_downloaded_items(const char *tracked_dir, bool is_html, void *userdata) { +static void get_downloaded_items(const char *tracked_dir, int is_html, void *userdata) { struct dirent *dir; DIR *d = opendir(tracked_dir); if(!d) @@ -200,8 +192,8 @@ static void command_downloaded(const char *rss_config_dir, const char *html_conf Buffer downloaded_items; buffer_init(&downloaded_items); - get_downloaded_items(rss_tracked_dir, false, &downloaded_items); - get_downloaded_items(html_tracked_dir, true, &downloaded_items); + get_downloaded_items(rss_tracked_dir, 0, &downloaded_items); + get_downloaded_items(html_tracked_dir, 1, &downloaded_items); qsort(downloaded_items.data, buffer_get_size(&downloaded_items, sizeof(DownloadedListData)), sizeof(DownloadedListData), compare_downloaded_item); DownloadedListData *list_it = buffer_begin(&downloaded_items); @@ -214,6 +206,11 @@ static void command_downloaded(const char *rss_config_dir, const char *html_conf buffer_deinit(&downloaded_items); } +static void torrent_list_callback(int id, float percentage_finished, const char *name, void *userdata) { + (void)userdata; + fprintf(stderr, "id: |%d|, done: |%g|, name: |%s|\n", id, percentage_finished, name); +} + int main(int argc, char **argv) { if(argc < 2) usage(); @@ -240,15 +237,8 @@ int main(int argc, char **argv) { usage(); } -/* - Buffer buffer; - buffer_init(&buffer); - - const char *args[] = { "curl", "-s", "-L", "-f", "https://google.com", NULL }; - program_exec(args, program_buffer_write_callback, &buffer); - printf("program output: %.*s\n", (int)buffer.size, (char*)buffer.data); + transmission_get_all_torrents(torrent_list_callback, NULL); + printf("is transmission daemon running? %s\n", transmission_is_daemon_running() == 0 ? "yes" : "no"); - buffer_deinit(&buffer); -*/ return 0; } @@ -11,6 +11,13 @@ #define READ_END 0 #define WRITE_END 1 +int program_empty_callback(char *data, int size, void *userdata) { + (void)data; + (void)size; + (void)userdata; + return 0; +} + int program_exec(const char **args, ProgramOutputCallback output_callback, void *userdata) { /* 1 arguments */ if(args[0] == NULL) @@ -4,6 +4,8 @@ /* Return 0 if you want to continue reading. @data is null-terminated */ typedef int (*ProgramOutputCallback)(char *data, int size, void *userdata); +int program_empty_callback(char *data, int size, void *userdata); + /* @args need to have at least 2 arguments. The first which is the program name and the last which is NULL, which indicates end of args diff --git a/transmission.c b/transmission.c new file mode 100644 index 0000000..59b136c --- /dev/null +++ b/transmission.c @@ -0,0 +1,87 @@ +#include "transmission.h" +#include "program.h" +#include "buffer.h" +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +#define NUM_COLUMNS 10 + +static int program_buffer_write_callback(char *data, int size, void *userdata) { + Buffer *buffer = userdata; + buffer_append(buffer, data, size); + return 0; +} + +int transmission_is_daemon_running() { + const char *args[] = { "transmission-remote", "-si", NULL }; + return program_exec(args, program_empty_callback, NULL); +} + +int transmission_start_daemon() { + /* TODO: Make seed ratio configurable */ + const char *args[] = { "transmission-daemon", "--global-seedratio", "2.0", "--download-dir", NULL }; + int res = program_exec(args, program_empty_callback, NULL); + if(res != 0) + return res; + + fprintf(stderr, "Waiting for the transmission daemon to startup...\n"); + while(transmission_is_daemon_running()) { + const useconds_t one_hundred_ms = 1000 * 1000 * 100; + usleep(one_hundred_ms); + } + fprintf(stderr, "The transmission daemon is now running!\n"); + return 0; +} + +int transmission_add_torrent(const char *url) { + const char *args[] = { "transmission-remote", "-a", "--", url, NULL }; + return program_exec(args, program_empty_callback, NULL); +} + +int transmission_get_all_torrents(TorrentListCallback callback, void *userdata) { + int result = 0; + + Buffer buffer; + buffer_init(&buffer); + + const char *args[] = { "transmission-remote", "--list", NULL }; + int exec_res = program_exec(args, program_buffer_write_callback, &buffer); + if(exec_res != 0) { + result = exec_res; + goto cleanup; + } + buffer_append(&buffer, "0", 1); + + char id[6]; + char done[6]; + char have[13]; + char format[7]; + char eta[33]; + char up[11]; + char down[11]; + char ratio[11]; + char status[33]; + char name[256]; + + char *end_of_first_line = strchr(buffer.data, '\n'); + if(!end_of_first_line) + goto cleanup; + + int num_bytes_read = 0; + size_t offset = end_of_first_line - (char*)buffer.data; + while(offset < buffer.size) { + /* ID, Done, Have (size, format), ETA, Up, Down, Ratio, Status, Name */ + int res = sscanf(buffer.data + offset, "%5s %5s %12s %6s %32s %10s %10s %10s %32s %[^\n] %n", id, done, have, format, eta, up, down, ratio, status, name, &num_bytes_read); + if(res == EOF || res != NUM_COLUMNS) + break; + /*printf("id: %s, done: %s, have: %s, format: %s, eta: %s, up: %s, down: %s, ratio: %s, status: %s, name: %s\n", id, done, have, format, eta, up, down, ratio, status, name);*/ + callback(atoi(id), atof(done), name, userdata); + offset += num_bytes_read; + } + + cleanup: + buffer_deinit(&buffer); + return result; +} diff --git a/transmission.h b/transmission.h new file mode 100644 index 0000000..c37ca3a --- /dev/null +++ b/transmission.h @@ -0,0 +1,14 @@ +#ifndef TRANSMISSION_H +#define TRANSMISSION_H + +/* @percentage_finished is a value between 0 and 100 [0.0, 100.0] */ +typedef void (*TorrentListCallback)(int id, float percentage_finished, const char *name, void *userdata); + +/* Returns 0 if the daemon is running, otherwise returns an error value */ +int transmission_is_daemon_running(); +int transmission_start_daemon(); + +int transmission_add_torrent(const char *url); +int transmission_get_all_torrents(TorrentListCallback callback, void *userdata); + +#endif |