Ραδιοφωνάκι με pyqt

...τα πάντα για το open source στον χώρο των gadgets, συζητήσεις, εργαλεία, open hardware, οδηγοί κ.ά.

Συντονιστής: adem1

Ραδιοφωνάκι με pyqt

Δημοσίευσηαπό malos » 10 Δεκ 2023, 15:10

Έχω ένα ραδιόφωνο widget για την Επιφάνεια εργασίας.

Ο κώδικάς του είναι αυτός:

Κώδικας: Επιλογή όλων
from PyQt5 import QtWidgets, QtMultimedia, QtXml, QtGui, QtCore

class RadioWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(RadioWidget, self).__init__(parent)
        self.setFixedSize(220, 100)
        self.setStyleSheet("background-color: #d4e8ed;")
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.move(1535, 350)
        self.play_button = QtWidgets.QRadioButton(self)
        self.play_button.setGeometry(10, 10, 70, 70)
        self.play_button.setIconSize(QtCore.QSize(64, 64))
        self.play_button.setChecked(False)
        self.play_button.setStyleSheet("QRadioButton::indicator {width: 0px; height: 0px;}")
        self.play_button.setToolTip("Κάνε κλικ για αναπαραγωγή/παύση")
        self.station_combo = QtWidgets.QComboBox(self)
        self.station_combo.setGeometry(90, 18, 128, 48)
        self.station_combo.setIconSize(QtCore.QSize(128, 48))
        self.station_combo.setStyleSheet("QComboBox::down-arrow {width: 0px; height: 0px;}")
        self.station_combo.setStyleSheet(
            """
            QComboBox {
                background-color: #c3c3c3;
                border: 1px solid #c3c3c3;
                border-radius: 10px;
            }
            QComboBox:hover {
                background-color: #e6f9ff;
                border: 1px solid #000000;
            }
            """
        )
        self.station_combo.setToolTip("Επιλογή σταθμού αναπαραγωγής")
        # Προσθήκη των στοιχείων στο QComboBox με χρήση QStandardItemModel
        self.model = QtGui.QStandardItemModel(self)
        self.station_combo.setModel(self.model)

        self.media_player = QtMultimedia.QMediaPlayer(self)
        self.read_stations()  # Καλεί τη μέθοδο για τη φόρτωση των σταθμών
        self.connect_signals()
        self.set_up_ui()

    def read_stations(self):
        dom = QtXml.QDomDocument()
        file = QtCore.QFile("stations.xml")
        file.open(QtCore.QIODevice.ReadOnly)
        dom.setContent(file)
        file.close()
        root = dom.documentElement()
        items = root.elementsByTagName("item")

        # Αδειάστε το QComboBox πριν την αρχικοποίηση
        self.station_combo.clear()

        for i in range(items.count()):
            item = items.item(i).toElement()
            label = item.attribute("label")
            id = item.attribute("id")
            url = QtCore.QUrl(id)  # Αφαιρέστε τη γραμμή αυτή, έτσι ώστε να μην αφαιρείται το πρωτόκολλο

            # Προσθήκη στοιχείου στο QComboBox
            self.station_combo.addItem(label, url)

    def connect_signals(self):
        self.play_button.toggled.connect(self.play_or_stop)
        self.station_combo.currentIndexChanged.connect(self.change_station)

    def set_up_ui(self):
        self.play_button.setIcon(QtGui.QIcon("play1.png"))

    @QtCore.pyqtSlot(int)
    def change_station(self, index):
        station_url = self.station_combo.currentData()
        print(f"Selected station: {self.station_combo.currentText()}, URL: {station_url}")

        media_content = QtMultimedia.QMediaContent(station_url)
        self.media_player.setMedia(media_content)

        self.play_or_stop(True)  # Ξεκινήστε αυτόματα την αναπαραγωγή όταν επιλέγετε νέο σταθμό

    @QtCore.pyqtSlot(bool)
    def play_or_stop(self, checked):
        if checked:
            self.play_button.setIcon(QtGui.QIcon("stop1.png"))
            url = self.station_combo.currentData()
            media_content = QtMultimedia.QMediaContent(url)
            self.media_player.setMedia(media_content)
            self.media_player.play()
        else:
            self.play_button.setIcon(QtGui.QIcon("play1.png"))
            self.media_player.stop()

if __name__ == "__main__":
    app = QtWidgets.QApplication([])
    radio_widget = RadioWidget()
    radio_widget.show()
    app.exec_()


Για να τρέξει σε kubuntu έπρεπε να δημιουργήσω ένα εικονικό περιβάλλον που λέγεται venv. Σε άλλη διανομή που έχω (Ubuntu με mate) δεν χρειάστηκε το venv.
Εξηγούμαι.
Για να τρέξει ο κώδικας πρέπει να εγκατασταθούν κάποιες βιβλιοθήκες python με το pip install.
Αυτό στην ubuntu mate μπορώ να το κάνω. Εϊναι η έκδοση 22.04. Ενώ στην kubuntu που είναι 23.04 δεν μπορώ. Ο λόγος αν κατάλαβα καλά
είναι κάποιες πολιτικές που άλλαξαν. Δεν με αφήνει να δώσω pip install. Με αφήνει μόνο μέσα από το venv περιβάλλον που είπα πριν.
Αυτό το περιβάλλον τοι στήνω στο ίδιο φάκελο που έχω και τον κώδικα του ραδιοφώνου. Επειδή ο κώδικας προστάζει να φορτωθούν κάποιες βιβλιοθήκες, αυτές θα είναι σε κάποιον φάκελο μέσα σε αυτόν το φάκελο του ραδιοφώνου όπως είπα.
Για παράδειγμα, το αρχείο του κώδικα λέγεται radio.py ( όπως θέλουμε το ονομάζουμε, αρκεί να έχει την κατάληξη " .py " )
Και το radio.py βρίσκεται στο φάκελο /home/user/scripts/radio. Ε στον ίδιο αυτό φάκελο βρίσκεται και ο φάκελος του εικονικού περιβάλλοντος.
Εγώ τον ονόμασα " radio-venv ". Για να δημιουργηθεί έδωσα εντολές στο τερματικό

Κώδικας: Επιλογή όλων
cd scripts/radio
python3 -m venv radio-venv


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

Μετά από αυτό δίνω την εντολή

Κώδικας: Επιλογή όλων
source radio-venv/bin/activate


και βλέπω τότε ότι εκεί που το τερματικό συνήθως δείχει αυτό πριν από το δρομέα

Κώδικας: Επιλογή όλων
user@pc:~/scripts/radio$


τώρα δείχνει αυτό, που είναι και ένδειξη ότι είμαι στο εικονικό αυτό περιβάλλον

Κώδικας: Επιλογή όλων
(radio-venv) user@pc:~/scripts/radio$


Εδώ θα δώσω τώρα κάποια pip install

Κώδικας: Επιλογή όλων
pip install PyQt5 sounddevice soundfile
pip install pyaudio


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

Κώδικας: Επιλογή όλων
python3 radio.py


(Αν κάποιος γνώστης που διαβάζει τώρα και δεν βαριέται να συμμετέχει ας δει στην αρχή του κώδικα το ποιες βιβλιοθήκες φορτώνονται κι ας συμπληρώσει τι χρειάζεται ακόμα)

Λείεπει όμως κάτι ακόμα.
Στον φάκελο που έχω τον κώδικα του radio.py υπάρχει κι ένα ακόμα αρχείο εκτός από το radio.py. Αυτό λέγεται stations.xml. Περιέχει μέσα τις διευθύνσεις (τα url) των σταθμών που θα παίζουν. Απλά ανοίγω ένα νέο έγγραφο με σεξί κλικ και "Δημιουργία εγγράφου" (ή "Νέο αρχείο" ή κάτι τέτοιο, ξέρετε). Εκεί μέσα φράφω αυτές τις γραμμές όπως φαίνονται

Κώδικας: Επιλογή όλων
<menu>
    <item label="Kiss FM" id="http://kissfm.live24.gr/kiss2111? Kiss FM"/>
    <item label="Love Radio" id="http://loveradio.live24.gr/loveradio-1000? Love Radio"/>
    <item label="Galaxy 92" id="http://galaxy.live24.gr/galaxy9292? Galaxy 92"/>
    <item label="Nitro Radio" id="http://nitro.live24.gr/nitro4555? Nitro Radio"/>
    <item label="Orange" id="http://orange.live24.gr/orange9320? Orange"/>
    <item label="Rock FM" id="https://az10.yesstreaming.net:8060/radio.mp3? Rock FM"/>
    <item label="Αθήνα 98.4" id="http://athina984.live24.gr/athina984? Αθήνα 984"/>
    <item label="Real FM" id="http://realfm2.live24.gr/realfm? Real FM"/>
    <item label="Σφαίρα" id="https://sfera.live24.gr/sfera4132? Σφαίρα"/>
    <item label="Ρυθμός 94.9" id="https://rythmos.live24.gr/rythmos? Ρυθμός 949"/>
    <item label="Voice 102.5" id="https://nitro.live24.gr/nitro4555? Voice 102.5"/>
    <item label="Rebel 105.2" id="https://netradio.live24.gr/rebel1052? Rebel 105.2"/>
    <item label="MAD" id="http://mediaserver.mad.tv/stream? MAD"/>
    <item label="ΕΡΤ Πρώτο" id="https://radiostreaming.ert.gr/ert-proto? ΕΡΤ Πρώτο"/>
    <item label="Κόντρα chanel" id="https://netradio.live24.gr/kontratv? Κόντρα chanel"/>
    <item label="Radio Gold" id="http://broadcast.hol.gr/radiogold? Radio Gold"/>
    <item label="Στο Κόκκινο" id="http://n05.radiojar.com/red-source? Στο Κόκκινο"/>
</menu>


και είναι έτοιμο.

Αλλά ΌΧΙ... λείπουν τα κουμπιά!
Στον ίδιο φάκελο λοιπόν έχωαυτά τα κουμπιά (που τα ζήτησα να μου τα φτιάξει τεχνητή νοημοσύνη. Ήθελα κάτι σε ασημί φουτουριστικό και δεν έβρισκα στην αναζήτηση του google)

Εικόνα
Εικόνα
down-pointing small red triangle smileys


Μπορεί όμως όποιος θέλει να βρει ό,τι του αρέσει.

Αυτό είναι όλο.

Εικόνα

Εικόνα


Ευχαριστώ που το διαβάσατε και ευχαριστώ που μου δίνεται η ευκαιρία να εκφραστώ. Όσο να ναι ικανοποίησα κάποια ανάγκη μου και είμαι ευγνώμων.
Επεξεργαστής: AMD Ryzen 9 5900x
Μνήμη Gskill 16gb (2X8gb), 3200 mh, CL 14
Μητρική: Asrock X570 phantom gaming X
Τροφοδοτικό: Corsair 850 platinum
Δίσκος: SSD Corsair MP600 (1 TB)
Άβαταρ μέλους
malos
saintTUX
saintTUX
 
Δημοσιεύσεις: 1234
Εγγραφή: 02 Νοέμ 2008, 12:00
Εκτύπωση

Re: Ραδιοφωνάκι με pyqt

Δημοσίευσηαπό malos » 09 Ιαν 2024, 15:11

Πρόσθεσα την ιδιότητα να έχει για φόντο ένα gif animation (έτσι για να θυμίζει τα εφφέ που έχουν οι media players). Kαι όταν πατάω το play και γίνεται αναπαραγωγή το gif αλλάζει και αντικαθίσταται από κάποιο άλλο (ένδειξη για μένα ότι γίνεται αναπαραγωγή)

Εικόνα

και

Εικόνα

Ο κώδικας
Κώδικας: Επιλογή όλων
from PyQt5 import QtWidgets, QtMultimedia, QtXml, QtGui, QtCore

class RadioWidget(QtWidgets.QWidget):
    def __init__(self, parent=None):
        super(RadioWidget, self).__init__(parent)
        self.is_playing = False
        self.setFixedSize(227, 90)
        self.setStyleSheet("background-color: transparent;")
        self.setWindowFlags(QtCore.Qt.FramelessWindowHint)
        self.move(1312, 258)

        self.view = QtWidgets.QGraphicsView(self)
        self.view.setGeometry(0, 0, 227, 90)
        self.view.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.view.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
        self.scene = QtWidgets.QGraphicsScene(self)
        self.view.setScene(self.scene)

        self.movie_quantum = QtGui.QMovie("gifs/quantum.gif")
        self.movie_quantum.frameChanged.connect(self.update_background)
        self.movie_item = self.scene.addPixmap(QtGui.QPixmap.fromImage(self.movie_quantum.currentImage()))
        self.movie_item.setTransformationMode(QtCore.Qt.SmoothTransformation)
        self.movie_quantum.start()

        self.movie_water = QtGui.QMovie("gifs/water.gif")
        self.movie_water.frameChanged.connect(self.update_water_background)
        self.movie_water_item = self.scene.addPixmap(QtGui.QPixmap.fromImage(self.movie_water.currentImage()))
        self.movie_water_item.setTransformationMode(QtCore.Qt.SmoothTransformation)
        self.movie_water_item.setOpacity(0)

        self.play_button = QtWidgets.QPushButton(self)
        self.play_button.setGeometry(5, 2, 70, 70)
        self.play_button.setIconSize(QtCore.QSize(64, 64))
        self.play_button.setChecked(False)
        self.play_button.setStyleSheet(
            """
            QPushButton {
                border-image: url('play1.png');
            }
            QPushButton:hover {
                border-image: url('play12.png');
            }
            """
        )
        self.play_button.setToolTip("Κάνε κλικ για αναπαραγωγή")

        self.stop_button = QtWidgets.QPushButton(self)
        self.stop_button.setGeometry(5, 2, 70, 70)
        self.stop_button.setIconSize(QtCore.QSize(64, 64))
        self.stop_button.setChecked(False)
        self.stop_button.setStyleSheet(
            """
            QPushButton {
                border-image: url('stop1.png');
            }
            QPushButton:hover {
                border-image: url('stop12.png');
            }
            """
        )
        self.stop_button.setToolTip("Κάνε κλικ για παύση")
        self.stop_button.hide()

        self.station_combo = QtWidgets.QComboBox(self)
        self.station_combo.setGeometry(83, 20, 128, 40)
        self.station_combo.setIconSize(QtCore.QSize(128, 40))
        self.station_combo.setStyleSheet("QComboBox::down-arrow {width: 0px; height: 0px;}")
        self.station_combo.setStyleSheet(
            """
            QComboBox {
                background-color: #a39c9c;
                border: 2px solid #d9d9d9;
                border-radius: 10px;
            }
            QComboBox:hover {
                background-color: #a4a4a4;
                border: 4px groove #000000;
            }
            """
        )
        self.station_combo.setToolTip("Επιλογή σταθμού αναπαραγωγής")

        self.model = QtGui.QStandardItemModel(self)
        self.station_combo.setModel(self.model)

        self.media_player = QtMultimedia.QMediaPlayer(self)
        self.read_stations()
        self.connect_signals()
        self.set_up_ui()

    def read_stations(self):
        dom = QtXml.QDomDocument()
        file = QtCore.QFile("stations.xml")
        file.open(QtCore.QIODevice.ReadOnly)
        dom.setContent(file)
        file.close()
        root = dom.documentElement()
        items = root.elementsByTagName("item")

        self.station_combo.clear()

        for i in range(items.count()):
            item = items.item(i).toElement()
            label = item.attribute("label")
            id = item.attribute("id")
            url = QtCore.QUrl(id)

            self.station_combo.addItem(label, url)

    def connect_signals(self):
        self.play_button.clicked.connect(self.play_or_stop)
        self.stop_button.clicked.connect(self.play_or_stop)
        self.station_combo.currentIndexChanged.connect(self.change_station)
        self.media_player.stateChanged.connect(self.update_background_color)

    def set_up_ui(self):
        self.play_button.setIcon(QtGui.QIcon("play1.png"))

    @QtCore.pyqtSlot(int)
    def change_station(self, index):
        station_url = self.station_combo.currentData()
        print(f"Selected station: {self.station_combo.currentText()}, URL: {station_url}")

        media_content = QtMultimedia.QMediaContent(station_url)
        self.media_player.setMedia(media_content)

        if self.is_playing:
            self.media_player.play()

    @QtCore.pyqtSlot()
    def play_or_stop(self):
        self.is_playing = not self.is_playing

        if self.is_playing:
            self.play_button.setIcon(QtGui.QIcon("stop1.png"))
            self.stop_button.show()
            self.play_button.hide()
            url = self.station_combo.currentData()
            media_content = QtMultimedia.QMediaContent(url)
            self.media_player.setMedia(media_content)
            self.media_player.play()

            self.movie_water.start()
            self.movie_water_item.setOpacity(1)
        else:
            self.stop_button.hide()
            self.play_button.setIcon(QtGui.QIcon("play1.png"))
            self.play_button.show()
            self.media_player.stop()

            self.movie_quantum.start()
            self.movie_water_item.setOpacity(0)

        self.update_background_color()

    def update_background_color(self):
        self.setStyleSheet(f"background-color: transparent;")

    def enterEvent(self, event):
        self.setStyleSheet("color: white; background-color: #000301;")

    def leaveEvent(self, event):
        self.setStyleSheet(f"background-color: transparent;")

    def paintEvent(self, event):
        pass

    @QtCore.pyqtSlot()
    def update_background(self):
        self.movie_item.setPixmap(QtGui.QPixmap.fromImage(self.movie_quantum.currentImage()))
        self.repaint()

    @QtCore.pyqtSlot()
    def update_water_background(self):
        self.movie_water_item.setPixmap(QtGui.QPixmap.fromImage(self.movie_water.currentImage()))
        self.repaint()


if __name__ == "__main__":
    import sys
    app = QtWidgets.QApplication(sys.argv)
    radio_widget = RadioWidget()
    radio_widget.show()
    sys.exit(app.exec_())
Επεξεργαστής: AMD Ryzen 9 5900x
Μνήμη Gskill 16gb (2X8gb), 3200 mh, CL 14
Μητρική: Asrock X570 phantom gaming X
Τροφοδοτικό: Corsair 850 platinum
Δίσκος: SSD Corsair MP600 (1 TB)
Άβαταρ μέλους
malos
saintTUX
saintTUX
 
Δημοσιεύσεις: 1234
Εγγραφή: 02 Νοέμ 2008, 12:00
Εκτύπωση

Re: Ραδιοφωνάκι με pyqt

Δημοσίευσηαπό Maras » 10 Ιαν 2024, 21:09

Ανέβασε ένα screenshot να δούμε το desktop σου, εάν θέλεις.
“Long is the way, and hard, that out of hell leads up to light.”
Άβαταρ μέλους
Maras
saintTUX
saintTUX
 
Δημοσιεύσεις: 1495
Εγγραφή: 25 Ιούλ 2017, 12:49
Εκτύπωση


Επιστροφή στο Gadgets με Λογισμικό Ανοιχτού Κώδικα