summaryrefslogtreecommitdiff
path: root/src/fruits/cap
diff options
context:
space:
mode:
Diffstat (limited to 'src/fruits/cap')
-rw-r--r--src/fruits/cap/cap.c267
-rw-r--r--src/fruits/cap/cap.h55
-rw-r--r--src/fruits/cap/meson.build8
3 files changed, 0 insertions, 330 deletions
diff --git a/src/fruits/cap/cap.c b/src/fruits/cap/cap.c
deleted file mode 100644
index 3f5f5e8..0000000
--- a/src/fruits/cap/cap.c
+++ /dev/null
@@ -1,267 +0,0 @@
-#include <al/random.h>
-
-#include "../../cache/handlers/file.h"
-#ifdef AKIYO_HAS_CURL
-#include "../../cache/handlers/http.h"
-#endif
-
-#include "cap.h"
-
-void cap_init(struct cap_runner *cap, bool (*callback)(void *, u8, str *, str *, void *), void *userdata)
-{
- cap->callback = callback;
- cap->userdata = userdata;
- al_array_init(cap->lists);
-#if CAP_USE_PYTHON
- sho_client_init(&cap->search, NULL);
-#endif
-}
-
-static struct cap_list *list_from_name(struct cap_runner *cap, str *name)
-{
- struct cap_list *list;
- al_array_foreach_ptr(cap->lists, i, list) {
- if (al_str_eq(&list->name, name)) {
- return list;
- }
- }
- return NULL;
-}
-
-static struct cch_entry *entry_for_unique_id(struct cap_runner *cap, str *unique_id)
-{
- struct cch_entry *entry = NULL;
-#ifdef AKIYO_HAS_CURL
- bool is_search = al_str_at(unique_id, 0) == ';';
- if (is_search || al_str_cmp(unique_id, al_str_c("https://"), 0, 8) == 0 ||
- al_str_cmp(unique_id, al_str_c("http://"), 0, 7) == 0) {
-#if CAP_USE_PYTHON
- str provider;
- str query;
- al_str_from(&provider, "");
- al_str_from(&query, "");
- if (al_str_cmp(unique_id, al_str_c("https://twitter.com"), 0, 19) == 0 ||
- al_str_cmp(unique_id, al_str_c("https://x.com"), 0, 13) == 0) {
- al_str_cat(&query, al_str_c("tweet:"));
- al_str_cat(&query, unique_id);
- al_str_cat(&provider, al_str_c("twitter"));
- } else if (al_str_cmp(unique_id, al_str_c("https://instagram.com"), 0, 21) == 0) {
- s32 slash = al_str_rfind(unique_id, '/');
- if (slash >= 0) {
- al_str_cat(&query, al_str_substr(unique_id, slash + 1, unique_id->len));
- }
- al_str_cat(&provider, al_str_c("instagram"));
- } else {
- if (is_search) {
- al_str_cat(&query, al_str_substr(unique_id, 1, unique_id->len));
- } else {
- al_str_cat(&query, al_str_c("link:"));
- al_str_cat(&query, unique_id);
- }
- al_str_cat(&provider, al_str_c("youtube"));
- }
- s32 id = sho_client_create_search(&cap->search, &provider, &query);
- al_str_free(&provider);
- al_str_free(&query);
- if (id < 0) return NULL;
- struct sho_search *search = sho_client_get_search(&cap->search, id);
- if (!search || !sho_search_from_page(search, 0)) return NULL;
- struct sho_result_page *page = &al_array_at(search->pages, 0);
- struct sho_post *post;
- al_array_foreach_ptr(page->posts, i, post) {
- struct sho_post_media *media;
- al_array_foreach_ptr(post->media, j, media) {
- if (media->url.len > 0) {
- entry = cch_handler_http_create(&media->url);
- break;
- }
- }
- if (entry) break;
- }
- sho_client_discard_search(&cap->search, id);
-#else
- if (!is_search) entry = cch_handler_http_create(unique_id);
-#endif
- if (entry) entry->handler->maybe_spawn_worker(entry->handler, 0);
- } else // {
-#endif
- entry = cch_handler_file_create(unique_id);
- // }
- return entry;
-}
-
-static bool buffer_entry(struct cap_runner *cap, struct cap_list *list, struct cap_list_entry *entry)
-{
- if (entry->errored) return false;
- if (entry->buffer_requested) return true;
- entry->entry = entry_for_unique_id(cap, &entry->unique_id);
- if (!entry->entry || !cap->callback(cap->userdata, CAP_BUFFER, &list->name, &entry->unique_id, entry->entry)) {
- entry->errored = true;
- return false;
- }
- entry->buffer_requested = true;
- return true;
-}
-
-static void maybe_cleanup_entries(struct cap_runner *cap, struct cap_list *list)
-{
- struct cap_list_entry *entry;
- al_array_foreach_ptr(list->entries, i, entry) {
- if (entry->buffer_requested && abs(list->current - (s32)i) >= 3) {
- cap->callback(cap->userdata, CAP_UNLOAD, &list->name, &entry->unique_id, NULL);
- entry->buffer_requested = false;
- }
- }
-}
-
-static bool list_skip_internal(struct cap_runner *cap, struct cap_list *list, s32 n);
-
-static void list_pump_internal(struct cap_runner *cap, struct cap_list *list, bool buffer)
-{
- s32 size = (s32)list->entries.size;
- if (size <= list->current) return;
- if (buffer) list->buffer = true;
- if (list->set != list->current) {
- struct cap_list_entry *entry = &al_array_at(list->entries, list->current);
- if (list->swap && !entry->buffer_requested) {
- list->swap = false;
- return;
- }
- if (!buffer_entry(cap, list, entry)) {
- list_skip_internal(cap, list, list->forward ? 1 : -1);
- return;
- }
- cap->callback(cap->userdata, list->swap ? CAP_SWAP : CAP_SET, &list->name, &entry->unique_id, NULL);
- list->set = list->current;
- }
- if (list->buffer) {
- for (s32 i = 1; i <= 2; i++) {
- if (list->current + i < size) {
- buffer_entry(cap, list, &al_array_at(list->entries, list->current + i));
- list->buffer = false;
- }
- if (list->current - i >= 0) {
- buffer_entry(cap, list, &al_array_at(list->entries, list->current - i));
- }
- }
- }
- maybe_cleanup_entries(cap, list);
-}
-
-bool list_skip_internal(struct cap_runner *cap, struct cap_list *list, s32 n)
-{
- s32 size = (s32)list->entries.size;
- if (list->current + n < 0 || list->current + n >= size) {
- return false;
- }
- list->current += n;
- list->forward = n >= 0;
- list_pump_internal(cap, list, false);
- return true;
-}
-
-void cap_make_list(struct cap_runner *cap, str *name)
-{
- struct cap_list list;
- al_str_clone(&list.name, name);
- list.current = 0;
- list.forward = true;
- list.set = -1;
- list.idle = false;
- list.buffer = false;
- list.swap = false;
- aki_mutex_init(&list.mutex);
- al_array_init(list.entries);
- al_array_push(cap->lists, list);
-}
-
-void cap_list_add(struct cap_runner *cap, str *name, str *unique_id)
-{
- struct cap_list *list = list_from_name(cap, name);
- if (!list) return;
- aki_mutex_lock(&list->mutex);
- struct cap_list_entry entry;
- al_str_clone(&entry.unique_id, unique_id);
- entry.entry = NULL;
- entry.errored = false;
- entry.buffer_requested = false;
- al_array_push(list->entries, entry);
- if (list->idle && list_skip_internal(cap, list, 1)) {
- list->idle = false;
- } else {
- list_pump_internal(cap, list, false);
- }
- aki_mutex_unlock(&list->mutex);
-}
-
-bool cap_list_skip(struct cap_runner *cap, str *name, s32 n)
-{
- struct cap_list *list = list_from_name(cap, name);
- if (!list) return false;
- aki_mutex_lock(&list->mutex);
- bool ret = list_skip_internal(cap, list, n);
- aki_mutex_unlock(&list->mutex);
- return ret;
-}
-
-void cap_list_pump(struct cap_runner *cap, str *name, bool buffer)
-{
- struct cap_list *list = list_from_name(cap, name);
- if (!list) return;
- aki_mutex_lock(&list->mutex);
- list_pump_internal(cap, list, buffer);
- aki_mutex_unlock(&list->mutex);
-}
-
-bool cap_list_set_completed(struct cap_runner *cap, str *name)
-{
- struct cap_list *list = list_from_name(cap, name);
- if (!list) return false;
- aki_mutex_lock(&list->mutex);
- list->swap = true;
- list->idle = !list_skip_internal(cap, list, 1);
- bool ret = !list->idle && list->swap;
- list->swap = false;
- aki_mutex_unlock(&list->mutex);
- return ret;
-}
-
-// https://benpfaff.org/writings/clc/shuffle.html
-void cap_list_shuffle(struct cap_runner *cap, str *name)
-{
- struct cap_list *list = list_from_name(cap, name);
- if (!list) return;
- aki_mutex_lock(&list->mutex);
- u32 size = list->entries.size;
- if (size > 0) {
- for (u32 i = 0; i < size - 1; i++) {
- u32 j = i + al_rand() / (AL_RAND_MAX / (size - i) + 1);
- struct cap_list_entry tmp = al_array_at(list->entries, j);
- al_array_at(list->entries, j) = al_array_at(list->entries, i);
- al_array_at(list->entries, i) = tmp;
- }
- list->set = -1;
- list_pump_internal(cap, list, false);
- }
- aki_mutex_unlock(&list->mutex);
-}
-
-static void list_close_internal(struct cap_list *list)
-{
- struct cap_list_entry *entry;
- al_array_foreach_ptr(list->entries, i, entry) {
- al_str_free(&entry->unique_id);
- }
- al_array_free(list->entries);
- aki_mutex_destroy(&list->mutex);
- al_str_free(&list->name);
-}
-
-void cap_close(struct cap_runner *cap)
-{
- struct cap_list *list;
- al_array_foreach_ptr(cap->lists, i, list) {
- list_close_internal(list);
- }
- al_array_free(cap->lists);
-}
diff --git a/src/fruits/cap/cap.h b/src/fruits/cap/cap.h
deleted file mode 100644
index 69d4d6d..0000000
--- a/src/fruits/cap/cap.h
+++ /dev/null
@@ -1,55 +0,0 @@
-#pragma once
-
-#define CAP_USE_PYTHON 0
-
-#include <al/array.h>
-#include <al/str.h>
-#include <aki/thread.h>
-
-#if CAP_USE_PYTHON
-#include "../../shoki/src/search.h"
-#endif
-
-struct cap_list_entry {
- str unique_id;
- struct cch_entry *entry;
- bool buffer_requested;
- bool errored;
-};
-
-struct cap_list {
- str name;
- s32 current;
- bool forward;
- s32 set;
- bool idle;
- bool buffer;
- bool swap;
- struct aki_mutex mutex;
- array(struct cap_list_entry) entries;
-};
-
-enum {
- CAP_BUFFER = 0,
- CAP_SET,
- CAP_SWAP,
- CAP_UNLOAD
-};
-
-struct cap_runner {
- array(struct cap_list) lists;
-#if CAP_USE_PYTHON
- struct sho_client search;
-#endif
- bool (*callback)(void *, u8, str *, str *, void *);
- void *userdata;
-};
-
-void cap_init(struct cap_runner *cap, bool (*callback)(void *, u8, str *, str *, void *), void *userdata);
-void cap_make_list(struct cap_runner *cap, str *name);
-void cap_list_add(struct cap_runner *cap, str *name, str *unique_id);
-bool cap_list_skip(struct cap_runner *cap, str *name, s32 n);
-void cap_list_pump(struct cap_runner *cap, str *name, bool buffer);
-bool cap_list_set_completed(struct cap_runner *cap, str *name);
-void cap_list_shuffle(struct cap_runner *cap, str *name);
-void cap_close(struct cap_runner *cap);
diff --git a/src/fruits/cap/meson.build b/src/fruits/cap/meson.build
deleted file mode 100644
index f85ab00..0000000
--- a/src/fruits/cap/meson.build
+++ /dev/null
@@ -1,8 +0,0 @@
-cap_src = ['cap.c']
-cap_deps = [common_deps]
-use_python = true
-if use_python
- cap_deps += [shoki]
-endif
-cap = declare_dependency(sources: cap_src,
- dependencies: cap_deps)