mirror of
https://github.com/janishutz/midi-micro-bit_sound-converter.git
synced 2025-11-25 05:44:24 +00:00
Major refactor
I have spent some time (like two hours) fixing up the app, getting it up to a somewhat better level. Code is still bad, but that's that. If anybody is interested to make the code neater, feel free to open a PR!
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
__pycache__
|
||||||
80
README.md
80
README.md
@@ -1,34 +1,66 @@
|
|||||||
# midi-micro-bit_sound-converter
|
<div id="title" align="center">
|
||||||
|
<h1>Midi to Micro:bit Sound converter</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div id="badges" align="center">
|
||||||
|
<img src="https://img.shields.io/github/license/janishutz/midi-micro-bit_sound-converter.svg">
|
||||||
|
<img src="https://img.shields.io/github/repo-size/janishutz/midi-micro-bit_sound-converter.svg">
|
||||||
|
<img src="https://img.shields.io/github/languages/top/janishutz/midi-micro-bit_sound-converter">
|
||||||
|
<img src="https://img.shields.io/github/directory-file-count/janishutz/midi-micro-bit_sound-converter.svg">
|
||||||
|
<br>
|
||||||
|
<img alt="GitHub Repo stars" src="https://img.shields.io/github/stars/janishutz/midi-micro-bit_sound-converter">
|
||||||
|
<img alt="GitHub watchers" src="https://img.shields.io/github/watchers/janishutz/midi-micro-bit_sound-converter">
|
||||||
|
<img src="https://img.shields.io/github/issues-pr-raw/janishutz/midi-micro-bit_sound-converter">
|
||||||
|
<img alt="GitHub forks" src="https://img.shields.io/github/forks/janishutz/midi-micro-bit_sound-converter">
|
||||||
|
<img alt="GitHub commit activity" src="https://img.shields.io/github/commit-activity/m/janishutz/midi-micro-bit_sound-converter">
|
||||||
|
<br>
|
||||||
|
<img alt="GitHub all releases" src="https://img.shields.io/github/downloads/janishutz/midi-micro-bit_sound-converter/total?label=Downloads (total)">
|
||||||
|
<img alt="GitHub release (latest by date)" src="https://img.shields.io/github/downloads/janishutz/midi-micro-bit_sound-converter/latest/total?label=Downloads (latest)">
|
||||||
|
<img src="https://img.shields.io/github/release/janishutz/midi-micro-bit_sound-converter.svg">
|
||||||
|
<img src="https://img.shields.io/github/package-json/v/janishutz/midi-micro-bit_sound-converter.svg?label=Development Version">
|
||||||
|
</div>
|
||||||
|
|
||||||
This app allows you to convert a midi file to the code needed for micro:bit programming
|
This app allows you to convert a midi file to the code needed for micro:bit programming
|
||||||
|
|
||||||
Creating Music with the micro:bit is a hassle. This little app will allow you to take any midi-file and convert it into the list needed for micro:bit.
|
Creating Music with the micro:bit is a hassle. This little app will allow you to take any midi-file and convert it into the list needed for micro:bit.
|
||||||
|
|
||||||
## INSTALLATION:
|
# Installation
|
||||||
Download the files by clicking on code, then on zip.
|
Download the files by clicking on code, then on zip or clone the repo locally using
|
||||||
You will need to install some dependencies, as well as python 3.8. If you haven't already go ahead and download python 3.8 and make sure to also include pip,
|
```
|
||||||
as this will be used right after. Now, you will need to type the following commands in the terminal / command prompt:
|
git clone https://github.com/janishutz/midi-micro-bit_sound-converter
|
||||||
pip install kivy[base]
|
```
|
||||||
pip install kivymd
|
|
||||||
pip install pyperclip
|
|
||||||
pip install mido
|
|
||||||
|
|
||||||
You can run the app by heading into the folder you downloaded the zip file into, unzipping it and then by running the midi-converter.py file in the terminal / command prompt. (python3 midi-converter.py)
|
Then, run
|
||||||
You may do this as follows:
|
```
|
||||||
### Linux and MacOS:
|
pip install -r requirements.txt
|
||||||
Use cd./Path/To/File
|
```
|
||||||
|
in the repo's folder (i.e. the folder you just cloned or downloaded and extracted)
|
||||||
|
|
||||||
### Linux
|
Alternatively, create a venv using
|
||||||
You may download the bash script that is located under releases. Give it execute permissions (e.g run chmod +x ./Path/To/File) and then run the file with ./Path/To/File
|
```
|
||||||
|
python -m venv midi-converter
|
||||||
|
```
|
||||||
|
|
||||||
### Windows:
|
and activate it using
|
||||||
Click on the navigation bar (the one where the path is displayed) and type: cmd
|
```
|
||||||
|
source ./midi-converter/bin/active
|
||||||
|
```
|
||||||
|
|
||||||
|
The dependencies of this project are `mido`, `pyperclip`, `kivymd` and `kivy[base]`
|
||||||
|
|
||||||
|
|
||||||
### SPECIAL notes for Linux users:
|
# Running
|
||||||
You'll need to install some other dependencies first. Use your distro's package manager (apt-get for Debian based distros, dnf for Fedora based and pacman for arch-based distros). I'll show an example with debian based distros here: (you may also run the script under releases if you run a debian based distro.
|
Open a terminal in the file location where you saved / cloned this repo to. Type
|
||||||
sudo apt-get install xclip
|
```
|
||||||
sudo apt-get install xsel
|
python midi_converter.py
|
||||||
sudo apt-get install wl-clipboard
|
```
|
||||||
|
|
||||||
### OTHER OPTION:
|
to run the app
|
||||||
You may also run it in a venv (Virtual Environment), e.g. in Thonny. You still must install kivy[base], kivymd, pyperclip and mido in that venv (by using the manager of the IDE you are running)
|
|
||||||
|
|
||||||
|
## Notes for Linux users:
|
||||||
|
On some Linux distros, `xclip` and `xsel` don't come pre-installed. Install these dependencies.
|
||||||
|
|
||||||
|
|
||||||
|
# Development
|
||||||
|
Be warned, the code base is still very ugly. I only spent about two hours cleaning up the old code, so it still looks ugly. I will probably not clean up the code much more. Some variable names will simply stay weird
|
||||||
|
|||||||
@@ -1,122 +0,0 @@
|
|||||||
"""@package docstring
|
|
||||||
This is a simplification of the csv module"""
|
|
||||||
|
|
||||||
import csv
|
|
||||||
|
|
||||||
|
|
||||||
class CsvRead:
|
|
||||||
"""This is a class that reads csv files and depending on the module selected does do different things with it"""
|
|
||||||
def __init__(self):
|
|
||||||
self.__imp = ""
|
|
||||||
self.__raw = ""
|
|
||||||
self.__raw_list = ""
|
|
||||||
|
|
||||||
def importing(self, path):
|
|
||||||
"""Returns a list of the imported csv-file, requires path, either direct system path or relative path"""
|
|
||||||
self.__imp = open(path)
|
|
||||||
self.__raw = csv.reader(self.__imp, delimiter=',')
|
|
||||||
self.__raw_list = list(self.__raw)
|
|
||||||
self.__imp.close()
|
|
||||||
return self.__raw_list
|
|
||||||
|
|
||||||
|
|
||||||
class CsvWrite:
|
|
||||||
"""This is a class that modifies csv files"""
|
|
||||||
def __init__(self):
|
|
||||||
self.__impl = []
|
|
||||||
self.__strpop = []
|
|
||||||
self.__removed = []
|
|
||||||
self.__removing = 0
|
|
||||||
self.__change = 0
|
|
||||||
self.__appending = 0
|
|
||||||
self.__imp = []
|
|
||||||
self.__raw = []
|
|
||||||
|
|
||||||
def rem_str(self, path, row):
|
|
||||||
"""Opens the csv-file in write mode which is specified as an argument either as direct or relative path"""
|
|
||||||
self.__imp = open(path)
|
|
||||||
self.__raw = csv.reader(self.__imp, delimiter=',')
|
|
||||||
self.__impl = list(self.__raw)
|
|
||||||
self.__removed = self.__impl.pop(row + 1)
|
|
||||||
with open(path, "w") as removedata:
|
|
||||||
self.__removing = csv.writer(removedata, delimiter=',', quoting=csv.QUOTE_MINIMAL)
|
|
||||||
self.__removing.writerow(self.__impl.pop(0))
|
|
||||||
while len(self.__impl) > 0:
|
|
||||||
with open(path, "a") as removedata:
|
|
||||||
self.__removing = csv.writer(removedata, delimiter=',', quoting=csv.QUOTE_MINIMAL)
|
|
||||||
self.__removing.writerow(self.__impl.pop(0))
|
|
||||||
self.__imp.close()
|
|
||||||
removedata.close()
|
|
||||||
|
|
||||||
|
|
||||||
def chg_str(self, path, row, pos, new_value):
|
|
||||||
"""Opens the csv-file in write mode to change a value, e.g. if a recipes is changed."""
|
|
||||||
self.__imp = open(path)
|
|
||||||
self.__raw = csv.reader(self.__imp, delimiter=',')
|
|
||||||
self.__impl = list(self.__raw)
|
|
||||||
self.__strpop = self.__impl.pop(row)
|
|
||||||
self.__strpop.pop(pos)
|
|
||||||
self.__strpop.insert(pos, new_value)
|
|
||||||
self.__impl.insert(row, self.__strpop)
|
|
||||||
with open(path, "w") as changedata:
|
|
||||||
self.__change = csv.writer(changedata, delimiter=',', quoting=csv.QUOTE_MINIMAL)
|
|
||||||
self.__change.writerow(self.__impl.pop(0))
|
|
||||||
while len(self.__impl) > 0:
|
|
||||||
with open(path, "a") as changedata:
|
|
||||||
self.__removing = csv.writer(changedata, delimiter=',', quoting=csv.QUOTE_MINIMAL)
|
|
||||||
self.__removing.writerow(self.__impl.pop(0))
|
|
||||||
self.__imp.close()
|
|
||||||
changedata.close()
|
|
||||||
|
|
||||||
def chg_str_rem(self, path, row, pos):
|
|
||||||
"""Opens the csv-file in write mode to change a value, e.g. if a recipes is changed."""
|
|
||||||
self.__imp = open(path)
|
|
||||||
self.__raw = csv.reader(self.__imp, delimiter=',')
|
|
||||||
self.__impl = list(self.__raw)
|
|
||||||
self.__strpop = self.__impl.pop(row)
|
|
||||||
self.__strpop.pop(pos)
|
|
||||||
self.__strpop.pop(pos)
|
|
||||||
self.__impl.insert(row, self.__strpop)
|
|
||||||
with open(path, "w") as changedata:
|
|
||||||
self.__change = csv.writer(changedata, delimiter=',', quoting=csv.QUOTE_MINIMAL)
|
|
||||||
self.__change.writerow(self.__impl.pop(0))
|
|
||||||
while len(self.__impl) > 0:
|
|
||||||
with open(path, "a") as changedata:
|
|
||||||
self.__removing = csv.writer(changedata, delimiter=',', quoting=csv.QUOTE_MINIMAL)
|
|
||||||
self.__removing.writerow(self.__impl.pop(0))
|
|
||||||
self.__imp.close()
|
|
||||||
changedata.close()
|
|
||||||
|
|
||||||
def chg_str_add(self, path, row, new_value1, new_value2):
|
|
||||||
"""Opens the csv-file in write mode to change a value, e.g. if a recipes is changed."""
|
|
||||||
self.__imp = open(path)
|
|
||||||
self.__raw = csv.reader(self.__imp, delimiter=',')
|
|
||||||
self.__impl = list(self.__raw)
|
|
||||||
self.__strpop = self.__impl.pop(row)
|
|
||||||
self.__strpop.append(new_value1)
|
|
||||||
self.__strpop.append(new_value2)
|
|
||||||
self.__impl.insert(row, self.__strpop)
|
|
||||||
with open(path, "w") as changedata:
|
|
||||||
self.__change = csv.writer(changedata, delimiter=',', quoting=csv.QUOTE_MINIMAL)
|
|
||||||
self.__change.writerow(self.__impl.pop(0))
|
|
||||||
while len(self.__impl) > 0:
|
|
||||||
with open(path, "a") as changedata:
|
|
||||||
self.__removing = csv.writer(changedata, delimiter=',', quoting=csv.QUOTE_MINIMAL)
|
|
||||||
self.__removing.writerow(self.__impl.pop(0))
|
|
||||||
self.__imp.close()
|
|
||||||
changedata.close()
|
|
||||||
|
|
||||||
def app_str(self, path, value):
|
|
||||||
"""Opens the csv-file in append mode and writes given input. CsvWrite.app_str(path, value).
|
|
||||||
Path can be specified both as direct or relative. value is a list. Will return an error if type of value is
|
|
||||||
not a list."""
|
|
||||||
with open(path, "a") as appenddata:
|
|
||||||
self.__appending = csv.writer(appenddata, delimiter=',', quoting=csv.QUOTE_MINIMAL)
|
|
||||||
self.__appending.writerow(value)
|
|
||||||
appenddata.close()
|
|
||||||
|
|
||||||
def write_str(self, path, value):
|
|
||||||
with open(path, "w") as writedata:
|
|
||||||
self.__change = csv.writer(writedata, delimiter=',', quoting=csv.QUOTE_MINIMAL)
|
|
||||||
self.__change.writerow(value)
|
|
||||||
writedata.close()
|
|
||||||
@@ -1,96 +0,0 @@
|
|||||||
from mido import MidiFile
|
|
||||||
import pyperclip as pc
|
|
||||||
|
|
||||||
|
|
||||||
class MidiManagement:
|
|
||||||
def __init__(self):
|
|
||||||
pass
|
|
||||||
|
|
||||||
def addToClipboard(self, text):
|
|
||||||
pc.copy(text)
|
|
||||||
|
|
||||||
def analyse_track(self, path, trackname):
|
|
||||||
self.midi_imp = MidiFile(path, clip=True)
|
|
||||||
self.tracks = []
|
|
||||||
for self.track in self.midi_imp.tracks:
|
|
||||||
self.tracks.append(str(self.track))
|
|
||||||
if len(self.tracks) > 1:
|
|
||||||
self.tracks.pop(0)
|
|
||||||
else:
|
|
||||||
pass
|
|
||||||
self.track_ext = self.tracks.pop(0)
|
|
||||||
self.trackn = 0
|
|
||||||
while self.track_ext != trackname:
|
|
||||||
self.track_ext = self.tracks.pop(0)
|
|
||||||
self.trackn += 1
|
|
||||||
self.extracted_track = self.track_ext
|
|
||||||
self.__output_list = []
|
|
||||||
for self.msg in self.midi_imp.tracks[self.trackn]:
|
|
||||||
self.ext = str(self.msg)
|
|
||||||
self.note = self.ext[23:25]
|
|
||||||
if self.ext[0:8] == "note_on ":
|
|
||||||
try:
|
|
||||||
self.note_height = int(self.note)
|
|
||||||
self.note_decod_oct = self.note_height // 12
|
|
||||||
self.note_decode_tone = self.note_height % 12
|
|
||||||
if self.note_decode_tone == 1:
|
|
||||||
self.note_ext = "C"
|
|
||||||
elif self.note_decode_tone == 2:
|
|
||||||
self.note_ext = "C#"
|
|
||||||
elif self.note_decode_tone == 3:
|
|
||||||
self.note_ext = "D"
|
|
||||||
elif self.note_decode_tone == 4:
|
|
||||||
self.note_ext = "D#"
|
|
||||||
elif self.note_decode_tone == 5:
|
|
||||||
self.note_ext = "E"
|
|
||||||
elif self.note_decode_tone == 6:
|
|
||||||
self.note_ext = "F"
|
|
||||||
elif self.note_decode_tone == 7:
|
|
||||||
self.note_ext = "F#"
|
|
||||||
elif self.note_decode_tone == 8:
|
|
||||||
self.note_ext = "G"
|
|
||||||
elif self.note_decode_tone == 9:
|
|
||||||
self.note_ext = "G#"
|
|
||||||
elif self.note_decode_tone == 10:
|
|
||||||
self.note_ext = "A"
|
|
||||||
elif self.note_decode_tone == 11:
|
|
||||||
self.note_ext = "A#"
|
|
||||||
elif self.note_decode_tone == 12:
|
|
||||||
self.note_ext = "H"
|
|
||||||
|
|
||||||
self.ext_shortened = self.ext[40:]
|
|
||||||
self.pos = 0
|
|
||||||
for buchstabe in self.ext_shortened:
|
|
||||||
if buchstabe == "=":
|
|
||||||
self.pos += 1
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
self.pos += 1
|
|
||||||
|
|
||||||
self.timing_exp = self.ext_shortened[self.pos:]
|
|
||||||
self.__output = self.note_ext
|
|
||||||
self.__output += str(self.note_decod_oct)
|
|
||||||
self.__output += f":{self.timing_exp}"
|
|
||||||
self.__output_list.append(str(self.__output))
|
|
||||||
|
|
||||||
except:
|
|
||||||
pass
|
|
||||||
elif self.ext[0:8] == "note_off":
|
|
||||||
self.ext_shortened = self.ext[40:]
|
|
||||||
self.pos = 0
|
|
||||||
for buchstabe in self.ext_shortened:
|
|
||||||
if buchstabe == "=":
|
|
||||||
self.pos += 1
|
|
||||||
break
|
|
||||||
else:
|
|
||||||
self.pos += 1
|
|
||||||
self.__output = "R"
|
|
||||||
self.__output += f":{self.pos}"
|
|
||||||
|
|
||||||
self.timing_exp = self.ext_shortened[self.pos:]
|
|
||||||
self.__output_list.append(self.__output)
|
|
||||||
else:
|
|
||||||
pass
|
|
||||||
|
|
||||||
self.addToClipboard(str(self.__output_list))
|
|
||||||
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
/home/janis/Desktop/Water Drops Melodie.mid
|
|
||||||
|
@@ -10,15 +10,15 @@ TrackChooseScreen:
|
|||||||
italic: True
|
italic: True
|
||||||
color: (50, 50, 255, 1)
|
color: (50, 50, 255, 1)
|
||||||
FloatLayout:
|
FloatLayout:
|
||||||
Spinner:
|
MDRaisedButton:
|
||||||
id: track_spinner
|
size: "200dp", "50dp"
|
||||||
|
pos_hint: {"center_x": 0.5, "center_y": 0.5}
|
||||||
|
on_release: root.show_dropdown(self)
|
||||||
size_hint: 0.7, 0.2
|
size_hint: 0.7, 0.2
|
||||||
pos_hint: {"x": 0.15, "y":0.5}
|
pos_hint: {"x": 0.15, "y":0.5}
|
||||||
background_color: (0, 0, 0, 1)
|
|
||||||
text: "Select a track"
|
text: "Select a track"
|
||||||
values: ["Test"]
|
|
||||||
Button:
|
Button:
|
||||||
text: "confirm"
|
text: "confirm"
|
||||||
background_color: app.theme_cls.primary_color
|
background_color: app.theme_cls.primary_color
|
||||||
on_release:
|
on_release:
|
||||||
root.extract()
|
root.extract()
|
||||||
|
|||||||
99
lib/midi_management.py
Normal file
99
lib/midi_management.py
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
from mido import MidiFile
|
||||||
|
import pyperclip as pc
|
||||||
|
|
||||||
|
|
||||||
|
class MidiManagement:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def addToClipboard(self, text):
|
||||||
|
pc.copy(text)
|
||||||
|
|
||||||
|
def analyse_track(self, path, trackname):
|
||||||
|
mid = MidiFile(path, clip=True)
|
||||||
|
tracks = []
|
||||||
|
for i, track in enumerate(mid.tracks):
|
||||||
|
tracks.append('{} (Track {})'.format(track.name, i))
|
||||||
|
if len(tracks) > 1:
|
||||||
|
tracks.pop(0)
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
extracted_track = tracks.pop(0)
|
||||||
|
tracknumber = 0
|
||||||
|
while extracted_track != trackname:
|
||||||
|
extracted_track = tracks.pop(0)
|
||||||
|
tracknumber += 1
|
||||||
|
output_list = []
|
||||||
|
|
||||||
|
# Track messages
|
||||||
|
for msg in mid.tracks[tracknumber]:
|
||||||
|
midi_msg = str(msg)
|
||||||
|
if midi_msg[0:8] == "note_on ":
|
||||||
|
try:
|
||||||
|
msg_loc = midi_msg.index('note=')
|
||||||
|
note = midi_msg[msg_loc + 5:msg_loc + 7]
|
||||||
|
note_height = int(note)
|
||||||
|
note_decod_oct = note_height // 12
|
||||||
|
note_decode_tone = note_height % 12
|
||||||
|
note_ext = ""
|
||||||
|
if note_decode_tone == 1:
|
||||||
|
note_ext = "C"
|
||||||
|
elif note_decode_tone == 2:
|
||||||
|
note_ext = "C#"
|
||||||
|
elif note_decode_tone == 3:
|
||||||
|
note_ext = "D"
|
||||||
|
elif note_decode_tone == 4:
|
||||||
|
note_ext = "D#"
|
||||||
|
elif note_decode_tone == 5:
|
||||||
|
note_ext = "E"
|
||||||
|
elif note_decode_tone == 6:
|
||||||
|
note_ext = "F"
|
||||||
|
elif note_decode_tone == 7:
|
||||||
|
note_ext = "F#"
|
||||||
|
elif note_decode_tone == 8:
|
||||||
|
note_ext = "G"
|
||||||
|
elif note_decode_tone == 9:
|
||||||
|
note_ext = "G#"
|
||||||
|
elif note_decode_tone == 10:
|
||||||
|
note_ext = "A"
|
||||||
|
elif note_decode_tone == 11:
|
||||||
|
note_ext = "A#"
|
||||||
|
elif note_decode_tone == 12:
|
||||||
|
note_ext = "H"
|
||||||
|
|
||||||
|
ext_shortened = midi_msg[40:]
|
||||||
|
pos = 0
|
||||||
|
for buchstabe in ext_shortened:
|
||||||
|
if buchstabe == "=":
|
||||||
|
pos += 1
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
pos += 1
|
||||||
|
|
||||||
|
timing_exp = ext_shortened[pos:]
|
||||||
|
output = note_ext
|
||||||
|
output += str(note_decod_oct)
|
||||||
|
output += f":{timing_exp}"
|
||||||
|
output_list.append(str(output))
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
elif midi_msg[0:8] == "note_off":
|
||||||
|
ext_shortened = midi_msg[40:]
|
||||||
|
pos = 0
|
||||||
|
for buchstabe in ext_shortened:
|
||||||
|
if buchstabe == "=":
|
||||||
|
pos += 1
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
pos += 1
|
||||||
|
output = "R"
|
||||||
|
output += f":{pos}"
|
||||||
|
|
||||||
|
timing_exp = ext_shortened[pos:]
|
||||||
|
output_list.append(output)
|
||||||
|
else:
|
||||||
|
pass
|
||||||
|
|
||||||
|
self.addToClipboard(str(output_list))
|
||||||
|
|
||||||
@@ -6,14 +6,9 @@ mkdir ./midi-micro_bit-converter && cd ./midi-micro_bit-converter
|
|||||||
|
|
||||||
git clone https://github.com/simplePCBuilding/midi-micro-bit_sound-converter
|
git clone https://github.com/simplePCBuilding/midi-micro-bit_sound-converter
|
||||||
|
|
||||||
pip install kivy[base]
|
pip install kivy[base] kivymd pyperclip mido
|
||||||
pip install kivymd
|
|
||||||
pip install pyperclip
|
|
||||||
pip install mido
|
|
||||||
|
|
||||||
sudo apt-get install xclip
|
sudo apt-get install xclip xsel
|
||||||
sudo apt-get install xsel
|
|
||||||
sudo apt-get install wl-clipboard
|
|
||||||
|
|
||||||
cd ./midi-micro-bit_sound-converter
|
cd ./midi-micro-bit_sound-converter
|
||||||
python3 midi_converter.py
|
python3 midi_converter.py
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
|
from typing import Optional
|
||||||
from kivy.uix.screenmanager import ScreenManager
|
from kivy.uix.screenmanager import ScreenManager
|
||||||
from kivymd.uix.screen import MDScreen
|
from kivymd.uix.screen import MDScreen
|
||||||
|
from kivymd.uix.menu import MDDropdownMenu
|
||||||
|
from kivymd.uix.screen import MDScreen
|
||||||
from kivy.uix.popup import Popup
|
from kivy.uix.popup import Popup
|
||||||
from kivy.properties import ObjectProperty
|
from kivy.properties import ObjectProperty
|
||||||
from kivy.lang import Builder
|
from kivy.lang import Builder
|
||||||
@@ -7,10 +10,13 @@ from kivy.uix.label import Label
|
|||||||
from kivymd.app import MDApp
|
from kivymd.app import MDApp
|
||||||
from mido import MidiFile
|
from mido import MidiFile
|
||||||
import os
|
import os
|
||||||
import backend.midi_management
|
import lib.midi_management
|
||||||
import backend.csv_parsers
|
|
||||||
import time
|
|
||||||
|
|
||||||
|
global tracks
|
||||||
|
tracks = []
|
||||||
|
|
||||||
|
global filepath
|
||||||
|
filepath = ''
|
||||||
|
|
||||||
class HomeScreen(MDScreen):
|
class HomeScreen(MDScreen):
|
||||||
pass
|
pass
|
||||||
@@ -19,25 +25,27 @@ class HomeScreen(MDScreen):
|
|||||||
class FileChooserScreen(MDScreen):
|
class FileChooserScreen(MDScreen):
|
||||||
loadfile = ObjectProperty(None)
|
loadfile = ObjectProperty(None)
|
||||||
def load(self, path, filename):
|
def load(self, path, filename):
|
||||||
|
global filepath
|
||||||
try:
|
try:
|
||||||
self.path = os.path.join(path, filename[0])
|
self.path = os.path.join(path, filename[0])
|
||||||
try:
|
try:
|
||||||
self.mid = MidiFile(self.path, clip=True)
|
mid = MidiFile(self.path, clip=True)
|
||||||
backend.csv_parsers.CsvWrite().write_str("./backend/temp.csv", [self.path])
|
filepath = self.path
|
||||||
self.tracks = []
|
global tracks
|
||||||
for self.track in self.mid.tracks:
|
tracks = []
|
||||||
self.tracks.append(str(self.track))
|
for i, track in enumerate(mid.tracks):
|
||||||
if len(self.tracks) > 1:
|
tracks.append('{} (Track {})'.format(track.name, i))
|
||||||
self.tracks.pop(0)
|
if len(tracks) > 1:
|
||||||
screen_manager.get_screen("Track").ids.track_spinner.values = self.tracks
|
tracks.pop(0)
|
||||||
screen_manager.current = "Track"
|
screen_manager.current = "Track"
|
||||||
screen_manager.transition.direction = "up"
|
screen_manager.transition.direction = "up"
|
||||||
else:
|
else:
|
||||||
backend.midi_management.MidiManagement().analyse_track(str(self.path), self.tracks.pop(0))
|
lib.midi_management.MidiManagement().analyse_track(str(self.path), tracks.pop(0))
|
||||||
screen_manager.get_screen("Home").ids.infobox.text = "The command has been copied to the clipboard"
|
screen_manager.get_screen("Home").ids.infobox.text = "The command has been copied to the clipboard"
|
||||||
screen_manager.current = "Home"
|
screen_manager.current = "Home"
|
||||||
screen_manager.transition.direction = "right"
|
screen_manager.transition.direction = "right"
|
||||||
except:
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
self.popup_fe = Popup(title="FileError", content=Label(text="Please select a MIDI-File!"),
|
self.popup_fe = Popup(title="FileError", content=Label(text="Please select a MIDI-File!"),
|
||||||
size_hint=(0.4, 0.4), auto_dismiss=True)
|
size_hint=(0.4, 0.4), auto_dismiss=True)
|
||||||
self.popup_fe.open()
|
self.popup_fe.open()
|
||||||
@@ -49,16 +57,40 @@ class FileChooserScreen(MDScreen):
|
|||||||
|
|
||||||
|
|
||||||
class TrackChooseScreen(MDScreen):
|
class TrackChooseScreen(MDScreen):
|
||||||
def extract(self):
|
def show_dropdown(self, button):
|
||||||
self.chosen_track = self.ids.track_spinner.text
|
global tracks
|
||||||
if self.chosen_track == "Select a track":
|
menu_items = []
|
||||||
self.popup_ns = Popup(title="NoSelectionError", content=Label(text="Please select a Track!"),
|
for track in tracks:
|
||||||
|
menu_items.append(
|
||||||
|
{
|
||||||
|
"viewclass": "OneLineListItem",
|
||||||
|
"text": track,
|
||||||
|
"on_release": lambda t=track, menu=None : self.extract(t, menu)
|
||||||
|
}
|
||||||
|
)
|
||||||
|
|
||||||
|
menu = MDDropdownMenu(
|
||||||
|
caller=button,
|
||||||
|
items=menu_items,
|
||||||
|
width_mult=8,
|
||||||
|
)
|
||||||
|
|
||||||
|
# Pass the menu to each item in the lambda callback to dismiss the menu
|
||||||
|
for item in menu_items:
|
||||||
|
item["on_release"] = lambda track=item["text"], menu=menu: self.extract(track, menu)
|
||||||
|
|
||||||
|
menu.open()
|
||||||
|
|
||||||
|
def extract(self, item: str, menu: Optional[MDDropdownMenu] = None):
|
||||||
|
global filepath
|
||||||
|
if menu != None:
|
||||||
|
menu.dismiss()
|
||||||
|
if item == "Select a track":
|
||||||
|
popup_ns = Popup(title="NoSelectionError", content=Label(text="Please select a Track!"),
|
||||||
size_hint=(0.4, 0.4), auto_dismiss=True)
|
size_hint=(0.4, 0.4), auto_dismiss=True)
|
||||||
self.popup_ns.open()
|
popup_ns.open()
|
||||||
else:
|
else:
|
||||||
self.path = backend.csv_parsers.CsvRead().importing("./backend/temp.csv").pop(0)
|
lib.midi_management.MidiManagement().analyse_track(str(filepath), item)
|
||||||
self.path_transmit = self.path.pop(0)
|
|
||||||
backend.midi_management.MidiManagement().analyse_track(str(self.path_transmit), self.chosen_track)
|
|
||||||
screen_manager.get_screen("Home").ids.infobox.text = "The command has been copied to the clipboard"
|
screen_manager.get_screen("Home").ids.infobox.text = "The command has been copied to the clipboard"
|
||||||
screen_manager.current = "Home"
|
screen_manager.current = "Home"
|
||||||
screen_manager.transition.direction = "right"
|
screen_manager.transition.direction = "right"
|
||||||
|
|||||||
Reference in New Issue
Block a user