Ejemplo n.º 1
0
class MyWindow(QMainWindow):
    def __init__(self):
        QMainWindow.__init__(self)
        self.resize(1300, 700)
        self.setFixedSize(self.size())
        self.setWindowTitle('PyChord')
        self.add_combo_boxes()
        self.add_buttons()
        self.sl = QSlider(Qt.Horizontal, self)
        self.volume = QLCDNumber(self)
        self.add_slider()

        self.actual_key = None
        self.actual_meter = 4
        self.actual_instrument = instrument.Piano()
        self.melody_stream = stream.Stream()
        self.harmonized_melody_stream = stream.Stream()
        self.reset_stream(self.melody_stream)
        self.reset_stream(self.harmonized_melody_stream)
        mixer.init(44100, -16, 2, 1024)

        self.tmpStream = stream.Stream()
        self.tmpStream.insert(instrument.Piano())
        self.lpc = lily.translate.LilypondConverter()
        self.lpc.context = lily.lilyObjects.LyMusicList()
        self.keyboard = Keyboard(self)
        self.melody = Melody(self, self.actual_key)

    def change_volume(self, vl):
        mixer.music.set_volume(vl / 100.0)
        self.volume.display(vl)

    def add_buttons(self):
        play_button = QPushButton('Play', self)
        play_button.move(1100, 300)
        play_button.clicked.connect(self.play_notes)

        reset_button = QPushButton('Reset', self)
        reset_button.move(1100, 350)
        reset_button.clicked.connect(self.reset)

        notes_button = QPushButton('Show Notes', self)
        notes_button.clicked.connect(self.show_notes)
        notes_button.move(1100, 400)

        save_button = QPushButton('Save', self)
        save_button.clicked.connect(self.save)
        save_button.move(1100, 450)

    def add_combo_boxes(self):
        key_info = QLabel('Choose a key:', self)
        key_info.move(600, 50)
        key_choice = QComboBox(self)
        key_choice.move(600, 100)
        key_choice.addItems(['None', 'C', 'D', 'E', 'F', 'G', 'A', 'B'])
        key_choice.currentIndexChanged.connect(self.change_key)

        meter_info = QLabel('Choose a meter:', self)
        meter_info.move(400, 50)
        meter_choice = QComboBox(self)
        meter_choice.move(400, 100)
        meter_choice.addItems(['4/4', '3/4', '2/4'])
        meter_choice.currentIndexChanged.connect(self.change_meter)

        instrument_choice = QComboBox(self)
        instrument_choice.move(1100, 250)
        instrument_choice.addItems(
            ['Piano(default)', 'Guitar', 'Violin', 'Flute', 'Mandolin'])
        instrument_choice.currentIndexChanged.connect(self.change_instrument)

    def add_slider(self):
        self.sl.setMinimum(0)
        self.sl.setMaximum(100)
        self.sl.setValue(80)
        self.sl.setTickInterval(1)
        self.sl.move(1100, 220)
        self.sl.valueChanged.connect(
            lambda: self.change_volume(self.sl.value()))

        self.volume.move(1100, 180)
        self.volume.display(80)

    def play_notes(self):
        try:
            if not self.melody.is_well_rhythmic:
                confirm = QMessageBox()
                confirm.setWindowTitle('Error')
                confirm.setText('The rhythm is not correct.')
                confirm.setIcon(QMessageBox.Information)
                confirm.exec()
            else:
                if self.actual_key is not None:
                    self.melody.harmonize()
                    mixer.music.load(
                        self.harmonized_melody_stream.write('midi'))
                    mixer.music.play()
                else:
                    mixer.music.load(self.melody_stream.write('midi'))
                    mixer.music.play()
        except exceptions21.StreamException:
            pass

    def show_notes(self):
        if not self.melody.is_well_rhythmic:
            confirm = QMessageBox()
            confirm.setWindowTitle('Error')
            confirm.setText('The rhythm is not correct.')
            confirm.setIcon(QMessageBox.Information)
            confirm.exec()
        else:
            self.lpc.context.contents = []
            self.lpc.appendObjectsToContextFromStream(self.melody_stream)

            with open('notes.ly', 'w+') as f:
                f.write('\\version "2.20.0"\n')
                if self.actual_key is None:
                    f.write("{\n")
                    f.write('\\key c \\major \n')
                    f.write(str(self.lpc.context))
                    f.write("}\n")
                else:
                    f.write('{<<\n')
                    f.write('\\chords {')
                    for i in self.melody.list_of_chords:
                        f.write(i.lower() + " ")
                    f.write('}\n')
                    f.write('{\\key ' + self.actual_key.tonic.name.lower() +
                            ' \\' + self.actual_key.mode)
                    f.write('\n')
                    f.write(str(self.lpc.context))
                    f.write('}>>}\n')

            if platform.system() == 'Linux':
                process = subprocess.Popen(['lilypond notes.ly'], shell=True)
                process.wait(100)

                subprocess.Popen(['chmod 755 notes.pdf'], shell=True)
                subprocess.Popen(['xdg-open notes.pdf'], shell=True)

            elif platform.system() == 'Windows':
                process = subprocess.Popen(['powershell', 'lilypond notes.ly'])
                process.wait(100)

                subprocess.Popen(['powershell', '.\\notes.pdf'])

    def save(self):
        if not self.melody.is_well_rhythmic:
            confirm = QMessageBox()
            confirm.setWindowTitle('Error')
            confirm.setText('The rhythm is not correct.')
            confirm.setIcon(QMessageBox.Information)
            confirm.exec()
        else:
            if not os.path.exists('music'):
                os.makedirs('music')
            today = date.today()
            flag = True
            count = 1
            path = ''

            while flag is True:
                path = os.path.join('music',
                                    '{}.{}.mid'.format(str(count), str(today)))
                flag = os.path.isfile(path)
                count += 1

            self.harmonized_melody_stream.write('midi', fp=path)
            confirm = QMessageBox()
            confirm.setWindowTitle('Confirmation')
            confirm.setText('File saved')
            confirm.setIcon(QMessageBox.Information)
            confirm.exec()

    def add_note(self, my_note):
        self.melody.rhythmic_values_sum = sum(
            self.melody.note_buttons[i].rhythmic_value
            for i in range(len(self.melody.note_buttons)))
        if self.melody.rhythmic_values_sum < self.melody.max_notes:
            self.melody_stream.insert(self.melody.rhythmic_values_sum + 2,
                                      note.Note(my_note.nameWithOctave))
            for i in range(8):
                if mixer.Channel(i).get_busy():
                    pass
                else:
                    if platform.system() == 'Linux':
                        mixer.Channel(i).play(
                            mixer.Sound('notes/{}.wav'.format(my_note)))
                    elif platform.system() == 'Windows':
                        mixer.Channel(i).play(
                            mixer.Sound('notes\\{}.wav'.format(my_note)))
                    break
            self.melody.add_note_to_melody(my_note)
            self.melody.show_melody()

    def reset_stream(self, stream_to_reset):
        stream_to_reset.clear()
        stream_to_reset.insert(0, self.actual_instrument)
        stream_to_reset.insert(
            1, meter.TimeSignature('{}/4'.format(self.actual_meter)))

    def change_instrument(self, choice):
        instruments = [
            instrument.Piano(),
            instrument.AcousticGuitar(),
            instrument.Violin(),
            instrument.Flute(),
            instrument.Mandolin()
        ]
        self.actual_instrument = instruments[choice]
        self.melody_stream[0] = self.actual_instrument

    def reset(self):
        for button in self.melody.note_buttons:
            button.hide()
        self.melody.note_buttons.clear()
        self.melody.notes_counter = 0
        self.melody.rhythmic_values_sum = 0
        self.reset_stream(self.melody_stream)
        self.reset_stream(self.harmonized_melody_stream)

    def change_key(self, choice):
        self.reset()
        self.keyboard.reset()
        if choice == 0:
            self.actual_key = None
        else:
            keys = ['None', 'C', 'D', 'E', 'F', 'G', 'A', 'B']
            self.actual_key = key.Key(keys[choice])
            self.keyboard.on_key_change(self.actual_key)

        self.melody.actual_key = self.actual_key

    def change_meter(self, choice):
        self.reset()
        meters = [4, 3, 2]
        self.actual_meter = meters[choice]
        self.melody.on_meter_change(self.actual_meter)
        self.update(0, 0, 1000, 1000)

    def paintEvent(self, e):
        lines = QPainter(self)
        lines.setPen(QPen(QColor(240, 240, 240), 10, Qt.SolidLine))
        for i in range(17):
            lines.drawLine(250 + i * 45, 290, 250 + i * 45, 350)

        lines.setPen(QPen(Qt.black, 10, Qt.SolidLine))
        for i in range(5):
            lines.drawLine(250 + i * self.actual_meter * 45, 290,
                           250 + i * self.actual_meter * 45, 350)
        lines.end()