Un nuovo progetto…

I lettori più “datati” si ricorderanno di certo i Librogame degli anni ’80.
Personalmente da ragazzo ne lessi diversi e devo dire che li trovai divertenti.
Ricordandomi questo e venendo a conoscenza del Project AON che ha avuto il permesso dell’autore di pubblicare gratuitamente i libri della serie Lone Wolf (Lupo Solitario in Italia) ho pensato che avrei potuto realizzare una versione “portatile” dei libri per poterli leggere comodamente sul mio nokia N900.

Da un po’ di giorni ho iniziato a sviluppare il progetto e devo dire che procede abbastanza bene. Il primo libro è giocabile al 100% (ma devo ancora finire di testarlo) mentre per i successivi dovrò lavorarci ancora un po’.

Ecco comunque una piccola anteprima:

Non so quanto tempo mi servirà per completare il lavoro (devo rendere il mio programma compatibile con la licenza del Poject AON e fare un po’ di testing), ma non appena il programma verrà rilasciato lo saprete di sicuro da queste pagine. 🙂

Portaudio e libmad

Ho “scoperto” ieri una libreria audio compatibile con Windows e Linux: Portaudio.
Incuriosito ho deciso di provarla: un’ottima opportunità per provare ad utilizzarla insieme a MAD (libreria di decodifica MPEG) e scrivere un piccolo esempio di riproduzione di file MP3 cross-platform (sicuramente funziona su Windows e Linux e molto probabilmente anche su Nokia N900 ma non ho ancora provato).

Il risultato lo trovate in questo file.
Si tratta ovviamente di un esempio e non è un programma completo, ma dimostra la semplicità d’uso di Portaudio e MAD (due ottime librerie a mio parere).

La funzione main è molto semplice:

/* Main */
int main(int argc, char *argv[])
{
    printf("Mad and portaudio sample\n");
    printf("Copyright (c) 2011 Paolo Iommarini\n\n");

    char input[264] = "test.mp3";
    if (argc > 1)
        strcpy(input, argv[1]);
    printf("Input file: %s\n", input);

    PaError err = Pa_Initialize();
    if( err != paNoError ) goto error;
    printf("Portaudio initialized\n");

    mad_stream_init(&Stream);
    mad_header_init(&Header);
    mad_frame_init(&Frame);
    mad_synth_init(&Synth);
    mad_timer_reset(&Timer);
    printf("Mad initialized\n");

    input_fd = fopen(input, "rb");
    if (!input_fd){
        printf("Failed to open input file\n");
        goto end;
    }

    int size = ID3v2TagSize(input);
    printf("Tag size %i\n", size);
    fseek(input_fd, size, SEEK_SET);

    PaStream *stream;
    /* Open an audio I/O stream. */
    err = Pa_OpenDefaultStream( &stream,
                                0,
                                2,          /* stereo output */
                                paInt16,
                                SAMPLE_RATE,
                                INPUT_BUFFER_SIZE, /* frames per buffer, i.e. the number
                                                   of sample frames that PortAudio will
                                                   request from the callback. Many apps
                                                   may want to use
                                                   paFramesPerBufferUnspecified, which
                                                   tells PortAudio to pick the best,
                                                   possibly changing, buffer size.*/
                                patestCallback,
                                NULL );
    if( err != paNoError ) goto error;
    printf("Stream opened\n");

    err = Pa_StartStream( stream );
    if( err != paNoError ) goto error;
    printf("Stream started\n");

    printf("Waiting end of stream\n");
    while (!eos)
        Pa_Sleep(1000);

    err = Pa_StopStream( stream );
    if( err != paNoError ) goto error;

    err = Pa_Terminate();
    if( err != paNoError ) goto error;
    printf("Portaudio terminated\n");

    mad_synth_finish(&Synth);
    mad_header_finish(&Header);
    mad_frame_finish(&Frame);
    mad_stream_finish(&Stream);
    printf("Mad terminated\n");

end:
    return 0;

error:
    printf(  "PortAudio error: %s\n", Pa_GetErrorText( err ) );

    return 0;
}

Una cosa che salta all’occhio guardando il sorgente dell’esempio è che riproduce solo MP3 a 44.100Hz, 16 bit, stereo ma non è difficile adattarlo. 😉

QtBatteryWidget per Nokia N900

Ecco QtBatteryWidget: un widget per il desktop che visualizza informazioni sullo stato della batteria.
Le informazioni visualizzabili (sia standard che modulo bq27x00) sono:

  • Percentuale di carica
  • Carica mAh
  • Voltaggio mV
  • Tempo rimanente (di utilizzo o per terminare la ricarica)
  • Temperatura

Il tempo rimanente è calcolato semplicemente sull’ultima variazione della percentuale della batteria, quindi è un valore istantaneo, ma viene aggiornato dopo un po’…
Se state usando il telefono in modo “pesante” dopo un po’ il tempo rimanente scenderà, mentre se lasciate il telefono in standby il tempo rimanente aumenterà.

Durante la ricarica viene utilizzata (se disponibile) sempre la percentuale del modulo bq27x00, quindi appena collegate l’N900 la percentuale sale immediatamente (perché quella del bq27x00 è la carica percentuale effettiva della batteria).

Nella configurazione potete scegliere quali informazioni visualizzare ed il grado di opacità del widget.
La percentaule può essere visualizzata in modo grafico, standard (progressbar) o testuale.

Homepage
Package
Donazioni

Screenshot:

Bing Maps e WPF

Mi è capitato di dover sviluppare una applicazione desktop usando il WPF che visualizzasse le mappe di Bing.
Pensavo sarebbe stato facile (“E’ tutto di Microsoft, sarà sicuramente facile”, pensavo) ed invece con qualche rapida ricerca su internet mi sono reso conto che non esiste un metodo “standard”, semplice e supportato direttamente da Microsoft di fare ciò.

Ho cercato un po’ di documentazione, e vagliato almeno due possibilità

  • Scrivere una semplice applicazione Silverlight, renderla disponibile su qualche server ed usarla all’interno di una window WPF (ma anche l’embedding di Silverlight in WPF non è a noi “concesso” da Microsoft in modo nativo)
  • Scrivere una pagina HTML ed interagire con essa tramite Javascript.

La soluzione che ho scelto di utilizzare è la seconda: più semplice e senza necessità di hostare niente su un server.

Partiamo con un po’ di documentazione:
Qui potete trovare un esempio di utilizzo dei servizi SOAP di Bing.
Qui trovate un esempio di interazione tra WPF e WebBrowser tramite javascript.

Il progetto di esempio, che potete scaricare in fondo a questa mini-guida, è composto principalmente da una pagina HTML che si occupa di visualizzare le mappe di Bing e da una finestra WPF che interagisce con la pagina HTML fornendo coordinate e ricevendo informazioni da essa.
La classe che permette la conunicazione tra WPF e Javascript è la seguente:

[PermissionSet(SecurityAction.Demand, Name = "FullTrust")]
[ComVisible(true)]
public class ObjectForScriptingHelper
{
    Window1 mExternalWPF;
    public ObjectForScriptingHelper(Window1 w)
    {
        this.mExternalWPF = w;
    }

    public void ActionChanged(string action)
    {
      this.mExternalWPF.ActionChanged(action);
    }

    public void PinAdded(string latitude, string longitude)
    {
      this.mExternalWPF.PinAdded(latitude, longitude);
    }
}

Come vedete è molto semplice. Da notare soltanto i metodi ActionChanged e PinAdded, che sono quelli che verrano chiamati da Javascript per comunicare con il programma principale.

La pagina HTML usa i normali metodi AJAX utilizzati sul web.
Qui potete trovare molti esempi di utilizzo.

La parte WPF non fa altro che visualizzare il contenuto HTML in un controllo WebBrowser, comunicando con essa attraverso Javascript.

Visto che un esempio vale più di mille parole, ecco il progetto di test.
BingMapsTest

Per poterlo utilizzare dovete registrare un account al Bing Maps Account Center ed inserire la chiave nella costante:

private const string m_BingKey = "Your Bing Maps Key";

Debian: bloccare pacchetti alla versione corrente

Visto che mi dimentico sempre come si fa, pubblico qui questa mini guida così almeno so dove ritrovarla in modo semplice. 🙂

Per evitare che un pacchetto venga aggiornato con un apt-get upgrade è sufficiente metterlo in hold usando dpgk
echo "packageName hold" | dpkg --set-selections

Per rimuovere un pacchetto dallo stato di hold:
echo "packageName install" | dpkg --set-selections

Per controllare lo stato attuale di tutti i pacchetti:
dpkg --get-selections

Per controllare quelli in stato di hold:
dpkg --get-selections | grep hold