Χρησιμοποιήστε 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 Ελληνική μεταφραστική ομάδα GNOME team@gnome.gr 2012-2015 Δημήτρης Σπίγγος dmtrs32@gmail.com 2012, 2013 Μαρία Θουκιδίδου marablack3@gmail.com 2014 Θάνος Τρυφωνίδης tomtryf@gmail.com 2014, 2015 Συντονιστής κιθάρας

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

Εγκαταστήσετε ένα βασικό έργο χρησιμοποιώντας το Anjuta IDE.

Δημιουργήσετε ένα απλό GUI με τον σχεδιαστή UI του Anjuta.

Χρησιμοποιήσετε τη βιβλιοθήκη GStreamer για να παίξει ήχους.

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

Βασική γνώση της γλώσσας προγραμματισμού Vala.

Ένα εγκατεστημένο αντίγραφο του Anjuta.

Δημιουργήστε ένα έργο με το <app>Anjuta</app>

Πριν ξεκινήσετε να προγραμματίζετε, πρέπει να δημιουργήσετε ένα καινούργιο έργο στο 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, που εκτελεί τη διεπαφή χρήστη και ξεκινά την απάντηση για συμβάντα (όπως κλικ και πατήματα πλήκτρου).

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

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

Μια περιγραφή της διεπαφής χρήστη (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.

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

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