Visualizzazione post con etichetta Debian. Mostra tutti i post
Visualizzazione post con etichetta Debian. Mostra tutti i post

domenica 24 marzo 2019

Liberacus v3.3 - il programma gestionale per sartorie ora è rilasciato anche come pacchetto .deb

Ho rilasciato pochi giorni fa l'ultima versione di Liberacus, la novità più importante è che adesso fornisco un comodo pacchetto precompilato .deb, così che non dovrete più compilarlo dal codice sorgente, ma vi basterà installarlo con il comando dpkg:

>$ sudo dpkg --install liberacus-3.3.deb

Sempre che utilizziate una distribuzione Debian o una delle tante derivate (Ubuntu, Mint, ecc...), altrimenti dovrete compilarlo da voi.

Potete scaricarlo subito da qui.

I pacchetti da cui dipende il programma sono i seguenti:
  • libgtkmm-3.0
  • libxml++2.6
  • libsqlite3-0
Se non li avete già installati dovrete farlo prima di installare Liberacus.

Le novità rispetto alla versione precedente sono le seguenti:
  • aggiunta la possibilità di impostare un sovrapprezzo per lavori urgenti;
  • ridisegnata la pagina iniziale con la lista delle commissioni;
  • migliorata la funzione di importazione dei dati dai file XML delle precedenti versioni del programma;
  • ridisegnata l'interfaccia grafica delle preferenze;
  • le preferenze adesso sono contenute nel database e non sono più salvate sul file XML.
  • corretti diversi bug.

domenica 26 marzo 2017

Multi-threading e interfaccia grafica GTK+

Il multi-threading è la suddivisione di un processo in diversi sotto processi eseguiti in parallelo (o concorrentemente), questo ci permette di eseguire il nostro programma sfruttando la potenza di calcolo di tutti i core presenti nei moderni processori dotati di tecnologia multi-core.

Questa tecnica è molto utile soprattutto per migliorare le prestazioni in presenza di un carico di lavoro pesante, ma è anche utilizzata per preservare la reattività dell'interfaccia grafica in qualsiasi situazione.
Mentre negli anni ottanta era accettabile il fatto di dover attendere davanti al monitor mentre il computer finiva di elaborare l'operazione assegnata, al giorno d'oggi, trovarsi davanti ad un'interfaccia grafica che non risponde a nessun comando ci farebbe subito pensare che il software in esecuzione sia andato in crash o che comunque ci sia un problema.

Quando non è possibile velocizzare un'operazione al punto da renderla quasi istantanea, allora bisogna intrattenere l'utente per ingannare l'attesa. Ad esempio, se l'interfaccia grafica fornisce informazioni sullo stato dell'esecuzione di un'operazione complessa, l'utente attenderà sapendo che il software sta lavorando correttamente.

Iniziamo con il creare una classe che sia in grado di svolgere un compito su un thread separato dal programma principale.



E' una classe molto semplice: ha una variabile membro di tipo double chiamata fraction_done, che ci servirà a simulare l'esecuzione di un lavoro, ed una denominata wrk_mutex, che è di tipo mutex (dall'inglese mutual exclusion, mutua esclusione) fornito dalla standard library per impedire che più thread accedano contemporaneamente agli stessi dati.

Le funzioni membro sono solo due: start_work() che esegue il lavoro e get_fraction_done() che comunica lo stato dell'esecuzione.

All'interno della funzione start_work() troviamo un primo blocco, delimitato dalle parentesi graffe, all'interno del quale si invoca la classe lock_guard, che serve ad acquisire il mutex ed impedire a qualsiasi altro thread in esecuzione di interferire fino alla fine delle parentesi. All'interno di questo blocco protetto, fraction_done è inizializzato con il valore di 0.0.
Successivamente troviamo un loop infinito, all'interno del quale il thread in esecuzione attende 250 millisecondi con la chiamata di funzione sleep_for(), per simulare lo svolgimento di un'operazione complessa.
Quindi c'è un nuovo blocco di codice con una nuova acquisizione del mutex e si incrementa il valore di fraction_done, infine verifica se il lavoro è concluso (al raggiungimento del valore di 1.0) ed esce dal loop.

Ora scriviamo un piccolo programma che utilizza la nostra classe Worker.


Nella funzione main() viene dapprima creata un'istanza della classe Worker, quindi viene creato un nuovo thread che esegue la funzione membro start_work() di Worker. Da questo punto in poi il programma principale è eseguito in modo concorrenziale a start_work(), nel loop infinito all'interno di main() viene richiesto all'istanza di Worker il valore attuale di fraction_done.

Nella funzione get_fraction_done() viene invocata la classe lock_guard per impedire che fraction_done sia modificato mentre se ne comunica il valore.

Quindi viene stampato sul video il valore ottenuto (solo se diverso dall'ultimo ottenuto).
Se il valore ha raggiunto 1.0 allora esce dal loop perché il lavoro è terminato, infine viene invocata la funzione join() per riunire il thread al programma principale prima di rilasciare le risorse allocate e terminare.

Proviamo a compilare ed eseguire


Funziona come volevamo, il thread svolge il suo compito ed il programma principale ci tiene aggiornati sullo stato del lavoro.
Ora proviamo ad applicare la stessa tecnica ad un programma con interfaccia grafica realizzata con la libreria GTK+.

Utilizzerò l'IDE Anjuta per realizzare un nuovo programma GTK+.

Creiamo un nuovo progetto di tipo C++ GTKmm (semplice).
Nelle opzioni del progetto spuntiamo la voce "configura pacchetti esterni"
Spuntiamo il pacchetto pthread-stubs
Dopo aver creato il progetto andiamo a creare l'interfaccia grafica con Glade


Come potete vedere dall'immagine è una finestra con una barra progressiva ed un'etichetta per visualizzare lo stato del lavoro. Subito sotto ci sono i pulsanti per avviare e fermare il thread.

Ora modifichiamo la classe Worker per farla lavorare in un programma dotato di interfaccia grafica.


Analizzando l'header potete vedere l'aggiunta di alcune variabili membro:
- has_stopped - ci servirà per capire se il thread è fermo;
- shall_stop - utilizzato per comunicare al thread l'intenzione di fermarlo;
- caller_notification - questo è un signal che utilizzeremo per comunicare con il programma principale.

Inoltre sono stati aggiunte tre funzioni:
- has_stopped_working() - per sapere se il thread è fermo;
- stop_work() - per fermare il thread;
- signal_caller_notification() - per connettere il signal al nostro programma.

Per finire è stata modificata la funzione start_work(), con l'aggiunta dell'emissione del signal e la possibilità di fermare il lavoro tramite shall_stop.

Ora vediamo il programma principale.


Oltre al file main.cc ho creato una classe Controller che si occupa di gestire l'intera applicazione.
Di solito si trovano esempi o tutorial in C++ che utilizzano GTKmm dove si crea una classe derivata di Gtk::Window e si costruisce l'interfaccia da codice, il mio approccio è differente.
Per prima cosa preferisco creare l'interfaccia grafica con Glade, non vedo il vantaggio di costruirla tramite codice, per quanto riguarda questo pattern, è probabilmente frutto dalle precedenti esperienze di programmazione su OS X con Objective-C.

L'istanza di Controller creata in main() si occupa di recuperare gli elementi dell'interfaccia grafica dal file .ui, quindi in connect_signals() collega i signal dei pulsanti e di due altri oggetti: ctrl_worker e ctrl_dispatcher.
Il primo è un'istanza della classe Worker e collega il suo signal alla funzione on_worker_notification().
Il secondo è un oggetto della classe Gtk::Dispatcher ed è l'elemento fondamentale per garantire il corretto funzionamento del thread di Worker con l'interfaccia del programma principale.
Alla pressione del pulsante start viene creato un thread al quale viene affidata l'esecuzione della funzione start_work() di Worker, il puntatore denominato wrk_thread ne terrà traccia.
Ogni qualvolta il thread emette un signal questo verrà ricevuto dal programma ed eseguirà la funzione on_worker_notification() che, a sua volta, emetterà il signal del nostro ctrl_dispatcher.
Quest'ultimo verrà ricevuto dalla funzione on_dispatcher_notification() che si occuperà di verificare lo stato del thread, aggiornare l'interfaccia grafica ed eliminarlo se fermo.

Questo è il programma perfettamente funzionante.


Provando a non utilizzare l'istanza di Gtk::Dispatcher, collegando il signal di Worker direttamente alla funzione che gestisce il thread ed aggiorna l'interfaccia grafica, finiremmo con un crash dell'applicazione in un momento non precisato dell'esecuzione.


mercoledì 8 marzo 2017

Debian: installazione in modalità UEFI


Gli attuali sistemi basati su firmware UEFI (Unified Extensible Firmware Interface) hanno ormai rimpiazzato i vecchi computer con il BIOS (Basic Input/Output System), utilizzato fin dalla nascita dei primi PC.

Il BIOS ha molte limitazioni dovute alla sua progettazione che risale agli anni ‘80, ma per motivi di retrocompatibilià molte schede madri, oltre al firmware UEFI, supportano il boot in stile BIOS tramite CSM (Compatibility Support Module).

Al giorno d’oggi non c’è alcun motivo per installare Debian in modalità CSM, a meno che non si voglia installarlo in dual boot al fianco di una preesistente vecchia installazione di Windows.


In questa breve guida vedremo come installare Debian in modalità UEFI e come evitare e/o superare eventuali problemi.

Avvio in modalità UEFI

Il primo requisito per poter installare la nostra distribuzione GNU/Linux preferita in modalità UEFI è quello di dover avviare l’immagine disco di installazione da una penna USB in modalità UEFI!

Sembra un’ovvietà, ma spesso questo è il primo errore che si compie. Se il disco di installazione è inavvertitamente avviato tramite CSM, l’installazione proseguirà con la stessa modalità. Visto che sullo stesso sistema non possono convivere due sistemi operativi avviabili in modalità diverse, tanto vale disabilitare il modulo di retro-compatibilità CSM nella configurazione del firmware UEFI e scegliere l’opzione di boot “solo UEFI”.

Tabella delle partizioni GPT

Secondo requisito fondamentale è il partizionamento del disco di destinazione dell’installazione che deve essere di tipo GPT o GUId Partition Table (Globally Unique Identifier) e non il vecchio standard MS-DOS denominato MBR (Master Boot Record).

Proprio come il BIOS, il MBR porta con se molte limitazioni dovute ai limiti hardware del tempo in cui fu progettato, tra le quali la dimensione massima di 2 TB per i dischi di avvio e solo quattro partizioni primarie possibili.

Purtroppo non c’è modo di modificare la tabella delle partizioni durante l’installazione del sistema, quindi dovrete provvedere a preparare il disco di destinazione prima.

Fate attenzione, modificare la tabella delle partizioni comporta la perdita di tutte le partizioni esistenti e quindi di tutti i dati, se avete dati da mettere al sicuro è meglio fare un backup prima di procedere.

Modificare la Tabella delle partizioni con gparted

E’ possibile modificare il partizionamento del disco utilizzando gparted: dopo aver scelto il disco interessato, dal menù Dispositivo selezionare la voce “Crea tabella delle partizioni...” e create una tabella di tipo GPT.

E’ possibile scaricare l’immagine disco live dal sito di Gparted per poterlo avviare tramite una penna USB e preparare il disco interno del vostro PC.


Modificare la Tabella delle partizioni dal Terminale con fdisk


E’ possibile modificare la tabella delle partizioni anche da riga di comando utilizzando fdisk, uno strumento interattivo che permette di gestire le partizioni dei dischi.

La sintassi del comando è molto semplice:


# fdisk /dev/[nome del disco]


Per esempio, se il disco da partizionare è un disco SATA sda1


# fdisk /dev/sda1


Se invece dovete partizionare un moderno SSD M.2 PCIe allora sarà


#fdisk /dev/nvme0n1


Ricordatevi di eseguire questo comando come root.

Una volta invocato, fdisk attenderà i vostri ordini, digitando il carattere m potete visualizzare la lista dei comandi.

Con il carattere g potete creare una nuova tabella delle partizioni GPT vuota.

Completate digitando w per scrivere le modifiche e uscire.

Partizione di boot EFI

Ora che il disco è pronto potete procedere con l'installazione, ma c'è ancora un potenziale problema da sistemare. Quando avete cambiato la tabella delle partizioni avete distrutto tutte le partizioni preesistenti, l'installer di Debian è in grado di creare automaticamente le partizioni necessarie al sistema operativo, ma non si preoccupa di creare la partizione di avvio necessaria per UEFI.

Quindi, quando vi verrà richiesto, scegliete di partizionare manualmente il disco e create una partizione di 200 MB, con filesystem FAT32, punto di mount /boot/efi e spuntate il flag per renderla avviabile.

Ora che avete creato la partizione EFI, potete creare le restanti partizioni da utilizzare con Debian.

Errore nell’installazione del boot loader


Capita a volte che l’installazione del boot loader GRUB 2 fallisca e, dopo la segnalazione dell’errore, ci si ritrova davanti al menù iniziale dell’installer.

Mi sono imbattuto in questo problema durante l’installazione su un SSD con interfaccia M.2 di tipo PCIe, ho risolto nel seguente modo.

Dal menù con l'elenco dei passi dell'installazione selezionate la voce in basso per aprire una shell.

Prima di mostrarvi i comandi vorrei chiarire una cosa, quando aprite una shell dall’installer non avete accesso al sistema che avete installato sul disco, ma siete in un ambiente limitato che risiede in memoria. La root del disco di installazione è montata nella directory target. La prima cosa da fare è creare un collegamento tra le directory di sistema dell’ambiente in memoria e quelle del sistema sul disco, a questo scopo utilizziamo il comando mount con l’opzione bind.


# mount –bind /dev  /target/dev

# mount –bind /dev/pts  /target/dev/pts
# mount –bind /proc  /target/proc

# mount –bind /sys  /target/sys

Ora le directory /dev, /dev/pts, /proc e /sys sono legate a quelle sul disco.

Copiate il file resolv.conf per permettere il collegamento a internet dal sistema sul disco con


# cp /etc/resolv.conf /target/etc


Quindi eseguiamo il comando chroot per poter accedere come utente root al sistema installato sul disco di destinazione.


# chroot /target /bin/bash


Da questo momento in poi state eseguendo dei comandi sul sistema installato, procediamo all’installazione di GRUB.


# aptitude update

# aptitude install grub-efi-amd64
# update-grub

# grub-install –target=x86_64-efi /dev/nvme0n1

Dove nvme0n1 è il disco SSD M.2 PCIe, ma se state installando GRUB su un disco di tipo SATA allora sarà probabilmente sda.


Uscite dalla shell con il comando exit (da eseguire due volte) e scegliete di continuare senza installare GRUB. Vi apparirà un avviso per ricordarvi che senza GRUB il sistema non sarà avviabile, ignoratelo pure e andate avanti fino al riavvio.


Se il problema era causato dal disco SSD M.2 PCIe proseguite con questi passi per evitare di avere problemi di boot al prossimo riavvio, altrimenti fermatevi qui.

Alcuni aggiustamenti per i dischi SSD M.2 PCIe

Una volta riavviato dal sistema installato, aprite il Terminale e aggiungete “nvme” al file /etc/initramfs-tools/modules con


# nano /etc/initramfs-tools/modules


Dopo aver aggiunto una riga con la parola nvme salvate con Ctrl+O e uscite con Ctrl+X.

A questo punto eseguite questo comando:


# update-initramfs -u


Ora modificate il file grub in /etc/default


# nano /etc/default/grub


aggiungete la seguente linea


GRUB_CMDLINE_LINUX="intel_pstate=no_hwp"


Dopo aver salvato eseguite


# update-grub


A questo punto il vostro SSD funzionerà senza problemi.

lunedì 27 febbraio 2017

Custom Arcade Desk: costruire una postazione da sala giochi in puro stile anni '80/'90


In questo post vi parlerò di un progetto che ho realizzato lo scorso anno e che ho battezzato “Custom Arcade Desk”, in pratica si tratta di una scrivania con doppia postazione da gioco per rivivere il fascino delle sale giochi degli anni '80/'90.



Come avrete intuito, se seguite questo blog, il computer al quale ho collegato la postazione da gioco è alimentato da una distribuzione GNU/Linux: Debian 8 (Jessie), recentemente aggiornato a Debian 9 (Stretch).
Comunque è possibile usare qualsiasi altra distribuzione GNU/Linux, incluso Raspbian per Raspberry Pi.

Custom Arcade Desk

Prima di iniziare la carrellata di foto, vediamo la lista dei materiali che ho utilizzato:

- due pannelli in OSB (Oriented Strand Board) da 25 mm di spessore, è un materiale composto da pezzi di legno incollati insieme, in modo simile al truciolato, ma con la caratteristica di essere più resistente;

- un pannello di plexiglas da 3mm di spessore;

- un adesivo permanente polimerico laminato opaco sul quale ho fatto stampare un'illustrazione del gioco Tastunoko vs Capcom;

- una scheda Ultimarc I-PAC 2, è il circuito che si occupa di tradurre i segnali dei pulsanti e del joystick in caratteri e li invia al computer tramite il cavo USB;

- due joystick Sanwa JLF-TP-8YT;

- sedici pulsanti Sanwa OBSF-30 da 30mm di larghezza;

- quattro pulsanti Sanwa OBSF-24 da 24mm di larghezza;

- cavo elettrico mono-polare;

- 20 terminali fastom da 2,8 mm;

- bordo per pannelli preincollato (si applica a caldo con un ferro da stiro);

- flatting per proteggere il legno;

- stucco francese;



Gli utensili necessari per realizzare questo progetto sono:

- un trapano con punte a tazza da 30mm e da 24mm;

- un seghetto alternativo con lame per legno e per metallo;

- una fresatrice per il legno;

- carta vetrata a grana media e fine;

- avvitatore;

- saldatore elettrico;


Una fonte preziosa di informazioni riguardanti i materiali da utilizzare, i diversi costruttori di joystick e pulsanti, nonché i vari schemi di disposizione dei tasti la potete trovare su questo sito.


 Questa era la mia piccola scrivania Ikea modello MICKE che utilizzavo per il computer. Notare come il piano si è era curvato al centro e mostrava segni di cedimento.

L'economica scrivania Ikea MICKE

Ho smontato il piano originale e tolto il cassetto.



Questo è un pannello in OSB da 25 mm, della stessa misura di quello originale, ma il materiale è più pesante e molto più resistente. Ho recuperato e montato gli agganci originali Ikea.

Agganci Ikea montati sul pannello in OSB


Il piano sostitutivo si monta alla perfezione come l'originale


Al posto del cassetto ho montato un altro piano che utilizzo per la tastiera ed il mouse, ho riutilizzato il meccanismo scorrevole per farlo a scomparsa.



Questo è un altro pannello in OSB da 25 mm di spessore, ma di dimensioni maggiori, che estende la scrivania. Sopra c'è un pannello in plexiglas da 3 mm.

Piano superiore con plexiglas e schemi di disposizione dei pulsanti e joystick


Lo schema della disposizione del joystick e dei pulsanti è quello standard utilizzato nelle sale giochi giapponesi.


Di seguito i fori da 30 mm realizzati con una punta a tazza.

Fori da 30mm e catena di fastom per il collegamento a terra dei pulsanti

I due fori da 24 mm per i tasti di servizio, per questi ho utilizzato una mecchia per il legno.

Fori da 24mm e mecchia per legno montata sul trapano

Fori per le due postazioni completati


Fresatura da 3 mm nell'area dove poggia la piastra del joystick.

Fresatura di 3mm di profondità
Il piano delle dimensioni di quello originale è montato su quello superiore di dimensioni maggiori, una fresatura profonda nella parte inferiore della scrivania facilita il montaggio dei pulsanti.

Parte inferiore della scrivania

Dopo aver carteggiato con cura tutta la parte inferiore, ho dato una mano di flatting per proteggere il legno.



Stuccatura del piano per renderlo il più liscio possibile e prepararlo all'applicazione dell'adesivo. Anche sul lato superiore, dopo aver carteggiato, ho passato una mano di flatting.

Il pannello in OSB non è perfettamente liscio e va stuccato

Applicazione del bordo bianco preincollato con il ferro da stiro.

Rifinitura con bordo per pannelli bianco
Questo è il cablaggio completato. Tutti i componenti sono collegati tramite terminali fastom da 2,8 mm, la scheda I-PAC 2 invece è dotata di morsetti a vite.

La scheda I-PAC 2 invia dei caratteri per ogni pulsante premuto o per ciascuna delle 4 direzioni del joystick, proprio come fosse una tastiera, quindi basta un text editor per verificare che tutto funzioni correttamente.

Test di funzionamento con gedit

Applicazione dell'adesivo permanente che ho fatto realizzare su misura, questo adesivo è stato laminato per essere resistente all'usura.

Con l'adesivo applicato l'aspetto è decisamente migliore

Ho montato il plexiglas ed i pulsanti. I joystick sono dei Sanwa con pallina e copri leva in alluminio colorato. I pulsanti sono Sanwa da 30mm e 24mm, la caratteristica forma convessa del tasto li rende ideali per i picchiaduro.

Scrivania completata

Vediamo ora la parte software ed il supporto per Linux.

La scheda I-PAC 2 viene riconosciuta dal sistema immediatamente e senza il bisogno di installare driver.
E'  preimpostata con la mappatura dei tasti del MAME (Multiple Arcade Machine Emulator), ma è possibile rimappare i controlli per mezzo di un apposito programma.
Ultimarc (la casa produttrice, vedi il sito) fornisce il programma per Windows, OS X e indirettamente anche per Linux. La libreria per configurare I-PAC 2 è infatti sviluppata da Katie Snow (vedi il sito) ed è scaricabile dal repository su github (link di github).


Iniziamo con l'installare il MAME inserendo i seguenti comandi come root

# apt update
# apt install mame mame-tools mame-extra

Per poter utilizzare il MAME ovviamente vi occorrono i file di dump delle rom dei videogiochi dell'epoca e questi non sono distribuiti con l'emulatore perché coperti dalle rigide regole del copyright.

Ora scaricate l'ultima versione della libreria Ultimarc dal repository di github (link download), è un archivio tar.gz. Decomprimete l'archivio con il comando:

tar -zxvf nome_file

Attualmente l'ultima versione è la seguente
$ tar -zxvf ultimarc-linux-1.1.update.tar.gz

Ora entrate nella directory con

$ cd ultimarc-linux-1.1

Nel file README ci sono le informazioni per la compilazione della libreria, in particolar modo ci serve sapere quali sono le librerie necessarie e sono le seguenti:

json-c (0.11), su Debian il pacchetto si chiama libjson-c-dev
libusb-dev, su Debian il pacchetto si chiama libusb-1.0-0-dev
libtool

Per finire vi serve il pacchetto build-essential per poter compilare, quindi installate tutto il necessario

# apt install build-essential libjson-c-dev libusb-1.0-0-dev libtool


Un'altra informazione importante che troverete nel file README è la necessità di copiare il file 21-ultimarc.rules nella directory di sistema /etc/udev/rules.d

# cp 21-ultimarc.rules /etc/udev/rules.d
Quindi procedete alla compilazione con
$ ./configure
$ make

Troverete l'eseguibile umtool all'interno della directory src/umtool, si invoca dal terminale e la sintassi è semplice

$ cd src/umtool
 
$ ./umtool ipac2.json

Dove ipac2.json è il nome del file di configurazione della scheda. All'interno della stessa directory ci sono vari file di configurazione di esempio, utilizzate solo i file ipac2 per la vostra scheda I-PAC2 e solo quelli denominati 2015 (la versione 2014 è per le schede più vecchie). Se non trovate i file .json dentro src/umtool allora scaricate da github il file source code e li troverete lì.
Potete aprire il file .json con un text editor e modificare a piacimento la mappatura dei tasti, è un operazione veramente semplice ed intuitiva.

Una volta preparato il file di configurazione basterà invocare il comando umtool per caricarlo sulla scheda. Vi consiglio comunque di conservare sempre una copia del file di configurazione di default.

Buon divertimento!

martedì 21 febbraio 2017

Come creare una RAM disk


Una RAM disk è una porzione della RAM di sistema che viene utilizzata come fosse un disco o un'unità di archiviazione.
Il grande vantaggio è la sua estrema velocità, di molto superiore anche al più veloce SSD in commercio. Il suo punto debole è invece la volatilità dei dati, se il computer si spegne o si riavvia, tutti i file contenuti in essa andranno persi.
Prima di creare una RAM disk, controlliamo la quantità di spazio disponibile in memoria con il comando free. Questo comando mostra il totale della memoria RAM a disposizione, lo spazio attualmente in uso e quello libero. Oltre alla RAM di sistema viene visualizzato anche lo spazio della partizione Swap se presente.

Il comando df invece mostra la quantità di spazio disponibile sulle unità di archiviazione montate.
Sul nostro sistema GNU/Linux abbiamo due diversi tipi di file system da utilizzare come RAM disk:
ramfs è il vecchio tipo di file system in memoria, ormai soppiantato da tmpfs, ed è lo stesso utilizzato da Linux come cache del file system. Ogni volta che avviene l'accesso ad un file sul disco, questo viene memorizzato in una cache in memoria così che, se dopo poco tempo viene richiesto di nuovo, sarà caricato velocemente dalla RAM.
La memoria utilizzata da ramfs è visualizzata dal comando free alla voce cached, mentre non viene visualizzato dal comando df. Inoltre non è possibile sapere la grandezza di ramfs, ne è possibile porre un limite massimo alla sua dimensione. ramfs continuerà a richiedere memoria fin quando il sistema si bloccherà a causa di un errore di out of memory.
tmpfs invece è un file system recente e risolve gran parte dei problemi di ramfs. E' possibile specificare la grandezza massima di tmpfs, se si tenta di occupare uno spazio maggiore otterremo un errore di disco esaurito, proprio come una partizione di un disco. Inoltre è possibile visualizzare tmpfs con il comando df insieme agli altri dischi e sapere quanto spazio c'è a disposizione. Questi vantaggi rendono tmpfs decisamente più gestibile di ramfs, ma c'è un unico lato negativo; se il sistema si trova a corto di RAM, i dati contenuti in tmpfs potrebbero essere scritti sulla partizione di Swap sul disco.

Creiamo una directory che utilizzeremo come punto di mount per la nostra RAM disk.

$ mkdir /mnt/ramdisk

Ora creiamo la RAM disk con il comando mount utilizzando la seguente sintassi:
mount -t [tipo] -o size=[dimensione] [tipo file system] [punto di mount]

Ad esempio creiamo una RAM disk di tipo tmpfs di 512 MB utilizzando come punto di mount la directory ramdisk posta in /mnt

# mount -t tmpfs -o size=512m tmpfs /mnt/ramdisk

Ricordatevi che per usare il comando mount dovete avere i privilegi di amministratore, per farlo potete anteporre “sudo” o utilizzare il comando “su” per eseguire mount come super utente.

Se volete avere una RAM disk sempre disponibile ad ogni avvio del sistema potete aggiungere la sua creazione nel file fstab.

Aprite fstab con l'editor nano (o qualsiasi altro editor di vostro gradimento)

# nano /etc/fstab

Ora aggiungete una riga come questa

tmpfs /mnt/ramdisk tmpfs nodev,nosuid,noexec,nodiratime,size=512M 0 0

Salvate e riavviate e troverete la vostra RAM disk già montata e pronta per l'utilizzo.

Non dimenticate che ogni file al suo interno, al riavvio del sistema, andrà perso!

mercoledì 15 febbraio 2017

Liberacus v3.0 - il programma gestionale per sartorie ha un nuovo database SQLite

Ho rilasciato oggi la versione v3.0 di Liberacus, il software gestionale per sartorie.
La peculiarità di questo aggiornamento è la transizione della gestione dei dati dal formato XML ad un database SQLite 3.



Spendo due parole per spiegare cosa è cambiato per chi non conosce SQLite ed i database in generale.



Prima Liberacus caricava interamente i dati da alcuni file XML, lavorava sugli stessi mantenendoli in memoria per poi salvarli sul disco.
Questo metodo può essere valido per un piccolo numero di dati e comporta comunque il rischio di perdere i dati in memoria se qualcosa va storto, come ad esempio un blackout improvviso.
Un altro problema di questo approccio è che se il numero dei dati diventa elevato, il tempo di caricamento dai file e di salvataggio su disco diventa elevato.

Ora, utilizzando il database SQLite, Liberacus non ha più bisogno di caricare tutti i dati in memoria, ma prenderà dal database, di volta in volta, solo quelli che gli serviranno al momento.
Ad ogni modifica o inserimento di nuovi dati, questi verranno salvati direttamente sul database nel disco. Il rischio di perdere i dati a causa di un blackout è estremamente ridotto.
I tempi di caricamento e salvataggio sono praticamente azzerati anche in presenza di un numero elevato di dati.

Liberacus è un software libero ed open source, siete liberi di scaricarlo, installarlo ed utilizzarlo a piacimento.
Vi ricordo che Liberacus è sviluppato per girare su qualsiasi distribuzione GNU/Linux, non è multi-piattaforma, quindi non chiedetemi come installarlo su Windows o su Mac.

Potete scaricare l'ultima versione da questo link.

giovedì 22 dicembre 2016

Iniziare a programmare con SDL 2 su Linux - parte 2


Nella prima parte di questo tutorial abbiamo visto come installare tutti gli strumenti di sviluppo e abbiamo creato il nostro primo programma sfruttando la libreria SDL 2. In questa seconda parte approfondiremo meglio l'utilizzo di g++ e valgrind, inoltre miglioreremo il nostro SDL Hello World.

Per tutti coloro che sono nuovi utenti del mondo Linux o che comunque non hanno esperienza nell'invocazione del compilatore g++ ho pensato di fare un po' di chiarezza sulla sintassi di questo comando.

La sintassi più semplice è
$ g++ [file sorgente]

L'eseguibile avrà il nome di default a.out.
Per specificare il nome dell'eseguibile basta aggiungere l'opzione -o [nome eseguibile], quindi
$ g++ [file sorgente] -o [nome eseguibile]

Se ci sono più file sorgenti basta elencarli
$ g++ [file sorgente 1] [file sorgente 2] -o [nome eseguibile]

Per finire, se dobbiamo utilizzare una libreria, come SDL 2 nel nostro caso, dobbiamo comunicarlo al linker tramite l'opzione -l (elle minuscola) seguita dal nome della libreria senza spazi.
$ g++ [file sorgenti] -o [nome eseguibile] -l[nome libreria]

Per la libreria SDL 2 scriveremo -lSDL2

Bene, questo è quanto abbiamo visto finora nella prima parte del tutorial, ma avrete notato che, quando la lista dei file sorgente aumenta, invocare g++ diventa decisamente scomodo.
Per semplificare il tutto possiamo utilizzare il comando make.

Il funzionamento di make è molto semplice, dobbiamo creare un file di testo dove forniremo tutte le informazioni necessarie per la compilazione, quali il compilatore da invocare, la lista dei file sorgente, le opzioni da passare al compilatore, ecc...
Una volta preparato il file chiamato Makefile, basterà invocare make e questo invocherà g++ per noi.
Questo è un esempio di Makefile per compilare il nostro SDL Hello World


Il contenuto del Makefile è abbastanza semplice da capire, man mano che aggiungiamo un file sorgente o un file header basterà aggiungerlo alla lista nel Makefile. Possiamo apportare tutte le modifiche che vogliamo nel Makefile e basterà invocare il comando make per compilare ed ottenere il file eseguibile.
Oltre a questo make si occupa di verificare se dall'ultima compilazione è cambiato qualcosa nei file sorgente, se nulla è cambiato ci verrà notificato.
Copiate ed incollate il testo in un file e salvatelo con il nome Makefile nella stessa directory dei file sorgente. Ora provate ad eseguire il comando
$ make

Decisamente più comodo, non è vero?



Passiamo ad un altro argomento: valgrind.
La scorsa volta avevamo installato valgrind in quanto ottimo strumento di debugging, in particolare per gli errori nella gestione delle allocazioni di memoria. La sintassi è semplice
$ valgrind ./[nome eseguibile]

L'eseguibile verrà avviato all'interno dell'ambiente di debugging di valgrind, il quale analizzerà tutte le allocazioni di memoria e le relative de-allocazioni delle stesse. Al termine del programma verrà stampato sul terminale un resoconto completo con un elenco degli eventuali errori rilevati.

Proviamolo con il nostro SDL Hello World
$ valgrind ./sdl_helloworld

L'esecuzione risulterà più lenta e alla fine avremo sul terminale un resoconto dettagliato.
Senza entrare troppo nei particolari, quello che ci interessa più di tutto il resto è l'ultima riga:
ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 6 from 2)

Nella sezione LEAK SUMMARY potete trovare altri dettagli sulle allocazioni di memoria.
E' ovvio che non è solo il vostro codice che viene analizzato, ma anche quello delle librerie utilizzate, quindi alcuni memory leaks possono essere causati da quest'ultime.

Bene, torniamo all'argomento principale di questo tutorial, SDL 2.
Nello scorso esempio abbiamo utilizzato la funzione SDL_loadBMP(), che carica un'immagine di tipo BMP (Windows bitmap) in un oggetto SDL_Surface.
Per quanto questa funzione sia molto comoda e semplice da utilizzare, il formato BMP è piuttosto limitato e scarsamente utilizzato al giorno d'oggi.
Nella libreria principale di SDL 2 non ci sono altre funzioni per caricare immagini di tipo diverse, quali ad esempio PNG o JPG, ma fortunatamente c'è un'altra libreria dedicata a questo scopo: SDL_image.

Prima cosa da fare è installare sul nostro sistema questa libreria.
$ su
(verrà richiesta la password di root)
# apt install libsdl2-image-dev



Ora che abbiamo installato SDL_image possiamo modificare il programma per aprire un'immagine di tipo PNG.

Aggiungiamo l'include con il file header di questa libreria in helloengine.h
#include <SDL2/SDL_image.h>

Come la libreria SDL 2 anche questa va inizializzata, quindi nella funzione init() della classe HelloEngine (helloengine.cc) aggiungiamo queste righe di codice per inizializzare SDL_image per il caricamento di immagini PNG, subito sotto l'inizializzazione di SDL 2.

// inizializzazione SDL_image per i file di tipo PNG
if ((IMG_Init(IMG_INIT_PNG) & IMG_INIT_PNG) != IMG_INIT_PNG)
{
    on_SDL_error(std::cout, "IMG_Init");
    return false;
}

Ora andiamo a modificare la parte di codice che carica l'immagine, è sempre nella funzione init() poco più in basso. Utilizzeremo la funzione IMG_LoadTexture() che ci restituisce direttamente un puntatore ad un oggetto di tipo SDL_Texture, quindi non avremo bisogno di crearla passando per un SDL_Surface.

// carica l'immagine in texture
std::string name = "helloworld.png";
if ((texture = IMG_LoadTexture(renderer, name.c_str())) == nullptr)
    on_SDL_error(std::cout, "IMG_LoadTexture");

Potete convertire l'immagine BMP in una di tipo PNG utilizzando Gimp e salvatela con il nome helloworld.png.

Prima di compilare ricordatevi che stiamo utilizzando un'altra libreria, quindi dovremo modificare il nostro Makefile aggiungendo -lSDL2_image alla lista delle librerie da linkare, subito dopo -lSDL2.

Terminate le modifiche questo è quello che dovreste ottenere
Compilate con
$ make

Ed ora avviate il programma
$ -/sdl_helloworld

Se non avete fatto errori il programma funzionerà come prima.
Bene, in questa seconda parte del tutorial dedicato ad SDL 2 abbiamo preso maggior confidenza con gli strumenti di sviluppo e debugging, inoltre abbiamo visto come usare la libreria SDL_image.
Nel prossimo tutorial faremo ulteriori modifiche e vedremo come funziona la gestione degli eventi.

martedì 20 dicembre 2016

Iniziare a programmare con SDL 2 su Linux


SDL (Simple DirectMedia Layer) è una libreria di sviluppo multi-piattaforma, scritta in linguaggio C, progettata per controllare facilmente video, grafica, audio, tastiera, mouse, joystick, ecc...
Queste capacità la rendono ideale per lo sviluppo di videogiochi, applicazioni multimediali ed emulatori.
Un grande vantaggio è il fatto di essere multi-piattaforma, questo infatti semplifica il porting sulle diverse piattaforme supportate (Linux, OS X, Windows, iOS e Android).
SDL 2.0 è rilasciata con licenza Zlib, che è una licenza per software libero ed è compatibile con la licenza GPL.

Vediamo subito come preparare il nostro sistema con tutti gli strumenti necessari per iniziare a programmare.
In questo tutorial utilizzerò Debian GNU/Linux 8.6 con il desktop manager di default GNOME.
Probabilmente già saprete che Debian è una distribuzione GNU/Linux universale ed è la base di molte altre distribuzioni derivate, tra le quali Ubuntu. Utilizzare Debian in questo tutorial mi permette di abbracciare una grossa fetta di utenti Linux.

La prima cosa di cui abbiamo bisogno sono gli strumenti di sviluppo fondamentali, quali il compilatore, il linker ed un debugger.
Il pacchetto build-essential ci fornirà tutta la suite di programmi utili allo sviluppo.

$ su
vi verrà chiesta la password di root.
Controlliamo se ci sono aggiornamenti del sistema disponibili con
# apt update
Se trovati procediamo con l'aggiornamento con
# apt upgrade

Quindi installiamo build-essential
# apt install build-essential


Analizzando la lista dei pacchetti installati, forse avrete notato che gdb (il debugger GNU) è nella lista dei pacchetti consigliati, ma non è stato installato. Possiamo installarlo manualmente con
# apt install gdb
Oppure verrà installato automaticamente quando andremo ad installare Valgrind.
Valgrind è un ottimo software di debug e profiling che, tra le altre cose, permette di scovare gli errori nella gestione della memoria, come ad esempio i memory leaks, ossia le allocazioni di memoria che non vengono liberate al termine del loro utilizzo.
# apt install valgrind


Ora che abbiamo gli strumenti fondamentali per lo sviluppo, possiamo installare la libreria SDL 2.0.

# apt install libsdl2-dev


Il pacchetto libsdl2-dev contiene la libreria SDL 2.0 e tutti i componenti fondamentali per sviluppare applicazioni con SDL, ma se provate a cercare i pacchetti libsdl2 disponibili troverete altri componenti che ne espandono le funzionalità.
# apt search libsdl2


Analizzeremo ed installeremo gli altri pacchetti nel prossimo tutorial, quando ci serviranno, per il momento iniziamo a fare un piccolo test di compilazione per verificare che tutte le operazioni di preparazione siano andate a buon fine.

Per questo tutorial utilizzerò gedit, l'editor di testo del desktop GNOME, semplice e leggero, sicuramente adatto per scrivere/modificare file di codice sorgente di piccole dimensioni.
Nonostante la sua estrema semplicità, con qualche piccolo accorgimento possiamo renderlo un discreto strumento di sviluppo.
Dopo aver lanciato gedit, clicchiamo sul menù dell'applicazione sulla barra dello schermo in alto accanto ad Attività, e selezioniamo la voce Preferenze. Comparirà una finestra con diverse opzioni divise per categorie, clicchiamo su Editor e modifichiamo l'ampiezza di tabulazione da 8 a 4. Personalmente trovo che 8 spazi siano decisamente troppi, ma siete liberi di impostare il numero di spazi che più vi aggrada.

Preferenze di gedit
Ora cliccate su Plugin e scorrete la lista in basso fino a trovare e spuntare l'opzione Terminale integrato. Questo ci permetterà di avere un Terminale nella parte bassa della finestra di gedit, evitando di dover passare da una finestra ad un'altra quando dobbiamo compilare o effettuare operazioni di debugging.


Adesso clicchiamo sull'icona menù, posta sulla finestra di gedit accanto al tasto x di chiusura, selezioniamo Vista e spuntiamo le voci Riquadro laterale e Riquadro inferiore.



Queste faranno visualizzare un riquadro laterale con la lista dei file aperti ed un riquadro inferiore con il Terminale integrato.
Per finire, nella barra di stato di gedit, cliccate su Testo semplice per far comparire un menù e selezionate C++ per usufruire della colorazione automatica del testo per la sintassi del linguaggio di programmazione che andremo ad utilizzare nel tutorial.


Al termine di queste personalizzazioni, gedit ha un aspetto decisamente più orientato alla programmazione e meno minimalista.

Facciamo un test veloce per verificare che tutto funzioni regolarmente, scriveremo il classico Hello World e proveremo a compilarlo.

E' indispensabile avere una conoscenza minima del linguaggio C++, altrimenti vi consiglio di andare a consultare un manuale o un tutorial specifico.
Salvate il file in Documenti con il nome helloworld.cc, quindi dal Terminale integrato di gedit, andate in Documenti e provate a compilare il vostro programma.

$ g++ helloworld.cc -o helloworld

Se non avete fatto errori la compilazione andrà a buon fine e potrete eseguire helloworld

$ ./helloworld
Hello World!

A questo punto facciamo un altro test, un nuovo Hello World, ma questa volta utilizzando SDL 2.
Andremo a creare una classe chiamata HelloEngine che sarà il motore della nostra applicazione, mentre nel file principale, chiamato sdl_helloworld.cc ci sarà la funzione main() che si occuperà di creare un'istanza di HelloEngine ed avviarne l'esecuzione.
E' una struttura simile a quello che si utilizza per lo sviluppo di un videogioco, in questo caso è molto semplificata in quanto non ha un loop e non gestisce alcun evento. Questo programma si limiterà ad aprire una finestra e visualizzare il messaggio Hello World, dopo 2 secondi d'attesa chiude la finestra e termina.

Questi sono i tre file del nostro SDL Hello World.

Iniziamo ad esaminare il file header della classe HelloEngine, all'inizio del file andiamo ad includere iostream e SDL2/SDL.h.
Il secondo è ovviamente indispensabile per utilizzare la libreria SDL2, mentre il primo è necessario quando andiamo a stampare gli eventuali messaggi d'errore tramite std::ostream.

Le funzioni membro sono solo 4:
- init() si occupa di inizializzare HelloEngine;
- start() avvia l'esecuzione;
- render() disegna l'immagine caricata nella finestra;
- on_SDL_error() stampa il messaggio d'errore sullo std::ostream indicato.

Per il resto il file header è piuttosto semplice, andiamo a vedere come queste 4 funzioni sono implementate in helloengine.cc.

Init() è la funzione che inizializza l'ambiente SDL invocando SDL_Init(), prima di poter utilizzare qualsiasi funzione della libreria SDL2 dobbiamo inizializzarla con questa funzione. Successivamente viene creata una finestra con SDL_CreateWindow(), quindi viene creata un'istanza di SDL_Renderer che ci servirà per tutte le operazioni grafiche.
Per finire viene caricata un'immagine BMP ottenendo un oggetto SDL_Surface con il quale viene creato un oggetto SDL_Texture.
Dopo aver ottenuto la nostra texture, viene distrutto l'oggetto SDL_Surface con la funzione SDL_FreeSurface() liberando la memoria allocata.

render() è incaricata di disegnare sulla finestra.
SDL_RenderClear() cancella il contenuto di renderer, SDL_RenderCopy() disegna la texture ottenuta dal caricamento dell'immagine su renderer, infine con SDL_RenderPresent() viene visualizzato il contenuto di renderer sulla finestra.

Start() avvia l'esecuzione vera e proprio di HelloEngine, inizialmente invoca init() per effettuare tutte le inizializzazioni, quindi esegue la funzione render() per disegnare sulla finestra. SDL_Delay() attende per il numero di millesecondi indicato, nel nostro caso attende 2 secondi e quindi esce con valore 0 per indicare che non ci sono stati errori.

on_SDL_error() stampa un messaggio d'errore sullo std::ostream indicato, di fatto è sempre std::cout.

Infine è bene soffermarsi sul distruttore della classe HelloEngine, che si occupa di de-allocare tutta la memoria utilizzata dal programma.
SDL2 ha una funzione specifica per ogni tipo di oggetto da de-allocare, non possiamo utilizzare il semplice delete. Abbiamo visto in init() la funzione SDL_FreeSurface() per distruggere l'SDL_Surface, qui utilizziamo SDL_DestroyTexture per l'SDL_Texture, SDL_DestroyRenderer per l'SDL_Renderer e SDL_Quit per chiudere l'intero ambiente SDL.

Il file sdl_helloworld.cc contiene la funzione main() del programma, il funzionamento è estremamente semplice, crea un'istanza di HelloEngine e ne invoca l'esecuzione con start(). Al termine dell'esecuzione distrugge l'istanza con il delete ed esce con lo stesso codice d'uscita dell'istanza.


Andiamo a compilare SDL Hello World con

$ g++ -std=c++11 helloengine.h helloengine.cc sdl_helloworld.cc -o sdl_helloworld -lSDL2


Prima di eseguire ricordatevi di mettere l'immagine helloworld.bmp nella stessa directory dell'eseguibile, altrimenti verrà visualizzata una finestra completamente nera.


Immagine BMP utilizzata per questo test


L'immagine verrà salvata come JPG, potete esportarla in formato BMP utilizzando Gimp oppure ne potete creare una voi. Ricordatevi che per poter essere caricata correttamente da SDL_LoadBMP() l'immagine deve avere un unico livello.
 
$ ./sdl_helloworld


SDL Hello World in esecuzione

In questo tutorial abbiamo installato gli strumenti di sviluppo e la libreria SDL 2 sul nostro sistema ed abbiamo visto un primo esempio di applicazione sviluppata con questa libreria.
Nel prossimo tutorial vedremo come caricare immagini di altri formati, gestire eventi come la pressione di un tasto o il click del mouse ed altro ancora.