Xfce Forum

Sub domains
 

You are not logged in.

#51 2022-07-11 09:34:35

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Empty Trash Can Sound[solved]

agashamu wrote:

I'm still wondering what can cause a script to stop working after some time? Like you said ToZ, a script should run from start to end, forever.

Best guess is that something fails along the way here.

	inotifywait -q -m -r -e delete $DIR | while read D E F; do 
		play /home/shamu/My-sounds/trash-empty.wav
                notify-send -i user-trash "Trash" "emtpy-trash sound should play"
	done

Try with

        while : ; do
	        inotifywait -q -m -r -e delete $DIR |  read
		play /home/shamu/My-sounds/trash-empty.wav
                notify-send -i user-trash "Trash" "emtpy-trash sound should play"
                sleep 2
	done

Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#52 2022-07-11 15:55:21

agashamu
Member
From: California
Registered: 2021-03-01
Posts: 77

Re: Empty Trash Can Sound[solved]

Thanks Misko_2083, If it stops again, I will try that! But I don't think it's the script because if it was, it would never work. But it does, for 30-40 minutes. After that the damn thing "goes to sleep" and only a reboot can make it work again.


Linux Mint Xfce 20.3

Offline

#53 2022-07-11 17:21:44

KBar
Moderator
Registered: 2021-11-05
Posts: 634

Re: Empty Trash Can Sound[solved]

agashamu wrote:

Maybe KBar has some ideas, but he's been silent...I guess, this crazy "no sense" trash empty sound project is not his style...

It's nothing like that, not at all. I've just been working on a couple of other shell scripts and this seemed to be one too many. Apologies.

What I usually do to debug my scripts is enable execution tracing and redirect stderr to a temporary file, so:

#!/bin/sh -x
exec 2>$(mktemp)

However, it can get rather big quite fast. Does your main loop run each second? If so, waiting for half an hour shouldn't cause any problem. Just keep an eye on the log file. `tail -f` works, but I usually open it in less, so that I can examine it more closely, and then press Shift+F to emulate `tail -f`.

I'm not familiar with how system sounds work. I'll try to look at it more closely and see if I can offer a solution. Make sure to re-read ToZ's instructions and double check your script for logic errors. While you're at it, run a shellcheck on it. It's available on many distros. `apt install shellcheck` & `shellcheck /path/to/script` should work.

Last edited by KBar (2022-07-11 17:31:18)


Remember to edit the subject of your topic to include the [SOLVED] tag once you're satisfied with the answers or have found a solution (in which case, don't forget to share it as well), so that other members of the community can quickly refer to it and save their time. Pretty please! tongue

Offline

#54 2022-07-11 18:18:18

agashamu
Member
From: California
Registered: 2021-03-01
Posts: 77

Re: Empty Trash Can Sound[solved]

Hi KBar, I knew it! Teasing you a little bit did wake you up...Thanks!
However:

KBar wrote:

Does your main loop run each second? If so, waiting for half an hour shouldn't cause any problem. Just keep an eye on the log file. `tail -f` works, but I usually open it in less, so that I can examine it more closely, and then press Shift+F to emulate `tail -f`.

Unfortunately, this is all "Chinese" to me...I love Linux but I found it too late, when I was already too old to learn. My brain is not like it used to be...That is why I rely on this great forum and wonderful people. This forum is by far the best, most friendly and helpful among all Linux forums.
I do re-read Toz's instructions. I'm sure the script is correct, otherwise it would not work at all. But something stops it...Anyway, I'm now running two different scripts in two distros, we'll see which one works better...
Sorry about "teasing" just tried to be funny...Thanks for stopping by!


Linux Mint Xfce 20.3

Offline

#55 2022-07-11 18:38:23

KBar
Moderator
Registered: 2021-11-05
Posts: 634

Re: Empty Trash Can Sound[solved]

There's at least half a dozen scripts of all colors and shapes, so to say that I'm confused a bit is not saying much.

What distro are you running? Is it Debian-based (Xubuntu, Debian Xfce, Devuan, and the likes)? If so, can you check whether you have any oom-reaper (out-of-memory killer, that runs as a daemon and kills processes that go over their OOM score) installed?

 dpkg -l '*oom*'

There are two most popular ones: earlyoom and oomd (now under systemd, I believe). I doubt a shell script would get such a bad OOM score from the kernel, but perhaps it's too intensive and gets killed by the daemon? I'd check that anyways.


Remember to edit the subject of your topic to include the [SOLVED] tag once you're satisfied with the answers or have found a solution (in which case, don't forget to share it as well), so that other members of the community can quickly refer to it and save their time. Pretty please! tongue

Offline

#56 2022-07-11 19:54:20

agashamu
Member
From: California
Registered: 2021-03-01
Posts: 77

Re: Empty Trash Can Sound[solved]

I'm running Ubuntu-based Linux Lite 5.8 and Linux Mint Xfce 20.3

 dpkg -l '*oom*'
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                        Version      Architecture Description
+++-===========================-============-============-========================================================================
un  foomatic-db                 <none>       <none>       (no description available)
ii  foomatic-db-compressed-ppds 20200401-1   all          OpenPrinting printer support - Compressed PPDs derived from the database
ii  foomatic-db-engine          4.0.13-4     amd64        OpenPrinting printer support - programs
un  foomatic-db-gutenprint      <none>       <none>       (no description available)
un  foomatic-db-hpijs           <none>       <none>       (no description available)
un  foomatic-filters            <none>       <none>       (no description available)
un  foomatic-filters-beh        <none>       <none>       (no description availab

Linux Mint Xfce 20.3

Offline

#57 2022-07-11 20:20:43

agashamu
Member
From: California
Registered: 2021-03-01
Posts: 77

Re: Empty Trash Can Sound[solved]

Hi ToZ, I put your latest script in place, sound was played, bubble showed up.
Now I'll keep an eye (I should say an ear) on it if it will stop again later.
Thank you!


Linux Mint Xfce 20.3

Offline

#58 2022-07-11 21:48:42

agashamu
Member
From: California
Registered: 2021-03-01
Posts: 77

Re: Empty Trash Can Sound[solved]

ToZ, computer has been running for over two hours now and script is still working, maybe we got it this time. However, if there is 4 files in trash, and I empty it, it plays the sound 4 times with 4 bubbles showing up. Very funny! Can it be fixed please?
Thanks


Linux Mint Xfce 20.3

Offline

#59 2022-07-11 23:20:38

ToZ
Administrator
From: Canada
Registered: 2011-06-02
Posts: 9,504

Re: Empty Trash Can Sound[solved]

Try this version:

#!/bin/bash
# requires inotify-tools

DIR="$HOME/.local/share/Trash/info"
LAST=$(date +%s)

# make sure that only one instance of this script is running per user
lockfile=/tmp/.trashsound.$USER.lockfile
if ( set -o noclobber; echo "locked" > "$lockfile") 2> /dev/null; then
   trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT
   echo "trashsoundDEBUG: Locking succeeded" >&2

	inotifywait -q -m -r -e delete $DIR | while read D E F; do 
		CURRENT=$(date +%s)
		[[  $(( $CURRENT-$LAST )) -gt 3 ]] && play /home/shamu/My-sounds/trash-empty.wav
                LAST=$CURRENT
	done

# can't create lockfile - notify user and quit
else
   echo "trashsoundDEBUG: Lock failed, check for existing process and/or lock file and delete - exiting." >&2
   exit 1
fi

I've added a 3 second window for not playing sounds while files are being deleted and I've removed the notification bubble.

Online

#60 2022-07-11 23:26:37

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Empty Trash Can Sound[solved]

This one will wait until everything is deleted from trash.

#!/bin/bash
# requires inotify-tools

DIR="$HOME/.local/share/Trash/info"

# make sure that only one instance of this script is running per user
lockfile=/tmp/.trashsound.$USER.lockfile
if ( set -o noclobber; echo "locked" > "$lockfile") 2> /dev/null; then
   trap 'rm -f "$lockfile"; exit $?' INT TERM EXIT
   echo "trashsoundDEBUG: Locking succeeded" >&2

        while : ; do
                inotifywait -q -m -r -e delete $DIR | read
                until [ -z "$(ls -A $DIR)" ]; do
                         sleep 0.1
                done
		play /home/shamu/My-sounds/trash-empty.wav
                notify-send -i user-trash "Trash" "emtpy-trash sound should play"
	done

# can't create lockfile - notify user and quit
else
   echo "trashsoundDEBUG: Lock failed, check for existing process and/or lock file and delete - exiting." >&2
   exit 1
fi

Edit: it was blocking sometimes, needed to use sleep to wait until the folder is empty.
(changed the script)

Last edited by Misko_2083 (2022-07-12 00:00:16)


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#61 2022-07-12 01:05:16

agashamu
Member
From: California
Registered: 2021-03-01
Posts: 77

Re: Empty Trash Can Sound[solved]

ToZ, Misko, thank you very much both of you, you guys are sooo wonderful!
I put Misko's script in my Mint, after a reboot, right after signing in, it started playing the sound again and again, and never quit...the sound I'm using here is a shotgun sound. It was so funny, I felt like being in Ukraine in a battlefield. Tried to reboot 3 times, it happened every time.
I put ToZ's script in my Lite, it did work great, even when deleting 5 files, it played the sound once.
I love Linux, it's amazing what people like you guys can do with one little script.

Last edited by agashamu (2022-07-12 02:30:04)


Linux Mint Xfce 20.3

Offline

#62 2022-07-12 11:50:27

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Empty Trash Can Sound[solved]

agashamu wrote:

ToZ, Misko, thank you very much both of you, you guys are sooo wonderful!
I put Misko's script in my Mint, after a reboot, right after signing in, it started playing the sound again and again, and never quit...the sound I'm using here is a shotgun sound. It was so funny, I felt like being in Ukraine in a battlefield. Tried to reboot 3 times, it happened every time.

Sorry about that, sort of works here. inotifywait had some bug depending on the version.

ToZ's script plays when a singlew file is deleted from trash.
I found this https://www.opensourceforu.com/2011/04/ … h-inotify/
and addapted the code to watch and play mp3 file when the trash is empty.
Uses libao for the audio sink and libmpg123 to play mp3.

Depends:
      libao-dev libmpg123-dev
Compiles with:
      gcc watch-trash.c -o watch-trash -lmpg123 -lao
  run with
      ./watch-trash /path/file.mp3

watch-trash.c

/* 
  watch-trash.c
  play sound when trash is emptied
  Code adapted from https://www.opensourceforu.com/2011/04/getting-started-with-inotify/ 
  Depends:
      libao libmpg123 (development libs)
  Compile with:
      gcc watch-trash.c -o watch-trash -lmpg123 -lao
  Run with:
      ./watch-trash /path/file.mp3
*/

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <limits.h>
#include <unistd.h>
#include <dirent.h>
#include <stdarg.h>
#include <ao/ao.h>
#include <mpg123.h>
#include <sys/file.h>
#include <errno.h>

#define PID_FILE "/tmp/.trashsound.lockfile"
#define BITS 8
#define MAX_EVENTS 1024 /*Max. number of events to process at one go*/
#define LEN_NAME 1024 /*Assuming length of the filename won't exceed 16 bytes*/
#define EVENT_SIZE  ( sizeof (struct inotify_event) ) /*size of one event*/
#define BUF_LEN     ( MAX_EVENTS * ( EVENT_SIZE + LEN_NAME )) /*buffer to store the data of events*/
 
char path[64];

int vspfunc (char *format, ...) {
   va_list aptr;
   int ret;

   va_start (aptr, format);
   ret = vsprintf (path, format, aptr);
   va_end (aptr);

   return (ret);
}

int number_of_files () {
    int file_count = 0;
    struct dirent * entry;
    DIR * dirp;

    dirp = opendir (path);
    
    while ((entry = readdir(dirp)) != NULL) {
        if (entry->d_type == DT_REG) { /* If entry is a regular file */
             file_count++;
        }
    }
    closedir(dirp);

    return file_count;
}

void play_file (char *music) {
    int driver, err;
    ao_device *dev;

    mpg123_handle *han;
    unsigned char *buff;
    size_t buffer_size;
    size_t done;


    ao_sample_format format;
    int channels, encoding;
    long rate;

    ao_initialize();
    driver = ao_default_driver_id();

    mpg123_init();
    han = mpg123_new (NULL, &err);
    buffer_size = mpg123_outblock(han);
    buff = (unsigned char*) malloc(buffer_size * sizeof(unsigned char));

    mpg123_open (han, music);
    mpg123_getformat (han, &rate, &channels, &encoding);

    format.bits = mpg123_encsize (encoding) * BITS;
    format.rate = rate;
    format.channels = channels;
    format.byte_format = AO_FMT_NATIVE;
    format.matrix = 0;
    dev = ao_open_live(driver, &format, NULL);
    while (mpg123_read (han, buff, buffer_size, &done) == MPG123_OK)
        ao_play(dev, buff, done);

    free(buff);
    ao_close(dev);
    mpg123_close(han);
    mpg123_delete(han);
    mpg123_exit();
    ao_shutdown();
}

void get_event (int fd) {
    char buffer[BUF_LEN];
    int length, i = 0;
 
    length = read( fd, buffer, BUF_LEN );  
    if ( length < 0 ) {
        perror( "read" );
    }  
  
    while ( i < length ) {
        struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
        if ( event->len ) {
            if ( event->mask & IN_DELETE) {
                if (event->mask | IN_ISDIR) {
                    printf( "The file %s was deleted with WD %d\n", event->name, event->wd );  
                }    
            }  
            i += EVENT_SIZE + event->len;
        }
    }
}

int main( int argc, char **argv ) {
    int wd, fd, n;
    char * home = getenv("HOME");
    char * trash = "/.local/share/Trash/info";

    if(argc < 2)
        exit(0);

    int pid_file = open (PID_FILE, O_CREAT | O_RDWR, 0644);
    int rc = flock (pid_file, LOCK_EX | LOCK_NB);
    if (rc) {
        if (EWOULDBLOCK == errno) {
           printf ( "App is allready running\n" );  
           return 1;
        }
    }

    vspfunc("%s%s", home, trash);

    fd = inotify_init();
    if ( fd < 0 ) {
        perror( "Couldn't initialize inotify");
    }

    wd = inotify_add_watch(fd, path, IN_DELETE); 
    if (wd == -1) {
        printf("Couldn't add watch to %s\n", path);
    } else {
        printf("Watching:: %s\n", path);
    }
  
    /* do it forever*/
    while(1) {
        get_event(fd);
        n = number_of_files();
        if (n < 1) {
            play_file (argv[1]);
        }
    } 
 
    /* Clean up*/
    inotify_rm_watch( fd, wd );
    close( fd );
    close( pid_file );
    return 0;
}

Maybe the name off the app is bad but it doesn't sound like a machine gun. smile

Edit: now only one instance of app can start

Last edited by Misko_2083 (2022-07-12 12:32:57)


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#63 2022-07-12 22:20:09

agashamu
Member
From: California
Registered: 2021-03-01
Posts: 77

Re: Empty Trash Can Sound[solved]

Thanks Misko_2083 for sharing this. I clicked on that link, and boy, oh boy...codes after codes and more codes. Wish I could understand any of those. I checked out your old posts here, wow, lots of scripts you have created, played with them with ToZ. You guys are great, not only helping out others, but enjoying Linux!! Good for you!!
I also noticed you are from Linux Lite. I love that distro, still running 5.8. Tried 6.0, but for me, the new Ubuntu version screwed it up. Can't install many little things that still running fine in 5.8.
Thank you Sir and have a great evening!


Linux Mint Xfce 20.3

Offline

#64 2022-07-13 22:40:11

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Empty Trash Can Sound[solved]

agashamu wrote:

played with them with ToZ.

OK, it's officially a bromance. big_smile


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#65 2022-07-15 14:49:10

Nili
Member
Registered: 2022-06-29
Posts: 20

Re: Empty Trash Can Sound[solved]

Misko is a genius, wherever he is, just helps and provide code.


Devuan/XFCE

Offline

#66 2022-07-18 08:51:16

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Empty Trash Can Sound[solved]

Nili wrote:

Misko is a genius, wherever he is, just helps and provide code.

Right here Nili, but would never agree with the genius estimation.

Updated the App.
sound-empty-trash is more descriptive name for it I think.

Added some file checks, we want to make sure it's a file, not an executable and that we can read it.
Now it's playing whenever a file(s) is/are moved to or removed from trash.

It's recommended to use a short mp3, not an opera. big_smile
I use this one: https://orangefreesounds.com/empty-trash-sound-effect/ * “Attribution-NonCommercial 4.0 International (CC BY-NC 4.0)”
Usage:
      ./sound-empty-trash /path/to/file.mp3

/* 
  sound-empty-trash.c
  play sound when trash is emptied
  Code adapted from https://www.opensourceforu.com/2011/04/getting-started-with-inotify/ 
  Depends:
      libao libmpg123 (development libs)
  Compile with:
      gcc sound-empty-trash.c -o   sound-empty-trash -lmpg123 -lao
  Run with:
      ./sound-empty-trash /path/file.mp3
*/
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/inotify.h>
#include <limits.h>
#include <unistd.h>
#include <dirent.h>
#include <stdarg.h>
#include <ao/ao.h>
#include <mpg123.h>
#include <sys/file.h>
#include <errno.h>
#include <string.h>

#define PID_FILE "/tmp/.trashsound.lockfile"
#define BITS 8
#define MAX_EVENTS 1024 /*Max. number of events to process at one go*/
#define LEN_NAME 1024 /*Assuming length of the filename won't exceed 16 bytes*/
#define EVENT_SIZE  ( sizeof (struct inotify_event) ) /*size of one event*/
#define BUF_LEN     ( MAX_EVENTS * ( EVENT_SIZE + LEN_NAME )) /*buffer to store the data of events*/
 
char path[64];

int vspfunc (char *format, ...) {
   va_list aptr;
   int ret;

   va_start (aptr, format);
   ret = vsprintf (path, format, aptr);
   va_end (aptr);

   return (ret);
}

int number_of_files () {
    int file_count = 0;
    struct dirent * entry;
    DIR * dirp;

    dirp = opendir (path);
    
    while ((entry = readdir(dirp)) != NULL) {
        if (entry->d_type == DT_REG) { /* If entry is a regular file */
             file_count++;
        }
    }
    closedir(dirp);

    return file_count;
}

void play_file (char *music) {
    int driver, err;
    ao_device *dev;

    mpg123_handle *han;
    unsigned char *buff;
    size_t buffer_size;
    size_t done;
    ao_sample_format format;
    int channels, encoding;
    long rate;

    ao_initialize();
    driver = ao_default_driver_id();

    mpg123_init();
    han = mpg123_new (NULL, &err);
    buffer_size = mpg123_outblock(han);
    buff = (unsigned char*) malloc(buffer_size * sizeof(unsigned char));

    mpg123_open (han, music);
    mpg123_getformat (han, &rate, &channels, &encoding);

    format.bits = mpg123_encsize (encoding) * BITS;
    format.rate = rate;
    format.channels = channels;
    format.byte_format = AO_FMT_NATIVE;
    format.matrix = 0;
    dev = ao_open_live(driver, &format, NULL);
    while (mpg123_read (han, buff, buffer_size, &done) == MPG123_OK)
        ao_play(dev, buff, done);

    free(buff);
    ao_close(dev);
    mpg123_close(han);
    mpg123_delete(han);
    mpg123_exit();
    ao_shutdown();
}

void get_event (int fd) {
    char buffer[BUF_LEN];
    int length, i = 0;
 
    length = read( fd, buffer, BUF_LEN );  
    if ( length < 0 ) {
        perror( "read" );
    }  

    while ( i < length ) {
        struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
        if ( event->len ) {
            if ( event->mask & IN_CREATE) {
                if (event->mask | IN_ISDIR)
                    printf( "The file %s was Created with WD %d\n", event->name, event->wd );       
            }
            if ( event->mask & IN_DELETE) {
                if (event->mask | IN_ISDIR) {
                    printf( "The file %s was deleted with WD %d\n", event->name, event->wd );  
                }    
            }
            i += EVENT_SIZE + event->len;
        }
    }
}

int check_file (char *fPath) {
    char * point;

    if (access(fPath, F_OK) != 0) {
       printf("The file '%s' does not exist\n", fPath);
       return 1;
    }
    if (access(fPath, R_OK )){
       printf("The File '%s' can't be read\n", fPath);
       return 1;
    }
    if (!access(fPath, X_OK )){
       printf("The File '%s' is an Executable\n",fPath);
       return 1;
    }
    if ((point = strrchr(fPath,'.')) != NULL ) {
         if (strcmp(point,".mp3") != 0) {
             printf("Unknown file type %s\n", point);
             return 1;
        }
    }
    return 0;
}

int main( int argc, char **argv ) {
    int wd, fd, n, new;
    char * home = getenv("HOME");
    char * trash = "/.local/share/Trash/info";

    if (argc < 2) {
       printf("Usage:\n\t%s 'file.mp3'", argv[0]);
       return 1;
    }

    int pid_file = open (PID_FILE, O_CREAT | O_RDWR, 0644);
    int rc = flock (pid_file, LOCK_EX | LOCK_NB);
    if (rc) {
        if (EWOULDBLOCK == errno) {
           printf ( "App is allready running\n" );  
           return 1;
        }
    }

    if (check_file(argv[1]))
        return 1;

    vspfunc("%s%s", home, trash);

    fd = inotify_init();
    if ( fd < 0 ) {
        perror( "Couldn't initialize inotify");
        return 1;
    }

    wd = inotify_add_watch(fd, path, IN_CREATE | IN_DELETE); 
    if (wd == -1) {
        printf("Couldn't add watch to %s\n", path);
    } else {
        printf("Watching:: %s\n", path);
    }

    n = number_of_files();
    /* do it forever*/
    while(1) {
        get_event(fd);
        new = number_of_files();
        if (n != new)  {
            play_file (argv[1]);
            printf("Playing\n");
        }
        n = number_of_files();
    } 
 
    /* Clean up*/
    inotify_rm_watch( fd, wd );
    close( fd );
    close( pid_file );
    return 0;
}

Edit: Added a video demo https://www.youtube.com/watch?v=iHMkIrQ76Xw

Last edited by Misko_2083 (2022-07-18 09:07:23)


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#67 2022-07-18 20:06:51

agashamu
Member
From: California
Registered: 2021-03-01
Posts: 77

Re: Empty Trash Can Sound[solved]

This script is quite incredible Misko!

Misko wrote:

but would never agree with the genius estimation

How about: The King of Linux Script Writing


Linux Mint Xfce 20.3

Offline

#68 2022-07-18 21:37:26

Misko_2083
Member
Registered: 2015-10-13
Posts: 191
Website

Re: Empty Trash Can Sound[solved]

agashamu wrote:

This script is quite incredible Misko!

Misko wrote:

but would never agree with the genius estimation

How about: The King of Linux Script Writing

It's actually written in C, and glad you like it.
I'm an ordinary guy occasionally visiting the forums.
ToZ and KBar are a better candidates for that title.


Do you want to exit the Circus?
https://www.youtube.com/watch?v=ZJwQicZHp_c

Offline

#69 2022-07-23 14:23:51

Nili
Member
Registered: 2022-06-29
Posts: 20

Re: Empty Trash Can Sound[solved]

Misko_2083 wrote:

Right here Nili, but would never agree with the genius estimation.

Everytime you post codes or help people, especially those on yad, I have this impression about you.


Devuan/XFCE

Offline

Board footer

Powered by FluxBB