Χρησιμοποιήστε GTK+ και GStreamer για να φτιάξετε ένα απλό πρόγραμμα ρυθμιστή κιθάρας για το GNOME. Αναδεικνύει πώς να χρησιμοποιήσετε το σχεδιαστή διεπαφής.
Έργο τεκμηρίωσης GNOME
gnome-doc-list@gnome.org
Johannes Schmid
jhs@gnome.org
Tiffany Antopolski
tiffany.antopolski@gmail.com
Marta Maria Casetti
mmcasetti@gmail.com 2013
Δημήτρης Σπίγγος
dmtrs32@gmail.com 2012, 2013

# Συντονιστής κιθάρας

      Σε αυτό το μάθημα, θα δημιουργήσουμε μια εφαρμογή που παίζει τόνους και μπορεί να συντονίσει μια κιθάρα. Θα μάθετε πώς να:

        Εγκαταστήσετε ένα βασικό έργο χρησιμοποιώντας το Anjuta IDE.
        Δημιουργήσετε ένα απλό GUI με τον σχεδιαστή UI του Anjuta.
        Χρησιμοποιήσετε τη βιβλιοθήκη GStreamer για να παίξει ήχους.

      Θα χρειαστείτε τα παρακάτω για να μπορέσετε να ακολουθήσετε αυτό το μάθημα:

        Βασική γνώση της γλώσσας προγραμματισμού Vala.
        Ένα εγκατεστημένο αντίγραφο του Anjuta.

# Δημιουργήστε ένα έργο με το Anjuta

Πριν ξεκινήσετε να προγραμματίζετε, πρέπει να δημιουργήσετε ένα καινούργιο έργο στο Anjuta. Έτσι θα δημιουργηθούν όλα τα απαραίτητα αρχεία που χρειάζονται για την εκτέλεση του κώδικα αργότερα. Επίσης θα ήταν χρήσιμο να τα κρατάτε όλα μαζί.

Ξεκινήστε το Anjuta και πατήστε δημιουργία νέου έργου ή αρχείο νέο έργο για να ανοίξετε τον οδηγό του έργου.

Πατήστε στην καρτέλα Vala και επιλέξτε GTK+ (απλό). Πατήστε συνέχεια και συμπληρώστε τις λεπτομέρειές σας στις επόμενες λίγες σελίδες. Χρησιμοποιήστε ως όνομα του έργου και του καταλόγου το guitar-tuner.

Βεβαιωθείτε ότι η ρύθμιση εξωτερικών πακέτων είναι ενεργή. Στην επόμενη σελίδα, επιλέξτε gstreamer-0.10 από τη λίστα για συμπερίληψη της βιβλιοθήκης GStreamer στο έργο σας. Κάντε κλικ στη συνέχεια

Κλικ στην εφαρμογή και το έργο θα δημιουργηθεί για σας. Από τις καρτέλες έργο ή αρχεία, ανοίξτε το src/guitar_tuner.vala με διπλό κλικ πάνω του. Θα πρέπει να δείτε κάποιο κώδικα που ξεκινάει με τις γραμμές:

using GLib; using Gtk;

# Κατασκευάστε τον κώδικα για πρώτη φορά

Ο κώδικας φορτώνει ένα (κενό) παράθυρο από το αρχείο περιγραφής διεπαφής χρήστη και το εμφανίζει. Περισσότερες λεπτομέρειες δίνονται παρακάτω· μπορεί να επιλέξετε να προσπεράστε αυτή τη λίστα αν καταλαβαίνετε τα βασικά:

Οι δύο γραμμές `using` εισάγουν χώρους ονομάτων έτσι ώστε να μην τους ονομάσουμε ρητά.

Ο κατασκευαστής της κλάσης `Main` δημιουργεί ένα νέο παράθυρο ανοίγοντας ένα αρχείο GtkBuilder (src/guitar-tuner.ui, που ορίζεται λίγες γραμμές παραπάνω), συνδέοντας τα σήματά του και έπειτα εμφανίζοντας τα σε παράθυρο. Αυτό το αρχείο GtkBuilder περιέχει μια περιγραφή μιας διεπαφής χρήστη και όλων των στοιχείων του. Μπορείτε να χρησιμοποιήσετε τον επεξεργαστή του Anjuta για σχεδίαση διεπαφών χρήστη GtkBuilder.

Η σύνδεση σημάτων είναι πώς ορίζετε τι συμβαίνει όταν πατάτε ένα κουμπί, ή όταν συμβεί κάποιο άλλο συμβάν. Εδώ, καλείται η συνάρτηση `on_destroy` (και τερματίζει την εφαρμογή) όταν κλείνετε το παράθυρο.

Η στατική συνάρτηση `main` τρέχει από προεπιλογή όταν ξεκινάτε μια εφαρμογή Vala. Καλεί λίγες συναρτήσεις που δημιουργούν την κύρια κλάση, ρυθμίζουν και έπειτα εκτελούν την εφαρμογή. Η συνάρτηση `Gtk.main` ξεκινά τον κύριο βρόχο του GTK, που εκτελεί τη διεπαφή χρήστη και ξεκινά την απάντηση για συμβάντα (όπως κλικ και πατήματα πλήκτρου).

Αυτός ο κώδικας είναι έτοιμος να χρησιμοποιηθεί. έτσι μπορείτε να τον μεταγλωττίσετε με κλικ κατασκευή κατασκευή έργου (ή πατώντας Shift F7). Όταν το κάνετε αυτό, θα εμφανιστεί ένας διάλογος. Αλλάξτε τη ρύθμιση σε προεπιλογή και έπειτα κλικ εκτέλεση για ρύθμιση του καταλόγου κατασκευής. Χρειάζεστε να το κάνετε αυτό μόνο μια φορά, για την πρώτη κατασκευή.

# Δημιουργία της διεπαφής χρήστη

Μια περιγραφή της διεπαφής χρήστη (UI) περιέχεται στο αρχείο του GtkBuilder src/guitar_tuner.ui που ορίστηκε στην κορυφή της κλάσης. Για να επεξεργαστείτε τη διεπαφή χρήστη, ανοίξτε το src/guitar_tuner.ui με διπλό κλικ πάνω του στην ενότητα έργο ή αρχεία. Θα βρεθείτε στο σχεδιαστή διεπαφής. Το παράθυρο σχεδίασης είναι στο κέντρο· τα γραφικά συστατικά και οι ιδιότητες γραφικού συστατικού είναι στα δεξιά και η παλέτα με τα διαθέσιμα γραφικά συστατικά είναι στα αριστερά.

Η διάταξη κάθε διεπαφής χρήστη στο Gtk+ οργανώνεται σε πλαίσια και πίνακες. Ας χρησιμοποιήσουμε εδώ ένα κάθετο GtkButtonBox για να αποδώσουμε έξι GtkButtons, ένα για κάθε μία από τις έξι χορδές της κιθάρας.

Στην καρτέλα παλέτα, από την ενότητα περιέκτες, επιλέξτε ένα πλαίσιο κουμπιού (GtkButtonBox) με κλικ στο εικονίδιο. Έπειτα κλικ στο παράθυρο σχεδίασης στο κέντρο για τοποθέτηση του στο παράθυρο. Ένας διάλογος θα εμφανίσει που μπορείτε να ορίσετε τον αριθμό των στοιχείων σε 6. Έπειτα κλικ στο δημιουργία.

Μπορείτε επίσης να αλλάξετε τον αριθμό των στοιχείων και τον προσανατολισμό στην καρτέλα γενικά στα δεξιά.

Τώρα, από την ενότητα έλεγχος και εμφάνιση της παλέτας επιλέξτε ένα κουμπί (GtkButton) με κλικ πάνω του. Τοποθετήστε το στην πρώτη ενότητα του GtkButtonBox με κλικ στην πρώτη ενότητα.

Έχοντας το κουμπί ακόμα επιλεγμένο, κυλήστε κάτω στην καρτέλα γενικά στα δεξιά της ιδιότητας ετικέτα και αλλάξτε την σε E. Αυτή θα είναι η χαμηλή χορδή της κιθάρας Ε.

Η καρτέλα γενικά εντοπίζεται στην ενότητα γραφικά συστατικά στα δεξιά.

Πηγαίνετε στην καρτέλα σήματα στην ενότητα γραφικά συστατικά στα δεξιά και βρείτε το σήμα `clicked` του κουμπιού. Μπορείτε να το χρησιμοποιήσετε για να συνδέσετε έναν χειριστή σημάτων που θα καλείται όταν πατηθεί το κουμπί από τον χρήστη. Για να το κάνετε αυτό, κλικ στο σήμα και πληκτρολογήστε `main_on_button_clicked` στη στήλη χειριστής και πατήστε Enter.

Επαναλάβετε τα παραπάνω βήματα για τα υπόλοιπα κουμπιά, προσθέστε τις επόμενες 5 χορδές με τα ονόματα A, D, G, B, και e.

Αποθηκεύστε τη σχεδίαση UI (πατώντας αρχείο αποθήκευση) και κρατήστε το ανοιχτό.

# Διοχετεύσεις GStreamer

Αυτή η ενότητα θα δείξει πώς να παράξει ο κώδικας ήχους. GStreamer είναι ο σκελετός πολυμέσων του GNOME - μπορείτε να τον χρησιμοποιήσετε για παίξιμο, εγγραφή και επεξεργασία βίντεο, ήχου, ροών ιστοκάμερας και τα παρόμοια. Εδώ, θα το χρησιμοποιήσουμε για να παράξουμε τόνους μιας συχνότητας.

Εννοιολογικά, το GStreamer λειτουργεί ως εξής: δημιουργείτε μια διοχέτευση που περιέχει διάφορα στοιχεία επεξεργασίας που πηγαίνουν από την πηγή στο ταμιευτήρα (έξοδο). Η πηγή μπορεί να είναι ένα αρχείο εικόνας, βίντεο, ή μουσικής, για παράδειγμα, και η έξοδος μπορεί να είναι γραφικό συστατικό ή κάρτα ήχου.

Ανάμεσα στην πηγή και στην έξοδο, μπορείτε να εφαρμόσετε διάφορα φίλτρα και οι μετατροπείς να χειριστούν εφέ, μετατροπές μορφών και λοιπά. Κάθε στοιχείο της διοχέτευσης έχει ιδιότητες που μπορούν να χρησιμοποιηθούν για να αλλάξουν τη συμπεριφορά τους.

Ένα παράδειγμα διοχέτευσης GStreamer.

# Ρύθμιση της διοχέτευσης

Σε αυτό το παράδειγμα θα χρησιμοποιήσουμε μια πηγή παραγωγής τόνων που λέγεται `audiotestsrc` και θα στείλουμε την έξοδο στην προεπιλεγμένη συσκευή ήχου του συστήματος, `autoaudiosink`. Πρέπει μόνο να ρυθμίσουμε την συχνότητα της παραγωγής τόνου· αυτό είναι διαθέσιμο μέσα από την ιδιότητα `freq` του `audiotestsrc`.

Χρειάζεται να προσθέσουμε μια γραμμή για αρχικοποίηση του GStreamer· βάλτε τον παρακάτω κώδικα στην γραμμή πάνω από την κλήση `Gtk.init` στη συνάρτηση `main`:

Gst.init (ref args);

Μετά, αντιγράψτε την ακόλουθη συνάρτηση στο guitar_tuner.vala μέσα στην κλάση μας `Main`:

Gst.Element sink; Gst.Element source; Gst.Pipeline pipeline;

private void play_sound(double frequency) { pipeline = new Gst.Pipeline ("note"); source = Gst.ElementFactory.make ("audiotestsrc", "source"); sink = Gst.ElementFactory.make ("autoaudiosink", "output");

/* set frequency */ source.set ("freq", frequency);

pipeline.add (source); pipeline.add (sink); source.link (sink);

pipeline.set_state (Gst.State.PLAYING);

/* stop it after 200ms */ var time = new TimeoutSource(200);

time.set_callback(() => { pipeline.set_state (Gst.State.NULL); return false; }); time.attach(null); }

Οι τρεις πρώτες γραμμές δημιουργούν τα στοιχεία πηγή και έξοδο του GStreamer (`Gst.Element`), και ένα στοιχείο διοχέτευσης (το οποίο θα χρησιμοποιηθεί σαν περιέκτης για τα δυο άλλα στοιχεία). Αυτά είναι μεταβλητές κλάσεων, έτσι ορίζονται έξω από τη μέθοδο. Δίνουμε το όνομα "note" στη διοχέτευση· ονομάζουμε την πηγή "source" και ρυθμίζεται στην πηγή `audiotestsrc`· και ονομάζουμε την έξοδο "output" και ρυθμίζεται στην έξοδο `autoaudiosink` (προεπιλεγμένη έξοδος κάρτας ήχου).

Η κλήση στο `source.set` ορίζει την ιδιότητα `freq` του στοιχείου πηγής σε `frequency`, η οποία έχει περαστεί ως όρισμα στη συνάρτηση `play_sound`. Αυτή είναι η συχνότητα της νότας σε Hertz· πολλές χρήσιμες συχνότητες θα οριστούν αργότερα.

Το `pipeline.add` βάζει την πηγή και την έξοδο στη διοχέτευση. Η διοχέτευση είναι ένα `Gst.Bin`,που είναι απλά ένα στοιχείο που μπορεί να περιέχει πολλαπλά άλλα στοιχεία GStreamer. Γενικά, μπορείτε να προσθέσετε όσα στοιχεία θέλετε στη διοχέτευση προσθέτοντας περισσότερες κλήσεις στο `pipeline.add`.

Κατόπιν, το `sink.link` χρησιμοποιείται για σύνδεση των στοιχείων μαζί, έτσι ώστε η έξοδος της πηγής (ένας τόνος) να πηγαίνει στην είσοδο της εξόδου (η οποία μετά είναι έξοδος στην κάρτα ήχου). Το `pipeline.set_state` χρησιμοποιείται έπειτα για την εκκίνηση της αναπαραγωγής, ρυθμίζοντας την κατάσταση της σωλήνωσης να παίξει (`Gst.State.PLAYING`).

Δεν θέλουμε να παίζουμε έναν ενοχλητικό ήχο για πάντα, οπότε το τελευταίο πράγμα που κάνει ο `play_sound` είναι να προσθέσει έναν `TimeoutSource`. Αυτό ορίζει ένα χρονικό όριο που θα σταματήσει τον ήχο· περιμένει για 200 ms πριν καλέσει τον χειριστή σήματος που ορίστηκε στη γραμμή που σταματά και καταστρέφει τη διοχέτευση. Επιστρέφει `false` για να αφαιρέσει την ίδια από το χρονικό όριο, αλλιώς θα συνέχιζε να καλείται κάθε 200 ms.

# Δημιουργία χειριστή σημάτων

Στον σχεδιαστή διεπαφών χρήστη, κάνατε όλα τα κουμπιά να καλούν την ίδια συνάρτηση, on_button_clicked, όταν πατηθούν. Στην πραγματικότητα, πληκτρολογούμε main_on_button_clicked που λέει στον σχεδιαστή UI ότι αυτή η μέθοδος είναι τμήμα του `Main` μας. Πρέπει να προσθέσουμε αυτή την συνάρτηση στο πηγαίο αρχείο.

Για να το κάνετε αυτό, στο αρχείο διεπαφής χρήστη (guitar_tuner.ui), επιλέξτε ένα από τα κουμπιά με κλικ πάνω του, έπειτα ανοίξτε guitar_tuner.vala (με κλικ στην καρτέλα στο κέντρο). Εναλλαγή στην καρτέλα σήματα στα δεξιά, που χρησιμοποιήσατε για τον ορισμό του ονόματος αρχείου. Τώρα, πάρτε τη γραμμή όπου ορίσατε το σήμα πατημένο και σύρσιμο και απόθεσή του στο πηγαίο αρχείο στην αρχή της κλάσης. Ο παρακάτω κώδικας θα προστεθεί στο πηγαίο σας αρχείο:

public void on_button_clicked (Gtk.Button sender) {

}

Μπορείτε επίσης να πληκτρολογήσετε απλά των κώδικα στην αρχή της κλάσης αντί της χρήσης συρσίματος και απόθεσης.

Αυτός ο χειριστής σήματος έχει μόνο ένα όρισμα: το `Gtk.Widget` που κάλεσε η συνάρτηση (στην περίπτωσή μας, πάντοτε ένα `Gtk.Button`).

# Ορισμός του χειριστή σημάτων

Θέλουμε να παίξουμε τον σωστό ήχο όταν ο χρήστης πατά ένα κουμπί. Για αυτό, ζωντανεύουμε τον χειριστή σήματος που ορίσαμε παραπάνω, `on_button_clicked`. Θα μπορούσαμε να έχουμε συνδέσει κάθε κουμπί σε διαφορετικό χειριστή σήματος, αλλά αυτό θα μπορούσε να οδηγήσει σε εκτεταμένο διπλασιασμό του κώδικα. Αντίθετα, μπορούμε να χρησιμοποιήσουμε την ετικέτα του κουμπιού για να καταλάβουμε ποιο κουμπί πατήθηκε:

public void on_button_clicked (Gtk.Button sender) { var label = sender.get_child () as Gtk.Label; switch (label.get_label()) { case "E": play_sound (329.63); break; case "A": play_sound (440); break; case "D": play_sound (587.33); break; case "G": play_sound (783.99); break; case "B": play_sound (987.77); break; case "e": play_sound (1318); break; default: break; } }

Το `Gtk.Button` που πατήθηκε περνά ως όρισμα (`sender`) στο `on_button_clicked`. Μπορούμε να πάρουμε την ετικέτα αυτού του κουμπιού χρησιμοποιώντας τον `get_child` και έπειτα να πάρουμε το κείμενο από αυτήν την ετικέτα χρησιμοποιώντας `get_label`.

Η πρόταση διακόπτη συγκρίνει το κείμενο ετικέτας με τις νότες που μπορούμε να παίξουμε και καλείται ο `play_sound` με την κατάλληλη συχνότητα για αυτήν την νότα. Αυτό παίζει τον τόνο· ο ρυθμιστής κιθάρας είναι έτοιμος!

# Κατασκευή και εκτέλεση της εφαρμογής

Όλος ο κώδικας πρέπει να είναι έτοιμος τώρα. Κλικ κατασκευή κατασκευή έργου για ανακατασκευή των πάντων και έπειτα τρέξιμο εκτέλεση για έναρξη της εφαρμογής.

Εάν δεν το έχετε ήδη κάνει, επιλέξτε την εφαρμογή Debug/src/guitar-tuner στον διάλογο που εμφανίζεται. Τελικά, πατήστε τρέξιμο και απολαύστε!

# Υλοποίηση αναφοράς

Αν αντιμετωπίσετε προβλήματα με το μάθημα, συγκρίνετε τον κώδικά σας με αυτόν τον κώδικα αναφοράς.

# Περαιτέρω ανάγνωση

Για να βρείτε περισσότερα για τη γλώσσα προγραμματισμού Vala ίσως θελήσετε να κοιτάξετε το μάθημα Vala και το τεκμηρίωση API Vala

# Επόμενα βήματα

Εδώ είναι κάποιες ιδέες για το πώς μπορείτε να επεκτείνετε αυτή την απλή παρουσίαση:

Βάλτε το πρόγραμμα να περνάει αυτόματα μέσα από τις νότες.

Κάντε το πρόγραμμα να αναπαράγει ηχογραφήσεις από αληθινές χορδές κιθάρας που έχουν εισαχθεί.

Για να το κάνετε αυτό, πρέπει να ρυθμίσετε μια πιο περίπλοκη διοχέτευση GStreamer που θα σας επιτρέπει να φορτώνετε και να αναπαράγετε αρχεία ήχου. Θα πρέπει να διαλέξετε τα στοιχεία GStreamer decoder και demuxer με βάση τον τύπο του αρχείου των ηχογραφημένων ήχων — για παράδειγμα το MP3 χρησιμοποιεί διαφορετικά στοιχεία από το Ogg Vorbis.

Ίσως χρειαστεί να συνδέσετε τα στοιχεία με πιο περίπλοκους τρόπους. Αυτό μπορεί να συμπεριλαμβάνει τη χρήση Εννοιών GStreamer που δεν καλύπτουμε σε αυτόν τον οδηγό, όπως και pad. Ίσως βρείτε χρήσιμη και την εντολή gst-inspect.

Αυτόματη ανάλυση νότων που παίζει ο χρήστης.

Μπορείτε να συνδέσετε μικρόφωνο και να ηχογραφήσετε από αυτό χρησιμοποιώντας την πηγή εισόδου. Ίσως κάποια μορφή της ανάλυσης φάσματος θα σας βοηθούσε να καταλάβετε ποια νότα παίζει;