Use @Itai-Nelken genapplist-yad.c program for faster preloading

pull/966/head
Botspot 3 years ago
parent c71624b440
commit 0853aef410

@ -0,0 +1,197 @@
/* ========================================================= *
* Pi-Apps app preloader for YAD GUI app list style. *
* Written by Itai-Nelken 09/09/2021 (MM/DD/YY). *
* --------------------------------------------------------- *
* gcc pi-apps_app-prel.c -o prel -Wall -Wextra -Wpedantic *
* ========================================================= */
#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <string.h>
#include <assert.h>
// check if a file exists
int fileExists(const char *path) {
FILE *file=fopen(path, "rb");
if (!file) {
return 1;
}
fclose(file);
return 0;
}
// fill a string with nul characters ('\0')
void str_zero(char *str) {
char *s=str;
while(*s++) {
*s='\0';
}
}
// get a single line from a file
void getLine(const char *filename, char *out, size_t size) {
FILE *f=fopen(filename, "r");
if(!f) {
perror("getLine(): fopen()");
} else {
fgets(out, size, f);
fclose(f);
}
}
// get the status of a app in pi-apps
void get_app_status(const char *app, char *status, size_t size) {
char path[250]={0}, st[4096]={0}, *directory=getenv("DIRECTORY");
snprintf(path, 250, "%s/data/status/%s", directory, app);
if (!fileExists(path)) { //if 'path' exists
getLine(path, st, 4096);
st[strlen(st)-1]='\0';
assert(strlen(st)<=size);
snprintf(status, size, "%s", st);
} else {
snprintf(path, 250, "%s/apps/%s/uninstall", directory, app);
if(!fileExists(path)) {
assert(strlen("uninstalled")<=size);
snprintf(status, size, "uninstalled");
} else {
fprintf(stderr, "ERROR: get_app_status(): No such app: \"%s\"!\n", app);
}
}
}
// get the status of a app in pi-apps but print 'none' if the app has no status file
// but it exists (it has a uninstall script)
void get_app_status_with_none(const char *app, char *status, size_t size) {
char path[250]={0}, st[4096]={0}, *directory=getenv("DIRECTORY");
snprintf(path, 250, "%s/data/status/%s", directory, app);
if (!fileExists(path)) { //if 'path' exists
getLine(path, st, 4096);
st[strlen(st)-1]='\0';
assert(strlen(st)<=size);
snprintf(status, size, "%s", st);
} else {
snprintf(path, 250, "%s/apps/%s/uninstall", directory, app);
if(!fileExists(path)) {
assert(strlen("none")<=size);
snprintf(status, size, "none");
} else {
fprintf(stderr, "ERROR: get_app_status(): No such app: \"%s\"!\n", app);
}
}
}
// get the path to the status icon for a app based on the it's status
void get_status_icon(const char *app, char *icon, size_t size) {
char path[300]={0}, *directory=getenv("DIRECTORY"), status[30]={0};
get_app_status_with_none(app, status, 30);
snprintf(path, 300, "%s/icons/%s.png", directory, status);
if(!fileExists(path)) {
assert(strlen(path)<=size);
strncpy(icon, path, size);
} else {
//fprintf(stderr, "ERROR: get_icon_name(): icon \"%s\" doesn't exist!\n", path);
assert(strlen(directory)+15<=size);
snprintf(icon, strlen(directory)+15, "%s/icons/none.png", directory);
}
}
// get the path to a app's icon
void get_app_icon(const char *app, char *icon, size_t size) {
char path[4096]={0}, *directory=getenv("DIRECTORY");
snprintf(path, 4096, "%s/apps/%s/icon-24.png", directory, app);
if(!fileExists(path)) {
assert(strlen(path)<=size);
strncpy(icon, path, size);
} else {
fprintf(stderr, "ERROR: get_app_icon(): app \"%s\" doesn't have a icon-24!\n", app);
}
}
// get the status and first line of the description of an app in a format like this:
// "(<STATUS>) <SHORT DESCRIPTION>"
void get_app_status_and_desc(const char *app, char *out, size_t out_size) {
char path[4096]={0}, buffer[out_size], status[30]={0}, *directory=getenv("DIRECTORY");
str_zero(buffer);
snprintf(path, 4096, "%s/apps/%s/description", directory, app);
if(!fileExists(path)) {
getLine(path, buffer, out_size);
buffer[strlen(buffer)-1]='\0'; // remove newline from end
get_app_status(app, status, 30);
snprintf(out, out_size+33, "(%s) %s", status, buffer);
} else {
fprintf(stderr, "ERROR: get_app_status_and_desc(): app \"%s\" doesn't have a description!\n", app);
}
}
// collect and print all the data
void print_all(const char *app) {
char st_icon[300]={0}, app_icon[4096]={0}, desc[4096]={0};
get_status_icon(app, st_icon, 300);
get_app_icon(app, app_icon, 4096);
get_app_status_and_desc(app, desc, 4096);
printf("%s\n%s\n%s\n%s\n%s\n", st_icon, app_icon, app, app, desc);
}
int main(void) {
if(!getenv("APPS")) {
fprintf(stderr, "ERROR: \"APPS\" environment variable isn't set!\n");
return 1;
}
if(!getenv("DIRECTORY")) {
fprintf(stderr, "ERROR: \"DIRECTORY\" environment variable isn't set!\n");
return 1;
}
char *separator="\n";
char *parsed;
parsed=strtok(getenv("APPS"), separator);
while(parsed!=NULL) {
print_all(parsed);
parsed=strtok(NULL, separator);
}
return 0;
}
/*** REQUIRED OUTPUT ***
* 1) status icon
* 2) app icon
* 3) app name
* 4) app folder name (in ~/pi-apps/apps)
* 5) status and short description
***********************/
/* LOOP OVER EVERY APP IN $HOME/PI-APPS/APPS *
char *home=getHomePath();
char path[strlen(home)+20];
str_zero(path);
snprintf(path, strlen(home)+20, "%s/pi-apps/apps", home);
DIR *dir;
struct dirent *d;
dir=opendir(path);
if(!dir) {
fprintf(stderr, "ERROR: failed to open directory \"%s\"!\n", path);
} else {
while((d=readdir(dir))!=NULL) {
if(strcmp(d->d_name, ".")&&strcmp(d->d_name, "..")&&strcmp(d->d_name, "template")) {
print_all(d->d_name);
}
}
closedir(dir);
}
**************************************************/
/*********************************************
void remove_all_chars(char* str, char c) {
char *pr = str, *pw = str;
while (*pr) {
*pw = *pr++;
pw += (*pw != c);
}
*pw = '\0';
}
***********************************************/

@ -31,22 +31,43 @@ listfile="${DIRECTORY}/data/preload/LIST-$(echo "$prefix" | tr -d '/')"
mkdir -p "${DIRECTORY}/data/preload"
{ #compile the genapplist-yad.c program
if [ ! -f "${DIRECTORY}/etc/genapplist-yad" ] && [ -f "${DIRECTORY}/etc/genapplist-yad.c" ];then
echo "Compiling genapplist-yad program..." 1>&2
command -v gcc >/dev/null || sudo apt install -y gcc 1>&2
gcc "${DIRECTORY}/etc/genapplist-yad.c" -o "${DIRECTORY}/etc/genapplist-yad" 1>&2 || failed=1
#Test the program and make sure it outputs 5 lines
if [ "$(APPS=Arduino DIRECTORY="$DIRECTORY" "${DIRECTORY}/etc/genapplist-yad" | wc -l)" != 5 ];then
failed=1
fi
if [ "$failed" == 1 ];then
rm -f "${DIRECTORY}/etc/genapplist-yad"
echo "The genapplist-yad program failed to compile." 1>&2
else
echo "Success! The genapplist-yad program has been compiled." 1>&2
fi
fi
}
mktimestamps() {
#these directories are checked for changes
checkdirs="${DIRECTORY}/apps
${DIRECTORY}/data/settings
${DIRECTORY}/data/status
${DIRECTORY}/data/update-status
${DIRECTORY}/etc"
timestamps=''
PREIFS="$IFS"
IFS=$'\n'
local IFS=$'\n'
for dir in $checkdirs
do
timestamps="$timestamps
dir $dir $(stat -c %Y "${dir}/$(ls -t "$dir" | head -n1)")"
done
IFS="$PREIFS"
#remove first empty newline and check a few other things for changes too
timestamps="prefix: $prefix
format: $format
@ -89,21 +110,13 @@ if [ $reloadlist == 1 ];then
#for app_categories() and app_status() functions
source "${DIRECTORY}/api"
vfiles="$(app_categories)" #generate paps within categories as folders
#generate a virtual file system with apps in folders represented as subdirectories
vfiles="$(echo "$vfiles" | grep . | sort | uniq)"
#echo "$vfiles" 1>&2
vfiles="$(app_categories | grep . | sort | uniq)" #generate a virtual file system with apps in folders represented as subdirectories
if [ ! -z "$prefix" ];then
echo "Showing apps within $prefix/" 1>&2
vfiles="$(echo "$vfiles" | grep "^$prefix/" | sed "s+$prefix/++g")"
fi
#echo "$vfiles" 1>&2
#remove apps within categories - show this layer of stuff only.
vfiles="$(echo "$vfiles" | sed 's+/.*+/+g' | sort | uniq)"
@ -114,6 +127,18 @@ if [ $reloadlist == 1 ];then
#get list of folders - excluding apps - and hide the hidden folder.
DIRS="$(echo "$vfiles" | grep '/' | tr -d '/' | grep -vx "hidden")"
#If updates available, show special Updates category
if "${DIRECTORY}/updater" get-status &>/dev/null;then
DIRS="Updates
$DIRS"
fi
#shuffle the list if enabled
if [ "$(cat "${DIRECTORY}/data/settings/Shuffle App list")" == 'Yes' ];then
APPS="$(echo "$APPS" | shuf)"
DIRS="$(echo "$DIRS" | shuf)"
fi
#remove apps that are not compatible with OS architecture
PREIFS="$IFS"
IFS=$'\n'
@ -128,12 +153,6 @@ if [ $reloadlist == 1 ];then
done
IFS="$PREIFS"
#shuffle the list if enabled
if [ "$(cat "${DIRECTORY}/data/settings/Shuffle App list")" == 'Yes' ];then
APPS="$(echo "$APPS" | shuf)"
DIRS="$(echo "$DIRS" | shuf)"
fi
if [ "$format" == yad ];then
PREIFS="$IFS"
IFS=$'\n'
@ -152,17 +171,27 @@ $i
$i/
App folder
"
done
done #finished preloading categories
for i in $APPS
do
LIST="$LIST$(echo "${DIRECTORY}/icons/$(cat "${DIRECTORY}/data/status/${i}" 2>/dev/null || echo "none").png")
#set to false to disable genapplist-yad program - use the original bash version
if true && [ -f "${DIRECTORY}/etc/genapplist-yad" ];then
LIST="$LIST$(DIRECTORY="$DIRECTORY" APPS="$APPS" "${DIRECTORY}/etc/genapplist-yad")
"
else
for i in $APPS
do
status1="$(cat "${DIRECTORY}/data/status/${i}" 2>/dev/null || echo "none")"
status2="$(echo "$status1" | sed 's/none/uninstalled/g')"
LIST="$LIST$(echo "${DIRECTORY}/icons/$status1.png")
${DIRECTORY}/apps/${i}/icon-24.png
$i
$i
"\("$(app_status "$i")"\)" $(echo "$(cat "${DIRECTORY}/apps/${i}/description" || echo "Description unavailable")" | head -n1)
"\("$status2"\)" $(head -n1 "${DIRECTORY}/apps/${i}/description" || echo "Description unavailable")
"
done
done
fi #finished preloading apps
IFS="$PREIFS"
elif [ "$format" == xlunch ];then
@ -186,7 +215,7 @@ ${i};$diricon;${i}/"
for i in $APPS
do
LIST="$LIST
${i} "\("$(app_status "${i}")"\)";${DIRECTORY}/apps/${i}/icon-64.png;${i}"
${i} ($(app_status "${i}"));${DIRECTORY}/apps/${i}/icon-64.png;${i}"
done
IFS="$PREIFS"
fi
@ -215,5 +244,5 @@ IFS="$PREIFS" ) &
echo "$LIST"
#re-preload all categories in background
#preload all categories in background
"${DIRECTORY}/etc/preload-daemon" "$format" &>/dev/null &

Loading…
Cancel
Save