Example #1
0
import kivy

kivy.require("2.0.0")

from kivy.config import Config

Config.set("graphics", "width", "480")
Config.set("graphics", "height", "320")

from audio_player import AudioPlayer
from config_handler import ConfigHandler
from constants import CONFIG_ENABLE_DARK_MODE_KEY
from kivymd.app import MDApp
from muezzin_carousel import MuezzinCarousel

audio_player = AudioPlayer()
config_handler = ConfigHandler()
enable_dark_mode = config_handler.get_setting(CONFIG_ENABLE_DARK_MODE_KEY)


class MuezzinApp(MDApp):
    """
    Main app for Muezzing
    """

    def build(self):
        """
        Sets the icon and theme parameters of Kivy, and returns an instance of the MuezzinCarousel
        :return: an instance of MuezzinCarousel
        """
        self.icon = "res/mosque_green.png"
Example #2
0
playlist = config.get("audio_playlist", {})



comm["audio_players"] = audio_players_count
comm["universe"] =  universe
comm["address"] =  address
comm["audio"] =  {}


artnetReceiver = ArtNetReceiver(universe, comm = comm)

for i in range(audio_players_count):
	# Create Player
	ap = AudioPlayer(address, playlist, artnetReceiver, comm)

	# Get Amount of Channels it is using
	address += ap.getDMXFootprint() or 4

	ap.printDMXFootprint()

	# add player to list
	audio_players[i] = ap

print "Running ArtnetReceiver"
artnetReceiver.start()

while True:
    try:
        time.sleep(5)
Example #3
0
class Artemis(QMainWindow, Ui_MainWindow):
    """Main application class."""
    def __init__(self):
        """Set all connections of the application."""
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("ARTΣMIS " + __VERSION__)
        self.set_initial_size()
        self.closing = False
        self.download_window = DownloadWindow()
        self.download_window.complete.connect(self.action_after_download)
        self.actionExit.triggered.connect(qApp.quit)
        self.action_update_database.triggered.connect(self.ask_if_download)
        self.action_check_db_ver.triggered.connect(self.check_db_ver)
        self.action_sigidwiki_com.triggered.connect(
            lambda: webbrowser.open(Constants.SIGIDWIKI))
        self.action_add_a_signal.triggered.connect(
            lambda: webbrowser.open(Constants.ADD_SIGNAL_LINK))
        self.action_aresvalley_com.triggered.connect(
            lambda: webbrowser.open(Constants.ARESVALLEY_LINK))
        self.action_forum.triggered.connect(
            lambda: webbrowser.open(Constants.FORUM_LINK))
        self.action_rtl_sdr_com.triggered.connect(
            lambda: webbrowser.open(Constants.RTL_SDL_LINK))
        self.action_github.triggered.connect(
            lambda: webbrowser.open(Constants.GITHUB_REPO))
        self.db = None
        self.current_signal_name = ''
        self.signal_names = []
        self.total_signals = 0

        # Forecast
        self.forecast_info_btn.clicked.connect(
            lambda: webbrowser.open(Constants.SPACE_WEATHER_INFO))
        self.forecast_data = ForecastData(self)
        self.update_forecast_bar.clicked.connect(self.start_update_forecast)
        self.update_forecast_bar.set_idle()
        self.forecast_data.update_complete.connect(self.update_forecast)

        # Spaceweather manager
        self.spaceweather_screen = SpaceWeatherManager(self)

        self.theme_manager = ThemeManager(self)

        self.filters = Filters(self)

        # #######################################################################################

        UrlColors = namedtuple("UrlColors", ["inactive", "active", "clicked"])
        self.url_button.colors = UrlColors("#9f9f9f", "#4c75ff", "#942ccc")
        self.category_labels = [
            self.cat_mil, self.cat_rad, self.cat_active, self.cat_inactive,
            self.cat_ham, self.cat_comm, self.cat_avi, self.cat_mar,
            self.cat_ana, self.cat_dig, self.cat_trunked, self.cat_utility,
            self.cat_sat, self.cat_navi, self.cat_interf, self.cat_num_stat,
            self.cat_time_sig
        ]

        self.property_labels = [
            self.freq_lab, self.band_lab, self.mode_lab, self.modul_lab,
            self.loc_lab, self.acf_lab, self.description_text
        ]

        self.url_button.clicked.connect(self.go_to_web_page_signal)

        # GFD
        self.freq_search_gfd_btn.clicked.connect(
            partial(self.go_to_gfd, GfdType.FREQ))
        self.location_search_gfd_btn.clicked.connect(
            partial(self.go_to_gfd, GfdType.LOC))
        self.gfd_line_edit.returnPressed.connect(
            partial(self.go_to_gfd, GfdType.LOC))

        # ##########################################################################################

        # Left list widget and search bar.
        self.search_bar.textChanged.connect(self.display_signals)
        self.signals_list.currentItemChanged.connect(self.display_specs)
        self.signals_list.itemDoubleClicked.connect(self.set_visible_tab)

        self.audio_widget = AudioPlayer(self.play, self.pause, self.stop,
                                        self.volume, self.loop,
                                        self.audio_progress, self.active_color,
                                        self.inactive_color)

        BandLabel = namedtuple("BandLabel", ["left", "center", "right"])
        self.band_labels = [
            BandLabel(self.elf_left, self.elf, self.elf_right),
            BandLabel(self.slf_left, self.slf, self.slf_right),
            BandLabel(self.ulf_left, self.ulf, self.ulf_right),
            BandLabel(self.vlf_left, self.vlf, self.vlf_right),
            BandLabel(self.lf_left, self.lf, self.lf_right),
            BandLabel(self.mf_left, self.mf, self.mf_right),
            BandLabel(self.hf_left, self.hf, self.hf_right),
            BandLabel(self.vhf_left, self.vhf, self.vhf_right),
            BandLabel(self.uhf_left, self.uhf, self.uhf_right),
            BandLabel(self.shf_left, self.shf, self.shf_right),
            BandLabel(self.ehf_left, self.ehf, self.ehf_right),
        ]

        self.main_tab.currentChanged.connect(self.hide_show_right_widget)

        self.updates_controller = UpdatesController(__LATEST_VERSION__, self)
        self.updates_controller.start()
        self.action_check_software_version.triggered.connect(
            self.updates_controller.start_verify_software_version)

        # Final operations.
        self.theme_manager.start()
        self.load_db()
        self.display_signals()

    def action_after_download(self):
        """Decide what to do after a successful download.

        If a new database was downloaded, show the signals."""
        if self.download_window.target is DownloadTarget.DATA_FOLDER:
            self.show_downloaded_signals()

    @pyqtSlot()
    def hide_show_right_widget(self):
        """Hide the audio player when forecast tabs are displayed."""
        if self.main_tab.currentWidget() == self.forecast_tab:
            self.fixed_audio_and_image.setVisible(False)
        elif not self.fixed_audio_and_image.isVisible():
            self.fixed_audio_and_image.setVisible(True)

    @pyqtSlot()
    def set_visible_tab(self):
        """Set the current main tab when double-clicking a signal name.

        Switch between main and filter tab when double-clicking multiple times."""
        set_main = False
        if self.main_tab.currentWidget() != self.signal_properties_tab:
            self.main_tab.setCurrentWidget(self.signal_properties_tab)
            set_main = True
        if self.signal_tab.currentWidget() != self.signal_main_tab or set_main:
            self.signal_tab.setCurrentWidget(self.signal_main_tab)
        else:
            self.signal_tab.setCurrentWidget(self.filter_tab)

    @pyqtSlot()
    def start_update_forecast(self):
        """Start the update of the 3-day forecast screen.

        Start the corresponding thread.
        """
        if not self.forecast_data.is_updating:
            self.update_forecast_bar.set_updating()
            self.forecast_data.update()

    @pyqtSlot(bool)
    def update_forecast(self, status_ok):
        """Update the 3-day forecast screen after a successful download.

        If the download was not successful throw a warning. In any case remove
        the downloaded data.
        """
        self.update_forecast_bar.set_idle()
        if status_ok:
            self.forecast_data.update_all_labels()
        elif not self.closing:
            pop_up(self,
                   title=Messages.BAD_DOWNLOAD,
                   text=Messages.BAD_DOWNLOAD_MSG).show()
        self.forecast_data.remove_data()

    @pyqtSlot()
    def go_to_gfd(self, by):
        """Open a browser tab with the GFD site.

        Make the search by frequency or location.
        Argument:
        by -- either GfdType.FREQ or GfdType.LOC.
        """
        query = "/?q="
        if by is GfdType.FREQ:
            value_in_mhz = self.freq_gfd.value() \
                * Constants.CONVERSION_FACTORS[self.unit_freq_gfd.currentText()] \
                / Constants.CONVERSION_FACTORS["MHz"]
            query += str(value_in_mhz)
        elif by is GfdType.LOC:
            query += self.gfd_line_edit.text()
        try:
            webbrowser.open(Constants.GFD_SITE + query.lower())
        except Exception:
            pass

    def set_initial_size(self):
        """Handle high resolution screens.

        Set bigger sizes for all the relevant fixed-size widgets.
        """
        d = QDesktopWidget().availableGeometry()
        w = d.width()
        h = d.height()
        self.showMaximized()

        if w > 3000 or h > 2000:
            self.fixed_audio_and_image.setFixedSize(540, 1150)
            self.fixed_audio_and_image.setMaximumSize(540, 1150)
            audio_btn_h, audio_btn_w = 90, 90
            self.play.setFixedSize(audio_btn_h, audio_btn_w)
            self.pause.setFixedSize(audio_btn_h, audio_btn_w)
            self.stop.setFixedSize(audio_btn_h, audio_btn_w)
            self.loop.setFixedSize(audio_btn_h, audio_btn_w)
            self.lower_freq_spinbox.setFixedWidth(200)
            self.upper_freq_spinbox.setFixedWidth(200)
            self.lower_freq_filter_unit.setFixedWidth(120)
            self.upper_freq_filter_unit.setFixedWidth(120)
            self.lower_freq_confidence.setFixedWidth(120)
            self.upper_freq_confidence.setFixedWidth(120)

            self.lower_band_spinbox.setFixedWidth(200)
            self.upper_band_spinbox.setFixedWidth(200)
            self.lower_band_filter_unit.setFixedWidth(120)
            self.upper_band_filter_unit.setFixedWidth(120)
            self.lower_band_confidence.setFixedWidth(120)
            self.upper_band_confidence.setFixedWidth(120)

            self.freq_gfd.setFixedWidth(200)
            self.unit_freq_gfd.setFixedWidth(120)

            self.mode_tree_widget.setMinimumWidth(500)
            self.modulation_list.setMinimumWidth(500)
            self.locations_list.setMinimumWidth(500)

            self.audio_progress.setFixedHeight(20)
            self.volume.setStyleSheet("""
                QSlider::groove:horizontal {
                    height: 12px;
                    background: #7a7a7a;
                    margin: 0 10px;
                    border-radius: 6px
                }
                QSlider::handle:horizontal {
                    background: qlineargradient(x1:0, y1:0, x2:1, y2:1, stop:0 gray, stop:0.5 white, stop:1.0 gray);
                    border: 1px solid #5c5c5c;
                    width: 28px;
                    margin: -8px -8px;
                    border-radius: 14px;
                }
                """)

    @pyqtSlot()
    def download_db(self):
        """Start the database download.

        Do nothing if already downloading.
        """
        if not self.download_window.isVisible():
            self.download_window.activate(
                get_download_target(DownloadTarget.DATA_FOLDER))

    @pyqtSlot()
    def ask_if_download(self):
        """Check if the database is at its latest version.

        If a new database is available automatically start the download.
        If not ask if should download it anyway.
        If already downloading do nothing.
        Handle possible connection errors.
        """
        if not self.download_window.isVisible():
            db_path = os.path.join(Constants.DATA_FOLDER, Database.NAME)
            try:
                with open(db_path, "rb") as file_db:
                    db = file_db.read()
            except Exception:
                self.download_db()
            else:
                try:
                    is_checksum_ok = checksum_ok(db, get_db_hash_code())
                except Exception:
                    pop_up(self,
                           title=Messages.NO_CONNECTION,
                           text=Messages.NO_CONNECTION_MSG).show()
                else:
                    if not is_checksum_ok:
                        self.download_db()
                    else:
                        answer = pop_up(
                            self,
                            title=Messages.UP_TO_DATE,
                            text=Messages.UP_TO_DATE_MSG,
                            informative_text=Messages.DOWNLOAD_ANYWAY_QUESTION,
                            is_question=True,
                            default_btn=QMessageBox.No).exec()
                        if answer == QMessageBox.Yes:
                            self.download_db()

    @pyqtSlot()
    def check_db_ver(self):
        """Check if the database is at its latest version.

        If a new database version is available, ask if it should be downloaded.
        If a new database version is not available display a message.
        If already downloading do nothing.
        Handle possible connection errors.
        """
        if not self.download_window.isVisible():
            db_path = os.path.join(Constants.DATA_FOLDER, Database.NAME)
            answer = None
            try:
                with open(db_path, "rb") as file_db:
                    db = file_db.read()
            except Exception:
                answer = pop_up(
                    self,
                    title=Messages.NO_DB,
                    text=Messages.NO_DB_AVAIL,
                    informative_text=Messages.DOWNLOAD_NOW_QUESTION,
                    is_question=True).exec()
                if answer == QMessageBox.Yes:
                    self.download_db()
            else:
                try:
                    is_checksum_ok = checksum_ok(db, get_db_hash_code())
                except Exception:
                    pop_up(self,
                           title=Messages.NO_CONNECTION,
                           text=Messages.NO_CONNECTION_MSG).show()
                else:
                    if is_checksum_ok:
                        pop_up(self,
                               title=Messages.UP_TO_DATE,
                               text=Messages.UP_TO_DATE_MSG).show()
                    else:
                        answer = pop_up(
                            self,
                            title=Messages.DB_NEW_VER,
                            text=Messages.DB_NEW_VER_MSG,
                            informative_text=Messages.DOWNLOAD_NOW_QUESTION,
                            is_question=True).exec()
                        if answer == QMessageBox.Yes:
                            self.download_db()

    @pyqtSlot()
    def show_downloaded_signals(self):
        """Load and display the database signal list."""
        self.search_bar.setEnabled(True)
        self.load_db()
        self.display_signals()

    def load_db(self):
        """Load the database from file.

        Populate the signals list and set the total number of signals.
        Handle possible missing file error.
        """
        try:
            self.db = read_csv(os.path.join(Constants.DATA_FOLDER,
                                            Database.NAME),
                               sep=Database.DELIMITER,
                               header=None,
                               index_col=0,
                               dtype={name: str
                                      for name in Database.STRINGS},
                               names=Database.NAMES)
        except FileNotFoundError:
            self.search_bar.setDisabled(True)
            answer = pop_up(self,
                            title=Messages.NO_DB,
                            text=Messages.NO_DB_AVAIL,
                            informative_text=Messages.DOWNLOAD_NOW_QUESTION,
                            is_question=True).exec()
            if answer == QMessageBox.Yes:
                self.download_db()
        else:
            # Avoid a crash if there are duplicated signals
            self.db = self.db.groupby(level=0).first()
            self.signal_names = self.db.index
            self.total_signals = len(self.signal_names)
            self.db.fillna(Constants.UNKNOWN, inplace=True)
            self.db[Signal.ACF] = ACFValue.list_from_series(
                self.db[Signal.ACF])
            self.db[Signal.WIKI_CLICKED] = False
            self.update_status_tip(self.total_signals)
            self.signals_list.clear()
            self.signals_list.addItems(self.signal_names)
            self.signals_list.setCurrentItem(None)
            self.modulation_list.addItems(self.collect_list(Signal.MODULATION))
            self.locations_list.addItems(self.collect_list(Signal.LOCATION))

    def collect_list(self, list_property, separator=Constants.FIELD_SEPARATOR):
        """Collect all the entries of a QListWidget.

        Handle multiple entries in one item separated by a separator.
        Keyword argument:
        separator -- the separator character for multiple-entries items.
        """
        values = self.db[list_property]
        values = list(
            set([
                x.strip() for value in values[values != Constants.UNKNOWN]
                for x in value.split(separator)
            ]))
        values.sort()
        values.insert(0, Constants.UNKNOWN)
        return values

    @pyqtSlot()
    def activate_if_toggled(self, radio_btn, *widgets):
        """If radio_btn is toggled, activate all *widgets.

        Do nothing otherwise.
        """
        toggled = radio_btn.isChecked()
        for w in widgets[:
                         -1]:  # Neglect the bool coming from the emitted signal.
            w.setEnabled(toggled)

    @pyqtSlot()
    def display_signals(self):
        """Display all the signal names which matches the applied filters."""
        text = self.search_bar.text()
        available_signals = 0
        for index, signal_name in enumerate(self.signal_names):
            if text.lower() in signal_name.lower() and self.filters.ok(
                    signal_name):
                self.signals_list.item(index).setHidden(False)
                available_signals += 1
            else:
                self.signals_list.item(index).setHidden(True)
        # Remove selected item.
        self.signals_list.setCurrentItem(None)
        self.update_status_tip(available_signals)

    def update_status_tip(self, available_signals):
        """Display the number of displayed signals in the status tip."""
        if available_signals < self.total_signals:
            self.statusbar.setStyleSheet(f'color: {self.active_color}')
        else:
            self.statusbar.setStyleSheet(f'color: {self.inactive_color}')
        self.statusbar.showMessage(
            f"{available_signals} out of {self.total_signals} signals displayed."
        )

    @pyqtSlot(QListWidgetItem, QListWidgetItem)
    def display_specs(self, item, previous_item):
        """Display the signal properties.

        'item' is the item corresponding to the selected signal
        'previous_item' is unused.
        """
        self.display_spectrogram()
        if item is not None:
            self.current_signal_name = item.text()
            self.name_lab.setText(self.current_signal_name)
            self.name_lab.setAlignment(Qt.AlignHCenter)
            current_signal = self.db.loc[self.current_signal_name]
            self.url_button.setEnabled(True)
            if not current_signal.at[Signal.WIKI_CLICKED]:
                self.url_button.setStyleSheet(
                    f"color: {self.url_button.colors.active};")
            else:
                self.url_button.setStyleSheet(
                    f"color: {self.url_button.colors.clicked};")
            category_code = current_signal.at[Signal.CATEGORY_CODE]
            undef_freq = is_undef_freq(current_signal)
            undef_band = is_undef_band(current_signal)
            if not undef_freq:
                self.freq_lab.setText(
                    format_numbers(current_signal.at[Signal.INF_FREQ],
                                   current_signal.at[Signal.SUP_FREQ]))
            else:
                self.freq_lab.setText("Undefined")
            if not undef_band:
                self.band_lab.setText(
                    format_numbers(current_signal.at[Signal.INF_BAND],
                                   current_signal.at[Signal.SUP_BAND]))
            else:
                self.band_lab.setText("Undefined")

            self.mode_lab.setText(current_signal.at[Signal.MODE])
            self.modul_lab.setText(current_signal.at[Signal.MODULATION])
            self.loc_lab.setText(current_signal.at[Signal.LOCATION])
            self.acf_lab.setText(
                ACFValue.concat_strings(current_signal.at[Signal.ACF]))
            self.description_text.setText(
                current_signal.at[Signal.DESCRIPTION])
            for cat, cat_lab in zip(category_code, self.category_labels):
                if cat == '0':
                    cat_lab.setStyleSheet(f"color: {self.inactive_color};")
                elif cat == '1':
                    cat_lab.setStyleSheet(f"color: {self.active_color};")
            self.set_band_range(current_signal)
            self.audio_widget.set_audio_player(self.current_signal_name)
        else:
            self.url_button.setEnabled(False)
            self.url_button.setStyleSheet(
                f"color: {self.url_button.colors.inactive};")
            self.current_signal_name = ''
            self.name_lab.setText("No Signal")
            self.name_lab.setAlignment(Qt.AlignHCenter)
            for lab in self.property_labels:
                lab.setText(Constants.UNKNOWN)
            for lab in self.category_labels:
                lab.setStyleSheet(f"color: {self.inactive_color};")
            self.set_band_range()
            self.audio_widget.set_audio_player()

    def display_spectrogram(self):
        """Display the selected signal's waterfall."""
        default_pic = Constants.DEFAULT_NOT_SELECTED
        item = self.signals_list.currentItem()
        if item:
            spectrogram_name = item.text()
            path_spectr = os.path.join(
                Constants.SPECTRA_FOLDER,
                spectrogram_name + Constants.SPECTRA_EXT)
            if not QFileInfo(path_spectr).exists():
                path_spectr = Constants.DEFAULT_NOT_AVAILABLE
        else:
            path_spectr = default_pic
        self.spectrogram.setPixmap(QPixmap(path_spectr))

    def activate_band_category(self, band_label, activate=True):
        """Highlight the given band_label.

        If activate is False remove the highlight (default to True).
        """
        color = self.active_color if activate else self.inactive_color
        for label in band_label:
            label.setStyleSheet(f"color: {color};")

    def set_band_range(self, current_signal=None):
        """Highlight the signal's band labels.

        If no signal is selected remove all highlights.
        """
        if current_signal is not None and not is_undef_freq(current_signal):
            lower_freq = safe_cast(current_signal.at[Signal.INF_FREQ], int)
            upper_freq = safe_cast(current_signal.at[Signal.SUP_FREQ], int)
            zipped = list(zip(Constants.BANDS, self.band_labels))
            for i, w in enumerate(zipped):
                band, band_label = w
                if lower_freq >= band.lower and lower_freq < band.upper:
                    self.activate_band_category(band_label)
                    for uband, uband_label in zipped[i + 1:]:
                        if upper_freq > uband.lower:
                            self.activate_band_category(uband_label)
                        else:
                            self.activate_band_category(uband_label, False)
                    break
                else:
                    self.activate_band_category(band_label, False)
        else:
            for band_label in self.band_labels:
                self.activate_band_category(band_label, False)

    @pyqtSlot()
    def go_to_web_page_signal(self):
        """Go the web page of the signal's wiki.

        Do nothing if no signal is selected.
        """
        if self.current_signal_name:
            self.url_button.setStyleSheet(
                f"color: {self.url_button.colors.clicked}")
            webbrowser.open(self.db.at[self.current_signal_name, Signal.URL])
            self.db.at[self.current_signal_name, Signal.WIKI_CLICKED] = True

    def closeEvent(self, event):
        """Extends closeEvent of QMainWindow.

        Shutdown all active threads and close all open windows."""
        self.closing = True
        if self.download_window.isVisible():
            self.download_window.close()
        if self.space_weather_data.is_updating:
            self.space_weather_data.shutdown_thread()
        if self.forecast_data.is_updating:
            self.forecast_data.shutdown_thread()
        super().closeEvent(event)
Example #4
0
    def __init__(self):
        """Set all connections of the application."""
        super().__init__()
        self.setupUi(self)
        self.setWindowTitle("ARTΣMIS " + __VERSION__)
        self.set_initial_size()
        self.closing = False
        self.download_window = DownloadWindow()
        self.download_window.complete.connect(self.action_after_download)
        self.actionExit.triggered.connect(qApp.quit)
        self.action_update_database.triggered.connect(self.ask_if_download)
        self.action_check_db_ver.triggered.connect(self.check_db_ver)
        self.action_sigidwiki_com.triggered.connect(
            lambda: webbrowser.open(Constants.SIGIDWIKI))
        self.action_add_a_signal.triggered.connect(
            lambda: webbrowser.open(Constants.ADD_SIGNAL_LINK))
        self.action_aresvalley_com.triggered.connect(
            lambda: webbrowser.open(Constants.ARESVALLEY_LINK))
        self.action_forum.triggered.connect(
            lambda: webbrowser.open(Constants.FORUM_LINK))
        self.action_rtl_sdr_com.triggered.connect(
            lambda: webbrowser.open(Constants.RTL_SDL_LINK))
        self.action_github.triggered.connect(
            lambda: webbrowser.open(Constants.GITHUB_REPO))
        self.db = None
        self.current_signal_name = ''
        self.signal_names = []
        self.total_signals = 0

        # Forecast
        self.forecast_info_btn.clicked.connect(
            lambda: webbrowser.open(Constants.SPACE_WEATHER_INFO))
        self.forecast_data = ForecastData(self)
        self.update_forecast_bar.clicked.connect(self.start_update_forecast)
        self.update_forecast_bar.set_idle()
        self.forecast_data.update_complete.connect(self.update_forecast)

        # Spaceweather manager
        self.spaceweather_screen = SpaceWeatherManager(self)

        self.theme_manager = ThemeManager(self)

        self.filters = Filters(self)

        # #######################################################################################

        UrlColors = namedtuple("UrlColors", ["inactive", "active", "clicked"])
        self.url_button.colors = UrlColors("#9f9f9f", "#4c75ff", "#942ccc")
        self.category_labels = [
            self.cat_mil, self.cat_rad, self.cat_active, self.cat_inactive,
            self.cat_ham, self.cat_comm, self.cat_avi, self.cat_mar,
            self.cat_ana, self.cat_dig, self.cat_trunked, self.cat_utility,
            self.cat_sat, self.cat_navi, self.cat_interf, self.cat_num_stat,
            self.cat_time_sig
        ]

        self.property_labels = [
            self.freq_lab, self.band_lab, self.mode_lab, self.modul_lab,
            self.loc_lab, self.acf_lab, self.description_text
        ]

        self.url_button.clicked.connect(self.go_to_web_page_signal)

        # GFD
        self.freq_search_gfd_btn.clicked.connect(
            partial(self.go_to_gfd, GfdType.FREQ))
        self.location_search_gfd_btn.clicked.connect(
            partial(self.go_to_gfd, GfdType.LOC))
        self.gfd_line_edit.returnPressed.connect(
            partial(self.go_to_gfd, GfdType.LOC))

        # ##########################################################################################

        # Left list widget and search bar.
        self.search_bar.textChanged.connect(self.display_signals)
        self.signals_list.currentItemChanged.connect(self.display_specs)
        self.signals_list.itemDoubleClicked.connect(self.set_visible_tab)

        self.audio_widget = AudioPlayer(self.play, self.pause, self.stop,
                                        self.volume, self.loop,
                                        self.audio_progress, self.active_color,
                                        self.inactive_color)

        BandLabel = namedtuple("BandLabel", ["left", "center", "right"])
        self.band_labels = [
            BandLabel(self.elf_left, self.elf, self.elf_right),
            BandLabel(self.slf_left, self.slf, self.slf_right),
            BandLabel(self.ulf_left, self.ulf, self.ulf_right),
            BandLabel(self.vlf_left, self.vlf, self.vlf_right),
            BandLabel(self.lf_left, self.lf, self.lf_right),
            BandLabel(self.mf_left, self.mf, self.mf_right),
            BandLabel(self.hf_left, self.hf, self.hf_right),
            BandLabel(self.vhf_left, self.vhf, self.vhf_right),
            BandLabel(self.uhf_left, self.uhf, self.uhf_right),
            BandLabel(self.shf_left, self.shf, self.shf_right),
            BandLabel(self.ehf_left, self.ehf, self.ehf_right),
        ]

        self.main_tab.currentChanged.connect(self.hide_show_right_widget)

        self.updates_controller = UpdatesController(__LATEST_VERSION__, self)
        self.updates_controller.start()
        self.action_check_software_version.triggered.connect(
            self.updates_controller.start_verify_software_version)

        # Final operations.
        self.theme_manager.start()
        self.load_db()
        self.display_signals()
Example #5
0
    def __init__(self):
        pygame.mixer.pre_init(frequency=44100, size=-16, channels=2)
        pygame.init()

        self.clock = Clock()

        info = pygame.display.Info()

        self.size = self.width, self.height = int(info.current_w *
                                                  .75), info.current_h
        self.screen = pygame.display.set_mode(self.size,
                                              flags=pygame.SCALED
                                              | pygame.FULLSCREEN,
                                              vsync=True)
        pygame.display.set_icon(pygame.image.load('img/icon.png'))

        if isfile('library/saved.library'):
            self.library = load(open('library/saved.library', 'rb'))
        else:
            self.library = Library()

        pygame.mouse.set_visible(False)

        self.screen_calls = [
            self.close_menu, self.draw_menu, self.draw_settings,
            self.draw_track_select, self.draw_track_setup, self.draw_new_track,
            self.draw_edit_track, self.draw_search
        ]

        self.delay_time = 2  # Pre-track delay time

        # Audio player
        self.audio_device = 1
        self.audio_player = AudioPlayer(self.delay_time)
        self.audio_player.set_device(self.audio_device)
        self.latency = self.audio_player.device.get_output_latency() * 0

        # In-game options
        self.layers_keys = {
            'A': [True, None],
            'B': [True, None],
            'C': [True, None],
            'D': [True, None],
            'E': [True, None],
            'F': [True, None]
        }
        self.prune_unused_layers = False

        # Difficulty
        self.preview_length = .6
        self.lenience = 0.06  # seconds +/- per beat

        # Fonts
        self.large_font = Font('font/unifont.ttf', 36)
        self.generic_font = Font('font/unifont.ttf', 26)
        self.small_font = Font('font/unifont.ttf', 16)

        # Sound Effects
        self.play_hit_sound = True
        self.bass_hit_sound_data = pygame.mixer.Sound(
            open('audio/bass.wav', 'rb').read())
        self.high_hit_sound_data = pygame.mixer.Sound(
            open('audio/high.wav', 'rb').read())
        pygame.mixer.set_num_channels(2)

        # GUI variables
        self.redraw_screen = True
        self.current_screen = Menu.TITLE
        self.last_screen = Menu.TITLE
        self.track_selection_index = 0
        '''
        Main menu screen objects
        '''
        self.main_title = self.large_font.render('RIZUMU', True, Menu.WHITE)
        self.main_title_box = self.main_title.get_rect()
        self.main_title_box.center = self.width / 2, 200

        self.main_play = self.large_font.render('Play', True,
                                                Menu.SELECTED_COLOR)
        self.main_play_box = self.main_play.get_rect()
        self.main_play_box.center = self.width / 2, 400

        self.main_settings = self.large_font.render(f'Settings', True,
                                                    Menu.WHITE)
        self.main_settings_box = self.main_settings.get_rect()
        self.main_settings_box.center = self.width / 2, 500
        '''
        Settings screen objects
        '''
        '''
        Track select screen objects
        '''
        self.selected_tracks = self.library.get_tracks(
            self.track_selection_index)
        self.select_track_0 = None
        self.select_track_1 = None
        self.select_track_2 = None
        self.select_track_3 = None
        self.select_track_4 = None
        self.select_track_5 = None
        self.select_track_6 = None

        self.render_selected_tracks()

        self.select_track_title = None
        self.select_track_artist = None
        self.select_track_album = None
        self.select_track_high_score = None
        self.select_track_high_score_accuracy = None
        self.select_track_high_score_layers = None
        self.select_track_duration = None
        self.select_track_difficulty = None
        self.select_track_num_beats_A = None
        self.select_track_num_beats_B = None
        self.select_track_num_beats_C = None
        self.select_track_num_beats_D = None
        self.select_track_num_beats_E = None
        self.select_track_num_beats_F = None

        self.render_selected_track_data()

        self.select_edit = self.generic_font.render('e: Edit', True,
                                                    Menu.WHITE)
        self.select_new = self.generic_font.render('n: New', True, Menu.WHITE)
        self.select_back = self.generic_font.render('⌫ : Back', True,
                                                    Menu.WHITE)
        self.select_play = self.generic_font.render('⏎ : Play', True,
                                                    Menu.WHITE)
        '''
        Track setup screen objects
        '''
        self.setup_toggle = self.generic_font.render('⏎ : Select/Toggle', True,
                                                     Menu.WHITE)
        self.setup_back = self.select_back
        '''
        New track screen objects
        '''
        self.new_track_edit = self.generic_font.render(
            '⏎ : Paste from clipboard', True, Menu.WHITE)
        self.new_track_save = self.generic_font.render('s: Save', True,
                                                       Menu.WHITE)
        self.new_track_cancel = self.generic_font.render(
            '⌫ : Cancel', True, Menu.WHITE)
        '''
        Edit track screen objects
        '''
        self.edit_track_delete = self.generic_font.render(
            'd: Delete', True, Menu.WHITE)
        '''
        Search track screen objects
        '''

        # Start drawing
        self.display_loop()
Example #6
0
def process_single_video(video_dir,
                         output_dir,
                         face_detection_model,
                         face_validation_model,
                         speaker_validation,
                         output_video_dir=None):
    # 将视频音轨导出到临时文件夹中,采样率为16000
    audio_tmp = os.path.join(config.temp_dir, 'audio.wav')
    command = (
        "ffmpeg -y -i %s -async 1 -ac 1 -vn -acodec pcm_s16le -ar 16000 %s > %s 2>&1"
        % (video_dir, audio_tmp, os.path.join(config.log_dir, "ffmpeg.log")))
    output = subprocess.call(command, shell=True, stdout=None)
    sample_rate, audio = wavfile.read(audio_tmp)
    # print(audio.shape)

    # 打开标签输出文件
    predict_results = open(output_dir, "w")
    # predict_results = open(os.path.join(os.getcwd(), 'result', POI, POI + '-' + str(config.video_num) + '.txt'), "w")

    # 初始化临时变量
    tracker_list = []
    candidates = []
    series_id = 0

    # 验证视频帧数
    cap = cv2.VideoCapture(video_dir)
    video_fps = cap.get(cv2.CAP_PROP_FPS)
    video_total_frame = cap.get(7)
    if config.enable_syncnet:
        assert video_fps == 25
    print("Video FPS:", video_fps)

    # 是否输出视频,若需要,则需要传入额外参数output_video_dir
    if config.write_video:
        videoWriter = cv2.VideoWriter(
            os.path.join(output_video_dir, 'song.avi'),
            cv2.VideoWriter_fourcc(*'XVID'), video_fps, (1280, 720))

    # 视频宽度大于1280时,缩放至 1280 * 720
    if cap.get(cv2.CAP_PROP_FRAME_WIDTH) > 1280:
        need_to_resize = True
    else:
        need_to_resize = False

    # 跳读n帧 debug 过程中使用,实际运行中不可跳读
    # start_frame = 0
    # cap.set(cv2.CAP_PROP_POS_FRAMES, start_frame)
    # shot_count = start_frame - 1

    shot_count = 0

    print("\033[94mstart process\033[0m")
    print("total frames: %s.." % (video_total_frame))
    video_type = video_dir.split("/")[-2]
    if config.enable_multi_conf:
        if video_type == "interview" or video_type == "speech":
            config.starting_confidence = config.easy_starting_confidence
            config.patient_confidence = config.easy_patient_confidence
        elif "entertain" in video_type or "tv" in video_type:
            config.starting_confidence = config.hard_starting_confidence
            config.patient_confidence = config.hard_patient_confidence
        else:
            config.starting_confidence = config.normal_starting_confidence
            config.patient_confidence = config.normal_patient_confidence
    # print("\033[94mthreshold:  %s & %s\033[0m" % (str(config.starting_confidence), str(config.patient_confidence)))
    start_time = time.time()
    while True:
        # resize
        if need_to_resize:
            success, raw_image = cap.read()
            if not success:
                break
            raw_image = cv2.resize(raw_image, (1280, 720))
        else:
            success, raw_image = cap.read()
        if not success:
            break
        image = raw_image.copy()
        bboxes, landmarks = face_detection_model.update(raw_image)

        # track
        new_tracker_list = []
        for tracker in tracker_list:
            tracked, bbox = tracker.update(raw_image, shot_count)
            # if target lost, start SyncNet process
            if tracked is False:
                if config.debug:
                    print("tracking failed")
                if config.enable_syncnet:
                    if config.debug:
                        print(16000 * tracker.start_shot // video_fps,
                              16000 * (tracker.end_shot) // video_fps)

                    # 默认视频帧速率为25时,截取相应音频并验证长度是否合规
                    part_audio = audio[int(16000 * tracker.start_shot //
                                           video_fps):int(16000 *
                                                          (tracker.end_shot) //
                                                          video_fps)]
                    if len(part_audio) != len(
                            tracker.sync_seq) * 16000 // video_fps:
                        print("fatal: video and audio does not match")
                        print("startshot", tracker.start_shot)
                        print("endshot", tracker.end_shot)
                        print(tracker.series_name)
                        print(len(tracker.sync_seq))
                        print(len(part_audio))
                        # exit(-1)]
                    if config.debug:
                        wavfile.write('temp/segment.wav', 16000, part_audio)
                        player = AudioPlayer('temp/segment.wav')

                    # 分别使用原音轨和空音轨调用 SyncNet,对于空音轨中置信度高于 的部分,将原音轨中计算出的相应置信度置零
                    offset, confidence, dists_npy = speaker_validation.evaluate(
                        video_fps, tracker.sync_seq, part_audio)
                    silent_audio = np.zeros(part_audio.shape,
                                            dtype=audio.dtype)
                    __, conf_silent, __ = speaker_validation.evaluate(
                        video_fps, tracker.sync_seq, silent_audio)
                    # print(conf_silent)
                    confidence[conf_silent > config.conf_silent_threshold] = 0
                    # confidence = conf_silent

                    # debug 模式下输出额外信息
                    if config.debug:
                        print("Sequence length:", len(tracker.sync_seq))
                        debug_cap = cv2.VideoCapture(video_dir)
                        debug_cap.set(1, tracker.start_shot)
                        player.play()
                        for i in range(len(tracker.sync_seq)):
                            if i < 6:
                                if need_to_resize:
                                    __, img = debug_cap.read()
                                    img = cv2.resize(img, (1280, 720))
                                else:
                                    __, img = debug_cap.read()
                                cv2.imshow('Speaking', img)
                                cv2.waitKey(40)
                            else:
                                if need_to_resize:
                                    __, img = debug_cap.read()
                                    img = cv2.resize(img, (1280, 720))
                                else:
                                    __, img = debug_cap.read()
                                box = tracker.bbox_seq[i]
                                lip_box = tracker.lip_box_seq[i]
                                try:
                                    confidence_caption = 'Conf: %.3f' % (
                                        confidence[i - 6])
                                    clr = int(
                                        max(min(confidence[i - 6] * 30, 255),
                                            0))
                                    cv2.rectangle(img, (box[0], box[1]),
                                                  (box[2], box[3]),
                                                  (0, clr, 255 - clr), 2,
                                                  cv2.LINE_AA)
                                    cv2.rectangle(img,
                                                  (lip_box[2], lip_box[0]),
                                                  (lip_box[3], lip_box[1]),
                                                  (255, 0, 0), 2, cv2.LINE_AA)
                                except:
                                    confidence_caption = 'Conf: exceeded'
                                    cv2.rectangle(img, (box[0], box[1]),
                                                  (box[2], box[3]),
                                                  (0, 0, 255), 2, cv2.LINE_AA)
                                cv2.putText(img, confidence_caption,
                                            (int(box[0]), int(box[1]) + 20),
                                            cv2.FONT_HERSHEY_PLAIN, 1,
                                            (0, 0, 0), 2)
                                cv2.putText(img, confidence_caption,
                                            (int(box[0]), int(box[1]) + 20),
                                            cv2.FONT_HERSHEY_PLAIN, 1,
                                            (255, 255, 255), 1)
                                cv2.imshow('Speaking', img)
                                cv2.waitKey(40)
                        cv2.waitKey(0)
                    prelabels = speaker_validation.verification(
                        confidence, tracker.start_shot, predict_results)
                    candidates = candidates + prelabels
            else:
                new_tracker_list.append(tracker)
        tracker_list = new_tracker_list

        # for each face detected
        for boundary, landmark in zip(bboxes, landmarks):
            boundary = boundary.astype(np.int)
            center = [
                int((boundary[1] + boundary[3]) / 2),
                int((boundary[0] + boundary[2]) / 2)
            ]
            validation = face_validation_model.confirm_validity(
                raw_image, boundary=boundary, landmark=landmark)

            if validation:
                caption = "Yes"
                # 验证该人脸是否已经被某个追踪器追踪
                tracking = isTracking((center[1], center[0]), tracker_list)
                lip_center = np.mean(landmark[3:], axis=0)
                # new target
                if not tracking:
                    series_id += 1
                    new_tracker = CV_Tracker(raw_image, boundary, series_id,
                                             lip_center, shot_count)
                    tracker_list.append(new_tracker)
                else:
                    # 验证追踪器是否追踪到该人脸
                    for tracker in tracker_list:
                        if tracker.valid is True:
                            continue
                        if tracker.is_valid(center):
                            # build lip picture sequence
                            tracker.update_lip_seq(raw_image, boundary,
                                                   lip_center)
            else:
                caption = "No"

            # showimg 模式下输出人脸检测,识别,追踪信息
            if config.showimg:
                cv2.rectangle(image, (boundary[0], boundary[1]),
                              (boundary[2], boundary[3]), (0, 255, 0), 2,
                              cv2.LINE_AA)
                index_color = 0
                for point in landmark:
                    pos = (point[0], point[1])
                    cv2.circle(image, pos, 1,
                               (255, 255, 255 / 68 * index_color), -1)
                    index_color = index_color + 1
                # lip center
                lip_center = np.mean(landmark[3:], axis=0)
                cv2.circle(image, (lip_center[0], lip_center[1]), 1, (0, 0, 0),
                           -1)
                for tracker in tracker_list:
                    if tracker.tracked is True:
                        bbox = tracker.bbox
                        cv2.rectangle(
                            image, (int(bbox[0]), int(bbox[1])),
                            (int(bbox[2] + bbox[0]), int(bbox[3] + bbox[1])),
                            (255, 0, 0), 2, cv2.LINE_AA)
                        cv2.putText(image, str(tracker.series_name),
                                    (int(bbox[0]), int(bbox[1]) - 10),
                                    cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 0), 2)
                        cv2.putText(image, str(tracker.series_name),
                                    (int(bbox[0]), int(bbox[1]) - 10),
                                    cv2.FONT_HERSHEY_PLAIN, 1, (255, 255, 255),
                                    1)
                    else:
                        print("Warning a invalid tracker was not removed")
                cv2.putText(image, str(caption),
                            (boundary[0], boundary[1] - 10),
                            cv2.FONT_HERSHEY_PLAIN, 1, (0, 0, 0), 2)
                cv2.putText(image, str(caption),
                            (boundary[0], boundary[1] - 10),
                            cv2.FONT_HERSHEY_PLAIN, 1, (255, 255, 255), 1)

        # 对于追踪区域中没有人脸的tracker,判断是否需要关闭tracker
        new_tracker_list = []
        for tracker in tracker_list:
            if tracker.valid is False:
                tracker.drop_count += 1
                tracker.update_lip_seq(raw_image, None, None)
            if tracker.drop():
                tracker.set_end_shot(shot_count)
                if config.debug:
                    print("tracker missed the target")
                # 关闭 tracker 前,处理tracker保存的视频序列
                if config.enable_syncnet:
                    part_audio = audio[int(16000 // video_fps *
                                           tracker.start_shot
                                           ):int(16000 // video_fps *
                                                 (tracker.end_shot -
                                                  config.patience + 1))]
                    if len(part_audio) != len(
                            tracker.sync_seq[:-config.patience]
                    ) * 16000 // video_fps:
                        print("fatal: video and audio does not match")
                        print("startshot", tracker.start_shot)
                        print("endshot", tracker.end_shot)
                        print(len(tracker.sync_seq))
                        print(len(part_audio))
                        # exit(-2)
                    if config.debug:
                        wavfile.write('temp/segment.wav', 16000, part_audio)
                        player = AudioPlayer('temp/segment.wav')

                    offset, confidence, dists_npy = speaker_validation.evaluate(
                        video_fps, tracker.sync_seq[:-config.patience],
                        part_audio)
                    silent_audio = np.zeros(part_audio.shape,
                                            dtype=audio.dtype)
                    __, conf_silent, __ = speaker_validation.evaluate(
                        video_fps, tracker.sync_seq[:-config.patience],
                        silent_audio)
                    # print(conf_silent)
                    confidence[conf_silent > config.conf_silent_threshold] = 0
                    # confidence = conf_silent

                    if config.debug:
                        print("Sequence length:",
                              len(tracker.sync_seq[:-config.patience]))

                        debug_cap = cv2.VideoCapture(video_dir)
                        debug_cap.set(1, tracker.start_shot)
                        player.play()
                        for i in range(
                                len(tracker.sync_seq) - config.patience):
                            if i < 6:
                                if need_to_resize:
                                    __, img = debug_cap.read()
                                    img = cv2.resize(img, (1280, 720))
                                else:
                                    __, img = debug_cap.read()
                                cv2.imshow('Speaking', img)
                                cv2.waitKey(40)
                            else:
                                if need_to_resize:
                                    __, img = debug_cap.read()
                                    img = cv2.resize(img, (1280, 720))
                                else:
                                    __, img = debug_cap.read()
                                box = tracker.bbox_seq[i]
                                lip_box = tracker.lip_box_seq[i]
                                try:
                                    confidence_caption = 'Conf: %.3f' % (
                                        confidence[i - 6])
                                    clr = int(
                                        max(min(confidence[i - 6] * 30, 255),
                                            0))
                                    cv2.rectangle(img, (box[0], box[1]),
                                                  (box[2], box[3]),
                                                  (0, clr, 255 - clr), 2,
                                                  cv2.LINE_AA)
                                    cv2.rectangle(img,
                                                  (lip_box[2], lip_box[0]),
                                                  (lip_box[3], lip_box[1]),
                                                  (255, 0, 0), 2, cv2.LINE_AA)
                                except:
                                    confidence_caption = 'Conf: exceeded'
                                    cv2.rectangle(img, (box[0], box[1]),
                                                  (box[2], box[3]),
                                                  (0, 0, 255), 2, cv2.LINE_AA)
                                cv2.putText(img, confidence_caption,
                                            (int(box[0]), int(box[1]) + 20),
                                            cv2.FONT_HERSHEY_PLAIN, 1,
                                            (0, 0, 0), 2)
                                cv2.putText(img, confidence_caption,
                                            (int(box[0]), int(box[1]) + 20),
                                            cv2.FONT_HERSHEY_PLAIN, 1,
                                            (255, 255, 255), 1)
                                cv2.imshow('Speaking', img)
                                cv2.waitKey(40)
                        cv2.waitKey(0)
                    prelabels = speaker_validation.verification(
                        confidence, tracker.start_shot, predict_results)
                    candidates = candidates + prelabels
            else:
                new_tracker_list.append(tracker)
        tracker_list = new_tracker_list

        # 进度展示
        if shot_count % 1000 == 0 and shot_count != 0:
            print('Shot {:d}, FPS {:.2f} '.format(
                shot_count, 1000 / (time.time() - start_time)),
                  end='\n')
            start_time = time.time()

        if config.showimg:
            cv2.imshow('Video', image)
        if config.write_video:
            videoWriter.write(image)
        shot_count += 1

        # 跳出循环
        if cv2.waitKey(10) == 27:
            break

    predict_results.close()

    if config.enable_dataclean:
        dataclean(output_dir, video_total_frame)

    # evaluate
    if config.enable_evaluation:
        index = video_dir.rfind('.')
        FPR, Recall = evaluate_result(video_dir[:index] + ".csv", output_dir,
                                      video_total_frame)
Example #7
0
 def _play_song_thread_func(path):
     a = AudioPlayer()
     a.play_song(path)
     return None
Example #8
0
class Menu:

    EXIT = 0
    TITLE = 1
    SETTINGS = 2
    TRACK_SELECT = 3
    TRACK_SETUP = 4
    NEW_TRACK = 5
    EDIT_TRACK = 6
    SEARCH = 7

    WHITE = (255, 255, 255)
    GRAY = (128, 128, 128)
    A_COLOR = (255, 128, 128)
    B_COLOR = (255, 255, 128)
    C_COLOR = (128, 255, 128)
    D_COLOR = (128, 255, 255)
    E_COLOR = (128, 128, 255)
    F_COLOR = (255, 128, 255)
    SELECTED_COLOR = D_COLOR
    ENABLED_COLOR = C_COLOR
    DISABLED_COLOR = A_COLOR

    DIFFICULTY_COLORS = (C_COLOR, C_COLOR, C_COLOR, B_COLOR, B_COLOR, A_COLOR,
                         D_COLOR, E_COLOR, F_COLOR)

    def __init__(self):
        pygame.mixer.pre_init(frequency=44100, size=-16, channels=2)
        pygame.init()

        self.clock = Clock()

        info = pygame.display.Info()

        self.size = self.width, self.height = int(info.current_w *
                                                  .75), info.current_h
        self.screen = pygame.display.set_mode(self.size,
                                              flags=pygame.SCALED
                                              | pygame.FULLSCREEN,
                                              vsync=True)
        pygame.display.set_icon(pygame.image.load('img/icon.png'))

        if isfile('library/saved.library'):
            self.library = load(open('library/saved.library', 'rb'))
        else:
            self.library = Library()

        pygame.mouse.set_visible(False)

        self.screen_calls = [
            self.close_menu, self.draw_menu, self.draw_settings,
            self.draw_track_select, self.draw_track_setup, self.draw_new_track,
            self.draw_edit_track, self.draw_search
        ]

        self.delay_time = 2  # Pre-track delay time

        # Audio player
        self.audio_device = 1
        self.audio_player = AudioPlayer(self.delay_time)
        self.audio_player.set_device(self.audio_device)
        self.latency = self.audio_player.device.get_output_latency() * 0

        # In-game options
        self.layers_keys = {
            'A': [True, None],
            'B': [True, None],
            'C': [True, None],
            'D': [True, None],
            'E': [True, None],
            'F': [True, None]
        }
        self.prune_unused_layers = False

        # Difficulty
        self.preview_length = .6
        self.lenience = 0.06  # seconds +/- per beat

        # Fonts
        self.large_font = Font('font/unifont.ttf', 36)
        self.generic_font = Font('font/unifont.ttf', 26)
        self.small_font = Font('font/unifont.ttf', 16)

        # Sound Effects
        self.play_hit_sound = True
        self.bass_hit_sound_data = pygame.mixer.Sound(
            open('audio/bass.wav', 'rb').read())
        self.high_hit_sound_data = pygame.mixer.Sound(
            open('audio/high.wav', 'rb').read())
        pygame.mixer.set_num_channels(2)

        # GUI variables
        self.redraw_screen = True
        self.current_screen = Menu.TITLE
        self.last_screen = Menu.TITLE
        self.track_selection_index = 0
        '''
        Main menu screen objects
        '''
        self.main_title = self.large_font.render('RIZUMU', True, Menu.WHITE)
        self.main_title_box = self.main_title.get_rect()
        self.main_title_box.center = self.width / 2, 200

        self.main_play = self.large_font.render('Play', True,
                                                Menu.SELECTED_COLOR)
        self.main_play_box = self.main_play.get_rect()
        self.main_play_box.center = self.width / 2, 400

        self.main_settings = self.large_font.render(f'Settings', True,
                                                    Menu.WHITE)
        self.main_settings_box = self.main_settings.get_rect()
        self.main_settings_box.center = self.width / 2, 500
        '''
        Settings screen objects
        '''
        '''
        Track select screen objects
        '''
        self.selected_tracks = self.library.get_tracks(
            self.track_selection_index)
        self.select_track_0 = None
        self.select_track_1 = None
        self.select_track_2 = None
        self.select_track_3 = None
        self.select_track_4 = None
        self.select_track_5 = None
        self.select_track_6 = None

        self.render_selected_tracks()

        self.select_track_title = None
        self.select_track_artist = None
        self.select_track_album = None
        self.select_track_high_score = None
        self.select_track_high_score_accuracy = None
        self.select_track_high_score_layers = None
        self.select_track_duration = None
        self.select_track_difficulty = None
        self.select_track_num_beats_A = None
        self.select_track_num_beats_B = None
        self.select_track_num_beats_C = None
        self.select_track_num_beats_D = None
        self.select_track_num_beats_E = None
        self.select_track_num_beats_F = None

        self.render_selected_track_data()

        self.select_edit = self.generic_font.render('e: Edit', True,
                                                    Menu.WHITE)
        self.select_new = self.generic_font.render('n: New', True, Menu.WHITE)
        self.select_back = self.generic_font.render('⌫ : Back', True,
                                                    Menu.WHITE)
        self.select_play = self.generic_font.render('⏎ : Play', True,
                                                    Menu.WHITE)
        '''
        Track setup screen objects
        '''
        self.setup_toggle = self.generic_font.render('⏎ : Select/Toggle', True,
                                                     Menu.WHITE)
        self.setup_back = self.select_back
        '''
        New track screen objects
        '''
        self.new_track_edit = self.generic_font.render(
            '⏎ : Paste from clipboard', True, Menu.WHITE)
        self.new_track_save = self.generic_font.render('s: Save', True,
                                                       Menu.WHITE)
        self.new_track_cancel = self.generic_font.render(
            '⌫ : Cancel', True, Menu.WHITE)
        '''
        Edit track screen objects
        '''
        self.edit_track_delete = self.generic_font.render(
            'd: Delete', True, Menu.WHITE)
        '''
        Search track screen objects
        '''

        # Start drawing
        self.display_loop()

    def render_selected_tracks(self):
        def get_color(track):
            if not track:
                return Menu.WHITE
            else:
                return Menu.DIFFICULTY_COLORS[min(8, int(track.difficulty))]

        self.select_track_0 = self.generic_font.render(
            f'{self.selected_tracks[0]}', True,
            get_color(self.selected_tracks[0]))
        self.select_track_1 = self.generic_font.render(
            f'{self.selected_tracks[1]}', True,
            get_color(self.selected_tracks[1]))
        self.select_track_2 = self.generic_font.render(
            f'{self.selected_tracks[2]}', True,
            get_color(self.selected_tracks[2]))
        self.select_track_3 = self.generic_font.render(
            f'{self.selected_tracks[3]}', True,
            get_color(self.selected_tracks[3]))
        self.select_track_4 = self.generic_font.render(
            f'{self.selected_tracks[4]}', True,
            get_color(self.selected_tracks[4]))
        self.select_track_5 = self.generic_font.render(
            f'{self.selected_tracks[5]}', True,
            get_color(self.selected_tracks[5]))
        self.select_track_6 = self.generic_font.render(
            f'{self.selected_tracks[6]}', True,
            get_color(self.selected_tracks[6]))

    def render_selected_track_data(self):
        if self.selected_tracks[3]:
            color = Menu.DIFFICULTY_COLORS[min(
                8, int(self.selected_tracks[3].difficulty))]
            self.select_track_title = self.large_font.render(
                f'{self.selected_tracks[3].title}', True, color)
            self.select_track_artist = self.generic_font.render(
                f'{self.selected_tracks[3].artist}', True, Menu.WHITE)
            self.select_track_album = self.generic_font.render(
                f'{self.selected_tracks[3].album}', True, Menu.WHITE)
            self.select_track_high_score = self.generic_font.render(
                f'High Score: {self.selected_tracks[3].high_score}', True,
                Menu.WHITE)
            self.select_track_high_score_accuracy = self.generic_font.render(
                f'{self.selected_tracks[3].high_score_accuracy:.3f}%', True,
                Menu.WHITE)
            self.select_track_high_score_layers = self.generic_font.render(
                f'{self.selected_tracks[3].high_score_layers}', True,
                Menu.WHITE)
            self.select_track_duration = self.generic_font.render(
                f'{seconds_to_readable_time(self.selected_tracks[3].duration)}',
                True, Menu.WHITE)
            self.select_track_difficulty = self.generic_font.render(
                f'Difficulty: {self.selected_tracks[3].difficulty}', True,
                color)

            self.select_track_num_beats_A = self.generic_font.render(
                f'{self.selected_tracks[3].num_beats["A"]}', True,
                Menu.A_COLOR)
            self.select_track_num_beats_B = self.generic_font.render(
                f'{self.selected_tracks[3].num_beats["B"]}', True,
                Menu.B_COLOR)
            self.select_track_num_beats_C = self.generic_font.render(
                f'{self.selected_tracks[3].num_beats["C"]}', True,
                Menu.C_COLOR)
            self.select_track_num_beats_D = self.generic_font.render(
                f'{self.selected_tracks[3].num_beats["D"]}', True,
                Menu.D_COLOR)
            self.select_track_num_beats_E = self.generic_font.render(
                f'{self.selected_tracks[3].num_beats["E"]}', True,
                Menu.E_COLOR)
            self.select_track_num_beats_F = self.generic_font.render(
                f'{self.selected_tracks[3].num_beats["F"]}', True,
                Menu.F_COLOR)

    def draw_menu(self):
        label_selection_index = 0
        while 1:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.current_screen = Menu.EXIT
                    return
                elif event.type == pygame.KEYDOWN:
                    self.redraw_screen = True
                    if event.key == pygame.K_UP:
                        self.main_play = self.large_font.render(
                            'Play', True, Menu.SELECTED_COLOR)
                        self.main_settings = self.large_font.render(
                            f'Settings', True, Menu.WHITE)
                        label_selection_index = 0
                    elif event.key == pygame.K_DOWN:
                        self.main_play = self.large_font.render(
                            'Play', True, Menu.WHITE)
                        self.main_settings = self.large_font.render(
                            f'Settings', True, Menu.SELECTED_COLOR)
                        label_selection_index = 1
                    elif event.key == pygame.K_RETURN:
                        if label_selection_index == 0:
                            self.current_screen = Menu.TRACK_SELECT
                        elif label_selection_index == 1:
                            self.current_screen = Menu.SETTINGS
                        return
                    elif event.key == pygame.K_BACKSPACE:
                        self.current_screen = Menu.EXIT
                        return

            if self.redraw_screen:
                self.redraw_screen = False
                self.screen.fill((0, 0, 0))

                self.screen.blit(self.main_title, self.main_title_box)
                self.screen.blit(self.main_play, self.main_play_box)
                self.screen.blit(self.main_settings, self.main_settings_box)

                pygame.display.flip()

            self.clock.tick(30)

    def draw_settings(self):
        pass

    # noinspection PyArgumentList
    def draw_track_select(self):
        pygame.key.set_repeat(250, 20)
        while 1:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.current_screen = Menu.EXIT
                    return
                elif event.type == pygame.KEYDOWN:
                    self.redraw_screen = True
                    if event.key == pygame.K_UP:
                        self.track_selection_index = max(
                            self.track_selection_index - 1, 0)
                        self.selected_tracks = self.library.get_tracks(
                            self.track_selection_index)
                        self.render_selected_tracks()
                        self.render_selected_track_data()
                    elif event.key == pygame.K_DOWN:
                        self.track_selection_index = min(
                            self.track_selection_index + 1,
                            len(self.library.saved_tracks) - 1)
                        self.selected_tracks = self.library.get_tracks(
                            self.track_selection_index)
                        self.render_selected_tracks()
                        self.render_selected_track_data()
                    else:
                        if event.key == pygame.K_RETURN:
                            self.current_screen = Menu.TRACK_SETUP
                            return
                        elif event.key == pygame.K_BACKSPACE:
                            self.current_screen = Menu.TITLE
                            return
                        elif event.key == pygame.K_e:
                            self.current_screen = Menu.EDIT_TRACK
                            return
                        elif event.key == pygame.K_n:
                            self.current_screen = Menu.NEW_TRACK
                            return

            if self.redraw_screen:
                self.redraw_screen = False
                self.screen.fill((0, 0, 0))

                pygame.draw.rect(self.screen, Menu.GRAY,
                                 (15, 220, self.width - 30, 60), 1)
                pygame.draw.line(self.screen, Menu.GRAY, (0, 500),
                                 (self.width, 500))

                self.screen.blit(self.select_track_0, (15, 30))
                self.screen.blit(self.select_track_1, (30, 100))
                self.screen.blit(self.select_track_2, (45, 170))
                select_track_3_text_box = self.select_track_3.get_rect()
                select_track_3_text_box.center = 0, 250
                self.screen.blit(self.select_track_3,
                                 (60, select_track_3_text_box[1]))
                self.screen.blit(self.select_track_4, (45, 310))
                self.screen.blit(self.select_track_5, (30, 380))
                self.screen.blit(self.select_track_6, (15, 450))

                self.screen.blit(self.select_edit, (15, self.height - 30))
                self.screen.blit(self.select_new, (165, self.height - 30))
                self.screen.blit(self.select_back,
                                 (self.width - 300, self.height - 30))
                self.screen.blit(self.select_play,
                                 (self.width - 150, self.height - 30))

                if self.selected_tracks[3]:
                    self.screen.blit(self.select_track_title, (15, 525))
                    self.screen.blit(self.select_track_artist, (15, 600))
                    self.screen.blit(self.select_track_album, (15, 650))
                    self.screen.blit(self.select_track_high_score, (15, 700))
                    self.screen.blit(self.select_track_high_score_accuracy,
                                     (self.width * .3, 700))
                    self.screen.blit(self.select_track_high_score_layers,
                                     (self.width * .45, 700))
                    self.screen.blit(self.select_track_difficulty, (15, 750))

                    self.screen.blit(self.select_track_num_beats_A, (15, 800))
                    self.screen.blit(self.select_track_num_beats_B, (90, 800))
                    self.screen.blit(self.select_track_num_beats_C, (165, 800))
                    self.screen.blit(self.select_track_num_beats_D, (240, 800))
                    self.screen.blit(self.select_track_num_beats_E, (315, 800))
                    self.screen.blit(self.select_track_num_beats_F, (390, 800))
                    self.screen.blit(self.select_track_duration, (500, 800))

                pygame.display.flip()

            self.clock.tick(60)

    def draw_track_setup(self):
        label_selection_index = 0
        while 1:
            for event in pygame.event.get():
                if event.type == pygame.QUIT:
                    self.current_screen = Menu.EXIT
                    return
                elif event.type == pygame.KEYDOWN:
                    self.redraw_screen = True
                    if event.key == pygame.K_RETURN:
                        if label_selection_index == 0:
                            pygame.key.set_repeat()
                            self.play_track(self.selected_tracks[3])
                            self.current_screen = Menu.TRACK_SELECT
                            return
                        elif label_selection_index == 1:
                            # toggle prune unused layers
                            self.prune_unused_layers = not self.prune_unused_layers
                        else:
                            # toggle enable for key
                            self.layers_keys[ALL_LAYERS[
                                label_selection_index -
                                2]][0] = not self.layers_keys[ALL_LAYERS[
                                    label_selection_index - 2]][0]
                    elif event.key == pygame.K_BACKSPACE:
                        self.current_screen = Menu.TRACK_SELECT
                        return
                    elif event.key == pygame.K_DOWN:
                        label_selection_index = min(7,
                                                    label_selection_index + 1)
                        break
                    elif event.key == pygame.K_UP:
                        label_selection_index = max(0,
                                                    label_selection_index - 1)
                        break
                    elif event.key != pygame.K_ESCAPE and event.key != pygame.K_SPACE:
                        if label_selection_index >= 2:
                            for key, value in self.layers_keys.items():
                                if value[1] == event.key:
                                    self.layers_keys[key][1] = None
                            self.layers_keys[ALL_LAYERS[label_selection_index -
                                                        2]][1] = event.key

            if self.redraw_screen:
                self.redraw_screen = False
                self.screen.fill((0, 0, 0))

                start_label = self.large_font.render(
                    'START', True, Menu.SELECTED_COLOR
                    if label_selection_index == 0 else Menu.WHITE)
                start_label_text_box = start_label.get_rect()
                start_label_text_box.center = self.width / 2, 200
                self.screen.blit(start_label, start_label_text_box)

                prune_unused_layers_label = self.generic_font.render(
                    'Prune unused layers:', True, Menu.SELECTED_COLOR
                    if label_selection_index == 1 else Menu.WHITE)
                prune_unused_layers_enabled_label = self.generic_font.render(
                    f'{self.prune_unused_layers}', True, Menu.ENABLED_COLOR
                    if self.prune_unused_layers else Menu.DISABLED_COLOR)
                self.screen.blit(prune_unused_layers_label, (25, 275))
                self.screen.blit(prune_unused_layers_enabled_label, (325, 275))

                # A layer
                A_label = self.generic_font.render(
                    'Layer A:', True, Menu.SELECTED_COLOR
                    if label_selection_index == 2 else Menu.WHITE)
                A_enabled_label = self.generic_font.render(
                    f'{"Enabled" if self.layers_keys["A"][0] else "Disabled"}',
                    True, Menu.ENABLED_COLOR
                    if self.layers_keys["A"][0] else Menu.DISABLED_COLOR)
                A_key_label = self.generic_font.render(
                    f'Key: {None if self.layers_keys["A"][1] is None else pygame.key.name(self.layers_keys["A"][1])}',
                    True, Menu.WHITE)
                self.screen.blit(A_label, (25, 350))
                self.screen.blit(A_enabled_label, (175, 350))
                self.screen.blit(A_key_label, (325, 350))

                # B layer
                B_label = self.generic_font.render(
                    'Layer B:', True, Menu.SELECTED_COLOR
                    if label_selection_index == 3 else Menu.WHITE)
                B_enabled_label = self.generic_font.render(
                    f'{"Enabled" if self.layers_keys["B"][0] else "Disabled"}',
                    True, Menu.ENABLED_COLOR
                    if self.layers_keys["B"][0] else Menu.DISABLED_COLOR)
                B_key_label = self.generic_font.render(
                    f'Key: {None if self.layers_keys["B"][1] is None else pygame.key.name(self.layers_keys["B"][1])}',
                    True, Menu.WHITE)
                self.screen.blit(B_label, (25, 425))
                self.screen.blit(B_enabled_label, (175, 425))
                self.screen.blit(B_key_label, (325, 425))

                # C layer
                C_label = self.generic_font.render(
                    'Layer C:', True, Menu.SELECTED_COLOR
                    if label_selection_index == 4 else Menu.WHITE)
                C_enabled_label = self.generic_font.render(
                    f'{"Enabled" if self.layers_keys["C"][0] else "Disabled"}',
                    True, Menu.ENABLED_COLOR
                    if self.layers_keys["C"][0] else Menu.DISABLED_COLOR)
                C_key_label = self.generic_font.render(
                    f'Key: {None if self.layers_keys["C"][1] is None else pygame.key.name(self.layers_keys["C"][1])}',
                    True, Menu.WHITE)
                self.screen.blit(C_label, (25, 500))
                self.screen.blit(C_enabled_label, (175, 500))
                self.screen.blit(C_key_label, (325, 500))

                # D layer
                D_label = self.generic_font.render(
                    'Layer D:', True, Menu.SELECTED_COLOR
                    if label_selection_index == 5 else Menu.WHITE)
                D_enabled_label = self.generic_font.render(
                    f'{"Enabled" if self.layers_keys["D"][0] else "Disabled"}',
                    True, Menu.ENABLED_COLOR
                    if self.layers_keys["D"][0] else Menu.DISABLED_COLOR)
                D_key_label = self.generic_font.render(
                    f'Key: {None if self.layers_keys["D"][1] is None else pygame.key.name(self.layers_keys["D"][1])}',
                    True, Menu.WHITE)
                self.screen.blit(D_label, (25, 575))
                self.screen.blit(D_enabled_label, (175, 575))
                self.screen.blit(D_key_label, (325, 575))

                # E layer
                E_label = self.generic_font.render(
                    'Layer E:', True, Menu.SELECTED_COLOR
                    if label_selection_index == 6 else Menu.WHITE)
                E_enabled_label = self.generic_font.render(
                    f'{"Enabled" if self.layers_keys["E"][0] else "Disabled"}',
                    True, Menu.ENABLED_COLOR
                    if self.layers_keys["E"][0] else Menu.DISABLED_COLOR)
                E_key_label = self.generic_font.render(
                    f'Key: {None if self.layers_keys["E"][1] is None else pygame.key.name(self.layers_keys["E"][1])}',
                    True, Menu.WHITE)
                self.screen.blit(E_label, (25, 650))
                self.screen.blit(E_enabled_label, (175, 650))
                self.screen.blit(E_key_label, (325, 650))

                # F layer
                F_label = self.generic_font.render(
                    'Layer F:', True, Menu.SELECTED_COLOR
                    if label_selection_index == 7 else Menu.WHITE)
                F_enabled_label = self.generic_font.render(
                    f'{"Enabled" if self.layers_keys["F"][0] else "Disabled"}',
                    True, Menu.ENABLED_COLOR
                    if self.layers_keys["F"][0] else Menu.DISABLED_COLOR)
                F_key_label = self.generic_font.render(
                    f'Key: {None if self.layers_keys["F"][1] is None else pygame.key.name(self.layers_keys["F"][1])}',
                    True, Menu.WHITE)
                self.screen.blit(F_label, (25, 725))
                self.screen.blit(F_enabled_label, (175, 725))
                self.screen.blit(F_key_label, (325, 725))

                self.screen.blit(self.setup_toggle,
                                 (self.width - 450, self.height - 30))
                self.screen.blit(self.setup_back,
                                 (self.width - 150, self.height - 30))

                pygame.display.flip()

            self.clock.tick(30)

    def draw_new_track(self):
        label_selection_index = 0
        clipboard = paste()
        new_track_filepath = clipboard if isfile(
            clipboard) and clipboard[clipboard.rindex('.'):] in (
                '.flac', '.opus', '.mp3', '.m4a') else None
        new_track = Track(new_track_filepath) if new_track_filepath else None

        while 1:
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_RETURN:
                        if label_selection_index == 0:
                            clipboard = paste()
                            new_track_filepath = clipboard if isfile(
                                clipboard
                            ) and clipboard[clipboard.rindex('.'):] in (
                                '.flac', '.opus', '.mp3', '.m4a') else None
                            new_track = Track(new_track_filepath
                                              ) if new_track_filepath else None
                            break
                        elif label_selection_index == 1:
                            new_track.set_title(paste())
                            break
                        elif label_selection_index == 2:
                            new_track.set_artist(paste())
                            break
                        elif label_selection_index == 3:
                            new_track.set_album(paste())
                            break
                    elif event.key == pygame.K_s:
                        self.current_screen = Menu.TRACK_SELECT
                        if new_track:
                            new_index = self.library.add_track(new_track)
                            self.save_library()
                            if new_index is not None:
                                self.track_selection_index = new_index
                                self.selected_tracks = self.library.get_tracks(
                                    self.track_selection_index)
                                self.render_selected_tracks()
                                self.render_selected_track_data()
                        return
                    elif event.key == pygame.K_BACKSPACE:
                        self.current_screen = Menu.TRACK_SELECT
                        return
                    elif event.key == pygame.K_DOWN:
                        label_selection_index = min(3,
                                                    label_selection_index + 1)
                        break
                    elif event.key == pygame.K_UP:
                        label_selection_index = max(0,
                                                    label_selection_index - 1)
                        break

            if self.redraw_screen:
                self.screen.fill((0, 0, 0))

                new_track_file_text = self.generic_font.render(
                    'Paste filepath from clipboard', True, Menu.SELECTED_COLOR
                    if label_selection_index == 0 else Menu.WHITE)
                new_track_file_text_box = new_track_file_text.get_rect()
                new_track_file_text_box.center = self.width / 2, 200
                self.screen.blit(new_track_file_text, new_track_file_text_box)

                clipboard = paste()
                new_track_clipboard_text = self.small_font.render(
                    f'Clipboard: {clipboard}', True, Menu.WHITE)
                self.screen.blit(new_track_clipboard_text,
                                 (10, self.height - 200))

                self.screen.blit(self.new_track_edit, (15, self.height - 30))
                self.screen.blit(self.new_track_save,
                                 (self.width - 300, self.height - 30))
                self.screen.blit(self.new_track_cancel,
                                 (self.width - 150, self.height - 30))

                self.screen.blit(
                    self.generic_font.render(
                        f'Title: {new_track.title if new_track else "None"}',
                        True, Menu.SELECTED_COLOR
                        if label_selection_index == 1 else Menu.WHITE),
                    (10, 300))
                self.screen.blit(
                    self.generic_font.render(
                        f'Artist: {new_track.artist if new_track else "None"}',
                        True, Menu.SELECTED_COLOR
                        if label_selection_index == 2 else Menu.WHITE),
                    (10, 375))
                self.screen.blit(
                    self.generic_font.render(
                        f'Album: {new_track.album if new_track else "None"}',
                        True, Menu.SELECTED_COLOR
                        if label_selection_index == 3 else Menu.WHITE),
                    (10, 450))

                pygame.display.flip()

            self.clock.tick(30)

    def draw_edit_track(self):
        label_selection_index = 0
        track = self.selected_tracks[3]

        old_title = track.title
        old_artist = track.artist
        old_album = track.album

        while 1:
            for event in pygame.event.get():
                if event.type == pygame.KEYDOWN:
                    if event.key == pygame.K_RETURN:
                        if label_selection_index == 0:
                            track.set_title(paste())
                            break
                        elif label_selection_index == 1:
                            track.set_artist(paste())
                            break
                        elif label_selection_index == 2:
                            track.set_album(paste())
                            break
                    elif event.key == pygame.K_d:
                        track.delete_map()
                        self.library.remove_track(self.track_selection_index)
                        self.save_library()
                        if self.track_selection_index >= len(
                                self.library.saved_tracks):
                            self.track_selection_index -= 1
                        self.selected_tracks = self.library.get_tracks(
                            self.track_selection_index)
                        self.render_selected_tracks()
                        self.render_selected_track_data()
                        self.current_screen = Menu.TRACK_SELECT
                        return
                    elif event.key == pygame.K_s:
                        if track.title != old_title:
                            self.library.add_track(
                                self.library.remove_track(
                                    self.track_selection_index))
                        self.save_library()
                        self.render_selected_tracks()
                        self.render_selected_track_data()
                        self.current_screen = Menu.TRACK_SELECT
                        return
                    elif event.key == pygame.K_BACKSPACE:
                        track.set_title(old_title)
                        track.set_artist(old_artist)
                        track.set_album(old_album)
                        self.current_screen = Menu.TRACK_SELECT
                        return
                    elif event.key == pygame.K_DOWN:
                        label_selection_index = min(2,
                                                    label_selection_index + 1)
                        break
                    elif event.key == pygame.K_UP:
                        label_selection_index = max(0,
                                                    label_selection_index - 1)
                        break

            if self.redraw_screen:
                self.screen.fill((0, 0, 0))

                clipboard = paste()
                edit_track_clipboard_text = self.small_font.render(
                    f'Clipboard: {clipboard}', True, Menu.WHITE)
                self.screen.blit(edit_track_clipboard_text,
                                 (10, self.height - 200))

                self.screen.blit(self.new_track_edit, (15, self.height - 30))
                self.screen.blit(self.edit_track_delete,
                                 (400, self.height - 30))
                self.screen.blit(self.new_track_save,
                                 (self.width - 300, self.height - 30))
                self.screen.blit(self.new_track_cancel,
                                 (self.width - 150, self.height - 30))

                self.screen.blit(
                    self.generic_font.render(
                        f'Title: {track.title}', True, Menu.SELECTED_COLOR if
                        label_selection_index == 0 else Menu.WHITE), (10, 300))
                self.screen.blit(
                    self.generic_font.render(
                        f'Artist: {track.artist}', True, Menu.SELECTED_COLOR if
                        label_selection_index == 1 else Menu.WHITE), (10, 375))
                self.screen.blit(
                    self.generic_font.render(
                        f'Album: {track.album}', True, Menu.SELECTED_COLOR if
                        label_selection_index == 2 else Menu.WHITE), (10, 450))

                pygame.display.flip()

            self.clock.tick(30)

    def draw_search(self):
        pass

    def display_loop(self):
        while 1:
            self.screen_calls[self.current_screen]()
            if self.current_screen == 0:
                break

    def play_track(self, track):
        if isfile(track.audio_filepath) and isfile(track.map_filepath):
            self.audio_player.idle.wait()
            enabled_layers_keys = {
                layer: key[1]
                for layer, key in self.layers_keys.items() if key[0]
            }
            game = Game(self.screen, self.width, self.height,
                        self.audio_player, track, enabled_layers_keys,
                        self.preview_length, self.lenience,
                        self.prune_unused_layers, self.latency,
                        self.play_hit_sound,
                        [self.bass_hit_sound_data, self.high_hit_sound_data])
            game.start_game()
            while game.restart:
                self.audio_player.idle.wait()
                game = Game(
                    self.screen, self.width, self.height, self.audio_player,
                    track, enabled_layers_keys, self.preview_length,
                    self.lenience, self.prune_unused_layers, self.latency,
                    self.play_hit_sound,
                    [self.bass_hit_sound_data, self.high_hit_sound_data])
                game.start_game()
            self.save_library()
            self.render_selected_track_data()

    def save_library(self):
        dump(self.library, open('library/saved.library', 'wb'))

    def close_menu(self):
        self.save_library()
        self.audio_player.idle.wait()
        self.audio_player.close()
        pygame.display.quit()
Example #9
0
    assert os.path.exists(args.audio_dir), "audio dir doesn't exist?"
    assert os.path.isdir(args.audio_dir), "audio dir not a dir?"
    assert os.path.exists(args.lightning_rpc), "rpc file doesn't exist?"
    assert os.path.exists("/dev/" + args.blockchain_device), ("device doesn't "
                                                              "exist?")
    assert os.path.exists(args.blockchain_dir), "blockchain dir doesn't exist?"
    assert os.path.isdir(args.blockchain_dir), "blockchain dir not a dir?"

    r = reactor
    # setup urwid screen output
    sui = ScreenUI(r, args.console)
    # listen on ZMQ for new blocks
    bc_info = Bitcoind.getblockchaininfo()
    block_hash = bc_info['bestblockhash'] if bc_info else None
    queue = NewBlockQueue(r, sui, AudioPlayer(), block_hash)
    # start periodic timers
    pu = PeriodicUpdates(sui)
    r.callLater(0.5, pu.run)

    sr = SystemResources(r, sui, args.blockchain_dir, args.blockchain_device)
    sr.run()

    ni = NodeInfo(r, sui)
    ni.run()

    lni = LnNodeInfo(r, sui, args.lightning_rpc)
    lni.run()

    j = Jukebox(r, sui, args.audio_dir, args.lightning_rpc)
    j.run()
Example #10
0
def main():
    prices = Prices()
    weather = Weather()

    def wake_up_routine(number):
        if number == 1:
            w1 = Weather()
            send_message = "God morgen Tommy! I dag kan du forvente følgende temperaturer " + w1.min_max_weather(
            )
            channel = "raspberry-pi"
            slack_client.api_call("chat.postMessage",
                                  channel=channel,
                                  text=send_message)
            audio = AudioPlayer()
            audio.music_then_radio("random", 10, 300, "random")

    def send_bitcoin_price(channel):
        price_bit = prices.get_bitcoin_price()
        send_msg_bit = "Den nåværende prisen for Bitcoin er: " + price_bit[0]
        returns_msg_bit = "Din nåværende avkastning på Bitcoin er: " + price_bit[
            1]
        slack_client.api_call("chat.postMessage",
                              channel=channel,
                              text=send_msg_bit)
        slack_client.api_call("chat.postMessage",
                              channel=channel,
                              text=returns_msg_bit)

    def send_dogecoin_price(channel):
        price_dog = prices.get_dogecoin_price()
        send_msg_dog = "Den nåværende prisen for Dogecoin er: " + price_dog[0]
        # returns_msg_dog = "Din nåværende avkastning på Bitcoin er: " + price_dog[1]
        slack_client.api_call("chat.postMessage",
                              channel=channel,
                              text=send_msg_dog)
        # slack_client.api_call("chat.postMessage", channel=channel, text=returns_msg_dog)

    def send_litecoin_price(channel):
        price_ltc = prices.get_litecoin_price()
        send_msg_ltc = "Den nåværende prisen for Litecoin er: " + price_ltc[0]
        returns_msg_ltc = "Din nåværende avkastning på Litecoin er: " + price_ltc[
            1]
        slack_client.api_call("chat.postMessage",
                              channel=channel,
                              text=send_msg_ltc)
        slack_client.api_call("chat.postMessage",
                              channel=channel,
                              text=returns_msg_ltc)

    def morning_messages():
        time = datetime.now().time()
        hour = str(time)[0:2]
        global sent
        if hour == "09" and not sent:
            morning_prices()
            morning_weather()
            sent = True
        if hour == "10" and sent:
            sent = False

    def morning_weather():
        curr_weather = weather.min_max_weather().split()
        minimum = curr_weather[0]
        maximum = curr_weather[1]
        send_message = f"I dag kan du forvente temperaturer mellom {minimum} og {maximum}."
        channel = "raspberry-pi"
        slack_client.api_call("chat.postMessage",
                              channel=channel,
                              text=send_message)

    def morning_prices():
        channel = "raspberry-pi"
        good_morning_msg = "God morgen Tommy! Håper du får en fin dag :)"
        slack_client.api_call("chat.postMessage",
                              channel=channel,
                              text=good_morning_msg)
        send_bitcoin_price(channel)
        send_dogecoin_price(channel)
        send_litecoin_price(channel)

    tokens = {}
    with open('configs.json') as json_data:
        tokens = json.load(json_data)
    slack_client = SlackClient(tokens.get("slack_bot_token"))
    alarm = Alarm()
    if slack_client.rtm_connect(auto_reconnect=True):
        print("Connected!")
        while True:
            morning_messages()
            try:
                messages = slack_client.rtm_read()
            except:
                print("Disconnected.")
                print("Reconnecting...")
                time.sleep(20)
                slack_client.rtm_connect()
                messages = slack_client.rtm_read()
            if alarm.alarm_active():
                if alarm.check_alarm():
                    wake_up_routine(1)
            # print(messages)
            if messages:
                for message in messages:
                    if message.get("subtype") is None and message.get(
                            'user') is not None and message.get(
                                'text'
                            ) is not None and "BOT TEST" in message.get(
                                'text'):
                        channel = message["channel"]
                        send_message = "Responding to `BOT TEST` message sent by user <@%s>" % message[
                            "user"]
                        slack_client.api_call("chat.postMessage",
                                              channel=channel,
                                              text=send_message)

                    if message.get("subtype") is None and message.get(
                            'user') is not None and message.get(
                                'text') is not None and "audio" in message.get(
                                    'text'):
                        command = message.get('text')
                        command_lst = command.split()
                        command = " ".join(command_lst[1:])
                        au1 = AudioPlayer()
                        au1.audio_handler(command)

                    if message.get("subtype") is None and message.get(
                            'user') is not None and message.get(
                                'text'
                            ) is not None and "weather_now" in message.get(
                                'text'):
                        command = message.get('text')
                        command_lst = command.split()
                        command = " ".join(command_lst[1:])
                        weather = Weather()
                        send_message = weather.weather_handler(command)
                        channel = message["channel"]
                        slack_client.api_call("chat.postMessage",
                                              channel=channel,
                                              text=send_message)

                    if message.get("subtype") is None and message.get(
                            'user') is not None and message.get(
                                'text'
                            ) is not None and "weather_min_max" in message.get(
                                'text'):
                        weather = Weather()
                        send_message = weather.min_max_weather()
                        channel = message["channel"]
                        slack_client.api_call("chat.postMessage",
                                              channel=channel,
                                              text=send_message)

                    if message.get("subtype") is None and message.get(
                            'user') is not None and message.get(
                                'text'
                            ) is not None and "set_alarm" in message.get(
                                'text'):
                        command = message.get('text')
                        command_lst = command.split()
                        alarm.set_alarm(int(command_lst[1]),
                                        int(command_lst[2]),
                                        int(command_lst[3]),
                                        int(command_lst[4]))

                    if message.get("subtype") is None and message.get(
                            'user'
                    ) is not None and message.get(
                            'text'
                    ) is not None and "get_bitcoin_price" in message.get(
                            'text'):
                        send_bitcoin_price(message["channel"])

                    if message.get("subtype") is None and message.get(
                            'user'
                    ) is not None and message.get(
                            'text'
                    ) is not None and "get_dogecoin_price" in message.get(
                            'text'):
                        send_dogecoin_price(message["channel"])

                    if message.get("subtype") is None and message.get(
                            'user'
                    ) is not None and message.get(
                            'text'
                    ) is not None and "get_litecoin_price" in message.get(
                            'text'):
                        send_litecoin_price(message["channel"])

                    if message.get("subtype") is None and message.get(
                            'user'
                    ) is not None and message.get(
                            'text'
                    ) is not None and "get_crypto_price" in message.get(
                            'text'):
                        channel = message["channel"]
                        send_bitcoin_price(channel)
                        send_dogecoin_price(channel)
                        send_litecoin_price(channel)

            time.sleep(4)
    else:
        print("Connection Failed")
Example #11
0
    def __init__(self):
        "初始化"

        dir = os.path.dirname(game_settings['save_folder'])
        if not os.path.exists(dir):
            os.makedirs(dir)

        self.initGameSettings()

        #读取设置文件
        loadPrcFile("config/PandaConfig.prc")

        loadPrcFileData(
            '', 'win-size ' + str(game_settings['screen_resolution'][0]) +
            ' ' + str(game_settings['screen_resolution'][1]))

        #构造Panda3D的ShowBase
        ShowBase.__init__(self)

        #Retrieving available resolutions
        #self.makeDefaultPipe()
        di = self.pipe.getDisplayInformation()
        self.supportedResolutions = []
        for index in range(di.getTotalDisplayModes()):
            self.supportedResolutions.append((di.getDisplayModeWidth(index),
                                              di.getDisplayModeHeight(index)))

        color_themes.initStyles()

        props = WindowProperties(self.win.getProperties())
        props.setSize(int(game_settings['screen_resolution'][0]),
                      int(game_settings['screen_resolution'][1]))
        if game_settings['full_screen'] and not props.getFullscreen():
            props.setFullscreen(True)
        props.setTitle(game_settings['window_title'])
        self.win.requestProperties(props)

        self.cam2dp.node().getDisplayRegion(0).setSort(
            -20)  #Set render2dp to background
        self.disableMouse()  #Disable panda3d's default mouse control
        self.cam.node().getDisplayRegion(0).setActive(
            0)  #disable default camera
        self.audioPlayer = AudioPlayer()
        self.focusStack = []  #a stack that shows windowstop window gets focus

        self._loadReadText()
        self._loadGlobalData()

        #add event handlers
        self.accept('alt-enter', self.toggleFullScreen)
        self.accept('save_data', self.save)
        self.accept('load_data', self.load)
        self.accept('load_memory', self.loadMemory)
        self.accept('request_focus', self.grantFocus)
        self.accept('remove_focus', self.cancelFocus)
        self.accept('return_to_title', self.returnToTitle)
        self.accept('start_game', self.startGame)
        self.accept('load_game', self.loadGame)
        self.accept('config_form', self.showConfig)
        self.accept('exit_game', self.exit)
        self.accept('quick_save', self.quickSave)
        self.accept('quick_load', self.quickLoad)
        self.accept('auto_save', self.autoSave)
        self.accept('print_screen', self.takeScrnShot)
        self.accept('f10', self.takeScrnShot)

        #Font setting
        self.textFont = color_themes.default_font

        #背景设置
        self.setBackgroundColor(0, 0, 0, 1)
        self.backgroundImage = None

        self.initGameWindows()

        self.mainMenu = None
        self.storyManager = None
Example #12
0
class SogalBase(ShowBase):
    """The ShowBase of the sogal
    Attributes:
    supportedResolutions: player's system supported resolutions, Note that it is constructed after the initialization of ShowBase.
    """
    def __init__(self):
        "初始化"

        dir = os.path.dirname(game_settings['save_folder'])
        if not os.path.exists(dir):
            os.makedirs(dir)

        self.initGameSettings()

        #读取设置文件
        loadPrcFile("config/PandaConfig.prc")

        loadPrcFileData(
            '', 'win-size ' + str(game_settings['screen_resolution'][0]) +
            ' ' + str(game_settings['screen_resolution'][1]))

        #构造Panda3D的ShowBase
        ShowBase.__init__(self)

        #Retrieving available resolutions
        #self.makeDefaultPipe()
        di = self.pipe.getDisplayInformation()
        self.supportedResolutions = []
        for index in range(di.getTotalDisplayModes()):
            self.supportedResolutions.append((di.getDisplayModeWidth(index),
                                              di.getDisplayModeHeight(index)))

        color_themes.initStyles()

        props = WindowProperties(self.win.getProperties())
        props.setSize(int(game_settings['screen_resolution'][0]),
                      int(game_settings['screen_resolution'][1]))
        if game_settings['full_screen'] and not props.getFullscreen():
            props.setFullscreen(True)
        props.setTitle(game_settings['window_title'])
        self.win.requestProperties(props)

        self.cam2dp.node().getDisplayRegion(0).setSort(
            -20)  #Set render2dp to background
        self.disableMouse()  #Disable panda3d's default mouse control
        self.cam.node().getDisplayRegion(0).setActive(
            0)  #disable default camera
        self.audioPlayer = AudioPlayer()
        self.focusStack = []  #a stack that shows windowstop window gets focus

        self._loadReadText()
        self._loadGlobalData()

        #add event handlers
        self.accept('alt-enter', self.toggleFullScreen)
        self.accept('save_data', self.save)
        self.accept('load_data', self.load)
        self.accept('load_memory', self.loadMemory)
        self.accept('request_focus', self.grantFocus)
        self.accept('remove_focus', self.cancelFocus)
        self.accept('return_to_title', self.returnToTitle)
        self.accept('start_game', self.startGame)
        self.accept('load_game', self.loadGame)
        self.accept('config_form', self.showConfig)
        self.accept('exit_game', self.exit)
        self.accept('quick_save', self.quickSave)
        self.accept('quick_load', self.quickLoad)
        self.accept('auto_save', self.autoSave)
        self.accept('print_screen', self.takeScrnShot)
        self.accept('f10', self.takeScrnShot)

        #Font setting
        self.textFont = color_themes.default_font

        #背景设置
        self.setBackgroundColor(0, 0, 0, 1)
        self.backgroundImage = None

        self.initGameWindows()

        self.mainMenu = None
        self.storyManager = None

    def initGameWindows(self):
        '''
        Initializing the common save, load and config forms
        if you want better customization with them,
        override this!
        '''
        self.saveForm = SaveForm()
        self.loadForm = LoadForm()
        self.configForm = ConfigForm()

    def initGameSettings(self):
        '''
        Initializing game settings
        some complex game settings can be written here
        This will run before panda3d ShowBase constructed
        '''
        loadDefaultSettings('config/default.sconf')
        self._loadSettings()

    def initMainMenu(self, customMainMenu=None):
        '''Call this to initialize and show main menu'''

        if not self.mainMenu:
            if not customMainMenu:
                self.mainMenu = MainMenu()
            else:
                self.mainMenu = customMainMenu
        self.mainMenu.open()

    def isStarted(self):
        return bool(self.storyManager)

    def getCurrentFocus(self):
        if len(self.focusStack) > 0:
            return self.focusStack[-1]
        else:
            return None

    def hasFocus(self, obj):
        '''returns whether the object is the current focus'''
        return self.getCurrentFocus() == obj

    def grantFocus(self, obj):
        pre = self.getCurrentFocus()
        if obj in self.focusStack:
            self.focusStack.remove(obj)
            self.focusStack.append(obj)
        else:
            self.focusStack.append(obj)
        if pre != obj:
            if pre:
                pre.defocused()
            obj.focused()

    def cancelFocus(self, obj):
        if obj in self.focusStack:
            self.focusStack.remove(obj)
            obj.defocused()
        cur = self.getCurrentFocus()
        if cur != obj and cur:
            cur.focused()

    def setGameBackgroundImage(self, path):
        ''' Load a total background image '''
        if self.backgroundImage:
            self.backgroundImage.destroy()
        self.backgroundImage = OnscreenImage(parent=aspect2dp,
                                             image=path)  # @UndefinedVariable

    def save(self, saving, fileName, message):

        info = SavingInfo(message, datetime.now())
        try:
            save_data(
                game_settings['save_folder'] + fileName +
                game_settings['save_type'], saving)
            save_data(
                game_settings['save_folder'] + fileName +
                game_settings['save_infotype'], info)
        except Exception as error:
            safeprint(error)
            return

        self.saveForm.reloadMember(fileName)
        self.loadForm.reloadMember(fileName)

        self._saveReadText()
        self._saveGlobalData()

    def quickSave(self, saving, message):
        global_data['currentQuicksave'] += 1
        if global_data['currentQuicksave'] > MAX_QUICKSAVE:
            global_data['currentQuicksave'] = 1
        currentqs = global_data['currentQuicksave']
        self.save(saving, 'quick_save' + str(currentqs), message)

    def autoSave(self, saving, message):
        global_data['currentAutosave'] += 1
        if global_data['currentAutosave'] > MAX_AUTOSAVE:
            global_data['currentAutosave'] = 1
        currentas = global_data['currentAutosave']
        self.save(saving, 'auto_save' + str(currentas), message)

    def load(self, fileName):

        try:
            savedData = load_data(game_settings['save_folder'] + fileName +
                                  game_settings['save_type'])
        except Exception as error:
            safeprint(error)
            return

        if self.mainMenu:
            self.mainMenu.close()
        if self.storyManager:
            self.storyManager.destroy()
        self.audioPlayer.stopAll(0.5)
        restoreRuntimeData(savedData)
        self.audioPlayer.reload()
        self.storyManager = StoryManager()

    def quickLoad(self):
        if self.hasQuickData():
            self.load('quick_save' + str(global_data['currentQuicksave']))

    def hasQuickData(self):
        return exists(game_settings['save_folder'] + 'quick_save' +
                      str(global_data['currentQuicksave']) +
                      game_settings['save_type'])

    def loadMemory(self, dumped):
        try:
            loaded = pickle.loads(dumped)
        except Exception as exp:
            safeprint(exp)
            return

        self.storyManager.destroy()
        self.audioPlayer.stopAll(0.5)
        restoreRuntimeData(loaded)
        self.audioPlayer.reload()
        self.storyManager = StoryManager()

    def getStyle(self, sheet=None):
        return rgetStyle(sheet)

    def setStyle(self, value):
        return rsetStyle(value)

    def toggleFullScreen(self):
        props = WindowProperties(self.win.getProperties())
        if not props.getFullscreen():
            props.setSize(int(game_settings['screen_resolution'][0]),
                          int(game_settings['screen_resolution'][1]))
            props.setFullscreen(True)
        else:
            props.setFullscreen(False)
        self.win.requestProperties(props)

        game_settings['full_screen'] = not game_settings['full_screen']

        if self.configForm:
            self.configForm.refreshSettings()

        messenger.send('window-event', [self])

    def exitfunc(self, *args, **kwargs):
        self._saveReadText()
        self._saveGlobalData()
        self._saveSettings()
        return ShowBase.exitfunc(self, *args, **kwargs)

    def startGame(self, scene):
        if self.mainMenu:
            self.mainMenu.close()
        if self.storyManager:
            self.storyManager.destroy()
        self.audioPlayer.stopAll(0.5)
        self.storyManager = StoryManager()
        self.storyManager.beginScene(scene)

    def loadGame(self):
        self.loadForm.show()

    def showConfig(self):
        self.configForm.show()

    def exit(self):
        sys.exit()

    def returnToTitle(self):
        if self.storyManager:
            self.storyManager.destroy()
        self.audioPlayer.stopAll(0.5)
        if self.mainMenu:
            self.mainMenu.open()

    def takeScrnShot(self):
        '''Take a screenshot'''
        dir = os.path.dirname('screenshots/')
        if not os.path.exists(dir):
            os.makedirs(dir)

        self.screenshot(namePrefix='screenshots/screenshot', defaultFilename=1)

    def setScreenResolution(self, resolution=None, fullscreen=None):
        game_settings['screen_resolution'] = resolution or game_settings[
            'screen_resolution']
        if fullscreen is not None:
            game_settings['full_screen'] = fullscreen
        self._applyScreenResolution()

    def _loadReadText(self):
        if not exists(game_settings['save_folder'] + 'read.dat'):
            return
        try:
            read = load_data(game_settings['save_folder'] + 'read.dat')
        except Exception as exp:
            safeprint(exp)
            return
        restoreReadText(read)

    def _loadGlobalData(self):
        if not exists(game_settings['save_folder'] + 'global.dat'):
            return
        try:
            gdata = load_data(game_settings['save_folder'] + 'global.dat')
        except Exception as exp:
            safeprint(exp)
            return
        restoreGlobalData(gdata)

    def _loadSettings(self):
        if not exists(game_settings['save_folder'] + 'config.dat'):
            return
        try:
            settings = load_data(game_settings['save_folder'] + 'config.dat')
        except Exception as error:
            safeprint(error)
            return
        restoreSettings(settings)

    def _saveReadText(self):
        try:
            save_data(game_settings['save_folder'] + 'read.dat', read_text)
        except Exception as exp:
            safeprint(exp)

    def _saveGlobalData(self):
        try:
            save_data(game_settings['save_folder'] + 'global.dat', global_data)
        except Exception as exp:
            safeprint(exp)

    def _saveSettings(self):
        try:
            save_data(game_settings['save_folder'] + 'config.dat',
                      game_settings)
        except Exception as exp:
            safeprint(exp)

    def _applyScreenResolution(self):

        props = WindowProperties(self.win.getProperties())
        if not props.getFullscreen:
            props.setSize(int(game_settings['screen_resolution'][0]),
                          int(game_settings['screen_resolution'][1]))
            props.setFullscreen(game_settings['full_screen'])
        else:
            props.setFullscreen(game_settings['full_screen'])
            props.setSize(int(game_settings['screen_resolution'][0]),
                          int(game_settings['screen_resolution'][1]))

        self.win.requestProperties(props)

        if self.configForm:
            self.configForm.refreshSettings()

        messenger.send('window-event', [self])
Example #13
0
    def __init__(self):
        "初始化"
                
        dir = os.path.dirname(game_settings['save_folder'])
        if not os.path.exists(dir):
            os.makedirs(dir)
        
        self.initGameSettings()
        
        #读取设置文件
        loadPrcFile("config/PandaConfig.prc")
        
        loadPrcFileData('', 'win-size ' + str(game_settings['screen_resolution'][0]) + ' ' + str(game_settings['screen_resolution'][1]) )
        
        #构造Panda3D的ShowBase
        ShowBase.__init__(self)
        
        #Retrieving available resolutions
        #self.makeDefaultPipe()
        di = self.pipe.getDisplayInformation()
        self.supportedResolutions = []
        for index in range(di.getTotalDisplayModes()):
            self.supportedResolutions.append((di.getDisplayModeWidth(index), di.getDisplayModeHeight(index)))
        
        
        color_themes.initStyles()
        
        props = WindowProperties( self.win.getProperties() )
        props.setSize(int(game_settings['screen_resolution'][0]),int(game_settings['screen_resolution'][1]))
        if game_settings['full_screen'] and not props.getFullscreen():
            props.setFullscreen(True)
        props.setTitle(game_settings['window_title'])
        self.win.requestProperties(props)
        
        self.cam2dp.node().getDisplayRegion(0).setSort(-20)  #Set render2dp to background
        self.disableMouse() #Disable panda3d's default mouse control
        self.cam.node().getDisplayRegion(0).setActive(0) #disable default camera
        self.audioPlayer = AudioPlayer()
        self.focusStack = [] #a stack that shows windowstop window gets focus
        
        self._loadReadText()
        self._loadGlobalData()

            
        #add event handlers
        self.accept('alt-enter', self.toggleFullScreen)
        self.accept('save_data', self.save)
        self.accept('load_data', self.load)
        self.accept('load_memory', self.loadMemory)
        self.accept('request_focus', self.grantFocus)
        self.accept('remove_focus', self.cancelFocus)
        self.accept('return_to_title', self.returnToTitle)
        self.accept('start_game', self.startGame)
        self.accept('load_game', self.loadGame)
        self.accept('config_form', self.showConfig)
        self.accept('exit_game', self.exit)
        self.accept('quick_save', self.quickSave)
        self.accept('quick_load', self.quickLoad)
        self.accept('auto_save', self.autoSave)
        self.accept('print_screen', self.takeScrnShot)
        self.accept('f10', self.takeScrnShot)
        
        #Font setting
        self.textFont = color_themes.default_font
        
        #背景设置
        self.setBackgroundColor(0,0,0,1); 
        self.backgroundImage = None
            
        self.initGameWindows()
        
        self.mainMenu = None
        self.storyManager = None
Example #14
0
class SogalBase(ShowBase): 
    """The ShowBase of the sogal
    Attributes:
    supportedResolutions: player's system supported resolutions, Note that it is constructed after the initialization of ShowBase.
    """
    
    def __init__(self):
        "初始化"
                
        dir = os.path.dirname(game_settings['save_folder'])
        if not os.path.exists(dir):
            os.makedirs(dir)
        
        self.initGameSettings()
        
        #读取设置文件
        loadPrcFile("config/PandaConfig.prc")
        
        loadPrcFileData('', 'win-size ' + str(game_settings['screen_resolution'][0]) + ' ' + str(game_settings['screen_resolution'][1]) )
        
        #构造Panda3D的ShowBase
        ShowBase.__init__(self)
        
        #Retrieving available resolutions
        #self.makeDefaultPipe()
        di = self.pipe.getDisplayInformation()
        self.supportedResolutions = []
        for index in range(di.getTotalDisplayModes()):
            self.supportedResolutions.append((di.getDisplayModeWidth(index), di.getDisplayModeHeight(index)))
        
        
        color_themes.initStyles()
        
        props = WindowProperties( self.win.getProperties() )
        props.setSize(int(game_settings['screen_resolution'][0]),int(game_settings['screen_resolution'][1]))
        if game_settings['full_screen'] and not props.getFullscreen():
            props.setFullscreen(True)
        props.setTitle(game_settings['window_title'])
        self.win.requestProperties(props)
        
        self.cam2dp.node().getDisplayRegion(0).setSort(-20)  #Set render2dp to background
        self.disableMouse() #Disable panda3d's default mouse control
        self.cam.node().getDisplayRegion(0).setActive(0) #disable default camera
        self.audioPlayer = AudioPlayer()
        self.focusStack = [] #a stack that shows windowstop window gets focus
        
        self._loadReadText()
        self._loadGlobalData()

            
        #add event handlers
        self.accept('alt-enter', self.toggleFullScreen)
        self.accept('save_data', self.save)
        self.accept('load_data', self.load)
        self.accept('load_memory', self.loadMemory)
        self.accept('request_focus', self.grantFocus)
        self.accept('remove_focus', self.cancelFocus)
        self.accept('return_to_title', self.returnToTitle)
        self.accept('start_game', self.startGame)
        self.accept('load_game', self.loadGame)
        self.accept('config_form', self.showConfig)
        self.accept('exit_game', self.exit)
        self.accept('quick_save', self.quickSave)
        self.accept('quick_load', self.quickLoad)
        self.accept('auto_save', self.autoSave)
        self.accept('print_screen', self.takeScrnShot)
        self.accept('f10', self.takeScrnShot)
        
        #Font setting
        self.textFont = color_themes.default_font
        
        #背景设置
        self.setBackgroundColor(0,0,0,1); 
        self.backgroundImage = None
            
        self.initGameWindows()
        
        self.mainMenu = None
        self.storyManager = None
        
    def initGameWindows(self):
        '''
        Initializing the common save, load and config forms
        if you want better customization with them,
        override this!
        '''
        self.saveForm = SaveForm()
        self.loadForm = LoadForm() 
        self.configForm = ConfigForm()
        
    def initGameSettings(self):
        '''
        Initializing game settings
        some complex game settings can be written here
        This will run before panda3d ShowBase constructed
        '''
        loadDefaultSettings('config/default.sconf')
        self._loadSettings()

        

        
    def initMainMenu(self,customMainMenu = None):
        '''Call this to initialize and show main menu'''
        
        if not self.mainMenu:
            if not customMainMenu:
                self.mainMenu = MainMenu()
            else: self.mainMenu = customMainMenu
        self.mainMenu.open()
    
    def isStarted(self):
        return bool(self.storyManager)

        
    def getCurrentFocus(self):
        if len(self.focusStack) > 0:
            return self.focusStack[-1]
        else: return None
        
    def hasFocus(self,obj):
        '''returns whether the object is the current focus'''
        return self.getCurrentFocus() == obj
        
    def grantFocus(self,obj):
        pre = self.getCurrentFocus()
        if obj in self.focusStack:
            self.focusStack.remove(obj)
            self.focusStack.append(obj)
        else:
            self.focusStack.append(obj)
        if pre != obj:
            if pre:
                pre.defocused()
            obj.focused()
        
    def cancelFocus(self,obj):
        if obj in self.focusStack:
            self.focusStack.remove(obj)
            obj.defocused()
        cur = self.getCurrentFocus()
        if cur != obj and cur:
            cur.focused()
        
    def setGameBackgroundImage(self,path):
        ''' Load a total background image '''
        if self.backgroundImage:
            self.backgroundImage.destroy()
        self.backgroundImage = OnscreenImage(parent=aspect2dp, image=path)  # @UndefinedVariable
        
    def save(self,saving,fileName,message):
        
        info = SavingInfo(message,datetime.now())
        try:
            save_data(game_settings['save_folder'] + fileName + game_settings['save_type'], saving)
            save_data(game_settings['save_folder'] + fileName + game_settings['save_infotype'], info)
        except Exception as error:
            safeprint(error)
            return
        
        self.saveForm.reloadMember(fileName)
        self.loadForm.reloadMember(fileName)
        
        self._saveReadText()
        self._saveGlobalData()
        
    def quickSave(self, saving, message):
        global_data['currentQuicksave'] += 1
        if global_data['currentQuicksave'] > MAX_QUICKSAVE:
            global_data['currentQuicksave'] = 1
        currentqs = global_data['currentQuicksave']
        self.save(saving, 'quick_save' + str(currentqs), message)
        
    def autoSave(self, saving, message):
        global_data['currentAutosave'] += 1
        if global_data['currentAutosave'] > MAX_AUTOSAVE:
            global_data['currentAutosave'] = 1
        currentas = global_data['currentAutosave']
        self.save(saving, 'auto_save' + str(currentas), message)
        
    def load(self,fileName):
        
        try:
            savedData = load_data(game_settings['save_folder'] + fileName + game_settings['save_type'])
        except Exception as error:
            safeprint(error)
            return
        
        if self.mainMenu:
            self.mainMenu.close()
        if self.storyManager:
            self.storyManager.destroy()
        self.audioPlayer.stopAll(0.5)
        restoreRuntimeData(savedData)
        self.audioPlayer.reload()
        self.storyManager = StoryManager()
        
    def quickLoad(self):
        if self.hasQuickData():
            self.load('quick_save' + str(global_data['currentQuicksave']))
        
    def hasQuickData(self):
        return exists(game_settings['save_folder'] + 'quick_save' + str(global_data['currentQuicksave']) + game_settings['save_type'])
        
    def loadMemory(self,dumped):
        try:
            loaded = pickle.loads(dumped)
        except Exception as exp: 
            safeprint(exp)
            return
        
        self.storyManager.destroy()
        self.audioPlayer.stopAll(0.5)
        restoreRuntimeData(loaded)
        self.audioPlayer.reload()
        self.storyManager = StoryManager()   
        
    def getStyle(self, sheet = None):
        return rgetStyle(sheet)
    
    def setStyle(self,value):
        return rsetStyle(value)
    
    def toggleFullScreen(self):
        props = WindowProperties( self.win.getProperties() )
        if not props.getFullscreen():
            props.setSize(int(game_settings['screen_resolution'][0]),int(game_settings['screen_resolution'][1]))
            props.setFullscreen(True)
        else:
            props.setFullscreen(False)
        self.win.requestProperties(props)
        
        game_settings['full_screen'] = not game_settings['full_screen']
        
        if self.configForm:
            self.configForm.refreshSettings()
            
        messenger.send('window-event', [self])
        
    def exitfunc(self, *args, **kwargs):
        self._saveReadText()
        self._saveGlobalData()
        self._saveSettings()
        return ShowBase.exitfunc(self, *args, **kwargs)
    
    def startGame(self,scene):
        if self.mainMenu:
            self.mainMenu.close()
        if self.storyManager:
            self.storyManager.destroy()
        self.audioPlayer.stopAll(0.5)
        self.storyManager = StoryManager()
        self.storyManager.beginScene(scene)
        
    def loadGame(self):
        self.loadForm.show()
        
    def showConfig(self):
        self.configForm.show()
        
    def exit(self):
        sys.exit()
        
    def returnToTitle(self):
        if self.storyManager:
            self.storyManager.destroy()
        self.audioPlayer.stopAll(0.5)
        if self.mainMenu:
            self.mainMenu.open()
            
    def takeScrnShot(self):
        '''Take a screenshot'''
        dir = os.path.dirname('screenshots/')
        if not os.path.exists(dir):
            os.makedirs(dir)
        
        self.screenshot(namePrefix = 'screenshots/screenshot', defaultFilename = 1)
        
    def setScreenResolution(self, resolution = None, fullscreen = None):
        game_settings['screen_resolution'] = resolution or game_settings['screen_resolution']
        if fullscreen is not None:
            game_settings['full_screen'] = fullscreen
        self._applyScreenResolution()
            
    def _loadReadText(self):
        if not exists(game_settings['save_folder']+ 'read.dat'):
            return
        try:
            read = load_data(game_settings['save_folder']+ 'read.dat')
        except Exception as exp:
            safeprint(exp)
            return
        restoreReadText(read)
        
    def _loadGlobalData(self):
        if not exists(game_settings['save_folder']+ 'global.dat'):
            return
        try:
            gdata = load_data(game_settings['save_folder']+ 'global.dat')
        except Exception as exp:
            safeprint(exp)
            return
        restoreGlobalData(gdata)
        
    def _loadSettings(self):
        if not exists(game_settings['save_folder']+ 'config.dat'):
            return
        try:
            settings = load_data(game_settings['save_folder'] + 'config.dat')
        except Exception as error:
            safeprint(error)
            return    
        restoreSettings(settings)
    
    def _saveReadText(self):
        try:
            save_data(game_settings['save_folder']+ 'read.dat', read_text)
        except Exception as exp: 
            safeprint(exp)
            
    def _saveGlobalData(self):
        try:
            save_data(game_settings['save_folder']+ 'global.dat', global_data)
        except Exception as exp: 
            safeprint(exp)
            
    def _saveSettings(self):
        try:
            save_data(game_settings['save_folder']+ 'config.dat', game_settings)
        except Exception as exp: 
            safeprint(exp)
            
    def _applyScreenResolution(self):
        
        props = WindowProperties( self.win.getProperties() )
        if not props.getFullscreen:
            props.setSize(int(game_settings['screen_resolution'][0]),int(game_settings['screen_resolution'][1]))
            props.setFullscreen(game_settings['full_screen'])
        else:
            props.setFullscreen(game_settings['full_screen'])
            props.setSize(int(game_settings['screen_resolution'][0]),int(game_settings['screen_resolution'][1]))
            
        self.win.requestProperties(props)
        
        if self.configForm:
            self.configForm.refreshSettings()
            
        messenger.send('window-event', [self])
Example #15
0
from audio_player import AudioPlayer
from audio_recorder import AudioRecorder
import time
import os

if __name__ == "__main__":
    # Usage example for pyaudio
    while True:
        # play the audio
        a = AudioPlayer("sample_1202.wav")
        print("Start Playing: {}".format(time.time()))
        os.system("ping -c 1 1.1.1.1")  # punch play start
        a.play(start=0, end=11.5)
        print("End Playing: {}".format(time.time()))
        os.system("ping -c 1 8.8.4.4")  # punch play end
        a.close()

        # Start recording
        b = AudioRecorder()
        print("Waiting")
        print()
        time.sleep(180)