lunedì 10 dicembre 2012

Programmare con Clutter (versione 1.12.2): Timeline e animazioni. Tutorial parte 2


Proseguiamo con la seconda parte del tutorial sulla programmazione con Clutter. Nella prima parte avevamo creato un programma che si limitava a disegnare un quadrato verde su sfondo nero, questa volta aggiungeremo un po di movimento!


Creiamo un'istanze della classe ClutterTimeline

Faremo in modo che il nostro “attore” ruoti sull'asse z (l'asse della profondità, quella retta passante per il vostro occhio che va dritta dentro lo schermo).

Per ottenere questa animazione utilizzeremo una nuova classe: ClutterTimeline.
Un timeline non è altro che un cronometro che chiama una funzione (generalmente chiamata call-back function) ogni n millisecondi.

Per prima cosa creiamo un timeline ed avviamo il cronometro, aggiungiamo queste righe prima di clutter_actor_show(stage);


ClutterTimeline *timeline_rotation = clutter_timeline_new(500);
g_signal_connect(timeline_rotation, "new-frame", G_CALLBACK(on_timeline_rotation_new_frame), rect);
clutter_timeline_set_repeat_count (timeline_rotation, -1);
clutter_timeline_start(timeline_rotation);

Prima di proseguire guardiamo insieme il codice che abbiamo aggiunto:


  • clutter_timeline_new() crea l'istanza della classe  ClutterTimeline, timeline_rotation è il suo puntatore. 500 è un valore in millisecondi, il nostro cronometro chiamerà la funzione di ritorno (call-back function) dopo mezzo secondo.
  • g_signal_connect() collega la funzione di ritorno al nostro cronometro, vediamo i parametri passati: timeline_rotation è il puntatore al nostro timeline, “new-frame” è una stringa che definisce il tipo di funzione di ritorno, in questo caso è una funzione che disegna il nuovo frame dell'animazione. G_CALLBACK(on_timeline_rotation_new_frame) è la nostra funzione di ritorno, in realtà non l'abbiamo ancora definita, ma lo faremo tra poco. L'ultimo parametro è un puntatore a qualsiasi tipo di dato che vorremmo passare alla nostra funzione di ritorno, in questo caso passiamo il puntatore al nostro attore, rect.
  • clutter_timeline_set_repeat_count () imposta le volte che il cronometro deve ripetersi, passando -1 si ripeterà all'infinito;
  • clutter_timeline_start() avvia il cronometro e quindi la nostra animazione.

All'uscita del programma ci dobbiamo ricordare di liberare le risorse allocate dalla nostra timeline, aggiungiamo questa riga prima di return error;


g_object_unref (timeline_rotation);


Definiamo la funzione di ritorno del nostro timeline

Se provassimo a compilare adesso riceveremmo un errore che ci segnala che la nostra funzione di ritorno  on_timeline_rotation_new_frame non è stata definita, quindi mettiamoci al lavoro.


L'idea è quella di incrementare di n gradi la rotazione del nostro attore ad ogni chiamata di ritorno del cronometro, per farlo avremo bisogno di una variabile globale che contenga il valore di rotazione applicata al nostro attore.

Aggiungiamo quindi subito dopo #include <clutter/clutter.h>


gdouble rotation = 0;

Partiamo quindi da una rotazione di 0 gradi. Aggiungiamo di seguito la definizione della funzione di ritorno:


void on_timeline_rotation_new_frame(ClutterTimeline *timeline, gint frame_num, ClutterActor* actor)
{
    rotation += 0.5;
    clutter_actor_set_rotation_angle(actor, CLUTTER_Z_AXIS, rotation);
}

Vediamo subito i parametri ricevuti dalla funzione:


  • timeline è il puntatore al cronometro che ha chiamato la funzione;
  • frame_num è il numero del frame. Noi non utilizzeremo questo valore, ma c'è perché è previsto nelle funzioni di ritorno di tipo “new-frame”;
  • actor è il nostro attore, questo parametro lo abbiamo aggiunto noi per ottenere il nostro scopo, cioè quello di applicare la rotazione.

Al suo interno la nostra funzione è piuttosto semplice, dapprima incrementa di 0.5 il valore di rotazione, quindi applica la rotazione con la funzione clutter_actor_set_rotation_angle(), alla quale passiamo il puntatore all'attore, l'asse sul quale viene applicata la rotazione e la variabile con il valore della rotazione.

Adesso possiamo compilare ed avviare il nostro programma per vedere quel bel quadrato verde ruotare sull'asse Z.


Avrete sicuramente notato che la rotazione avviene sul vertice in alto a sinistra del quadrato e non al centro. Questo avviene perché il vertice in alto a sinistra è il punto di riferimento di default per tutte le trasformazioni applicate all'attore.

Aggiungiamo un'istruzione che modifica il punto di riferimento del nostro attore subito prima di aggiungerlo allo stage:


clutter_actor_set_pivot_point (rect, 0.5, 0.5);

I due valori 0.5 sono riferiti rispettivamente all'asse X e a quello Y. Per quanto riguarda l'asse X, 0 corrisponde al vertice sinistro (default) e 1 è quello destro, 0.5 indica quindi al centro. Sull'asse Y, 0 è il vertice in alto (default), 1 è quello in basso, 0.5 è il centro.


Compiliamo ed avviamo il programma, il nostro quadrato verde adesso ruota correttamente.


Il programma completo fin qui dovrebbe avere questo aspetto:


#include <stdio.h>
#include <stdlib.h>
#include <clutter/clutter.h>
gdouble rotation = 0;
void on_timeline_rotation_new_frame(ClutterTimeline *timeline, gint frame_num, ClutterActor* actor)
{
    rotation += 0.5;
    clutter_actor_set_rotation_angle(actor, CLUTTER_Z_AXIS, rotation);
}
int main(int argc, char *argv[])
{
    ClutterInitError error = clutter_init(&argc, &argv);
    ClutterColor stage_color = { 0, 0, 0, 255 };
    ClutterActor *stage = clutter_stage_new(); clutter_actor_set_size(stage, 512, 512);
    clutter_actor_set_background_color(stage, &stage_color);
    ClutterColor actor_color = { 0, 255, 0, 128 };
    ClutterActor *rect = clutter_actor_new();
    clutter_actor_set_background_color(rect, &actor_color);
    clutter_actor_set_size(rect, 100, 100);
    clutter_actor_set_position(rect, 100, 100);
    clutter_actor_set_pivot_point (rect, 0.5, 0.5);
    clutter_actor_add_child(stage, rect);
    ClutterTimeline *timeline_rotation = clutter_timeline_new(500);
    g_signal_connect(timeline_rotation, "new-frame", G_CALLBACK(on_timeline_rotation_new_frame), rect);
    clutter_timeline_set_repeat_count (timeline_rotation, -1);
    clutter_timeline_start(timeline_rotation);
    clutter_actor_show(stage);
    g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);
    clutter_main();
    g_object_unref(timeline_rotation);
    return error;
}

Per poter introdurre l'utilizzo della classe ClutterTimeline abbiamo utilizzato una funzione di ritorno per creare l'animazione del nostro attore, ma in realtà, per ottenere questo tipo di animazioni, possiamo utilizzare le proprietà animabili della classe ClutterActor o la classe ClutterTransition. Non allarmatevi, non stiamo complicando le cose ma vedremo come può essere facile creare delle animazioni anche complesse con poche righe di codice.

Ci sono sostanzialmente due modi per definire l'animazione di un attore: utilizzare l'animazione implicita della classe ClutterActor o definire un'animazione in modo esplicito tramite la classe ClutterTransition. Iniziamo con il primo modo.



Animazione implicita della classe ClutterActor

Per sperimentare le funzioni di animazione integrate nella classe ClutterActor dobbiamo smantellare tutto quello che abbiamo fatto finora, cioè possiamo eliminare il timeline e la funzione di ritorno. Eliminiamo anche la variabile globale rotation e aggiungiamo queste righe di codice subito dopo clutter_actor_add_child(stage, rect);


clutter_actor_save_easing_state (rect);
clutter_actor_set_easing_delay (rect, 500);
clutter_actor_set_easing_duration (rect, 500);
clutter_actor_set_rotation_angle (rect, CLUTTER_Z_AXIS, 360.0);
clutter_actor_restore_easing_state (rect);

Provate a compilare ed eseguire il programma, vedrete il quadrato ruotare e quindi fermarsi definitivamente. Adesso guardiamo il codice che abbiamo aggiunto:


  • clutter_actor_save_easing_state() è la prima funzione che va chiamata per definire l'animazione implicita dell'attore, salva il così detto easing state;
  • clutter_actor_set_easing_delay() imposta un ritardo espresso in millisecondi prima di iniziare l'animazione, nel nostro caso è di mezzo secondo;
  • clutter_actor_set_easing_duration() imposta la durata dell'animazione, cioè quanti millisecondi impiegherà il nostro attore per portare a termine l'animazione che gli abbiamo assegnato. Ancora una volta abbiamo immesso un valore corrispondente a mezzo secondo;
  • clutter_actor_set_rotation_angle(), questa funzione ruota l'attore rect sull'asse Z di 360 gradi, cioè un giro completo;
  • clutter_actor_restore_easing_state() è la funzione che chiude la definizione dell'animazione implicita e l'avvia.

Ricapitolando abbiamo detto al nostro attore di aspettare mezzo secondo prima di iniziare a muoversi, quindi di ruotare di 360 gradi sull'asse Z e di farlo con la velocità necessaria per impiegare mezzo secondo per concludere la rotazione.

I parametri animabili di un attore sono molteplici, ad esempio le sue coordinate, la rotazione sugli assi, la trasparenza, ecc... L'animazione implicita è molto semplice da utilizzare e conveniente per animazioni semplici, ma non ci permette di definire animazioni che si ripetono all'infinito.

Per ottenere animazioni più complesse o infinite come quella che avevamo ottenuto inizialmente con l'utilizzo di ClutterTimeline è necessario utilizzare l'animazione esplicita.


Animazione esplicita con la classe ClutterTransition

Ancora una volta dobbiamo fare un passo indietro, rimuovete il codice che definiva l'animazione implicita che avevamo aggiunto precedentemente e sostituitelo con questo:



ClutterTransition *transition = clutter_property_transition_new ("rotation-angle-z");
clutter_transition_set_from (transition, G_TYPE_DOUBLE, 0.0);
clutter_transition_set_to (transition, G_TYPE_DOUBLE, 360.0);
clutter_timeline_set_duration (CLUTTER_TIMELINE (transition), 500);
clutter_timeline_set_repeat_count (CLUTTER_TIMELINE (transition), -1);
clutter_actor_add_transition (rect, "centrifuga", transition);

Compilate ed eseguite il programma, il nostro quadrato ruota velocemente senza fermarsi! Vediamo che cosa abbiamo fatto nel dettaglio:

  • clutter_property_transition_new() crea un'istanza della classe ClutterTransition, il parametro “rotation_angle_z” definisce il tipo di animazione come rotazione sull'asse Z;
  • clutter_transition_set_from() imposta il valore di partenza dell'animazione, nel nostro caso la rotazione usa valori di tipo double ed il valore di partenza è 0;
  • clutter_transition_set_to() imposta invece il valore finale, 360 gradi è un giro completo;
  • clutter_timeline_set_duration() imposta la durata dell'animazione, intesa come velocità d'esecuzione. Notare che questa funzione fa parte della classe ClutterTimeline, ma noi gli passiamo il puntatore della nostra istanza di ClutterTransition utilizzando la macro per il cast CLUTTER_TIMELINE(). In poche parole gli diciamo di prendere il puntatore come fosse di tipo ClutterTimeline;
  • clutter_timeline_set_repeat_count() è la stessa identica funzione che abbiamo utilizzato con il nostro timeline all'inizio del tutorial, imposta ad infinito il numero di ripetizioni dell'animazione;
  • clutter_actor_add_transition() aggiunge l'animazione all'attore, da questo momento verrà avviata. “centrifuga” è il nome che abbiamo dato a questa animazione per identificarla, un attore infatti può contenere più animazioni definite con la classe ClutterTransition, aggiungendo più animazioni semplici otterremo animazioni complesse.

Con questo concludo la seconda parte del tutorial e mi impegno ad approfondire ulteriormente gli altri aspetti di Clutter nel prossimo tutorial.

Vi consiglio sempre di andare a guardare sulla guida di riferimento la sintassi completa delle istruzioni che abbiamo fin qui utilizzato. Utilizzate DevHelp o andate sul sito per farlo.


Per domande, suggerimenti, o segnalazioni di errori vi invito a lasciare dei commenti.


mercoledì 28 novembre 2012

Programmare con Clutter (versione 1.12.2): creare un'applicazione. Tutorial parte 1


Clutter è un libreria grafica open source che serve principalmente a creare interfacce grafiche basate su OpenGL ed in grado di sfruttare l'accelerazione della GPU. Con Clutter possiamo creare interfacce animate e gestire gli eventi di input dell'utente.
La libreria è multi piattaforma (X11, Darwin e Win32), è scritta in C ed offre anche la possibilità di utilizzarla attraverso altri linguaggi di programmazione.

Questo tutorial ha lo scopo di illustrare degli esempi pratici per imparare a sviluppare programmi con Clutter aggiornato all'ultima versione, la 1.12.2.
Mi sono avvicinato a questa libreria da poco tempo per creare una piccola applicazione per bambini, ed è stato difficile trovare su internet dei tutorial aggiornati all'ultima versione.
Visto che ci sono molte classi e funzioni deprecate dalle precedenti versioni, ecco una guida che va a colmare questa lacuna!

Per questo tutorial utilizzerò il linguaggio C (visto che sembra non sia ancora pronto il binding in C++) .

Prepariamo gli strumenti necessari per iniziare

Queste istruzioni si riferiscono ad Ubuntu (sto utilizzando la 12.10), per la preparazione degli strumenti di sviluppo su altri sistemi vi consiglio di consultare la documentazione sul sito ufficiale.

Il primo passo per iniziare a programmare e' installare gli strumenti di sviluppo sulla nostra macchina. Aprite Ubuntu Software Center, cliccate sul campo di ricerca in alto a destra e digitate “anjuta”, quindi selezionate Anjuta e cliccate su “Installa”.

Anjuta e' un ambiente di sviluppo integrato, cioè un software che aiuta i programmatori nello sviluppo del codice. In particolare e' rivolto allo sviluppo di applicazioni in ambiente GNOME.

Adesso vi serve la libreria Clutter, pulite il campo di ricerca di Ubuntu Software Center e digitate “libclutter dev”. Selezionate “OpenGL based interactive canvas library (development files)”, il nome del pacchetto è “libclutter-1.0-dev”, quindi cliccate su “ulteriori informazioni”. Quindi spuntate il componente aggiuntivo “OpenGL based interactive canvas library (documentation)“ e cliccate su Installa.

Ultimo strumento fondamentale è DevHelp, che vi permetterà di consultare la guida di riferimento di Clutter, cercate “devhelp” su Ubuntu Software Center ed installatelo, ora siete pronti all'azione.

Creiamo un nuovo progetto

Faremo un semplice programma che inizialmente si limita a creare una finestra con lo sfondo di colore nero e rappresentarla sullo schermo. Successivamente aggiungeremo altri elementi.

  • Iniziamo con lanciare Anjuta e selezionare Nuovo – Progetto nel menu File o sulla barra degli strumenti.
  • Quando compare la finestra di selezione del tipo di progetto, selezionate C e quindi Generico, quindi cliccate su continua.
  • Nella schermata successiva date un nome al progetto, ad esempio clutter_tutorial, quindi se volete il vostro nome ed indirizzo email. Il numero di versione non e' importante, andiamo avanti.
  • Nel campo destinazione cliccate sul tasto apri e selezionate la posizione dove mettere il progetto. Vi consiglio di creare una nuova cartella.
  • Spuntate l'opzione “Configura pacchetti esterni”, le altre opzioni le lasciamo con i valori di default, clicchiamo su continua.
  • Nella schermata che visualizza la lista dei pacchetti spuntiamo il pacchetto clutter-1.0 e clicchiamo su Continua, quindi su Applica.

Modifichiamo il file main.c

Apriamo il file main.c e aggiungiamo dopo #include<stdio.h>
#include <stdlib.h>
#include <clutter/clutter.h>

Cancelliamo le righe all'interno della funzione main() e sostituiamole con queste:

int main (int argc, char *argv[])
{
    ClutterInitError error = clutter_init(&argc, &argv);

    ClutterColor stage_color = { 0, 0, 0, 255 };

    ClutterActor *stage = clutter_stage_new();
    clutter_actor_set_size(stage, 512, 512);
    clutter_actor_set_background_color(stage, &stage_color);
    clutter_actor_show(stage);

    clutter_main();
    return error;
}

Adesso proviamo a compilare e guardiamo il nostro programma in azione.

clutter_tutorial crea una finestra nera sullo schermo

Per il momento il programma è molto grezzo, non possiamo fare molto oltre a vedere questa finestra nera sul nostro schermo. Dopo aver chiuso la finestra possiamo vedere che il programma rimane in esecuzione e siamo costretti a fermarlo da Anjuta, selezionando la voce “Ferma programma” dal menu Esegui.
Adesso analizziamo insieme il codice:

  • clutter_init() inizializza la libreria. Prima di qualsiasi chiamata di funzione bisogna inizializzare Clutter con questa istruzione. Come vedete riceve i parametri della funzione main(), infatti può ricevere dall'invocazione da riga di comando dei parametri. Il valore di ritorno è costituito da eventuali errori durante l'inizializzazione.
  • ClutterColor è la struttura che definisce il colore e viene inizializzata con i valori di rosso, verde, blu e di opacità, con valori che vanno da zero a 255. Nel nostro caso sono 3 zeri per ottenere il nero e 255 per avere un colore pieno senza trasparenze.

Prima di andare avanti bisogna fermarci per un po di teoria riguardante Clutter.
La classe ClutterActor è la base fondamentale di tutta libreria, ogni oggetto grafico rappresentato sullo schermo è un attore che si muove su un palcoscenico (stage). Lo stesso stage è comunque un'istanza della classe ClutterActor. Per prima cosa viene creato un palcoscenico, quindi vengono creati gli attori e vengono aggiunti al palcoscenico per diventare visibili.

  • clutter_stage_new() crea il palcoscenico, stage è il puntatore al nostro palcoscenico;
  • clutter_actor_set_size() definisce la larghezza e l'altezza di un attore, in questo caso viene utilizzato per definire le dimensioni del nostro palcoscenico, infatti nei parametri viene passato stage e le dimensioni di 512 di larghezza per 512 di altezza;
  • clutter_actor_set_background_color() definisce il colore di sfondo di un attore, nel nostro caso assegniamo il colore nero che avevamo definito in stage_color, al nostro palcoscenico stage;
  • clutter_actor_show() rende visibile l'attore, noi rendiamo visibile il nostro stage;
  • clutter_main() passa il controllo al main loop, cioè attende il verificarsi degli eventi, che possono essere ad esempio delle azioni da parte dell'utente;

Ora facciamo in modo che quando chiudiamo la finestra il programma si arresti, basta aggiungere questa riga dopo clutter_actor_show(stage);

g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL);

Questa funzione collega il segnale “destroy”, che viene lanciato da stage quando viene distrutto, con la chiamata alla funzione clutter_main_quit() che interrompe il main loop del programma. Ora, quando chiuderemo la finestra, stage verrà distrutto e lancerà il segnale “destroy”, quindi verrà chiamata la funzione clutter_main_quit() che terminerà il programma.
Compilate e provate a lanciare il programma e quindi a chiudere la finestra.

clutter_tutorial esce con codice d'errore 1 che corrisponde a CLUTTER_INIT_SUCCESS, cioè nessun errore.


E' arrivato il momento di aggiungere un attore sul nostro palcoscenico, aggiungiamo le seguenti righe dopo clutter_actor_set_background_color(stage, &stage_color);

ClutterColor actor_color = { 0, 255, 0, 128 };
ClutterActor *rect = clutter_actor_new();
clutter_actor_set_background_color(rect, &actor_color);
clutter_actor_set_size(rect, 100, 100);
clutter_actor_set_position(rect, 100, 100);
clutter_actor_add_child(stage, rect);

Analizziamo il codice che abbiamo aggiunto:
  • prima di tutto inizializziamo actor_color con un colore verde intenso;
  • clutter_actor_new() crea un nuovo attore, rect è il puntatore al nostro attore;
  • clutter_actor_set_background_color() è la stessa funzione che abbiamo usato per definire il colore del palcoscenico, adesso passiamo rect, che è il nostro attore e l'indirizzo del colore che abbiamo definito in actor_color;
  • anche clutter_actor_set_size() è lo stesso che abbiamo utilizzato prima, questa volta definiamo le dimensioni del nostro attore;
  • clutter_actor_set_position() definisce la posizione dell'attore sul palcoscenico, le coordinate sono rispettivamente la posizione sull'asse x seguita da quella sull'asse y. Le origini degli assi sono poste sull'angolo in alto a sinistra della finestra.
  • Ora che l'attore è pronto per andare sulla scena lo aggiungiamo al palcoscenico con la funzione clutter_actor_add_child(). Nel momento in cui l'attore viene aggiunto al palcoscenico questo diventa visibile.

Provate a compilare ed avviare il programma, ora vedrete un bel quadrato verde all'interno della nostra finestra nera.

un attore verde è sulla scena!
Il programma completo dovrebbe avere questo aspetto:


#include <stdio.h>
#include <stdlib.h>
#include <clutter/clutter.h> 
int main(int argc, char *argv[])
{
    ClutterInitError error = clutter_init(&argc, &argv);
    ClutterColor stage_color = { 0, 0, 0, 255 };
    ClutterActor *stage = clutter_stage_new();
    clutter_actor_set_size(stage, 512, 512);
    clutter_actor_set_background_color(stage, &stage_color);
    ClutterColor actor_color = { 0, 255, 0, 128 }; 
    ClutterActor *rect = clutter_actor_new();
    clutter_actor_set_background_color(rect, &actor_color);
    clutter_actor_set_size(rect, 100, 100);
    clutter_actor_set_position(rect, 100, 100);
    clutter_actor_add_child(stage, rect);
    clutter_actor_show(stage);
    g_signal_connect (stage, "destroy", G_CALLBACK (clutter_main_quit), NULL); 
    clutter_main();
    return error;
}

Qui si conclude la prima parte del nostro tutorial, mi rendo conto che abbiamo visto poco fino a questo momento, ma ci siamo fatti un'idea della semplicità di utilizzo di Clutter.

Per ulteriori informazioni riguardanti la sintassi delle funzioni vi consiglio di consultare la guida di riferimento utilizzando DevHelp o sul sito.

Se avete dubbi, domande o suggerimenti vi invito a lasciare dei commenti, a presto!

venerdì 16 novembre 2012

Cambia il target di Maxtrix.nix


Dopo qualche mese di pausa torno a scrivere suggerimenti e guide sperando di potervi essere d'aiuto. Forse avete notato che è cambiata l'intestazione del blog ed è scomparso qualsiasi riferimento ad OS X ed al mondo Apple in generale.
Purtroppo l'ultimo MacBook in mio possesso è andato in pensione, risaliva al lontano 2007 ( informaticamente parlando è una data lontana! ) e comunque non mi sarebbe stato possibile rimanere aggiornato con l'ultima versione di OS X.
Ormai da qualche anno utilizzo come sistema operativo principale Ubuntu e quindi ho dovuto ristringere il target al solo mondo GNU/Linux.
Spero di riuscire ad attirare la curiosità anche di quanti non utilizzano abitualmente una distribuzione GNU/Linux.


Rinominare una serie di file con un unico comando dal Terminale


A chi non è mai capitato di dover rinominare una lunga serie di file, come ad esempio una collezione di foto? Farlo con l'interfaccia grafica di un qualsiasi file manager è una procedura lunga e noiosa, costringendo l'utente a dover cliccare su ogni file per rinominarlo a mano!
Con il comando rename possiamo rinominare una serie di file in un colpo solo.
La sintassi di questo comando è la seguente:

rename [espressione regolare] files

La sintassi dell'espressione regolare è quella di Perl, in sintesi ha questa forma:

s / caratteri da sostituire / nuovi caratteri /

Per quanto riguarda files, possiamo utilizzare delle wildcard per selezionare i file da modificare.
Vediamo alcuni esempi per chiarire:

rename s/.jpeg/.jpg/ *.jpeg

*.jpeg informa rename che deve prendere tutti i file che terminano con .jpeg, quindi l'espressione regolare s/.jpeg/.jpg/ sostituisce ogni occorrenza della stringa .jpeg con la stringa .jpg.
Quindi se abbiamo i file

a.jpg
b.jpeg
c.jpg
d.jpeg

rename modificherà rispettivamente

b.jpeg in b.jpg
d.jpeg in d.jpg.

La sintassi delle espressioni regolari, seppur inizialmente può apparire piuttosto complessa, è uno strumento potente e versatile. Tramite l'uso di metacaratteri possiamo ottenere delle espressioni più complesse, vediamone alcuni:

^    inizio della stringa
$    fine della stringa
*    nessuna o più ripetizioni
+    una o più ripetizioni
{}   numero esatto della ripetizione

Vediamo degli esempi pratici:

rename s/^/foto/ *.jpg

Aggiunge la stringa foto davanti al nome di tutti i file che terminano con .jpg, ad esempio
01.jpg diventerà foto01.jpg.

rename s/$/foto/ *.jpg

Aggiunge la stringa foto alla fine del nome di tutti i file che terminano con .jpg, ad esempio
01.jpg diventerà 01foto.jpg.

rename s/ae*/e/ *

Tutte le occorrenze di una 'a' che sia seguita da nessuna o più 'e', verranno sostituite con e.

rename s/ae+/e/ *

Tutte le occorrenze di una 'a' che sia seguita da una o più 'e', verranno sostituite con e.

rename s/a{3}/a/ *

Tutte le occorrenze di 'aaa' verranno sostituite con 'a'.

Per ulteriori informazioni sulla sintassi di rename potete consultare le istruzioni con il solito
man rename

Mentre per la sintassi delle espressioni regolari in Perl vi segnalo questa pagina.

domenica 29 aprile 2012

Problemi con Hard Disk esterni ed accesso ai file in Ubuntu? Potrebbe essere un problema di permessi dei file


Premessa
I sistemi Unix-like gestiscono tutto come file, le directory tramite cui sono ordinati i file sono anch'esse file, lo stesso vale per i dispositivi, i singoli processi, ecc. Tutti i file hanno associati un utente proprietario, un gruppo di utenti e dei permessi che ne regolano l'accesso. Solo il super utente "root" ha la possibilità di accedere a qualsiasi file nel sistema senza tenere conto dei permessi.

Utilizziamo il Terminale
Il terminale è lo strumento che ci permette di visualizzare ed eventualmente modificare i proprietari ed i permessi di accesso ai file. Questo potente e flessibile strumento è temuto e ritenuto troppo complicato da molti utenti, soprattutto da quelli poco pratici degli ambienti Unix-like, ma in realtà, con un minimo di pratica, si dimostra molto più efficace e veloce di qualsiasi gestore di file con interfaccia grafica.

Visualizzare proprietari e permessi con il comando ls
Per poter visualizzare i proprietari ed i permessi dei file possiamo usare il comando ls con l'opzione -l, digitiamo quindi:
ls -l
e vedremo la lista dei file contenuti nella directory corrente arricchita da diverse informazioni, come ad esempio:

drwxr-xr-x 2 massi massi 4096 feb 7 14:52 Documenti
-rw-r--r-- 1 massi massi 179 feb 7 14:36 examples.desktop
drwxr-xr-x 2 massi massi 4096 apr 24 11:28 Immagini
drwxr-xr-x 2 massi massi 4096 feb 7 14:52 Modelli
drwxr-xr-x 2 massi massi 4096 feb 7 14:52 Musica
drwxr-xr-x 2 massi massi 4096 feb 7 14:52 Pubblici
drwxr-xr-x 5 massi massi 4096 apr 27 16:43 Scaricati
drwxr-xr-x 2 massi massi 4096 apr 28 13:15 Scrivania
drwxr-xr-x 2 massi massi 4096 apr 27 23:42 Video

la prima stringa di lettere rappresenta i permessi di accesso ai file, analizziamo insieme quella relativa alla directory Documenti:
d il primo carattere, ci informa che il file è una directory;
rwx è la prima terna di caratteri che rappresentano i permessi di accesso del proprietario, r sta per read (lettura), w sta per write (scrittura) e x sta per execute (esecuzione). Quindi il proprietario ha la facoltà di leggere, scrivere ed eseguire il file.
r-x è la seconda terna e rappresenta i permessi del gruppo a cui appartiene il file. In questo caso gli appartenenti al gruppo hanno facoltà di lettura ed esecuzione, ma non di scrittura.
r-x è l'ultima terna e si riferisce a tutti gli altri utenti. I permessi sono gli stessi riservati al gruppo, cioè lettura ed esecuzione.

Successivamente abbiamo il nome del proprietario e quello del gruppo, tutti i file sono di proprietà dell'utente massi e del gruppo massi.

Modificare il proprietario e il gruppo dei file
Per modificare il proprietario e il gruppo di un file usiamo il comando chown.

Ad esempio creiamo un file di prova con il seguente comando:

touch prova

Il comando touch creerà un file con il nome prova, il proprietario e il gruppo sarà quello dell'utente corrente. Se volessimo cambiare il proprietario del file prova con l'utente paolo ed il gruppo lavoro scriveremo:

sudo chown paolo:lavoro prova

Ora il proprietario sarà paolo ed il gruppo lavoro. Come vedete dall'esempio è necessario usare il comando sudo per poter ottenere il permesso di modificare il proprietario ed il gruppo di un file.

Modificare i permessi di accesso di un file
Per modificare i permessi di accesso di un file utilizziamo il comando chmod, anche in questo caso è necessario utilizzare sudo.

I permessi di accesso di prova sono -rw-rw-r--, che vuol dire accesso in lettura e scrittura per il proprietario e gli appartenenti al gruppo, accesso solo in lettura per gli altri. Nessuno ha il permesso di eseguire il file.

La sintassi del comando è: chmod [ugoa] [+-=] [permessi] [file]

Il primo gruppo di parametri serve ad indicare a quali tipologia di utenti vogliamo applicare le modifiche di accesso.
u sta per user, cioè il proprietario del file.
g sta per group, cioè il gruppo.
o sta per others, cioè tutti gli altri.
a sta per all, tutti senza distinzioni.
Ad esempio, volendo modificare i permessi di accesso al proprietario e al gruppo scriveremmo ug, se invece volessimo modificare i permessi agli altri utenti scriveremmo o, se ancora volessimo applicarle a tutti scriveremmo a oppure ugo.

Il secondo gruppo di parametri serve ad indicare se vogliamo aggiungere un permesso con + o toglierlo con -.

Nel terzo gruppo di parametri andremo a specificare quali permessi vogliamo modificare, quindi r per lettura, w per scrittura e x per esecuzione.

Torniamo al nostro file d'esempio prova e poniamo il caso volessimo aggiungere il permesso in scrittura per tutti gli altri utenti:

sudo chmod o+w prova

Ora i permessi di prova saranno -rw-rw-rw-

Problemi con Hard Disk esterni causati dai permessi di accesso

Se vi è capitato di collegare un hard disk esterno e questo non appare nell'elenco delle periferiche nel Nautilus, mentre su un altro sistema viene riconosciuto senza problemi, allora potreste avere un problema di permessi di accesso.

Provate a collegare l'hard disk e poi aprite il Terminale e digitate il comando:

cd /media

per impostare come directory corrente /media. In questa directory troveremo tutte le periferiche collegate rappresentate da rispettive directory. Proviamo a visualizzarne il contenuto con le informazioni dettagliate dei proprietari e dei permessi di accesso con il comando:

ls -l

Se vedete una directory con il nome dell'hard disk che il Nautilus si rifiuta di mostrarvi allora questa è la conferma che il problema sta nei permessi di accesso.

Qui entra in gioco il permesso di accesso in esecuzione di cui non abbiamo parlato in precedenza. Questo permesso, applicato ai file eseguibili, permette all'utente di avviare l'esecuzione del file. Per i file di tipo directory invece assume un altro ruolo, cioè permette l'accesso e l'utilizzo della directory stessa. Se ad esempio utilizziamo il comando cd su una directory che non ha il permesso in esecuzione, questo fallirà e non riuscirà ad impostare la directory corrente.

Detto questo, torniamo al nostro hard disk che poniamo il caso si chiami esterno. Se vogliamo che qualunque utente possa accedere all'hard disk possiamo verificare che i permessi di accesso r (in lettura) e x (in esecuzione) siano garantiti a tutti. Se così non fosse possiamo modificare i permessi di accesso digitando il comando:

sudo chmod a+rx esterno

Ora sul Nautilus dovreste poter vedere il disco esterno.

In questo breve tutorial ho parlato molto brevemente dei comandi chown e chmod, per ulteriori informazioni dettagliate sulle opzioni e sui parametri accettati da questi comandi vi consiglio di guardare la documentazione offerta con il comando man.
Ad esempio digitando man chown avrete accesso alla documentazione dettagliata del comando.

venerdì 27 gennaio 2012

Come spostare la libreria di iTunes e iPhoto su un Hard Disk esterno

Attenzione: le operazioni di seguito descritte comportano il rischio potenziale di perdita dei dati. Procedete con molta cautela ed assicuratevi di effettuare un backup prima di iniziare. Non sarò in ogni caso ritenuto responsabile di eventuali danni arrecati al vostro sistema, la guida ha il solo scopo informativo.


Con l'avvento degli SSD (Solid State Drive), con le loro dimensioni contenute a fronte di un costo ancora piuttosto elevato, e' diventato fondamentale utilizzare un disco esterno per conservare i nostri dati. Le applicazioni che maggiormente necessitano di spazio su disco sul nostro Mac sono sicuramente iTunes e iPhoto che, con le loro librerie di contenuti, possono occupare diverse decine di Gb sul nostro prezioso SSD interno.
Per quanto riguarda iTunes, spostare la libreria su un disco esterno e' una cosa molto semplice:
  • spostate la cartella iTunes che trovate dentro la cartella Musica della vostra home sul disco esterno;
  • aprite iTunes, andate nelle preferenze e quindi cliccate sull'icona avanzate. La prima opzione e' Posizione cartella iTunes Media. Cliccate su modifica e selezionate la nuova posizione della cartella iTunes sul vostro disco esterno.


    spostare la cartella di iTunes

Ora iTunes funziona regolarmente e non occupa spazio sullo SSD interno.

Fare la stessa cosa con iPhoto non e' altrettanto semplice, questo infatti non permette di spostare la posizione della sua libreria di contenuti in un'altra posizione.
La procedura e' più macchinosa e comporta dei limiti, prima di iniziare quindi bisogna considerare alcuni aspetti:
  1. esportare e successivamente re-importare le foto vi farà perdere irrimediabilmente la loro organizzazione in eventi, i tag, le informazioni relative alle facce ed ai luoghi delle foto. Dovrete riorganizzare tutto da capo, quindi, se la vostra libreria e' di dimensioni notevoli, potrebbe essere necessario un gran lavoro per farlo.
  2. anche dopo aver esportato tutte le foto sul disco esterno, iPhoto si ostinerà ad importare le foto dalla vostra fotocamera copiandole nella libreria. Dovrete successivamente spostarle manualmente sul disco esterno.
  3. iPhoto salva comunque molti dati nella libreria, crea delle copie nel caso effettuate delle modifiche alle foto e crea delle copie rimpicciolite per visualizzare le anteprime delle foto. Quindi, nonostante tutto, la libreria di iPhoto occuperà dello spazio sul vostro SSD interno.

Iniziamo ad esportare tutte le foto contenute in iPhoto sul disco esterno. Preparate una cartella sul vostro hard disk per contenere tutte le vostre foto, decidete voi come organizzarle. Potrete ad esempio esportare le foto per eventi e metterle in cartelle separate per ciascun evento.
  • per esportare le foto di iPhoto, selezionate le foto che volete esportare, quindi cliccate sulla voce Esporta dal menu Archivio.
  • vi apparirà la finestra di dialogo dell'esportazione, selezionate Esporta documento, quindi scegliete come tipo la voce originale, quindi cliccate sul tasto Esporta.
esportare le foto di iPhoto



Una volta terminata l'esportazione di tutte le vostre foto sul disco esterno, potete selezionare tutte le foto che avete esportato e cancellatele premendo il tasto back space.
Vuotate il cestino di iPhoto dal menu iPhotoVuota cestino di iPhoto.
Se non avete commesso clamorosi errori, ora la libreria di iPhoto e' vuota e tutte le vostre foto sono sul disco esterno.
A questo punto andate sulle preferenze di iPhoto, cliccate su Avanzate e deselezionate la casella Importazione: Copia elementi nella libreria di iPhoto. Questo impedirà ad iPhoto di copiare le foto importate nella libreria.


impedire ad iPhoto di copiare le foto nella libreria


Ora potete iniziare ad importare le foto precedentemente esportate sul disco esterno dal menu Archivio → Importa nella libreria.
Le foto rimarranno sul disco esterno ma saranno visualizzate in iPhoto come prima.

mercoledì 11 gennaio 2012

Sostituire l'HD del vostro Mac con un SSD

Attenzione: le operazioni di sostituzione del HD ed installazione di OS X di seguito descritte comportano il rischio potenziale di perdita dei dati o il danneggiamento del computer in caso di operazioni errate durante lo smontaggio. Non sarò in ogni caso ritenuto responsabile di eventuali danni arrecati al vostro sistema, la guida ha il solo scopo informativo.

SSD e' l'acronimo di Solid-State Drive, in italiano Unità a Stato Solido. Questo tipo di dispositivo utilizza una memoria a stato solido (memoria flash) al posto del tradizionale disco magnetico degli Hard Disk. I vantaggi sono una velocità di accesso (sia in lettura che in scrittura) superiore e non paragonabile a qualsiasi HD, l'assenza della meccanica di rotazione del disco, quindi nessuna vibrazione e nessun rumore, ed infine consumi nettamente inferiori. Gli svantaggi sono il prezzo per bit decisamente elevato, circa 10 volte il costo di un HD tradizionale ed una teorica minore durata dell'unità a causa del limite di riscrittura delle memorie flash.

In quest'ultimo periodo comunque i prezzi sono divenuti più accessibili e la sostituzione dell'HD interno con un SSD migliora nettamente le prestazioni del nostro vecchio computer. Un SSD da 64 Gb e' più che sufficiente per installare OS X e tutte le nostre applicazioni, mentre un HD utilizzato come unità secondaria potrà contenere i dati più ingombranti.

Io ho installato un SSD sul mio vecchio MacBook del 2007, adesso si avvia in pochi secondi e si spegne con altrettanta velocità, anche le applicazioni si aprono molto più velocemente di prima.

L'installazione meccanica dell'unità dipende dal tipo di Mac sul quale lo installate e comunque e' assolutamente identica alla procedura di installazione di un normale HD.

Questo post vi guiderà nell'installazione del sistema operativo e nel passaggio dei vostri dati e di tutte le applicazioni.



Prima di iniziare



  • Vi servirà un HD esterno sul quale effettuare il backup con Time Machine e dove sposterete i file troppo ingombranti.
  • Ovviamente avete bisogno di un supporto di installazione di OS X, che può essere un DVD (leggi qui come crearlo) o l'apposita penna USB venduta da Apple.



Verificare lo spazio necessario ed effettuare un backup



Prima cosa da fare e' verificare quanto spazio occupa il vostro sistema e assicurarci che il nostro SSD possa contenerlo. Se avete l'HD interno pieno di film e' giunto il momento di spostarli su un HD esterno. La libreria di iPhoto potrebbe avere dimensioni notevoli se avete diverse migliaia di foto e soprattutto se avete molti filmati importati dalla fotocamera. In questo caso spostare le foto e i filmati su un HD esterno e' un processo macchinoso, infatti al contrario di iTunes, non e' possibile spostare la posizione della libreria su un HD esterno. Infine la libreria di iTunes potrebbe anch'essa avere dimensioni proibitive per un SSD, ma fortunatamente, dalla preferenze di iTunes in avanzate, e' possibile spostare la posizione della libreria su un HD esterno. Qualsiasi altra applicazione di editing video, come iMovie o Final Cut Pro, dovrà conservare i suoi dati su un HD esterno se non volete riempire fino all'orlo il vostro SSD.



Una volta ripulito e sistemato il vostro HD interno siamo pronti per effettuare un backup con Time Machine su un HD esterno. Alla fine delle operazioni avrete un backup snello del vostro sistema attuale ed i vostri preziosi ed ingombranti dati su un HD esterno (se c'e' abbastanza spazio lo stesso del backup).



Montaggio del SSD e ripristino del sistema



A questo punto potete montare l'SSD all'interno del computer e rimuovere il vecchio HD, la procedura varia a secondo del modello di Mac in vostro possesso. Uno volta terminato, inserite la penna USB di installazione, collegate anche l'HD esterno del backup e accendete il computer (se avete creato il DVD di installazione, inserite quello subito dopo l'accensione). Fate in modo di avviare il Mac dal supporto di installazione, quindi iniziate la procedura di installazione sull'SSD interno. Quando vi verrà chiesto se volete importare gli utenti e le applicazioni da un'altro Mac, selezionate la voce “importa da un backup di Time Machine” e scegliete il backup che avete fatto sul disco esterno.

Una volta terminato e riavviato il Mac, come per magia, vi troverete davanti lo stesso identico sistema che avevate prima, ma sul vostro velocissimo SSD.

Provate ad avviare le applicazioni, vedrete che differenza!