diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index de610f13..5b586a6b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -24,7 +24,7 @@ jobs: uses: bilelmoussaoui/flatpak-github-actions/flatpak-builder@v3 with: bundle: Ensembles.flatpak - manifest-path: com.github.subhadeepjasu.ensembles.yml + manifest-path: com.github.ensemblesaw.ensembles.yml run-tests: true repository-name: appcenter repository-url: https://flatpak.elementary.io/repo.flatpakrepo diff --git a/.gitignore b/.gitignore index 00a18a74..54d54d31 100644 --- a/.gitignore +++ b/.gitignore @@ -11,3 +11,8 @@ null.d *~ .~lock* xtleak.kcg.* +subprojects/ens-shell-gtk +subprojects/ens-shell-cli +subprojects/ens-aw-core +subprojects/enstl +subprojects/libvinject diff --git a/com.github.ensemblesaw.ensembles.yml b/com.github.ensemblesaw.ensembles.yml new file mode 100644 index 00000000..299fcdba --- /dev/null +++ b/com.github.ensemblesaw.ensembles.yml @@ -0,0 +1,203 @@ +app-id: com.github.ensemblesaw.ensembles +runtime: io.elementary.Platform +runtime-version: '7.3' +sdk: io.elementary.Sdk +command: com.github.ensemblesaw.ensembles +finish-args: + - '--share=ipc' + - '--socket=fallback-x11' + - '--socket=wayland' + - '--socket=pulseaudio' + - '--device=all' + - '--filesystem=home' + # Required for system wide dark style preference + - '--system-talk-name=org.freedesktop.Accounts' + # Required for media keys and MPRIS access + - '--own-name=org.mpris.MediaPlayer2.com.github.subhadeepjasu.ensembles' + - '--talk-name=org.gnome.SettingsDaemon.MediaKeys' + # For PipeWire + - '--filesystem=xdg-run/pipewire-0' + - '--system-talk-name=org.freedesktop.RealtimeKit1' +modules: + # Adds dependency injection + - name: vinject + buildsystem: meson + sources: + - type: git + url: https://gitlab.com/geeky_endeavours/vinject.git + branch: main + + + # Adds support for lv2 virtual instruments and effects plugins + - name: lv2 + buildsystem: meson + cleanup: + - /bin + - /include + - /lib/pkgconfig + - /share + sources: + - type: archive + url: https://lv2plug.in/spec/lv2-1.18.10.tar.xz + sha256: 78c51bcf21b54e58bb6329accbb4dae03b2ed79b520f9a01e734bd9de530953f + post-install: + - install -Dm644 -t $FLATPAK_DEST/share/licenses/lv2 ../COPYING + - ln -sf lv2.pc $FLATPAK_DEST/lib/pkgconfig/lv2core.pc + + # Allows Ensembles to act as a lv2 host + - name: lilv + buildsystem: meson + modules: + - name: serd + buildsystem: meson + sources: + - type: archive + url: https://download.drobilla.net/serd-0.30.16.tar.xz + sha256: f50f486da519cdd8d03b20c9e42414e459133f5a244411d8e63caef8d9ac9146 + post-install: + - install -Dm644 -t $FLATPAK_DEST/share/licenses/serd ../COPYING + cleanup: + - /bin + - /include + - /lib/pkgconfig + - /share/man + - name: sord + buildsystem: meson + sources: + - type: archive + url: https://download.drobilla.net/sord-0.16.14.tar.xz + sha256: 220fd97d5fcb216e7b85db66f685bfdaad7dc58a50d1f96dfb2558dbc6c4731b + post-install: + - install -Dm644 -t $FLATPAK_DEST/share/licenses/sord ../COPYING + cleanup: + - /bin + - /include + - /lib/pkgconfig + - /share/doc + - /share/man + - name: sratom + buildsystem: meson + sources: + - type: archive + url: https://download.drobilla.net/sratom-0.6.14.tar.xz + sha256: 9982faf40db83aedd9b3850e499fecd6852b8b4ba6dede514013655cffaca1e6 + post-install: + - install -Dm644 -t $FLATPAK_DEST/share/licenses/sratom ../COPYING + cleanup: + - /include + - /lib/pkgconfig + sources: + - type: archive + url: https://download.drobilla.net/lilv-0.24.20.tar.xz + sha256: 4fb082b9b8b286ea92bbb71bde6b75624cecab6df0cc639ee75a2a096212eebc + post-install: + - install -Dm644 -t $FLATPAK_DEST/share/licenses/lilv ../COPYING + cleanup: + - /bin + - /etc + - /include + - /lib/pkgconfig + - /share/man + + - name: zix + buildsystem: meson + sources: + - type: git + url: https://github.com/drobilla/zix.git + tag: v0.4.2 + + - name: suil + buildsystem: meson + sources: + - type: archive + url: https://download.drobilla.net/suil-0.10.20.tar.xz + sha256: 334a3ed3e73d5e17ff400b3db9801f63809155b0faa8b1b9046f9dd3ffef934e + post-install: + - install -Dm644 -t $FLATPAK_DEST/share/licenses/suil ../COPYING + cleanup: + - /bin + - /include + - /lib/pkgconfig + - /share/man + + # Synthesizer backend + - name: fluidsynth + buildsystem: cmake-ninja + cleanup: + - /bin + - /include + - /lib/pkgconfig + - /share/man + - '*.so' + sources: + - type: archive + url: https://github.com/FluidSynth/fluidsynth/archive/v2.3.4.tar.gz + sha256: 1529ef5bc3b9ef3adc2a7964505912f7305103e269e50cc0316f500b22053ac9 + + # MIDI controller support + - name: portmidi + buildsystem: cmake + sources: + - type: git + url: https://github.com/PortMidi/portmidi.git + tag: v2.0.3 + + + # Install styles + - name: styles + buildsystem: meson + sources: + - type: git + url: https://github.com/ensemblesaw/styles.git + branch: main + + # CLI shell + - name: ens-shell-cli + buildsystem: meson + sources: + - type: git + url: https://github.com/ensemblesaw/ens-shell-cli.git + branch: main + + # Arranger Workstation Core + - name: ens-aw-core + buildsystem: meson + build-options: + config-opts: + - -Dprofile=default + - -Dbuildtype=release + sources: + - type: git + url: https://github.com/ensemblesaw/ens-aw-core.git + branch: main + + # GTK Shell + - name: ens-shell-gtk + buildsystem: meson + build-options: + config-opts: + - -Dprofile=default + - -Dbuildtype=release + sources: + - type: git + url: https://github.com/ensemblesaw/ens-shell-gtk.git + branch: main + + # The app itself + - name: ensembles + buildsystem: meson + build-options: + config-opts: + - -Dprofile=default + - -Dbuildtype=release + sources: + - type: dir + path: . + + # Adds default soundfont + - name: ensemblesGMSoundfonts + buildsystem: meson + sources: + - type: archive + url: https://gitlab.com/SubhadeepJasu/ensemblesgmsoundfont/-/archive/v0.0.3/ensemblesgmsoundfont-v0.0.3.tar.gz + sha256: 0b5ecca24623dabc9ea546c49cc25ebb3f419d6b61c035c603133a1032a4f2bc diff --git a/com.github.subhadeepjasu.ensembles.yml b/com.github.subhadeepjasu.ensembles.yml deleted file mode 100644 index ca784203..00000000 --- a/com.github.subhadeepjasu.ensembles.yml +++ /dev/null @@ -1,194 +0,0 @@ -app-id: com.github.subhadeepjasu.ensembles -runtime: io.elementary.Platform -runtime-version: '7.1' -sdk: io.elementary.Sdk -command: com.github.subhadeepjasu.ensembles -finish-args: - - '--share=ipc' - - '--socket=fallback-x11' - - '--socket=wayland' - - '--socket=pulseaudio' - - '--device=all' - - '--filesystem=home' - # Required for system wide dark style preference - - '--system-talk-name=org.freedesktop.Accounts' - # Required for media keys and MPRIS access - - '--own-name=org.mpris.MediaPlayer2.com.github.subhadeepjasu.ensembles' - - '--talk-name=org.gnome.SettingsDaemon.MediaKeys' - # For PipeWire - - '--filesystem=xdg-run/pipewire-0' - - '--system-talk-name=org.freedesktop.RealtimeKit1' -modules: - # Adds support for lv2 virtual instruments and effects plugins - - name: lv2 - buildsystem: simple - cleanup: - - /bin - - /include - - /pkgconfig - - /share - build-commands: - - python3 ./waf configure --prefix=$FLATPAK_DEST --lv2dir=$FLATPAK_DEST/lib/lv2 --copy-headers - - python3 ./waf build -j $FLATPAK_BUILDER_N_JOBS - - python3 ./waf install - sources: - - type: archive - url: https://lv2plug.in/spec/lv2-1.18.2.tar.bz2 - sha256: 4e891fbc744c05855beb5dfa82e822b14917dd66e98f82b8230dbd1c7ab2e05e - post-install: - - install -Dm644 -t $FLATPAK_DEST/share/licenses/lv2 COPYING - - ln -sf lv2.pc $FLATPAK_DEST/lib/pkgconfig/lv2core.pc - - # Allows Ensembles to act as a lv2 host - - name: lilv - buildsystem: simple - build-commands: - - python3 ./waf configure --prefix=$FLATPAK_DEST - - python3 ./waf build -j $FLATPAK_BUILDER_N_JOBS - - python3 ./waf install - modules: - - name: serd - buildsystem: simple - build-commands: - - python3 ./waf configure --prefix=$FLATPAK_DEST - - python3 ./waf build -j $FLATPAK_BUILDER_N_JOBS - - python3 ./waf install - sources: - - type: archive - url: https://download.drobilla.net/serd-0.30.10.tar.bz2 - sha256: affa80deec78921f86335e6fc3f18b80aefecf424f6a5755e9f2fa0eb0710edf - post-install: - - install -Dm644 -t /app/share/licenses/serd COPYING - cleanup: - - /bin - - /include - - /lib/pkgconfig - - /share/man - - name: sord - buildsystem: simple - build-commands: - - python3 ./waf configure --prefix=$FLATPAK_DEST - - python3 ./waf build -j $FLATPAK_BUILDER_N_JOBS - - python3 ./waf install - sources: - - type: archive - url: https://download.drobilla.net/sord-0.16.8.tar.bz2 - sha256: 7c289d2eaabf82fa6ac219107ce632d704672dcfb966e1a7ff0bbc4ce93f5e14 - post-install: - - install -Dm644 -t /app/share/licenses/sord COPYING - cleanup: - - /bin - - /include - - /lib/pkgconfig - - /share/man - - name: sratom - buildsystem: simple - build-commands: - - python3 ./waf configure --prefix=$FLATPAK_DEST - - python3 ./waf build -j $FLATPAK_BUILDER_N_JOBS - - python3 ./waf install - sources: - - type: archive - url: https://download.drobilla.net/sratom-0.6.8.tar.bz2 - sha256: 3acb32b1adc5a2b7facdade2e0818bcd6c71f23f84a1ebc17815bb7a0d2d02df - post-install: - - install -Dm644 -t /app/share/licenses/sratom COPYING - cleanup: - - /include - - /lib/pkgconfig - sources: - - type: archive - url: https://download.drobilla.net/lilv-0.24.12.tar.bz2 - sha256: 26a37790890c9c1f838203b47f5b2320334fe92c02a4d26ebbe2669dbd769061 - post-install: - - install -Dm644 -t /app/share/licenses/lilv COPYING - cleanup: - - /bin - - /etc - - /lib/pkgconfig - - /share/man - - - name: suil - buildsystem: simple - build-commands: - - python3 ./waf configure --prefix=$FLATPAK_DEST - - python3 ./waf build -j $FLATPAK_BUILDER_N_JOBS - - python3 ./waf install - sources: - - type: archive - url: http://download.drobilla.net/suil-0.10.10.tar.bz2 - sha256: 750f08e6b7dc941a5e694c484aab02f69af5aa90edcc9fb2ffb4fb45f1574bfb - post-install: - - install -Dm644 -t /app/share/licenses/suil COPYING - cleanup: - - /bin - - /include - - /lib/pkgconfig - - /share/man - - # Synthesizer backend - # - name: fluidsynth - # buildsystem: cmake-ninja - # config-opts: - # - -DLIB_SUFFIX= - # cleanup: - # - /bin - # - /include - # - /lib/pkgconfig - # - /share/man - # - '*.so' - # sources: - # - type: archive - # url: https://github.com/FluidSynth/fluidsynth/archive/v2.2.4.tar.gz - # sha256: 83cb1dba04c632ede74f0c0717018b062c0e00b639722203b23f77a961afd390 - - name: fluidsynth - buildsystem: cmake-ninja - config-opts: - - -DLIB_SUFFIX= - cleanup: - - /bin - - /include - - /lib/pkgconfig - - /share/man - - '*.so' - - '*.a' - sources: - - type: git - url: https://github.com/FluidSynth/fluidsynth - - # MIDI controller support - - name: portmidi - buildsystem: cmake-ninja - config-opts: - - -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=/app/lib - - -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY=/app/lib - - -DCMAKE_RUNTIME_OUTPUT_DIRECTORY=/app/bin - post-install: - - ln -s libportmidi.so /app/lib/libporttime.so - sources: - - type: archive - url: https://sourceforge.net/projects/portmedia/files/portmidi/217/portmidi-src-217.zip - sha256: 08e9a892bd80bdb1115213fb72dc29a7bf2ff108b378180586aa65f3cfd42e0f - - type: patch - path: patches/portmidi-no-java.patch - cleanup: - - /bin - - /lib/pkgconfig - - /include - - '*.a' - - '*.la' - - # The app itself - - name: ensembles - buildsystem: meson - sources: - - type: dir - path: . - - # Adds default soundfont - - name: ensemblesGMSoundfonts - buildsystem: meson - sources: - - type: archive - url: https://gitlab.com/SubhadeepJasu/ensemblesgmsoundfont/-/archive/v0.0.3/ensemblesgmsoundfont-v0.0.3.tar.gz - sha256: 0b5ecca24623dabc9ea546c49cc25ebb3f419d6b61c035c603133a1032a4f2bc diff --git a/data/Icons/128/com.github.ensemblesaw.ensembles.svg b/data/Icons/128/com.github.ensemblesaw.ensembles.svg new file mode 100644 index 00000000..97506b32 --- /dev/null +++ b/data/Icons/128/com.github.ensemblesaw.ensembles.svg @@ -0,0 +1,698 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/Icons/128/com.github.subhadeepjasu.ensembles.svg b/data/Icons/128/com.github.subhadeepjasu.ensembles.svg deleted file mode 100644 index f833964e..00000000 --- a/data/Icons/128/com.github.subhadeepjasu.ensembles.svg +++ /dev/null @@ -1,464 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/Icons/16/com.github.subhadeepjasu.ensembles.svg b/data/Icons/16/com.github.ensemblesaw.ensembles.svg similarity index 100% rename from data/Icons/16/com.github.subhadeepjasu.ensembles.svg rename to data/Icons/16/com.github.ensemblesaw.ensembles.svg diff --git a/data/Icons/24/com.github.subhadeepjasu.ensembles.svg b/data/Icons/24/com.github.ensemblesaw.ensembles.svg similarity index 73% rename from data/Icons/24/com.github.subhadeepjasu.ensembles.svg rename to data/Icons/24/com.github.ensemblesaw.ensembles.svg index 03762cef..a391ad43 100644 --- a/data/Icons/24/com.github.subhadeepjasu.ensembles.svg +++ b/data/Icons/24/com.github.ensemblesaw.ensembles.svg @@ -1,184 +1,184 @@ - - - + + + - - + + - - - - + + + + - - + + - - + + - + - + - + - + - + - + - - - - - - + + + + + + - - - + + + - + - - + + - - + + - + - - + + - - + + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - - + + - + - + - + - + - + - + - + - + - + - + diff --git a/data/Icons/32/com.github.ensemblesaw.ensembles.svg b/data/Icons/32/com.github.ensemblesaw.ensembles.svg new file mode 100644 index 00000000..d1fb3870 --- /dev/null +++ b/data/Icons/32/com.github.ensemblesaw.ensembles.svg @@ -0,0 +1,310 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/Icons/32/com.github.subhadeepjasu.ensembles.svg b/data/Icons/32/com.github.subhadeepjasu.ensembles.svg deleted file mode 100644 index dfcb9f14..00000000 --- a/data/Icons/32/com.github.subhadeepjasu.ensembles.svg +++ /dev/null @@ -1,310 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/Icons/48/com.github.ensemblesaw.ensembles.svg b/data/Icons/48/com.github.ensemblesaw.ensembles.svg new file mode 100644 index 00000000..2984d8f6 --- /dev/null +++ b/data/Icons/48/com.github.ensemblesaw.ensembles.svg @@ -0,0 +1,331 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/Icons/48/com.github.subhadeepjasu.ensembles.svg b/data/Icons/48/com.github.subhadeepjasu.ensembles.svg deleted file mode 100644 index 55f68f9f..00000000 --- a/data/Icons/48/com.github.subhadeepjasu.ensembles.svg +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/Icons/64/com.github.ensemblesaw.ensembles.svg b/data/Icons/64/com.github.ensemblesaw.ensembles.svg new file mode 100644 index 00000000..4b65e5c3 --- /dev/null +++ b/data/Icons/64/com.github.ensemblesaw.ensembles.svg @@ -0,0 +1,362 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/data/Icons/64/com.github.subhadeepjasu.ensembles.svg b/data/Icons/64/com.github.subhadeepjasu.ensembles.svg deleted file mode 100644 index ad42eba1..00000000 --- a/data/Icons/64/com.github.subhadeepjasu.ensembles.svg +++ /dev/null @@ -1,337 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/Icons/scalable/actions/plugin-add-symbolic.svg b/data/Icons/scalable/actions/plugin-add-symbolic.svg deleted file mode 100644 index 1c3cb996..00000000 --- a/data/Icons/scalable/actions/plugin-add-symbolic.svg +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - - - - - - - diff --git a/data/Icons/scalable/actions/style-break-symbolic.svg b/data/Icons/scalable/actions/style-break-symbolic.svg deleted file mode 100644 index 0900ecdd..00000000 --- a/data/Icons/scalable/actions/style-break-symbolic.svg +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/data/Icons/scalable/actions/style-sync-start-symbolic.svg b/data/Icons/scalable/actions/style-sync-start-symbolic.svg deleted file mode 100644 index c05a1bae..00000000 --- a/data/Icons/scalable/actions/style-sync-start-symbolic.svg +++ /dev/null @@ -1,69 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/data/Icons/scalable/emblems/plugin-audio-lv2-symbolic.svg b/data/Icons/scalable/emblems/plugin-audio-lv2-symbolic.svg deleted file mode 100644 index b534b296..00000000 --- a/data/Icons/scalable/emblems/plugin-audio-lv2-symbolic.svg +++ /dev/null @@ -1,3 +0,0 @@ - - - diff --git a/data/Icons/symbolic/com.github.subhadeepjasu.ensembles-symbolic.svg b/data/Icons/symbolic/com.github.ensemblesaw.ensembles-symbolic.svg similarity index 100% rename from data/Icons/symbolic/com.github.subhadeepjasu.ensembles-symbolic.svg rename to data/Icons/symbolic/com.github.ensemblesaw.ensembles-symbolic.svg diff --git a/data/Images/Display/catalin-sandru-7SxSkCvVM1U-unsplash-blurred.jpg b/data/Images/Display/catalin-sandru-7SxSkCvVM1U-unsplash-blurred.jpg deleted file mode 100644 index b619a954..00000000 Binary files a/data/Images/Display/catalin-sandru-7SxSkCvVM1U-unsplash-blurred.jpg and /dev/null differ diff --git a/data/Images/Display/catalin-sandru-7SxSkCvVM1U-unsplash.jpg b/data/Images/Display/catalin-sandru-7SxSkCvVM1U-unsplash.jpg deleted file mode 100644 index 915cb581..00000000 Binary files a/data/Images/Display/catalin-sandru-7SxSkCvVM1U-unsplash.jpg and /dev/null differ diff --git a/data/Images/Display/catalin-sandru-7SxSkCvVM1U-unsplash.jpg.back b/data/Images/Display/catalin-sandru-7SxSkCvVM1U-unsplash.jpg.back deleted file mode 100644 index 49fed517..00000000 Binary files a/data/Images/Display/catalin-sandru-7SxSkCvVM1U-unsplash.jpg.back and /dev/null differ diff --git a/data/Images/Display/splash_screen.png b/data/Images/Display/splash_screen.png deleted file mode 100644 index d59ebadc..00000000 Binary files a/data/Images/Display/splash_screen.png and /dev/null differ diff --git a/data/Images/beat_counter.svg b/data/Images/beat_counter.svg deleted file mode 100644 index 06761c42..00000000 --- a/data/Images/beat_counter.svg +++ /dev/null @@ -1,549 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/data/Themes/Application.css b/data/Themes/Application.css deleted file mode 100644 index 855e0950..00000000 --- a/data/Themes/Application.css +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -.panel { - padding: 4px; -} - -.can-be-blurred { - filter: blur(0) brightness(1); - transition: filter 0.5s cubic-bezier(0, 0, 0, 1); -} - -.blurred { - filter: blur(16px) brightness(0.9); - transition: filter 0.2s ease-out; -} - -button { - outline: 0; - box-shadow: none; -} - -button.pulse { - animation: pulse 3s linear infinite; -} - -button.pulse-fill { - animation: pulse-alt 1s linear infinite; -} - -@keyframes pulse { - 0% { - background-color: @bg-color; - box-shadow: inset 0 0 0 1px alpha(#000, 0.1); - } - - 5% { - background-color: alpha(@accent_color, 0.7); - box-shadow: inset 0 0 8px @accent_color; - } - - 25% { - background-color: @bg-color; - box-shadow: inset 0 0 0 1px alpha(#000, 0.1); - } - - 30% { - background-color: alpha(@accent_color, 0.5); - box-shadow: inset 0 0 8px @accent_color; - } - - 50% { - background-color: @bg-color; - box-shadow: inset 0 0 0 1px alpha(#000, 0.1); - } - - 55% { - background-color: alpha(@accent_color, 0.7); - box-shadow: inset 0 0 8px @accent_color; - } - - 75% { - background-color: @bg-color; - box-shadow: inset 0 0 0 1px alpha(#000, 0.1); - } - - 80% { - background-color: alpha(@accent_color, 0.5); - box-shadow: inset 0 0 8px @accent_color; - } - - 100% { - background-color: @bg-color; - box-shadow: inset 0 0 0 1px alpha(#000, 0.1); - } -} - -@keyframes pulse-alt { - 0% { - background-color: @bg-color; - box-shadow: inset 0 0 0 1px alpha(#000, 0.1); - } - - 5% { - background-color: alpha(@accent_color_complimentary, 0.7); - box-shadow: inset 0 0 8px @accent_color_complimentary; - } - - 10% { - background-color: alpha(@accent_color_complimentary_alternate, 0.7); - box-shadow: inset 0 0 8px @accent_color_complimentary_alternate; - } - - 25% { - background-color: @bg-color; - box-shadow: inset 0 0 0 1px alpha(#000, 0.1); - } - - 30% { - background-color: alpha(@accent_color_complimentary, 0.5); - box-shadow: inset 0 0 8px @accent_color_complimentary; - } - - 35% { - background-color: alpha(@accent_color_complimentary_alternate, 0.7); - box-shadow: inset 0 0 8px @accent_color_complimentary_alternate; - } - - 50% { - background-color: @bg-color; - box-shadow: inset 0 0 0 1px alpha(#000, 0.1); - } - - 55% { - background-color: alpha(@accent_color_complimentary, 0.7); - box-shadow: inset 0 0 8px @accent_color_complimentary; - } - - 60% { - background-color: alpha(@accent_color_complimentary_alternate, 0.7); - box-shadow: inset 0 0 8px @accent_color_complimentary_alternate; - } - - 75% { - background-color: @bg-color; - box-shadow: inset 0 0 0 1px alpha(#000, 0.1); - } - - 80% { - background-color: alpha(@accent_color_complimentary, 0.5); - box-shadow: inset 0 0 8px @accent_color_complimentary; - } - - 85% { - background-color: alpha(@accent_color_complimentary_alternate, 0.7); - box-shadow: inset 0 0 8px @accent_color_complimentary_alternate; - } - - 100% { - background-color: @bg-color; - box-shadow: inset 0 0 0 1px alpha(#000, 0.1); - } -} - - -.beat-counter-0 { - background-image: url("resource://com/github/subhadeepjasu/ensembles/images/beat_counter_map"); -} - -.beat-counter-1 { - background-image: url("resource://com/github/subhadeepjasu/ensembles/images/beat_counter_map"); - background-position: 0px -32px; -} - -.beat-counter-2 { - background-image: url("resource://com/github/subhadeepjasu/ensembles/images/beat_counter_map"); - background-position: 0px -64px; -} - -.beat-counter-3 { - background-image: url("resource://com/github/subhadeepjasu/ensembles/images/beat_counter_map"); - background-position: 0px -96px; -} - -.beat-counter-4 { - background-image: url("resource://com/github/subhadeepjasu/ensembles/images/beat_counter_map"); - background-position: 0px -128px; -} - -.adw-listbox>row { - margin: 8px; - padding: 12px; - border-radius: 8px; - border: 1px solid #0002; - box-shadow: 0 2px 4px #0003, inset 0 0 0 1px #fff1; - transition: all 0.4s cubic-bezier(0, 0, 0, 1); -} - -.adw-listbox>row:selected { - background: alpha(@accent_color, 0.2); - box-shadow: 0 2px 4px alpha(shade(@accent_color, 0.6), 0.5), inset 0 0 0 1px #fff1; -} - -.adw-listbox>row>.header>.title>.subtitle { - font-size: small; - opacity: 0.5; -} - -dimming { - background: #0001; -} - -flap>.adw-listbox { - border-right: 1px solid #0004; -} - -.folded>.adw-listbox { - border-right: 1px solid #0006; - box-shadow: 0px 0px 32px 32px #0004; -} - -flap>stack { - filter: blur(0); - transform: scale(1); - transition: all 0.4s cubic-bezier(0, 0, 0, 1); -} - -stack.dimmed { - filter: blur(4px); -} - -/* KEYBOARD */ - -.keyboard { - background: shade(@bg_color, 0.9); - border-top: 1px solid #0006; - background-image: linear-gradient( - shade(@bg_color, 1.8) 0, - shade(@bg_color, 0.9) 16px, - alpha(shade(@bg_color, 0.4), 0.3) 17px, - shade(@bg_color, 1.8) 34px, #000 35px - ); -} - -.keyboard-info-bar button { - opacity: 0.5; - -gtk-icon-shadow: 0 0 0 #fff0; - transition: all 0.2s ease-out; -} - -.keyboard-info-bar button:hover { - opacity: 1; - -gtk-icon-shadow: 0 0 8px #fff; -} - -.key { - background: @bg_color; - background-image: linear-gradient(alpha(shade(@bg_color, 2), 0.5), alpha(shade(@bg_color, 0.8), 0.5)); - border-radius: 0px 0px 6px 6px; - border: 2px solid #000; - filter: none; - box-shadow: inset 0 0 0 1px #fff2; - transition: all 1s ease-out; -} - -.key.black { - background: @fg_color; - background-image: linear-gradient(alpha(shade(@bg_color, 2), 0.4), alpha(shade(@bg_color, 0.3), 0.5)); - box-shadow: inset 0 0 0 1px #fff2; - border-radius: 0px 0px 5px 5px; - transition: all 1s ease-out; -} - -.key:hover { - box-shadow: inset 0 0 0 1px #fff2, inset 0 -4px 12px #fff4; - filter: brightness(1.1); - transition: all 0.1s linear; -} - - -.key.black.activated { - box-shadow: inset 0 0 0 1px shade(@accent_color, 1.2), inset 0 -4px 12px alpha(shade(@accent_color, 1.5), 0.6), 0 0 12px alpha(@accent_color, 0.5); - background-color: mix(@accent_color, @fg_color, 0.2); - filter: brightness(1); - transition: all 0.1s linear; -} - -.key.activated { - box-shadow: inset 0 0 0 1px shade(@accent_color, 1.2), inset 0 -4px 12px alpha(shade(@accent_color, 1.5), 0.6), 0 0 12px alpha(@accent_color, 0.5); - background-color: @accent_color; - filter: brightness(1); - transition: all 0.1s linear; -} - -.display { - background: #000; - border-radius: 12px; - box-shadow: inset 0 1px 0 #0004, 0 1px 0 #fff3; - border: 2px solid #000; -} - -.display.fill { - box-shadow: 0 0 0 4px #000; - border-radius: 0; - border: none; -} - -.ensembles-logo-splash { - background-image: url("resource://com/github/subhadeepjasu/ensembles/images/display/splash_screen"); - background-position: center; - background-size: contain; - background-repeat: no-repeat; -} - -.splash-screen-background { - background-color: #202020; - background-position: center; - background-size: cover; - animation: ripple 1s 0.2s; - filter: brightness(1); - transition: filter 0.5s ease-in; - color: #fff; -} - -.splash-screen-background.fade-black { - filter: brightness(0); -} - -.splash-screen-text { - color: #fff; -} - -@keyframes ripple { - from { - background-image: radial-gradient(circle, #202020 0, #333 5%, #202020 6%); - } - - to { - background-image: radial-gradient(circle, #202020 0, #202020 90%, #202020 100%); - } -} - -.pseudowindow { - border-radius: 8px; - box-shadow: inset 0 0 0 2px #fff2, inset 0 0 0 1px #000; - padding: 8px; - background-image: linear-gradient(@bg_color, @bg_color), linear-gradient(@window_bg_color, @window_bg_color), linear-gradient(grey, grey); - box-shadow: 0 12px 24px #0008; - text-shadow: 0 1px #fff6, 0 -1px #0004; -} - -.pseudowindow-actual { - background: linear-gradient(#0004, #0004), url("resource://com/github/subhadeepjasu/ensembles/images/display/home_background_default_blurred"); - background-size: cover; - background-position: center; - border: none; - box-shadow: none; -} - -@import url("resource://com/github/subhadeepjasu/ensembles/theme/Display.css"); diff --git a/data/Themes/Display/Display.css b/data/Themes/Display/Display.css deleted file mode 100644 index e95a6316..00000000 --- a/data/Themes/Display/Display.css +++ /dev/null @@ -1,570 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ -/* Do not edit this file */ - -/* ///////////////////////////////////////////////////////////////////////////// -Mother class for the central display section -*/ - -.display { - font-family: "Exo2"; -} - -.display .display-stack { - filter: brightness(1); - transform: scale(1); - transition: filter 1.2s cubic-bezier(0, 0, 0, 1), transform 1.2s cubic-bezier(0, 0, 0, 1); -} - -.display .display-stack.fade-black { - transform: scale(0.9); - filter: brightness(0); -} - - -/* ///////////////////////////////////////////////////////////////////////////// -General Gtk Widgets -*/ -/* -Buttons -*/ -.display button { - border: 1px solid rgba(255, 255, 255, 0.2); - background: rgba(255, 255, 255, 0.1); - border-radius: 6px; - box-shadow: none; - text-shadow: none; - opacity: 0.6; - color: #fff; - padding: 0 0; - margin: 0; - transition: opacity 0.3s ease-out; -} - -.display button.accented { - border: 1px solid shade(@accent_color, 1); - background: shade(@accent_color, 0.75); - color: shade(@accent_color, 1.3); -} - -.display button:hover { - opacity: 1; -} - -.display button:active { - background: alpha(#fff, 0.07); -} - -.display .flat, -.display .image-button { - border: none; - background: alpha(#fff, 0.0); -} - -.display .flat:hover, -.display .image-button:disabled {} - -.display .flat:focus, -.display .image-button:focus {} - -.display .flat:hover, -.display .image-button:hover {} - -.display .linked button { - border-radius: 0; -} - -.display .linked button:first-child { - border-radius: 6px 0 0 6px; - border-right: transparent; -} - -.display .linked button:last-child { - border-radius: 0 6px 6px 0; -} - -/* -Switches -*/ - -.display switch { - background: linear-gradient(#6668, mix(#6668, @accent_color, 0.2)); - box-shadow: inset 0 0 0 1px alpha(mix(#ccc, @accent_color, 0.4), 0.2); - border: 1px solid #000; -} - -.display switch slider { - background: linear-gradient(45deg, #666, alpha(mix(#333, @accent_color, 0.7), 0.2)); - box-shadow: 4px -8px 28px #fff0, -4px 8px 32px #fff0, inset 0 0 0 1px #fff2, 0 4px 8px #0002; - outline: 0; - margin: 2px; - border: none; - transition: all 0.4s cubic-bezier(0, 0, 0, 1); -} - -.display switch:checked { - background: linear-gradient(45deg, #6668, mix(#6668, @accent_color, 0.2)); - box-shadow: inset 0 0 0 1px alpha(mix(#ccc, @accent_color, 0.4), 0.2), inset 1px 0 0 alpha(@accent_color, 0.6), - inset -1px 0 0 @accent_color_complimentary; -} - -.display switch:checked slider { - background: linear-gradient(45deg, @accent_color, @accent_color_complimentary); - box-shadow: 4px -8px 28px alpha(@accent_color_complimentary, 0.75), -4px 8px 32px alpha(@accent_color, 0.75), inset 0 0 0 1px #fff4, 0 4px 8px #0002; -} - -/* -Custom Widgets -*/ -/* -Knobs -*/ - -.display .knob { - background: none; - border-radius: 50%; - box-shadow: inset 0 0 0 1px #0008, inset 0 3px 6px #0008, 0 1px 0 #fff3, 0 8px 16px #0004, 0 -8px 16px #fff2; -} - -.display .knob-cover { - background: radial-gradient(75% 75% at 50% 25%, #444, #2227); - box-shadow: 0 0 0 12px #2228, 0 2px 8px #000a, inset 0 1px 1px #fff4, inset 0 -1px 1px #0008; - border: none; - border-radius: 50%; - margin: 12px; - transition: background 0.2s linear; -} - -.display .knob:hover .knob-cover { - background: radial-gradient(75% 75% at 50% 25%, #555, #3337); -} - -.display .knob.small { - background: rgba(255, 255, 255, 0.1); - border-radius: 50%; - opacity: 0.6; - box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.2); -} - -.display .knob.small .knob-cover { - background: #fff1; - box-shadow: 0 0 0 2px #fff2; - border: none; - border-radius: 50%; - margin: 8px; - transition: background 0.2s linear; -} - -.display .knob.small:hover { - opacity: 1; -} - - -.display .knob.small:hover .knob-cover { - background: #fff3; - box-shadow: 0 0 0 2px #0004; -} - -/* ///////////////////////////////////////////////////////////////////////////// -HomeScreen -*/ - -.display .homescreen { - background: radial-gradient(112% 112% at 50% 105%, mix(shade(@accent_color_complimentary, 0.6), #222, 0.84) 0%, #000 100%); -} - -.display .homescreen .homescreen-links-section { - background-image: linear-gradient(88deg, alpha(shade(@accent_color, 0.6), 0.75), alpha(shade(@accent_color_complimentary, 0.5), 0.75)), url("resource://com/github/subhadeepjasu/ensembles/images/display/home_background_default"); - background-position: center; - background-size: auto 100%; -} - -.homescreen-link-panel-top { - background: linear-gradient(92deg, - shade(@accent_color, 0.54) 12%, - mix(shade(@accent_color, 0.65), shade(@accent_color_complimentary, 0.5), 0.25) 18%, - mix(shade(@accent_color, 0.5), shade(@accent_color_complimentary, 0.5), 0.5) 74%, - mix(shade(@accent_color, 0.4), shade(@accent_color_complimentary, 0.55), 0.6) 100%); - margin: 8px; - border-radius: 6px; - border: 1px solid #fff2; - padding: 2px; - box-shadow: 0 8px 16px rgba(0, 0, 0, 0.25); -} - -.display .homescreen-link-panel-top-button { - background: none; - opacity: 1; - border: 0; - padding: 0; - box-shadow: none; - outline: none; - text-shadow: none; - text-decoration: none; - border-radius: 2px; - color: #fff; - margin: 2px; - transition: all 0.2s ease-out; -} - -.display .homescreen-link-panel-top-button:hover { - background: linear-gradient(91.74deg, alpha(@accent_color, 0.5), alpha(@accent_color, 0.3)); - box-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); -} - -.display .homescreen-link-panel-top-button:active { - background: linear-gradient(91.74deg, alpha(@accent_color_complimentary, 0.5), alpha(@accent_color, 0.75)); -} - -.display .homescreen-link-panel-top-button-header { - font-size: 14px; - font-weight: 700; - margin-top: 8px; -} - -.display .homescreen-link-panel-top-button-subheader { - font-size: 12px; -} - -.display .homescreen-link-panel-bottom-button { - background: #fff0; - border: none; - border-radius: 0; - font-weight: 700; - opacity: 1; - text-shadow: 0 1px 8px #0002; - color: shade(@accent_color, 1.3); - font-size: 13px; - padding: 4px; - padding-left: 0px; - transition: all 0.4s ease; -} - -.display .homescreen-link-panel-bottom-button-status { - background: #fff0; - font-weight: 400; - opacity: 0.5; - transition: all 0.4s ease; -} - -.display .homescreen-link-panel-bottom-button:hover { - background: #fff0; - color: #fff; -} - -.display .homescreen-link-panel-bottom-button separator { - background: shade(@accent_color, 1.3); - opacity: 0; - border: none; - border-radius: 2px; - margin-right: 8px; - padding: 1px; - transform: translateX(0); - transition: all 0.4s ease; -} - -.display .homescreen-link-panel-bottom-button:hover .homescreen-link-panel-bottom-button-status { - opacity: 1; - color: shade(@accent_color, 1.3); -} - -.display .homescreen-link-panel-bottom-button:hover separator { - opacity: 1; - transform: translateX(4px); -} - -.display .homescreen-panel-status { - border-top: 1px solid alpha(#000, 0.5); - padding-top: 8px; -} - -.display .homescreen-panel-status-header { - padding: 4px; - font-weight: 700; - opacity: 0.75; - font-size: 14px; - color: @accent_color; -} - -.display .homescreen-panel-status-label { - padding: 4px; - padding-top: 0; - opacity: 0.75; - color: #fff; - font-family: 'Michroma'; - font-weight: 400; - font-size: 24px; - color: shade(@accent_color, 2); -} - -.display .homescreen-panel-status-label-small { - font-weight: 600; - font-size: 14px; - font-style: italic; - color: shade(@accent_color, 2); -} - -/* ///////////////////////////////////////////////////////////////////////////// -Display Window -*/ - -.display .display-window-background { - background: radial-gradient(13.25% 17.73% at 8.54% 9.2%, alpha(@accent_color, 0.25) 0%, alpha(@accent_color, 0) 100%), - radial-gradient(17.27% 44.85% at 55.57% 47.73%, alpha(@accent_color_complimentary, 0.15) 0%, alpha(@accent_color_complimentary, 0) 100%), - radial-gradient(112% 112% at 50% 105%, mix(shade(@accent_color_complimentary, 0.6), #222, 0.84) 0%, #000 100%); - color: #fff; -} - -.display .display-window-header-bar { - padding: 18px; - box-shadow: none; - border-bottom: none; - background: none; - color: #fff; - text-shadow: none; - -gtk-icon-shadow: none; - border: none; - border-radius: 0; -} - -.display .display-window-header-bar .title { - font-size: 20px; - color: #fff; - font-weight: 500; -} - -.display .display-window-header-bar .subtitle { - font-size: 12px; - font-weight: 400; - opacity: 0.75; - color: shade(@accent_color, 1.5); -} - - -/* ///////////////////////////////////////////////////////////////////////////// -Menu -*/ - -.display .menu-box { - background: none; - color: #fff; - padding-left: 20px; - padding-right: 20px; -} - -.display .menu-box>.activatable { - color: #fff; - border-bottom: 1px solid alpha(@accent_color_complimentary, 0.1); -} - -.display .menu-box>.activatable:selected { - box-shadow: none; - background: linear-gradient(270deg, alpha(@accent_color_complimentary, 0) 0%, alpha(@accent_color_complimentary, 0.25) 51.04%, alpha(@accent_color_complimentary, 0) 100%); - background-size: 100% 54px; - background-repeat: no-repeat; - background-position: 0 100%; -} - -.display .menu-item-name { - font-size: 16px; -} - -.display .menu-box>.activatable:selected .menu-item-label { - text-shadow: none; -} - -.display .menu-item-index { - font-size: 13px; - font-family: 'Michroma'; -} - -.display .menu-item-description { - font-size: 0.8em; - margin-top: 8px; -} - -.display .menu-item-icon { - border: none; - box-shadow: none; -} - -.display .menu-item-category { - background: none; - color: @accent_color_complimentary; - border-radius: 0; - padding-left: 8px; - padding-top: 4px; - padding-bottom: 4px; - margin-bottom: 4px; - margin-left: -8px; - font-size: 16px; - font-weight: 900; - letter-spacing: 0.12em; - border-bottom: 1px solid alpha(@accent_color_complimentary, 0.5); -} - - -/* Plugin Menu ///////////////////////////////////////////////////////////////*/ -.display .plugin-flap dimming { - background: none; -} - -.display .plugin-list { - background: none; -} - -.display .plugin-item { - margin: 12px; - margin-right: 18px; - padding: 8px; - border-radius: 6px 24px 7px 6px; - border: 1px solid #000a; - background: linear-gradient(#444, #345); - box-shadow: 0 4px 12px #0002, inset 0 0 0 1px #fff2; - color: #fffc; - font-weight: bold; - font-size: 1.1rem; - text-shadow: 0 0 16px #fff0, 0 0 8px #fff7; - transition: all 1s ease-out; -} - -.display .plugin-item-info { - font-size: 0.82em; - text-shadow: none; - line-height: normal; -} - -.display .plugin-item:hover { - color: #fff; - background: linear-gradient(#444, #356); - box-shadow: 0 4px 12px #0002, inset 0 0 0 1px #fff2, inset 0 -1px #47a; - text-shadow: 0 0 16px #fffa, 0 0 8px #fffd; - transition: all 0.2s ease; -} - - -.display .plugin-item-insert-button { - background: #fff2; - border-radius: 50px; - padding: 8px; - border: 1px solid #fff4; -} - -.display .plugin-item-insert-button:hover { - background: #59b; - border-radius: 50px; - padding: 8px; - border: 1px solid #6bd; - outline: 0; -} - -.display .plugin-item-insert-button:active { - background: rgb(168, 187, 85); - border-radius: 50px; - padding: 8px; - border: 1px solid rgb(170, 221, 102); - outline: 0; -} - -.display .plugin-item-protocol { - filter: brightness(3); - opacity: 0.75; -} - -.display .menu-item.capture-attention { - animation: capture_attention 1s ease; -} - -@keyframes capture_attention { - 0% { - transform: rotateZ(0) scale(1); - background: #333; - box-shadow: 0 0 24px rgba(100, 187, 85, 0); - } - - 10% { - transform: rotateZ(-2deg) scale(1.2); - } - - 20% { - transform: rotateZ(2deg) scale(1.2); - } - - 30% { - transform: rotateZ(-2deg) scale(1.2); - } - - 40% { - transform: rotateZ(2deg) scale(1.2); - } - - 50% { - transform: rotateZ(0) scale(1.1); - background: rgb(100, 187, 85); - box-shadow: 0 0 24px rgb(100, 187, 85); - } - - 100% { - transform: rotateZ(0) scale(1); - background: #333; - box-shadow: 0 0 24px rgba(100, 187, 85, 0); - } -} - -.display .menu-item button { - border: 1px solid rgba(255, 255, 255, 0.2); - background: rgba(255, 255, 255, 0.1); -} - -.display .card { - background-image: linear-gradient(#444, mix(@accent_color_complimentary, #444, 0.9)); - border-radius: 16px; - border: 1px solid mix(@accent_color_complimentary, #666, 0.9); - outline: 0; - box-shadow: 0 12px 36px alpha(@accent_color_complimentary, 0.1), 0 2px 8px #0004; - color: mix(@accent_color_complimentary, #ccc, 0.8); - transition: all 1.2s cubic-bezier(0, 0, 0, 1); -} - -.display .card:hover { - background-image: linear-gradient(#444, mix(@accent_color_complimentary, #444, 0.75)); - border: 1px solid mix(@accent_color_complimentary, #666, 0.75); - box-shadow: 0 12px 36px alpha(@accent_color_complimentary, 0.5), 0 2px 12px #0008; - color: #fff; - transform: scale(1); -} - -.display .menu-item check { - background: rgba(255, 255, 255, 0.14); - opacity: 0.6; - color: #fff; - box-shadow: none; - padding: 6px; - border: 1px solid rgba(255, 255, 255, 0.3); - border-radius: 50%; - transition: all 0.3s ease-out; -} - -.display .menu-item check:hover { - opacity: 1; -} - - -.display .menu-item check:checked { - border: 1px solid alpha(shade(@accent_color, 1.3), 0.5); - background: alpha(@accent_color, 0.5); - opacity: 1; - box-shadow: 0px 6px 32px alpha(@accent_color, 0.75); -} - -.display .audio-switch check { - -gtk-icon-source: -gtk-icontheme("system-shutdown-symbolic"); - -gtk-icon-shadow: none; -} - -.display .menu-item.p-8 { - padding-top: 8px; - padding-bottom: 8px; -} diff --git a/data/com.github.subhadeepjasu.ensembles.appdata.xml.in b/data/com.github.ensemblesaw.ensembles.appdata.xml.in similarity index 89% rename from data/com.github.subhadeepjasu.ensembles.appdata.xml.in rename to data/com.github.ensemblesaw.ensembles.appdata.xml.in index e4eb3358..45ef0eac 100644 --- a/data/com.github.subhadeepjasu.ensembles.appdata.xml.in +++ b/data/com.github.ensemblesaw.ensembles.appdata.xml.in @@ -1,7 +1,7 @@ - + - com.github.subhadeepjasu.ensembles + com.github.ensemblesaw.ensembles CC0-1.0 GPL-3.0+ Ensembles @@ -28,37 +28,37 @@ #FFFFFF 0 - com.github.subhadeepjasu.ensembles + com.github.ensemblesaw.ensembles Subhadeep Jasu https://subhadeepjasu.github.io/#/project/ensembles https://github.com/SubhadeepJasu/ensembles/issues https://github.com/SubhadeepJasu/ensembles/issues subhadeep107@proton.me - com.github.subhadeepjasu.ensembles.desktop + com.github.ensemblesaw.ensembles.desktop Instant Playback - https://raw.githubusercontent.com/SubhadeepJasu/Ensembles/master/screenshots/Screenshot.png + https://raw.githubusercontent.com/ensemblesaw/ensembles-app/master/screenshots/Screenshot.png Style Menu - https://raw.githubusercontent.com/SubhadeepJasu/Ensembles/master/screenshots/ScreenshotStyles.png + https://raw.githubusercontent.com/ensemblesaw/ensembles-app/master/screenshots/ScreenshotStyles.png Per Channel Modulators - https://raw.githubusercontent.com/SubhadeepJasu/Ensembles/master/screenshots/ScreenshotChannelModulators.png + https://raw.githubusercontent.com/ensemblesaw/ensembles-app/master/screenshots/ScreenshotChannelModulators.png Master Knob LFO - https://raw.githubusercontent.com/SubhadeepJasu/Ensembles/master/screenshots/ScreenshotLFO.png + https://raw.githubusercontent.com/ensemblesaw/ensembles-app/master/screenshots/ScreenshotLFO.png Multi-track Recorder - https://raw.githubusercontent.com/SubhadeepJasu/Ensembles/master/screenshots/ScreenshotMultiTrackRecorder.png + https://raw.githubusercontent.com/ensemblesaw/ensembles-app/master/screenshots/ScreenshotMultiTrackRecorder.png Voice Menu and MIDI File Player - https://raw.githubusercontent.com/SubhadeepJasu/Ensembles/master/screenshots/ScreenshotVoice.png + https://raw.githubusercontent.com/ensemblesaw/ensembles-app/master/screenshots/ScreenshotVoice.png diff --git a/data/com.github.subhadeepjasu.ensembles.desktop.in b/data/com.github.ensemblesaw.ensembles.desktop.in similarity index 67% rename from data/com.github.subhadeepjasu.ensembles.desktop.in rename to data/com.github.ensemblesaw.ensembles.desktop.in index c259a0fa..ca692cfa 100644 --- a/data/com.github.subhadeepjasu.ensembles.desktop.in +++ b/data/com.github.ensemblesaw.ensembles.desktop.in @@ -4,9 +4,9 @@ GenericName=Arranger Workstation Comment=Play and arrange music live as a one-person band Categories=Audio;AudioVideo;Music;Midi;Education;GTK; MimeType=audio/midi -Exec=com.github.subhadeepjasu.ensembles %U -Icon=com.github.subhadeepjasu.ensembles +Exec=com.github.ensemblesaw.ensembles %U +Icon=com.github.ensemblesaw.ensembles Terminal=false Type=Application Keywords=midi;virtual;music;arranger;piano;keyboard;workstation; -X-GNOME-Gettext-Domain=com.github.subhadeepjasu.ensembles +X-GNOME-Gettext-Domain=com.github.ensemblesaw.ensembles diff --git a/data/com.github.subhadeepjasu.ensembles.kiosk.desktop b/data/com.github.ensemblesaw.ensembles.kiosk.desktop similarity index 76% rename from data/com.github.subhadeepjasu.ensembles.kiosk.desktop rename to data/com.github.ensemblesaw.ensembles.kiosk.desktop index b0352396..40029b8a 100644 --- a/data/com.github.subhadeepjasu.ensembles.kiosk.desktop +++ b/data/com.github.ensemblesaw.ensembles.kiosk.desktop @@ -1,7 +1,7 @@ [Desktop Entry] Name=Ensembles Comment=This session launches Ensembles Arranger Workstation in kiosk mode -Exec=com.github.subhadeepjasu.ensembles --kiosk +Exec=com.github.ensemblesaw.ensembles --kiosk Icon= DesktopNames=Ensembles Type=Application diff --git a/data/com.github.subhadeepjasu.ensembles.gresource.xml b/data/com.github.subhadeepjasu.ensembles.gresource.xml deleted file mode 100644 index 5ae12cf2..00000000 --- a/data/com.github.subhadeepjasu.ensembles.gresource.xml +++ /dev/null @@ -1,24 +0,0 @@ - - - - Themes/Application.css - Themes/Display/Display.css - - - - Icons/scalable/actions/style-break-symbolic.svg - Icons/scalable/actions/style-sync-start-symbolic.svg - Icons/scalable/actions/plugin-add-symbolic.svg - Icons/scalable/emblems/plugin-audio-lv2-symbolic.svg - - - - Images/beat_counter.svg - - - - Images/Display/splash_screen.png - Images/Display/catalin-sandru-7SxSkCvVM1U-unsplash.jpg - Images/Display/catalin-sandru-7SxSkCvVM1U-unsplash-blurred.jpg - - diff --git a/data/com.github.subhadeepjasu.ensembles.gschema.xml.in b/data/com.github.subhadeepjasu.ensembles.gschema.xml.in deleted file mode 100644 index 497dae8b..00000000 --- a/data/com.github.subhadeepjasu.ensembles.gschema.xml.in +++ /dev/null @@ -1,62 +0,0 @@ - - - - - - - - - - '0.0.0' - The currently installed version. - The currently installed version of Ensembles, updated only after the user launched the app. This is used to know when to trigger the Release Dialog. - - - - - -1 - The saved x-position of the window. - The saved x-position of the window. - - - -1 - The saved y-position of the window. - The saved y-position of the window. - - - 800 - The saved width of the window. - The saved width of the window. - - - 400 - The saved height of the window. - The saved height of the window. - - - false - Window maximized - If window should be maximized - - - "Default" - Display Unit Theme - - - - - '' - Enstl style path of the last used style - - - - - false - Automatically trigger a fill-in when changing style variation - - - "split-long" - Style chord detection mode - - - diff --git a/data/meson.build b/data/meson.build index 9c3b9188..0b54efbd 100644 --- a/data/meson.build +++ b/data/meson.build @@ -59,19 +59,6 @@ i18n.merge_file ( install_dir: join_paths (get_option ('datadir'), 'metainfo') ) -# Install Settings schema -schemas_conf = configuration_data() -schemas_conf.set('SCHEMA_ID', application_id) -schemas_conf.set('SCHEMA_PATH', schema_path) -schemas_conf.set('GETTEXT_PACKAGE', gettext_package) - -configure_file( - input: meson.project_name() + '.gschema.xml.in', - output: application_id + '.gschema.xml', - configuration: schemas_conf, - install_dir: join_paths(datadir, 'glib-2.0', 'schemas') -) - # Install documents install_subdir ( 'Docs', diff --git a/meson.build b/meson.build index b1e90a00..d7933656 100644 --- a/meson.build +++ b/meson.build @@ -1,12 +1,11 @@ # Project name, programming language and version project ( - 'com.github.subhadeepjasu.ensembles', + 'com.github.ensemblesaw.ensembles', 'c', 'vala', version: '0.1.0', meson_version: '>=0.57.0', default_options: [ - 'buildtype=debugoptimized', - 'wrap_mode=nofallback' + 'buildtype=debugoptimized' ] ) @@ -30,72 +29,68 @@ add_project_arguments ( add_project_arguments ( ['--vapidir', join_paths (meson.current_source_dir (), 'vapi')], - # Set Driver Compatibilities - '-D', 'ALSA_DRIVER', - '-D', 'PULSEAUDIO_DRIVER', - '-D', 'JACK_DRIVER', - # '-D', 'PIPEWIRE_CORE_DRIVER', # Uncomment to enable pipewire core support provided fluidsynth supports it + ['--vapidir', join_paths (meson.current_build_dir(), 'subprojects', 'ens-shell-gtk')], language: 'vala' ) -# Compiling resources -asresources = gnome.compile_resources ( - 'as-resources', - 'data/' + meson.project_name () + '.gresource.xml', - source_dir: 'data', - c_name: 'as' -) - -# Listing dependencies -dependencies = [ - dependency ('x11'), - dependency ('granite-7'), - dependency ('libadwaita-1'), - dependency ('gtk4'), - dependency ('glib-2.0'), - dependency ('gobject-2.0'), - dependency ('libsoup-3.0'), - dependency ('json-glib-1.0'), - dependency ('fluidsynth'), - dependency ('gstreamer-1.0'), - dependency ('lv2'), - dependency ('lilv-0'), - dependency ('suil-0'), - dependency ('zix-0', fallback: ['zix', 'zix_dep'], default_options: [ - 'tests=disabled', 'default_library=static', - 'docs=disabled', 'tests_cpp=disabled', - ]), - dependency ('libpipewire-0.3'), - meson.get_compiler ('vala').find_library ('posix'), - meson.get_compiler ('c').find_library ('m', required : true), - meson.get_compiler ('c').find_library ('X11', required : true), -] +build_dir = meson.current_build_dir() +message(build_dir.split('/')[-1]) # Set up the profile profile = get_option('profile') if profile == 'development' application_id = meson.project_name() + 'Devel' - schema_path = '/com/github/subhadeepjasu/ensemblesDevel/' + schema_path = '/com/github/ensemblesaw/ensemblesDevel/' else application_id = meson.project_name() - schema_path = '/com/github/subhadeepjasu/ensembles/' + schema_path = '/com/github/ensemblesaw/ensembles/' endif gettext_package = application_id +# Listing dependencies +dependencies = [ + dependency ('glib-2.0'), + dependency ('gee-0.8'), + # Core deps + dependency ('fluidsynth', required: false), + dependency ('lv2', required: false), + dependency ('lilv-0', required: false), + dependency ('suil-0', required: false), + dependency ('zix-0', fallback: ['zix', 'zix_dep'], default_options: [ + 'tests=disabled', 'default_library=static', + 'docs=disabled', 'tests_cpp=disabled', + ], required: false), + dependency ('portmidi', required: false), + dependency ('libpipewire-0.3', required: false), + dependency ('x11', required: false), + dependency ('granite-7', required: false), + dependency ('libadwaita-1', required: false), + dependency ('gtk4', required: false), + dependency ('gobject-2.0'), + dependency ('libsoup-3.0', required: false), + dependency ('json-glib-1.0', required: false), + dependency ('Vinject-0.0.0', fallback: ['libvinject', 'vinject_dep']), + dependency ('enstl-0', fallback: ['enstl', 'enstl_dep']), + dependency ('ens-shell-cli-0', fallback: ['ens-shell-cli', 'ens_shell_cli_dep'], + default_options: ['profile=' + profile]), + dependency ('ens-shell-gtk-0', fallback: ['ens-shell-gtk', 'ens_shell_gtk_dep'], + default_options: ['profile=' + profile]), + dependency ('ens-aw-core-0', fallback: ['ens-aw-core', 'ens_aw_core_dep'], + default_options: ['profile=' + profile]) +] + +datadir = get_option ('datadir') +subdir ('data') +subdir ('po') subdir ('src') # Define executable executable ( meson.project_name (), - asresources, sources, config_header, dependencies: dependencies, install: true ) -datadir = get_option ('datadir') -subdir ('data') -subdir ('po') - meson.add_install_script ('meson/post_install.py') diff --git a/meson/post_install.py b/meson/post_install.py index bf02d96a..aaa4826d 100644 --- a/meson/post_install.py +++ b/meson/post_install.py @@ -4,14 +4,11 @@ import subprocess prefix = environ.get('MESON_INSTALL_PREFIX', '/usr/local') -schemadir = path.join(environ['MESON_INSTALL_PREFIX'], 'share', 'glib-2.0', 'schemas') datadir = path.join(prefix, 'share') desktop_database_dir = path.join(datadir, 'applications') if not environ.get('DESTDIR'): - print('Compiling gsettings schemas…') - subprocess.call(['glib-compile-schemas', schemadir]) print('Updating desktop database…') subprocess.call(['update-desktop-database', '-q', desktop_database_dir]) print('Updating icon cache…') - subprocess.call(['gtk-update-icon-cache', '-qtf', path.join(datadir, 'icons', 'hicolor')]) \ No newline at end of file + subprocess.call(['gtk-update-icon-cache', '-qtf', path.join(datadir, 'icons', 'hicolor')]) diff --git a/src/Application.vala b/src/Application.vala deleted file mode 100644 index 3fb63493..00000000 --- a/src/Application.vala +++ /dev/null @@ -1,121 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles { - public Services.Settings settings; - - /** - * ## Ensembles Application - * - * Provides a GTK Application instance where only a single instance - * is allowed. - * The Ensembles application works as a conjuncture of two components: - * - Core: The arranger system and all it's plugins - * - Shell: The user interface - */ - public class Application : Gtk.Application { - static Application _instance = null; - - public static Application instance { - get { - if (_instance == null) { - _instance = new Application (); - } - return _instance; - } - } - - public static Services.EventBus event_bus = new Services.EventBus (); - - private string[] ? arg_file = null; - public static bool raw_midi_input = false; - public static bool kiosk_mode = false; - public static bool verbose = false; - - public static Shell.MainWindow main_window; - public static Core.ArrangerWorkstation arranger_workstation; - - construct { - flags |= ApplicationFlags.HANDLES_OPEN | - ApplicationFlags.HANDLES_COMMAND_LINE; - application_id = Constants.APP_ID; - settings = new Services.Settings (); - } - - protected override void activate () { - Console.log ("Initializing GUI Theme"); - Services.Theme.init_theme (); - - Console.log ("Initializing Main Window"); - main_window = new Shell.MainWindow (this); - this.add_window (main_window); - main_window.show_ui (); - Console.log ( - "GUI Initialization Complete!", - Console.LogLevel.SUCCESS - ); - - Console.log ("Initializing Arranger Workstation"); - arranger_workstation = new Core.ArrangerWorkstation (); - - if (settings.version != Constants.VERSION) { - settings.version = Constants.VERSION; - } - - if (Constants.PROFILE == "development") { - - } - } - - protected override int command_line (ApplicationCommandLine cmd) { - string[] args_cmd = cmd.get_arguments (); - unowned string[] args = args_cmd; - - GLib.OptionEntry [] options = new OptionEntry [5]; - options [0] = { "", 0, 0, OptionArg.STRING_ARRAY, ref arg_file, null, "URI" }; - options [1] = { "raw", 0, 0, OptionArg.NONE, ref raw_midi_input, _("Enable Raw MIDI Input"), null }; - options [2] = { "kiosk", 0, 0, OptionArg.NONE, ref kiosk_mode, _("Only show the info display"), null }; - options [3] = { "verbose", 0, 0, OptionArg.NONE, ref verbose, _("Print debug messages to terminal"), null }; - options [4] = { null }; - - var opt_context = new OptionContext ("actions"); - opt_context.add_main_entries (options, null); - try { - opt_context.parse (ref args); - } catch (Error err) { - warning (err.message); - return -1; - } - - if (verbose || raw_midi_input || kiosk_mode) { - Console.get_console_header (); - } - - if (raw_midi_input) { - print ("Raw MIDI Input Enabled! You can now enable midi input and connect your DAW\n"); - } - - if (kiosk_mode) { - print ("Starting Ensembles in Kiosk Mode\n"); - } - - if (arg_file != null && arg_file[0] != null) { - if (GLib.FileUtils.test (arg_file[0], GLib.FileTest.EXISTS) && - arg_file[0].down ().has_suffix (".mid")) { - File file = File.new_for_path (arg_file[0]); - open ({ file }, ""); - return 0; - } - } - - activate (); - return 0; - } - - public void init (string[] args) { - X.init_threads (); - } - } -} diff --git a/src/Core/Analysers/ChordAnalyser.vala b/src/Core/Analysers/ChordAnalyser.vala deleted file mode 100644 index 26214529..00000000 --- a/src/Core/Analysers/ChordAnalyser.vala +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Models; - -namespace Ensembles.Core.Analysers { - public class ChordAnalyser : Object { - private uint8[] key_track; - private uint8[] chord_possibility; - - public enum ChordDetectionMode { - SPLIT_LONG = 0, - SPLIT_SHORT = 1, - FULL_RANGE = 2 - } - - construct { - key_track = new uint8[13]; - chord_possibility = new uint8[144]; - } - - /** This function returns an inferred {@link Ensembles.Models.Chord} based on subsequent - * invocations of note-on and note-off events - * - * @param key Key or note number - * @param on Whether the key is pressed or released - * @return A {@link Ensembles.Models.Chord} as determined from subsequent keypresses - */ - public Chord infer (uint8 key, bool on) { - key_track [key % 12] = on ? 1 : 0; - - uint8 n_keys = 0; - int16 probable_root = -1; - - for (uint8 i = 0; i < 12; i++) { - n_keys += key_track[i]; - if (probable_root < 0 && key_track[i] == 1) { - probable_root = i; - } - } - - for (uint8 i = 0; i < 144; i++) { - chord_possibility[i] = 0; - } - - uint8 i = 0; - - if (n_keys < 4) { - // Major - for (; i < 5; i++) { - chord_possibility [i] = 6 * key_track[i] + key_track[i + 4] + key_track[i + 7]; // One way to play it - } - /* ^ - * | - * | - * Root contribution - */ - for (; i < 9; i++) { - chord_possibility [i] = key_track[i - 5] + 6 * key_track[i] + key_track[i + 4]; // Another way to play it - } - for (; i < 12; i++) { - chord_possibility [i] = key_track[i - 8] + key_track[i - 5] + 6 * key_track[i]; // Yet another way to play it - } - - // minor - for (; i < 17; i++) { - chord_possibility [i] = 6 * key_track[i - 12] + key_track[i - 12 + 3] + key_track[i - 12 + 7]; - } - for (; i < 21; i++) { - chord_possibility [i] = key_track[i - 12 - 5] + 6 * key_track[i - 12] + key_track[i - 12 + 3]; - } - for (; i < 24; i++) { - chord_possibility [i] = key_track[i - 12 - 9] + key_track[i - 12 - 5] + 6 * key_track[i - 12]; - } - - // diminished - for (; i < 29; i++) { - chord_possibility [i] = 6 * key_track[i - 24] + key_track[i - 24 + 3] + key_track[i - 24 + 6]; - } - for (; i < 33; i++) { - chord_possibility [i] = key_track[i - 24 + 6] + 6 * key_track[i - 24] + key_track[i - 24 + 3]; - } - for (; i < 36; i++) { - chord_possibility [i] = key_track[i - 24 - 9] + key_track[i - 24 - 6] + 6 * key_track[i - 24]; - } - - // suspended 2 - for (; i < 41; i++) { - chord_possibility [i] = 6 * key_track[i - 36] + key_track[i - 36 + 2] + key_track[i - 36 + 7]; - } - for (; i < 45; i++) { - chord_possibility [i] = key_track[i - 36 - 5] + 6 * key_track[i - 36] + key_track[i - 36 + 2]; - } - for (; i < 48; i++) { - chord_possibility [i] = key_track[i - 36 - 10] + key_track[i - 36 - 5] + 6 * key_track[i - 36]; - } - - // suspended 4 - for (; i < 53; i++) { - chord_possibility [i] = (i - 48 == probable_root && n_keys > 2 ? 7 : 6) * key_track[i - 48] + - key_track[i - 48 + 5] + key_track[i - 48 + 7]; - } - for (; i < 57; i++) { - chord_possibility [i] = key_track[i - 48 - 5] + - (i - 48 == probable_root && n_keys > 2 ? 7 : 6) * key_track[i - 48] + key_track[i - 48 + 5]; - } - for (; i < 60; i++) { - chord_possibility [i] = key_track[i - 48 - 7] + key_track[i - 48 - 5] + - (i - 48 == probable_root && n_keys > 2 ? 7 : 6) * key_track[i - 48]; - } - - // augmented - for (; i < 65; i++) { - chord_possibility [i] = 6 * key_track[i - 60] + key_track[i - 60 + 4] + key_track[i - 60 + 8]; - } - for (; i < 69; i++) { - chord_possibility [i] = key_track[i - 60 - 4] + 6 * key_track[i - 60] + key_track[i - 60 + 4]; - } - for (; i < 72; i++) { - chord_possibility [i] = key_track[i - 60 - 8] + key_track[i - 60 - 4] + 6 * key_track[i - 60]; - } - } else if (n_keys == 4) { - // Dominant Sixth - for (i = 72; i < 77; i++) { - chord_possibility [i] = 6 * key_track[i - 72] + key_track[i - 72 + 4] + - key_track[i - 72 + 7] + key_track[i - 72 + 9]; - } - for (; i < 81; i++) { - chord_possibility [i] = key_track[i - 72 - 5] + - key_track[i - 72 - 3] + 6 * key_track[i - 72] + key_track[i - 72 + 4]; - } - for (; i < 84; i++) { - chord_possibility [i] = key_track[i - 72 - 8] + - key_track[i - 72 - 5] + key_track[i - 72 - 3] + 6 * key_track[i - 72]; - } - - // Dominant Seventh - for (; i < 89; i++) { - chord_possibility [i] = 6 * key_track[i - 84] + key_track[i - 84 + 4] + - key_track[i - 84 + 7] + key_track[i - 84 + 10]; - } - for (; i < 93; i++) { - chord_possibility [i] = key_track[i - 84 - 5] + - key_track[i - 84 - 2] + 6 * key_track[i - 84] + key_track[i - 84 + 4]; - } - for (; i < 96; i++) { - chord_possibility [i] = key_track[i - 84 - 8] + - key_track[i - 84 - 5] + key_track[i - 84 - 2] + 6 * key_track[i - 84]; - } - - // Major Seventh - for (; i < 101; i++) { - chord_possibility [i] = 6 * key_track[i - 96] + - key_track[i - 96 + 4] + key_track[i - 96 + 7] + key_track[i - 96 + 11]; - } - for (; i < 105; i++) { - chord_possibility [i] = key_track[i - 96 - 5] + - key_track[i - 96 - 1] + 6 * key_track[i - 96] + key_track[i - 96 + 4]; - } - for (; i < 108; i++) { - chord_possibility [i] = key_track[i - 96 - 8] + - key_track[i - 96 - 5] + key_track[i - 96 - 1] + 6 * key_track[i - 96]; - } - - // minor seventh - for (; i < 113; i++) { - chord_possibility [i] = 6 * key_track[i - 108] + - key_track[i - 108 + 3] + key_track[i - 108 + 7] + key_track[i - 108 + 10]; - } - for (; i < 117; i++) { - chord_possibility [i] = key_track[i - 108 - 5] + - key_track[i - 108 - 2] + 6 * key_track[i - 108] + key_track[i - 108 + 3]; - } - for (; i < 120; i++) { - chord_possibility [i] = key_track[i - 108 - 9] + - key_track[i - 108 - 5] + key_track[i - 108 - 2] + 6 * key_track[i - 108]; - } - - // add9 - for (; i < 125; i++) { - chord_possibility [i] = 6 * key_track[i - 120] + - key_track[i - 120 + 4] + key_track[i - 120 + 7] + key_track[i - 120 + 2]; - } - for (; i < 129; i++) { - chord_possibility [i] = key_track[i - 120 - 5] + - key_track[i - 120 + 2] + 6 * key_track[i - 120] + key_track[i - 120 + 4]; - } - for (; i < 132; i++) { - chord_possibility [i] = key_track[i - 120 - 8] + - key_track[i - 120 - 5] + key_track[i - 120 - 10] + 6 * key_track[i - 120]; - } - } else if (n_keys == 5) { - // Dominant 9th - for (; i < 137; i++) { - chord_possibility [i] = 6 * key_track[i - 132] + - key_track[i - 132 + 4] + key_track[i - 132 + 7] + key_track[i - 132 + 10] + key_track[i - 132 + 2]; - } - for (; i < 141; i++) { - chord_possibility [i] = key_track[i - 132 - 5] + key_track[i - 132 - 2] + - key_track[i - 120 + 2] + 6 * key_track[i - 132] + key_track[i - 132 + 4]; - } - for (; i < 144; i++) { - chord_possibility [i] = key_track[i - 132 - 8] + - key_track[i - 132 - 5] + key_track[i - 132 - 2] + 6 * key_track[i - 132] + key_track[i - 120 - 10]; - } - } - - i = n_keys < 4 ? 0 : n_keys == 4 ? 72 : 132; - uint8 max_i = n_keys < 4 ? 72 : n_keys == 4 ? 132 : 144; - int16 max = -1; - int16 max_index = 0; - for (; i < max_i; i++) { - // printf("%d ", chord_possibility[i]); - if (max < chord_possibility[i]) { - max = chord_possibility[i]; - max_index = i; - } - } - - var chord = Chord (); - - // Set the chord type - if (max_index < 12) { - chord.type = ChordType.MAJOR; - } else if (max_index < 24) { - chord.type = ChordType.MINOR; - } else if (max_index < 36) { - chord.type = ChordType.DIMINISHED; - } else if (max_index < 48) { - chord.type = ChordType.SUSPENDED_2; - } else if (max_index < 60) { - chord.type = ChordType.SUSPENDED_4; - } else if (max_index < 72) { - chord.type = ChordType.AUGMENTED; - } else if (max_index < 84) { - chord.type = ChordType.SIXTH; - } else if (max_index < 96) { - chord.type = ChordType.SEVENTH; - } else if (max_index < 108) { - chord.type = ChordType.MAJOR_7TH; - } else if (max_index < 120) { - chord.type = ChordType.MINOR_7TH; - } else if (max_index < 132) { - chord.type = ChordType.ADD_9TH; - } else { - chord.type = ChordType.NINTH; - } - - // Set the root note - if (max > 0) { - if (max_index >= 0 && max_index <= 6) { - chord.root = convert_to_chord (max_index); - } else if (max_index >= 7 && max_index <= 18) { - chord.root = convert_to_chord (max_index - 12); - } else if (max_index >= 19 && max_index <= 30) { - chord.root = convert_to_chord (max_index - 24); - } else if (max_index >= 31 && max_index <= 42) { - chord.root = convert_to_chord (max_index - 36); - } else if (max_index >= 43 && max_index <= 54) { - chord.root = convert_to_chord (max_index - 48); - } else if (max_index >= 55 && max_index <= 66) { - chord.root = convert_to_chord (max_index - 60); - } else if (max_index >= 67 && max_index <= 78) { - chord.root = convert_to_chord (max_index - 72); - } else if (max_index >= 79 && max_index <= 90) { - chord.root = convert_to_chord (max_index - 84); - } else if (max_index >= 91 && max_index <= 102) { - chord.root = convert_to_chord (max_index - 96); - } else if (max_index >= 103 && max_index <= 114) { - chord.root = convert_to_chord (max_index - 108); - } else if (max_index >= 115 && max_index <= 126) { - chord.root = convert_to_chord (max_index - 120); - } else if (max_index >= 127 && max_index <= 138) { - chord.root = convert_to_chord (max_index - 132); - } else if (max_index >= 139 && max_index <= 156) { - chord.root = convert_to_chord (max_index - 150); - } else { - chord.root = ChordRoot.NONE; - } - } - - return chord; - } - - private ChordRoot convert_to_chord (int16 root) { - switch (root) { - case 0: - return ChordRoot.C; - case 1: - return ChordRoot.CS; - case 2: - return ChordRoot.D; - case 3: - return ChordRoot.EF; - case 4: - return ChordRoot.E; - case 5: - return ChordRoot.F; - case 6: - return ChordRoot.FS; - case -5: - return ChordRoot.G; - case -4: - return ChordRoot.AF; - case -3: - return ChordRoot.A; - case -2: - return ChordRoot.BF; - case -1: - return ChordRoot.B; - } - - return ChordRoot.NONE; - } - } -} diff --git a/src/Core/Analysers/StyleAnalyser.vala b/src/Core/Analysers/StyleAnalyser.vala deleted file mode 100644 index 3a503cba..00000000 --- a/src/Core/Analysers/StyleAnalyser.vala +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Models; - -namespace Ensembles.Core.Analysers { - /** - * A style analyser can analyse an `enstl` style and describe it. - * The analysis takes place when the object is created using the given path - * and the resulting `Style` object can be retreived using the - * `get_style ()` method. - */ - public class StyleAnalyser : Object { - public bool valid = false; - - private string enstl_path; - private string name; - private string genre; - private uint8[] copyright_notice; - private uint8 time_signature_n; - private uint8 time_signature_d; - private uint32 ticks_per_beat; - private uint32 tempo_ms; - private bool scale_type; - private StylePart[] parts; - - private const string[] EXPECTED_PARTS = { - "CONFIG", - "INT_1", - "INT_2", - "INT_3", - "BRK", - "VAR_A", - "FILL_A", - "VAR_B", - "FILL_B", - "VAR_C", - "FILL_C", - "VAR_D", - "FILL_D", - "END_1", - "EOS", - "END_2", - "EOS", - "END_3", - "EOS" - }; - - /** - * Creates a new `StyleAnalyser` object for analysing the style in the - * given path. - * - * @param enstl_path path to the enstl file - */ - public StyleAnalyser (string enstl_path) throws StyleError, Error { - this.enstl_path = enstl_path; - - var file_tokens = enstl_path.split ("/"); - string file_name = file_tokens[file_tokens.length - 1]; - int file_name_delimit_index = file_name.index_of_char ('@'); - genre = file_name.substring (0, file_name_delimit_index); - name = file_name.substring (file_name_delimit_index + 1, - file_name.index_of_char ('.') - file_name_delimit_index - 1).replace ("_", " "); - - var style_file = File.new_for_path (enstl_path); - - if (!style_file.query_exists ()) { - Console.log ("Style file is missing or invalid", Ensembles.Console.LogLevel.WARNING); - } - - uint8[] buffer; - - var fs = style_file.read (); - var dis = new DataInputStream (fs); - dis.set_byte_order (GLib.DataStreamByteOrder.LITTLE_ENDIAN); - - dis.seek (0, GLib.SeekType.END); - var filelen = dis.tell (); - dis.seek (0, GLib.SeekType.SET); - - buffer = new uint8[filelen]; - - if (!dis.read_all (buffer, out filelen)) { - dis.close (); - throw new StyleError.INVALID_FILE ("Failed to read style file. Make sure the file is accessible"); - } - - dis.close (); - - - ticks_per_beat = 0; - parts = new StylePart[18]; - uint8 expected_part_index = 0; - uint8 marker_index = 0; - bool default_tempo_acquired = false; - - for (uint64 i = 0; i < filelen; i++) { - // Find ticks per beat from MTHD header - if (buffer[i] == 0x4D && buffer[i + 1] == 0x54 && buffer[i + 2] == 0x68 && buffer[i + 3] == 0x64) { - uint8 a = buffer[i + 12]; - uint8 b = buffer[i + 13]; - ticks_per_beat = (a << 8) | (b & 0x000000FF); - } - - // Get Meta Events - if (ticks_per_beat > 0 && buffer[i] == 0xFF) { - // Find copyright notice - if (buffer[i + 1] == 0x02) { - uint8 copyright_str_len = buffer[i + 2]; - - copyright_notice = new uint8[copyright_str_len]; - for (uint8 j = 0; j < copyright_str_len; j++) { - copyright_notice[j] = buffer[i + 3 + j]; - } - } - - // Get default tempo - if (!default_tempo_acquired && buffer[i + 1] == 0x51) { - tempo_ms = get_tempo (buffer, i + 2); - default_tempo_acquired = true; - } - - // Find time signature - if (buffer[i + 1] == 0x58 && buffer[i + 2] == 0x04) { - time_signature_n = buffer[i + 3]; - time_signature_d = (uint8)Math.pow (2, buffer[i + 4]); - } - - // Get marker data - if (buffer[i + 1] == 0x06) { - uint8 marker_str_length = buffer[i + 2]; - uint8[] marker_str = new uint8[marker_str_length]; - - for (uint8 j = 0; j < marker_str_length; j++) { - marker_str[j] = buffer[i + 3 + j]; - } - - string str = (string)marker_str; - // Get measure - int marker_token_index = str.index_of_char (':'); - - int scale_type_index = str.index_of_char (';'); - - uint measure = 0; - if (marker_token_index > 0 && marker_token_index < marker_str_length) { - measure = uint.parse (str.substring (marker_token_index + 1, - scale_type_index < marker_str_length - ? scale_type_index - marker_token_index - 1: -1)); - } - - int i_scale_type = 0; - if (scale_type_index > 0 && scale_type_index < marker_str_length) { - i_scale_type = int.parse (str.substring (scale_type_index + 1)); - } - scale_type = i_scale_type > 0; - - var marker_name = str.substring (0, marker_token_index); - - if (marker_name[0] != 'C') { - parts[marker_index++] = StylePart () { - time_stamp = (uint)(((measure - 1) * 4 * time_signature_n * ticks_per_beat) - / time_signature_d), - style_part_type = get_style_part_type_from_marker (marker_name) - }; - } - - if (marker_name != EXPECTED_PARTS[expected_part_index++]) { - if (expected_part_index == 1) { - throw new StyleError.INVALID_LAYOUT ("Expected config marker"); - } else { - throw new StyleError.INVALID_LAYOUT ("Expected %s marker after %s marker", - EXPECTED_PARTS[expected_part_index - 1], EXPECTED_PARTS[expected_part_index - 2]); - } - } - } - } - } - } - - /** - * Get the analysed style object - */ - public Style get_style () { - return Style () { - name = this.name, - genre = this.genre, - tempo = (uint8)(60000000 / this.tempo_ms), - time_signature_n = this.time_signature_n, - time_signature_d = this.time_signature_d, - time_resolution = this.ticks_per_beat, - enstl_path = this.enstl_path, - copyright_notice = (string)this.copyright_notice, - scale_type = this.scale_type ? ChordType.MINOR : ChordType.MAJOR, - parts = this.parts - }; - } - - // private uint32 get_variable_length_value (uint8[] buffer, uint64 offset) { - // uint32 value = buffer[offset]; - - // uint8 c = 0xFF; - // uint i = 0; - - // if ((value & 0x80) > 0) { - // value &= 0x7F; - // do { - // c = buffer[offset + (i++)]; - // value = (value << 7) | (c & 0x7F); - // } while ((c & 0x80) > 0); - // } - - // return value; - // } - - private uint32 get_tempo (uint8[] buffer, uint64 offset) { - uint8 len = buffer[offset]; - - uint32 tempo = 0; - for (uint8 i = 1; i <= len; i++) { - tempo = (tempo << 8) | buffer[offset + i]; - } - - return tempo; - } - - private StylePartType get_style_part_type_from_marker (string marker) { - switch (marker) { - case "INT_1": - return (StylePartType.INTRO_1); - case "INT_2": - return (StylePartType.INTRO_2); - case "INT_3": - return (StylePartType.INTRO_3); - case "BRK": - return (StylePartType.BREAK); - case "VAR_A": - return (StylePartType.VARIATION_A); - case "VAR_B": - return (StylePartType.VARIATION_B); - case "VAR_C": - return (StylePartType.VARIATION_C); - case "VAR_D": - return (StylePartType.VARIATION_D); - case "FILL_A": - return (StylePartType.FILL_A); - case "FILL_B": - return (StylePartType.FILL_B); - case "FILL_C": - return (StylePartType.FILL_C); - case "FILL_D": - return (StylePartType.FILL_D); - case "END_1": - return (StylePartType.ENDING_1); - case "END_2": - return (StylePartType.ENDING_2); - case "END_3": - return (StylePartType.ENDING_3); - } - - return (StylePartType.EOS); - } - } -} diff --git a/src/Core/Analysers/VoiceAnalyser.vala b/src/Core/Analysers/VoiceAnalyser.vala deleted file mode 100644 index 24de4aaa..00000000 --- a/src/Core/Analysers/VoiceAnalyser.vala +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Models; - -namespace Ensembles.Core.Analysers { - public class VoiceAnalyser : Object { - private List voice_list; - - public signal void voice_analysed (string name); - - public VoiceAnalyser ( - AudioEngine.SynthProvider synth_provider, - string sf_path, - string sf_schema_path - ) { - voice_list = new List (); - - unowned Fluid.Synth sf_synth = synth_provider.utility_synth; - unowned Fluid.SoundFont soundfont = sf_synth.get_sfont (0); - - - FileStream stream = FileStream.open (sf_schema_path, "r"); - string? line = ""; - line = stream.read_line (); - string category = ""; - - uint index = 0; - unowned Fluid.Preset sf_preset = null; - soundfont.iteration_start (); - sf_preset = soundfont.iteration_next (); - while (sf_preset != null) { - int preset_num = sf_preset.get_num (); - int bank_num = sf_preset.get_banknum (); - var voice_name = sf_preset.get_name (); - - if (line != null) { - var parts = line.split (","); - int schema_bank = int.parse (parts[0]); - int schema_preset = int.parse (parts[1]); - - if (bank_num == schema_bank && preset_num == schema_preset) { - category = parts[2]; - line = stream.read_line (); - } - } - - voice_list.append (Voice () { - index = index++, - preset = (uint8) preset_num, - bank = (uint8) bank_num, - name = voice_name, - category = category, - sf_path = sf_path - }); - - Application.event_bus.send_initial_status (_("Loading voice: ") + voice_name + "…"); - Thread.usleep (15000); - - sf_preset = soundfont.iteration_next (); - } - } - - public Voice[] get_voices () { - var n = voice_list.length (); - var voices = new Voice[n]; - - for (uint i = 0; i < n; i++) { - var voice = voice_list.nth_data (i); - voices[i] = Voice () { - name = voice.name, - category = voice.category, - sf_path = voice.sf_path, - preset = voice.preset, - bank = voice.bank, - index = voice.index - }; - } - - return voices; - } - } -} diff --git a/src/Core/ArrangerWorkstation.vala b/src/Core/ArrangerWorkstation.vala deleted file mode 100644 index f4ae396b..00000000 --- a/src/Core/ArrangerWorkstation.vala +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Core.MIDIPlayers; -using Ensembles.Core.Plugins; -using Ensembles.Core.Racks; -using Ensembles.Models; - -namespace Ensembles.Core { - /** - * ## Arranger Workstation - * - * This forms the core of the app. This houses all the behind the scenes - * stuff that make every beat beat and every sound sound. - */ - public class ArrangerWorkstation : Object { - private AudioEngine.SynthProvider synth_provider; - private AudioEngine.Synthesizer synthesizer; - private StyleEngine style_engine; - private PluginManager plugin_manager; - private DSPRack main_dsp_rack; - private VoiceRack voice_l_rack; - private VoiceRack voice_r1_rack; - private VoiceRack voice_r2_rack; - - // Arranger Data - private Style[] styles; - private Style next_style; - private bool stopping_style; - - private Voice[] voices; - - private const string SF_PATH = Constants.SF2DATADIR + "/EnsemblesGM.sf2"; - private const string SF_SCHEMA_PATH = Constants.SF2DATADIR + "/EnsemblesGMSchema.csv"; - - construct { - #if PIPEWIRE_CORE_DRIVER - Pipewire.init (null, null); - #endif - synth_provider = new AudioEngine.SynthProvider (); - synth_provider.init_driver ("pulseaudio", 0.3); - Console.log ("Loading Soundfont from %s".printf (SF_PATH)); - try { - synthesizer = new AudioEngine.Synthesizer (synth_provider, SF_PATH); - } catch (FluidError e) { - Console.log (e.message, Console.LogLevel.ERROR); - } - - Console.log ("Initializing Plugin Racks"); - main_dsp_rack = new DSPRack (); - synthesizer.add_rack (main_dsp_rack); - - voice_l_rack = new VoiceRack (); - synthesizer.add_rack (voice_l_rack); - - voice_r1_rack = new VoiceRack (); - synthesizer.add_rack (voice_r1_rack); - - voice_r2_rack = new VoiceRack (); - synthesizer.add_rack (voice_r2_rack); - - build_events (); - } - - public ArrangerWorkstation () { - new Thread ("ensembles-data-discovery", load_data); - } - - /** - * Load all data like voices, styles and plugins - */ - public void load_data () { - Thread.usleep (500000); - // Load Styles - Console.log ("Searching for styles…"); - var style_loader = new FileLoaders.StyleFileLoader (); - uint n_styles = 0; - styles = style_loader.get_styles (out n_styles); - Console.log ( - "Found %u styles".printf (n_styles), - Console.LogLevel.SUCCESS - ); - - // Load Voices - Console.log ("Loading voices…"); - var voice_loader = new Analysers.VoiceAnalyser ( - synth_provider, - SF_PATH, - SF_SCHEMA_PATH - ); - Console.log ( - "Voices loaded successfully!", - Console.LogLevel.SUCCESS - ); - voices = voice_loader.get_voices (); - - // Load Plugins - Console.log ("Loading Audio Plugins…"); - plugin_manager = new PluginManager (); - Console.log ( - "%u Audio Plugins Loaded Successfully!" - .printf (plugin_manager.audio_plugins.length ()), - Console.LogLevel.SUCCESS - ); - - add_plugins_to_voice_racks (); - - Application.event_bus.send_initial_status (""); - - // Send ready signal - Idle.add (() => { - Ensembles.Application.event_bus.arranger_ready (); - return false; - }); - } - - private void build_events () { - Application.event_bus.style_play_toggle.connect (() => { - if (style_engine != null) { - style_engine.toggle_play (); - } - }); - - Application.event_bus.style_set_part.connect ( - (part) => { - if (style_engine != null) { - style_engine.queue_next_part (part); - } - } - ); - - Application.event_bus.style_break.connect (() => { - if (style_engine != null) { - style_engine.break_play (); - } - }); - - Application.event_bus.style_sync.connect (() => { - if (style_engine != null) { - style_engine.sync (); - } - }); - - Application.event_bus.style_change.connect ( - (style) => { - queue_change_style (style); - }); - } - - /** - * Creates a style engine with given style - * - * @param style A Style descriptor - */ - public void queue_change_style (Models.Style style) { - Console.log ("Changing style to the " + style.to_string ()); - next_style = style; - if (!stopping_style) { - stopping_style = true; - new Thread ("queue-load-style", () => { - uint8 current_tempo = 0; - bool was_playing = false; - StylePartType current_part = StylePartType.VARIATION_A; - if (style_engine != null) { - current_part = style_engine.current_part; - was_playing = style_engine.stop_and_wait (out current_tempo); - } - - style_engine = new StyleEngine ( - synth_provider, - next_style, - current_tempo - ); - stopping_style = false; - - style_engine.queue_next_part (current_part); - - if (was_playing) { - style_engine.play (); - } - }); - } - } - - /** - * Returns an array of styles loaded by the arranger workstation. - */ - public unowned Style[] get_styles () { - return styles; - } - - /** - * Returns an array of voices loaded by the arranger workstation. - */ - public unowned Voice[] get_voices () { - return voices; - } - - private void add_plugins_to_voice_racks () { - unowned List plugins = - plugin_manager.audio_plugins; - for (uint32 i = 0; i < plugins.length (); i++) { - if (plugins.nth_data (i).category == - AudioPlugins.AudioPlugin.Category.VOICE) { - try { - voice_l_rack.append (plugins.nth_data (i).duplicate ()); - voice_r1_rack.append (plugins.nth_data (i).duplicate ()); - voice_r2_rack.append (plugins.nth_data (i).duplicate ()); - } catch (PluginError e) { - - } - } - } - - voice_l_rack.active = true; - voice_r1_rack.active = true; - voice_r2_rack.active = true; - } - - public unowned List get_audio_plugins () { - return plugin_manager.audio_plugins; - } - - public unowned Racks.DSPRack get_main_dsp_rack () { - return main_dsp_rack; - } - - public unowned Racks.VoiceRack get_voice_rack ( - VoiceHandPosition position - ) { - switch (position) { - case VoiceHandPosition.LEFT: - return voice_l_rack; - case VoiceHandPosition.RIGHT_LAYERED: - return voice_r2_rack; - default: - return voice_r1_rack; - } - } - } -} diff --git a/src/Core/AudioEngine/SynthProvider.vala b/src/Core/AudioEngine/SynthProvider.vala deleted file mode 100644 index 7e95237a..00000000 --- a/src/Core/AudioEngine/SynthProvider.vala +++ /dev/null @@ -1,235 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Core.AudioEngine { - /** - * ## Synthesizer Instance Provider - * - * Manages FluidSynth instances and driver configurations. - */ - public class SynthProvider : Object { - private Fluid.Synth _rendering_synth; - private Fluid.AudioDriver rendering_driver; - private Fluid.Settings rendering_settings; - - public delegate void SynthRenderHandler ( - int len, - float* input_l, - float* input_r, - float** output_l, - float** output_r - ); - - private static float* wet_buffer_l; - private static float* wet_buffer_r; - - public static SynthRenderHandler synth_render_handler; - - ~SynthProvider () { - Fluid.free (wet_buffer_l); - Fluid.free (wet_buffer_r); - } - - /** - * This synth instance is used for actually renderring audio - */ - public unowned Fluid.Synth rendering_synth { - get { - if (_rendering_synth == null) { - rendering_settings = new Fluid.Settings (); - rendering_settings.setnum ("synth.gain", 1); - rendering_settings.setnum ("synth.overflow.percussion", 5000.0); - rendering_settings.setint ("synth.midi-channels", 64); - rendering_settings.setstr ("synth.midi-bank-select", "gs"); - rendering_settings.setint ("synth.polyphony", 1024); - - _rendering_synth = new Fluid.Synth (rendering_settings); - rendering_driver = new Fluid.AudioDriver.with_audio_callback ( - rendering_settings, - (synth, len, fx, aout) => { - // Log current unix time before the synthesizer processes audio - Synthesizer.processing_start_time = new DateTime.now_utc ().to_unix (); - - if (fx == null) { - /* Note that some audio drivers may not provide buffers for effects like - * reverb and chorus. In this case it's your decision what to do. If you - * had called process() like in the else branch below, no - * effects would have been rendered. Instead, you may mix the effects - * directly into the out buffers. */ - if (((Fluid.Synth)synth).process (len, aout, aout) != Fluid.OK) { - return Fluid.FAILED; - } - } else { - /* Call the synthesizer to fill the output buffers with its - * audio output. */ - if (((Fluid.Synth)synth).process (len, fx, aout) != Fluid.OK) { - return Fluid.FAILED; - } - } - - // All processing is stereo // Repeat processing if the plugin is mono - float* dry_buffer_l = aout[0]; - float* dry_buffer_r = aout[1]; - - // Apply effects here - if (wet_buffer_l == null || wet_buffer_r == null) { - wet_buffer_l = malloc (len * sizeof (float)); - wet_buffer_r = malloc (len * sizeof (float)); - } - - // int size_l, size_r; - - if (synth_render_handler != null) { - for (int k = 0; k < len; k++) { - wet_buffer_l[k] = dry_buffer_l[k]; - wet_buffer_r[k] = dry_buffer_r[k]; - } - /* - * The audio buffer data is sent to the plugin system - */ - synth_render_handler (len, - dry_buffer_l, - dry_buffer_r, - &wet_buffer_l, - &wet_buffer_r); - - for (int k = 0; k < len; k++) { - dry_buffer_l[k] = wet_buffer_l[k]; - dry_buffer_r[k] = wet_buffer_r[k]; - } - } - - return Fluid.OK; - }, _rendering_synth); - } - return _rendering_synth; - } - } - - private Fluid.Synth _utility_synth; - private Fluid.AudioDriver utility_driver; - private Fluid.Settings utility_settings; - - /** This instance is never used to render audio and only use for Midi players - */ - public unowned Fluid.Synth utility_synth { - get { - if (_utility_synth == null) { - utility_settings = new Fluid.Settings (); - utility_settings.setnum ("synth.overflow.percussion", 5000.0); - utility_settings.setstr ("synth.midi-bank-select", "gs"); - utility_settings.setint ("synth.cpu-cores", 4); - - _utility_synth = new Fluid.Synth (utility_settings); - utility_driver = new Fluid.AudioDriver (utility_settings, _utility_synth); - } - return _utility_synth; - } - } - - /** - * Sets driver configuration of synthesizer instance - * - * This should be called before accessing any synth - */ - public int init_driver (string driver_name, double buffer_length_multiplier) { - switch (driver_name) { - case "alsa": - rendering_settings.setstr ("audio.driver", "alsa"); - rendering_settings.setint ("audio.periods", 8); - rendering_settings.setint ("audio.period-size", (int)(86.0 + (buffer_length_multiplier * 938.0))); - rendering_settings.setint ("audio.realtime-prio", 80); - - utility_settings.setstr ("audio.driver", "alsa"); - utility_settings.setint ("audio.periods", 16); - utility_settings.setint ("audio.period-size", (int)(64.0 + (buffer_length_multiplier * 938.0))); - utility_settings.setint ("audio.realtime-prio", 70); - - return (int)(86.0 + (buffer_length_multiplier * 938.0)); - case "pulseaudio": - rendering_settings.setstr ("audio.driver", "pulseaudio"); - rendering_settings.setint ("audio.periods", 8); - rendering_settings.setint ("audio.period-size", - (int)(1024.0 + (buffer_length_multiplier * 3072.0))); - rendering_settings.setint ("audio.realtime-prio", 80); - // rendering_settings.setint ("audio.pulseaudio.adjust-latency", 0); - - utility_settings.setstr ("audio.driver", "pulseaudio"); - utility_settings.setint ("audio.periods", 2); - utility_settings.setint ("audio.period-size", 512); - utility_settings.setint ("audio.realtime-prio", 90); - utility_settings.setint ("audio.pulseaudio.adjust-latency", 0); - - return (int)(1024.0 + (buffer_length_multiplier * 3072.0)); - case "pipewire-pulse": - rendering_settings.setstr ("audio.driver", "pulseaudio"); - rendering_settings.setint ("audio.periods", 8); - rendering_settings.setint ("audio.period-size", (int)(512.0 + (buffer_length_multiplier * 3584.0))); - rendering_settings.setint ("audio.pulseaudio.adjust-latency", 0); - - utility_settings.setstr ("audio.driver", "pulseaudio"); - utility_settings.setint ("audio.periods", 2); - utility_settings.setint ("audio.period-size", 512); - - return (int)(512.0 + (buffer_length_multiplier * 3584.0)); - case "jack": - rendering_settings.setnum ("synth.gain", 0.005); - rendering_settings.setstr ("audio.driver", "jack"); - rendering_settings.setstr ("audio.jack.id", "Ensembles Audio Output"); - - utility_settings.setstr ("audio.driver", "jack"); - utility_settings.setstr ("audio.jack.id", "Ensembles Utility"); - - return 0; - case "pipewire": - rendering_settings.setstr ("audio.driver", "pipewire"); - rendering_settings.setint ("audio.period-size", (int)(256.0 + (buffer_length_multiplier * 3584.0))); - rendering_settings.setint ("audio.realtime-prio", 80); - rendering_settings.setstr ("audio.pipewire.media-role", "Production"); - rendering_settings.setstr ("audio.pipewire.media-type", "Audio"); - rendering_settings.setstr ("audio.pipewire.media-category", "Playback"); - - utility_settings.setstr ("audio.driver", "pipewire"); - utility_settings.setint ("audio.period-size", 256); - utility_settings.setint ("audio.realtime-prio", 90); - utility_settings.setstr ("audio.pipewire.media-role", "Game"); - utility_settings.setstr ("audio.pipewire.media-type", "Audio"); - utility_settings.setstr ("audio.pipewire.media-category", "Playback"); - - return (int)(256.0 + (buffer_length_multiplier * 3584.0)); - } - - return 0; - } - } -} - - -/* - * RENDER SYNTH CHANNEL UTILIZATION SCHEMATICS - * ---------------------------------------------- - * - * Style, Song: - * 0 - 15 - * - * Metronome: - * 16 - * - * MIDI INPUT: - * Voice R1 ~ 17 - * Voice R2 ~ 18 - * Voice L ~ 19 - * CHORD-EP ~ 20 - * CHORD-Strings ~ 21 - * CHORD-Bass ~ 22 - * - * CHIMES: - * 23 - * - * RECORDER: - * Voice R2 ~ 24 - * Voice L ~ 25 - * All tracks ~ 26 - 63 - */ diff --git a/src/Core/AudioEngine/SynthSettingsPresets.vala b/src/Core/AudioEngine/SynthSettingsPresets.vala deleted file mode 100644 index a42116f3..00000000 --- a/src/Core/AudioEngine/SynthSettingsPresets.vala +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - - namespace Ensembles.Core.AudioEngine.SynthSettingsPresets { - /** Reverb presets - */ - public class ReverbPresets { - public const double[] ROOM_SIZE = { 0.0, 0.1, 0.2, 0.3, 0.4, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9}; - public const double[] WIDTH = { 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20 }; - public const double[] LEVEL = { 0, 0.05, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1, 0.1 }; - } - - /** Chorus presets - */ - public class ChorusPresets { - public const double[] DEPTH = {0, 4, 4, 4, 6, 10, 20, 25, 30, 35, 40 }; - public const uint8[] NR = { 0, 2, 3, 3, 4, 5, 6, 8, 10, 16, 20 }; - public const double[] LEVEL = { 0, 0.1, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2, 0.2 }; - } - - public class ModulatorSettings : Object { - private int16[] pan_value; - private int16[] reverb_value; - private int16[] chorus_value; - private int16[] pitch_value; - private int16[] expression_value; - private int16[] modulation_value; - private int16[] cut_off_value; - private int16[] resonance_value; - - construct { - pan_value = new int16 [16]; - for (uint8 i = 0; i < 16; i++) { - pan_value[i] = -65; - } - - reverb_value = new int16 [16]; - for (uint8 i = 0; i < 16; i++) { - reverb_value[i] = -1; - } - - chorus_value = new int16 [16]; - for (uint8 i = 0; i < 16; i++) { - chorus_value[i] = -1; - } - - pitch_value = new int16 [16]; - for (uint8 i = 0; i < 16; i++) { - pitch_value[i] = -65; - } - - expression_value = new int16 [16]; - for (uint8 i = 0; i < 16; i++) { - expression_value[i] = -1; - } - - modulation_value = new int16 [16]; - for (uint8 i = 0; i < 16; i++) { - modulation_value[i] = -1; - } - - cut_off_value = new int16 [16]; - for (uint8 i = 0; i < 16; i++) { - cut_off_value[i] = -1; - } - - resonance_value = new int16 [16]; - for (uint8 i = 0; i < 16; i++) { - resonance_value[i] = -1; - } - } - - /** Gets the modulator value of style channel by modulator number - */ - public int16 get_mod_buffer_value (uint8 modulator, uint8 channel) { - switch (modulator) { - case 1: - return modulation_value[channel]; - case 10: - return pan_value[channel]; - case 11: - return expression_value[channel]; - case 66: - return pitch_value[channel]; - case 71: - return resonance_value[channel]; - case 74: - return cut_off_value[channel]; - case 91: - return reverb_value[channel]; - case 93: - return chorus_value[channel]; - } - return -1; - } - - /** Sets the modulator value of style channel by modulator number - */ - public void set_mod_buffer_value (uint8 modulator, uint8 channel, int16 value) { - switch (modulator) { - case 1: - modulation_value[channel] = value; - break; - case 10: - pan_value[channel] = value; - break; - case 11: - expression_value[channel] = value; - break; - case 66: - pitch_value[channel] = value; - break; - case 71: - resonance_value[channel] = value; - break; - case 74: - cut_off_value[channel] = value; - break; - case 91: - reverb_value[channel] = value; - break; - case 93: - chorus_value[channel] = value; - break; - } - } - } - - public class StyleGainSettings : Object { - /** Style gain values */ - public int16[] gain; - construct { - gain = new int16[16]; - for (uint i = 0; i < 16; i++) { - gain[i] = -1; - } - } - } -} diff --git a/src/Core/AudioEngine/Synthesizer.vala b/src/Core/AudioEngine/Synthesizer.vala deleted file mode 100644 index b0832dd8..00000000 --- a/src/Core/AudioEngine/Synthesizer.vala +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Core.AudioEngine { - /** - * ## Synthesizer - * - * The FluidSynth SoundFont™ Synthesizer forms the base audio engine for the - * app. - * - * All midi events either from the midi players or from the plugins will be - * to and from here. - * - * All sound from the plugins and samplers are also channel through this - * synthesizer. - */ - public class Synthesizer : Object { - - private bool _input_enabled = true; - - public bool input_enabled { - get { - return _input_enabled; - } - set { - _input_enabled = value; - } - } - - public bool layer { get; set; } - public bool split { get; set; } - - public static int64 processing_start_time; - - private static uint32 buffer_size; - - private Analysers.ChordAnalyser chord_analyser; - private SynthSettingsPresets.StyleGainSettings style_gain_settings; - private SynthSettingsPresets.ModulatorSettings modulator_settings; - private unowned Fluid.Synth rendering_synth; - - public List racks; - - public static double sample_rate { get; private set; } - - private int soundfont_id; - - construct { - chord_analyser = new Analysers.ChordAnalyser (); - style_gain_settings = new SynthSettingsPresets.StyleGainSettings (); - modulator_settings = new SynthSettingsPresets.ModulatorSettings (); - racks = new List (); - } - - public Synthesizer (SynthProvider synth_provider, string soundfont) throws FluidError { - Console.log ("Initializing Synthesizer…"); - rendering_synth = synth_provider.rendering_synth; - buffer_size = rendering_synth.get_internal_bufsize (); - double sample_rate = 1; - var s = rendering_synth.get_settings (); - s.getnum ("synth.sample-rate", out sample_rate); - Console.log ("Sample Rate: %0.1lf Hz".printf (sample_rate)); - Synthesizer.sample_rate = sample_rate; - SynthProvider.synth_render_handler = process_audio; - - if (Fluid.is_soundfont (soundfont)) { - soundfont_id = synth_provider.rendering_synth.sfload (soundfont, true); - synth_provider.utility_synth.sfload (soundfont, true); - - // Initialize Voices - rendering_synth.program_select (17, soundfont_id, 0, 0); - rendering_synth.program_select (18, soundfont_id, 0, 49); - rendering_synth.program_select (19, soundfont_id, 0, 33); - - // Initialize chord voices - rendering_synth.program_select (20, soundfont_id, 0, 5); - rendering_synth.program_select (21, soundfont_id, 0, 33); - rendering_synth.program_select (22, soundfont_id, 0, 49); - - // Initialize metronome voice - rendering_synth.program_select (16, soundfont_id, 128, 0); - - // Initialize intro chime voice - rendering_synth.program_select (23, soundfont_id, 0, 96); - } else { - throw new FluidError.INVALID_SF (_("SoundFont from path: %s is either missing or invalid"), soundfont); - } - - set_synth_defaults (); - - build_events (); - } - - private void build_events () { - Application.event_bus.style_midi_event.connect (handle_midi_event_from_player); - Application.event_bus.synth_send_event.connect (handle_midi_event); - Application.event_bus.synth_halt_notes.connect (halt_notes); - Application.event_bus.synth_sounds_off.connect (stop_all_sounds); - Application.event_bus.arranger_ready.connect (play_intro_sound); - Application.event_bus.voice_chosen.connect ((hand_position, name, bank, preset) => { - uint8 channel = 17; - switch (hand_position) { - case VoiceHandPosition.LEFT: - channel = 19; - break; - case VoiceHandPosition.RIGHT_LAYERED: - channel = 18; - break; - default: - break; - } - - rendering_synth.program_select (channel, soundfont_id, bank, preset); - }); - } - - private void set_synth_defaults () { - // CutOff for Realtime synth - rendering_synth.cc (17, MIDI.Control.CUT_OFF, 40); - rendering_synth.cc (18, MIDI.Control.CUT_OFF, 0); - rendering_synth.cc (19, MIDI.Control.CUT_OFF, 0); - - // Reverb and Chorus for R1 voice - rendering_synth.cc (17, MIDI.Control.REVERB, 100); - rendering_synth.cc (17, MIDI.Control.CHORUS, 100); - - // Reverb and Chorus for intro tone - rendering_synth.cc (23, MIDI.Control.REVERB, 127); - rendering_synth.cc (23, MIDI.Control.CHORUS, 100); - rendering_synth.cc (23, MIDI.Control.CUT_OFF, 40); - rendering_synth.cc (23, MIDI.Control.RESONANCE, 80); - - // Reverb and Chorus for Metronome - rendering_synth.cc (16, MIDI.Control.REVERB, 0); - rendering_synth.cc (16, MIDI.Control.CHORUS, 0); - - // Default gain for Realtime synth - rendering_synth.cc (17, MIDI.Control.GAIN, 100); - rendering_synth.cc (18, MIDI.Control.GAIN, 90); - rendering_synth.cc (19, MIDI.Control.GAIN, 80); - - - // Default pitch of all synths - for (int i = 17; i < 64; i++) { - rendering_synth.cc (i, MIDI.Control.EXPLICIT_PITCH, 64); - } - - // Default cut-off and resonance for recorder - for (int i = 24; i < 64; i++) { - rendering_synth.cc (i, MIDI.Control.CUT_OFF, 40); - rendering_synth.cc (i, MIDI.Control.RESONANCE, 10); - } - - // Default pitch for styles - for (int i = 0; i < 16; i++) { - rendering_synth.cc (i, MIDI.Control.EXPLICIT_PITCH, 64); - } - - set_master_reverb_active (true); - edit_master_reverb (8); - - set_master_chorus_active (true); - edit_master_chorus (2); - } - - private void play_intro_sound () { - Timeout.add (200, () => { - rendering_synth.noteon (23, 65, 110); - return false; - }); - - Timeout.add (300, () => { - rendering_synth.noteon (23, 60, 90); - return false; - }); - - Timeout.add (400, () => { - rendering_synth.noteon (23, 72, 127); - return false; - }); - - Timeout.add (500, () => { - rendering_synth.noteoff (23, 65); - rendering_synth.noteoff (23, 60); - rendering_synth.noteoff (23, 72); - return false; - }); - } - - private void process_audio ( - int len, - float* input_l, - float* input_r, - float** output_l, - float** output_r - ) { - foreach (var rack in racks) { - rack.process_audio ( - len, input_l, input_r, output_l, output_r - ); - - // Copy back to input for next rack - for (int i = 0; i < len; i++) { - input_l[i] = * (* output_l + i); - input_r[i] = * (* output_r + i); - } - } - } - - public void add_rack (Racks.Rack rack) { - racks.append (rack); - } - - public static uint32 get_buffer_size () { - return buffer_size; - } - - public static int64 get_process_start_time () { - return processing_start_time; - } - - private void edit_master_reverb (int level) { - if (rendering_synth != null) { - rendering_synth.set_reverb_group_roomsize (-1, SynthSettingsPresets.ReverbPresets.ROOM_SIZE[level]); - rendering_synth.set_reverb_group_damp (-1, 0.1); - rendering_synth.set_reverb_group_width (-1, SynthSettingsPresets.ReverbPresets.WIDTH[level]); - rendering_synth.set_reverb_group_level (-1, SynthSettingsPresets.ReverbPresets.LEVEL[level]); - } - } - - private void set_master_reverb_active (bool active) { - if (rendering_synth != null) { - rendering_synth.reverb_on (-1, active); - } - } - - private void edit_master_chorus (int level) { - if (rendering_synth != null) { - rendering_synth.set_chorus_group_depth (-1, SynthSettingsPresets.ChorusPresets.DEPTH[level]); - rendering_synth.set_chorus_group_level (-1, SynthSettingsPresets.ChorusPresets.LEVEL[level]); - rendering_synth.set_chorus_group_nr (-1, SynthSettingsPresets.ChorusPresets.NR[level]); - } - } - - private void set_master_chorus_active (bool active) { - if (rendering_synth != null) { - rendering_synth.chorus_on (-1, active); - } - } - - private int handle_midi_event (Fluid.MIDIEvent event) { - bool handled = false; - foreach (var rack in racks) { - var voice_rack = rack as Racks.VoiceRack; - if (voice_rack != null) { - if (voice_rack.send_midi_event (event) == Fluid.OK) { - handled = true; - } - } - } - - var type = event.get_type (); - var key = event.get_key (); - - switch (type) { - case MIDI.EventType.NOTE_ON: - Application.event_bus.synth_received_note ((uint8) key, true); - break; - case MIDI.EventType.NOTE_OFF: - Application.event_bus.synth_received_note ((uint8) key, false); - break; - default: - break; - } - - if (handled) { - return Fluid.OK; - } - - return rendering_synth.handle_midi_event (event); - } - - private int handle_midi_event_from_player (Fluid.MIDIEvent event) { - int type = event.get_type (); - int chan = event.get_channel (); - int cont = event.get_control (); - int value= event.get_value (); - - if (type == MIDI.EventType.CONTROL_CHANGE) { - if ( - cont == MIDI.Control.EXPLICIT_BANK_SELECT && - (value == 1 || value == 8 || value == 16 || value == 126) - ) { - int sf_id, program_id, bank_id; - rendering_synth.get_program (chan, out sf_id, out bank_id, out program_id); - rendering_synth.program_select (chan, soundfont_id, value, program_id); - } - - if (cont == MIDI.Control.GAIN) { - if (style_gain_settings.gain[chan] >= 0) { - event.set_value (style_gain_settings.gain[chan]); - } - } - - if (cont == MIDI.Control.PAN) { - if (modulator_settings.get_mod_buffer_value (MIDI.Control.PAN, (uint8)chan) >= -64) { - event.set_value (modulator_settings.get_mod_buffer_value (10, (uint8)chan)); - } - } else { - if (modulator_settings.get_mod_buffer_value ((uint8)cont, (uint8)chan) >= 0) { - event.set_value ( - modulator_settings.get_mod_buffer_value ((uint8)cont, (uint8)chan) - ); - } - } - } - - if (type == MIDI.EventType.NOTE_ON) { - // velocity_buffer[chan] = value; - } - - return rendering_synth.handle_midi_event (event); - } - - private void halt_notes (bool except_drums) { - for (uint8 i = 0; i < 16; i++) { - if (!except_drums || (i != 9 && i != 10)) { - rendering_synth.all_notes_off (i); - } - } - } - - private void stop_all_sounds () { - for (uint8 i = 0; i < 16; i++) { - rendering_synth.all_sounds_off (i); - } - } - } -} diff --git a/src/Core/Automators/Arperggiator.vala b/src/Core/Automators/Arperggiator.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Core/Automators/Harmonizer.vala b/src/Core/Automators/Harmonizer.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Core/Drivers/AudioDriverSniffer.vala b/src/Core/Drivers/AudioDriverSniffer.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Core/Drivers/MIDIInputHost.vala b/src/Core/Drivers/MIDIInputHost.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Core/FileLoaders/StyleFileLoader.vala b/src/Core/FileLoaders/StyleFileLoader.vala deleted file mode 100644 index 963bd33c..00000000 --- a/src/Core/FileLoaders/StyleFileLoader.vala +++ /dev/null @@ -1,82 +0,0 @@ -using Ensembles.Models; - -namespace Ensembles.Core.FileLoaders { - public class StyleFileLoader : Object { - public Style[] styles; - - private List style_list; - - private string stock_style_path; - private string user_style_path; - - public StyleFileLoader () { - stock_style_path = Constants.PKGDATADIR + "/StyleFiles"; - user_style_path = Environment.get_user_special_dir (GLib.UserDirectory.DOCUMENTS) + - "/ensembles" + "/styles"; - - style_list = new List (); - - try { - Dir dir = Dir.open (stock_style_path, 0); - string? name = null; - while ((name = dir.read_name ()) != null) { - string path = Path.build_filename (stock_style_path, name); - if (path.has_suffix (".enstl") && path.contains ("@")) { - try { - var analyser = new Analysers.StyleAnalyser (path); - style_list.append (analyser.get_style ()); - } catch (StyleError e) { - Console.log (e, Console.LogLevel.WARNING); - } catch (Error e) { - Console.log ("Style file not found or invalid!", Console.LogLevel.WARNING); - } - } - } - } catch (FileError e) { - Console.log ("Stock style directory not found", Console.LogLevel.WARNING); - } - - try { - Dir dir = Dir.open (user_style_path, 0); - string? name = null; - while ((name = dir.read_name ()) != null) { - string path = Path.build_filename (user_style_path, name); - if (path.has_suffix (".enstl") && path.contains ("@")) { - try { - var analyser = new Analysers.StyleAnalyser (path); - style_list.append (analyser.get_style ()); - } catch (StyleError e) { - Console.log (e, Console.LogLevel.WARNING); - } catch (Error e) { - Console.log ("Style file not found or invalid!", Console.LogLevel.WARNING); - } - } - } - } catch (FileError e) { - Console.log ("User style directory not found", Console.LogLevel.TRACE); - } - - style_list.sort (stylecmp); - } - - /** - * Get an array of style objects which can be passed into - * style engines to play them - */ - public Style[] get_styles (out uint len) { - len = style_list.length (); - var styles = new Style[len]; - uint i = 0; - - foreach (var style in style_list) { - styles[i++] = (owned)style; - } - - return styles; - } - - private CompareFunc stylecmp = (a, b) => { - return (a.genre).ascii_casecmp (b.genre); - }; - } -} diff --git a/src/Core/MIDIPlayers/MetronomeLFOPlayer.vala b/src/Core/MIDIPlayers/MetronomeLFOPlayer.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Core/MIDIPlayers/SongPlayer.vala b/src/Core/MIDIPlayers/SongPlayer.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Core/MIDIPlayers/StyleEngine.vala b/src/Core/MIDIPlayers/StyleEngine.vala deleted file mode 100644 index 764f059f..00000000 --- a/src/Core/MIDIPlayers/StyleEngine.vala +++ /dev/null @@ -1,689 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Models; - -namespace Ensembles.Core.MIDIPlayers { - /** - * ## Style Engine - * - * A style engine object can be made to play a particular Ensembles style. - * An Ensembles style is a special MIDI file with `.enstl` extension. - * The style engine can take care of style playback using the appropriate - * chords and changing the style part. - */ - public class StyleEngine : Object { - // Style data - private unowned Style style; - - // Fluid Player for style - private Fluid.Player style_player; - - // Utility synth for playing style file - private unowned Fluid.Synth utility_synth; - - // Player state - private uint32 absolute_beat_number = 0; - private uint32 absolute_measure_number = 0; - private StylePartType _current_part; - public StylePartType current_part { - get { - return _current_part; - } - private set { - _current_part = value; - Application.event_bus.style_current_part_changed (value); - } - } - private StylePartType _next_part; - private StylePartType next_part { - get { - return _next_part; - } - set { - _next_part = value; - Application.event_bus.style_next_part_changed (value); - } - } - private StylePartType current_variation; - - // Per channel note-on tracking flags - private int[] channel_note_on = { - -1, -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, -1, - -1, -1, -1, -1 - }; - - // Chord data - private Chord chord; - private bool alt_channels_active = false; - private HashTable part_bounds_map; - - // Change queues - private bool queue_fill = false; - private bool queue_break = false; - private bool queue_chord_change = false; - private bool force_change_part = false; - private bool sync_start = false; - private bool sync_stop = false; - - // Thresholds - private uint8 time_resolution_limit = 0; - private uint measure_length; - - construct { - part_bounds_map = new HashTable (direct_hash, direct_equal); - } - - /** - * Creates a new instance of a style engine object using the given style. - * - * @param synth_provider A synth provider object - * @param style The style to use for the style engine - * @param current_tempo If this value is greater than 0 then the style - * engine will be initialized with this value. - */ - public StyleEngine (AudioEngine.SynthProvider synth_provider, Models.Style? style, - uint8? custom_tempo = 0) { - this.style = style; - utility_synth = synth_provider.utility_synth; - - style_player = new Fluid.Player (utility_synth); - style_player.set_tick_callback ( (style_engine_ref, ticks) => { - return ((StyleEngine?)style_engine_ref).parse_ticks (ticks); - }, this); - style_player.set_playback_callback ((style_engine_ref, event) =>{ - return ((StyleEngine?)style_engine_ref).parse_midi_events (event); - }, this); - - style_player.add (style.enstl_path); - - style.update_part_hash_table (part_bounds_map); - - var actual_tempo = style_player.get_midi_tempo (); - if (custom_tempo >= 40) { - style_player.set_tempo (Fluid.TempoType.EXTERNAL_BPM, (double)custom_tempo); - actual_tempo = custom_tempo; - } - - if (actual_tempo < 130) { - time_resolution_limit = 1; - } else if (actual_tempo < 182) { - time_resolution_limit = 2; - } else { - time_resolution_limit = 3; - } - - current_variation = StylePartType.VARIATION_A; - next_part = StylePartType.VARIATION_A; - current_part = StylePartType.VARIATION_A; - - halt_continuous_notes (); - measure_length = style.time_resolution * style.time_signature_n; - } - - private void halt_continuous_notes () { - for (uint channel = 0; channel < 16; channel++) { - if (channel < 9 || channel > 10) { - channel_note_on[channel] = -1; - } - } - - Application.event_bus.synth_halt_notes (true); - } - - private int parse_ticks (int ticks) { - // If there is a chord change - if (queue_chord_change) { - queue_chord_change = false; - Application.event_bus.synth_halt_notes (true); - for (uint8 channel = 0; channel < 16; channel++) { - if ((channel < 9 || channel > 10) && channel_note_on[channel] >= 0) { - resend_key (channel_note_on[channel], channel); - } - } - } - - var current_part_bounds = part_bounds_map.get (current_part); - uint current_measure_start = (uint)Math.floor ((double)ticks / (double)measure_length) * measure_length; - uint current_measure_end = (uint)Math.ceil ((double)(ticks - 1) / (double)measure_length) * measure_length; - - // Fill Ins - if (queue_fill) { - queue_fill = false; - Application.event_bus.style_break_changed (false); - if (Ensembles.settings.autofill) { - switch (current_part) { - case StylePartType.VARIATION_A: - switch (next_part) { - case StylePartType.VARIATION_A: - current_part = StylePartType.FILL_A; - break; - case StylePartType.VARIATION_B: - current_part = StylePartType.FILL_A; - break; - case StylePartType.VARIATION_C: - current_part = StylePartType.FILL_B; - break; - case StylePartType.VARIATION_D: - current_part = StylePartType.FILL_C; - break; - default: - break; - } - break; - case StylePartType.VARIATION_B: - switch (next_part) { - case StylePartType.VARIATION_A: - current_part = StylePartType.FILL_A; - break; - case StylePartType.VARIATION_B: - current_part = StylePartType.FILL_B; - break; - case StylePartType.VARIATION_C: - current_part = StylePartType.FILL_B; - break; - case StylePartType.VARIATION_D: - current_part = StylePartType.FILL_C; - break; - default: - break; - } - break; - case StylePartType.VARIATION_C: - switch (next_part) { - case StylePartType.VARIATION_A: - current_part = StylePartType.FILL_A; - break; - case StylePartType.VARIATION_B: - current_part = StylePartType.FILL_B; - break; - case StylePartType.VARIATION_C: - current_part = StylePartType.FILL_C; - break; - case StylePartType.VARIATION_D: - current_part = StylePartType.FILL_C; - break; - default: - break; - } - break; - case StylePartType.VARIATION_D: - switch (next_part) { - case StylePartType.VARIATION_A: - current_part = StylePartType.FILL_A; - break; - case StylePartType.VARIATION_B: - current_part = StylePartType.FILL_B; - break; - case StylePartType.VARIATION_C: - current_part = StylePartType.FILL_D; - break; - case StylePartType.VARIATION_D: - current_part = StylePartType.FILL_D; - break; - default: - break; - } - break; - case StylePartType.BREAK: - switch (next_part) { - case StylePartType.VARIATION_A: - current_part = StylePartType.FILL_A; - break; - case StylePartType.VARIATION_B: - current_part = StylePartType.FILL_B; - break; - case StylePartType.VARIATION_C: - current_part = StylePartType.FILL_C; - break; - case StylePartType.VARIATION_D: - current_part = StylePartType.FILL_D; - break; - default: - break; - } - break; - default: - break; - } - } else { - switch (current_part) { - case StylePartType.VARIATION_A: - current_part = StylePartType.FILL_A; - break; - case StylePartType.VARIATION_B: - current_part = StylePartType.FILL_B; - break; - case StylePartType.VARIATION_C: - current_part = StylePartType.FILL_C; - break; - case StylePartType.VARIATION_D: - current_part = StylePartType.FILL_D; - break; - default: - switch (next_part) { - case StylePartType.VARIATION_A: - current_part = StylePartType.FILL_A; - break; - case StylePartType.VARIATION_B: - current_part = StylePartType.FILL_B; - break; - case StylePartType.VARIATION_C: - current_part = StylePartType.FILL_C; - break; - case StylePartType.VARIATION_D: - current_part = StylePartType.FILL_D; - break; - default: - break; - } - break; - } - } - - var fill_part_bounds = part_bounds_map.get (current_part); - var fill_start = fill_part_bounds.start + (ticks - current_measure_start); - - if (Ensembles.settings.autofill && next_part < current_variation) { - halt_continuous_notes (); - } - - return style_player.seek ((int)fill_start); - } - - // Break - if (queue_break) { - queue_break = false; - Application.event_bus.style_break_changed (true); - var break_part_bounds = part_bounds_map.get (StylePartType.BREAK); - var break_start = break_part_bounds.start + (ticks - current_measure_start); - current_part = StylePartType.BREAK; - halt_continuous_notes (); - - return style_player.seek ((int)break_start); - } - - bool measure; - if (is_beat (ticks, out measure)) { - Application.event_bus.beat (measure, style.time_signature_n, style.time_signature_d); - // print ("%d %u %u %u %u\n", ticks, current_part_bounds.start, - // current_part_bounds.end, current_measure_start, current_measure_end); - // print ("%d, %u, %d\n", ticks, current_measure_end, current_part); - - if (ticks >= current_measure_end) { - if (sync_stop) { - sync_stop = false; - sync_start = true; - Application.event_bus.style_sync_changed (true); - current_part = current_variation; - next_part = current_variation; - stop (); - } - switch (current_part) { - // If we are currently in a variation - case StylePartType.VARIATION_A: - case StylePartType.VARIATION_B: - case StylePartType.VARIATION_C: - case StylePartType.VARIATION_D: - // If the next part is the same, - // wait for current measure to end - current_variation = current_part; - if (current_part == next_part) { - if (ticks >= current_part_bounds.end) { - return seek_measure (part_bounds_map.get (next_part).start); - } - } else { - current_part = next_part; - return seek_measure (part_bounds_map.get (next_part).start); - } - break; - case StylePartType.INTRO_1: - case StylePartType.INTRO_2: - case StylePartType.INTRO_3: - if (current_part == next_part) { - next_part = current_variation; - } - if (ticks >= current_part_bounds.end || force_change_part) { - current_part = next_part; - force_change_part = false; - return seek_measure (part_bounds_map.get (next_part).start); - } - break; - case StylePartType.ENDING_1: - case StylePartType.ENDING_2: - case StylePartType.ENDING_3: - if (force_change_part) { - force_change_part = false; - current_part = next_part; - return seek_measure (part_bounds_map.get (next_part).start); - } - if (ticks >= current_part_bounds.end) { - if (current_part == next_part) { - current_part = current_variation; - next_part = current_variation; - stop (); - } else { - current_part = next_part; - return seek_measure (part_bounds_map.get (next_part).start); - } - } - break; - case StylePartType.FILL_A: - case StylePartType.FILL_B: - case StylePartType.FILL_C: - case StylePartType.FILL_D: - if (current_part == StylePartType.FILL_A) { - current_variation = StylePartType.VARIATION_A; - } else if (current_part == StylePartType.FILL_B) { - current_variation = StylePartType.VARIATION_B; - } else if (current_part == StylePartType.FILL_C) { - current_variation = StylePartType.VARIATION_C; - } else if (current_part == StylePartType.FILL_D) { - current_variation = StylePartType.VARIATION_D; - } - current_part = next_part; - return seek_measure (part_bounds_map.get (next_part).start); - case StylePartType.BREAK: - if (current_part == StylePartType.INTRO_1 || - current_part == StylePartType.INTRO_2 || - current_part == StylePartType.INTRO_3 || - current_part == StylePartType.ENDING_1 || - current_part == StylePartType.ENDING_2 || - current_part == StylePartType.ENDING_3) { - current_part = current_variation; - next_part = current_variation; - } else { - current_part = next_part; - } - Application.event_bus.style_break_changed (false); - return seek_measure (part_bounds_map.get (next_part).start); - default: - break; - } - } - } - - return Fluid.OK; - } - - private int seek_measure (int ticks) { - halt_continuous_notes (); - absolute_beat_number = ticks / style.time_resolution; - absolute_measure_number = ticks / (style.time_resolution * style.time_signature_n); - return style_player.seek (ticks); - } - - private bool is_beat (int ticks, out bool measure) { - var q = ticks / style.time_resolution; - if (q != absolute_beat_number) { - absolute_beat_number = q; - - var mq = ticks / (style.time_resolution * style.time_signature_n); - if (mq != absolute_measure_number) { - absolute_measure_number = mq; - measure = true; - } else { - measure = false; - } - return true; - } - - measure = false; - - return false; - } - - private int parse_midi_events (Fluid.MIDIEvent? event) { - int type = event.get_type (); - int channel = event.get_channel (); - int control = event.get_control (); - int key = event.get_key (); - int value = event.get_value (); - int velocity = event.get_velocity (); - - // Bypass voice halt signal - if (control == 120) { - return Fluid.OK; - } - // Check if alt_channel signal is active - else if (channel == 11 && control == 82) { - alt_channels_active = value > 63; - } - - // If alt channels is enabled, that means it will disable half of - // the channels based on the scale type - if (type == MIDI.EventType.NOTE_ON && alt_channels_active) { - if (style.scale_type != chord.type) { - if (channel == 0 || - channel == 2 || - channel == 3 || - channel == 4 || - channel == 6 || - channel == 7) { - return Fluid.OK; - } - } - } else { - if (channel == 11 || - channel == 12 || - channel == 13 || - channel == 14 || - channel == 15) { - return Fluid.OK; - } - } - - var new_event = new Fluid.MIDIEvent (); - new_event.set_type (type); - new_event.set_channel (channel); - new_event.set_pitch (event.get_pitch ()); - new_event.set_program (event.get_program ()); - new_event.set_value (value); - new_event.set_velocity (velocity); - new_event.set_control (control); - - // Track which notes are on so that they can be continued after - // chord change - if (channel < 9 || channel > 10) { - if (type == MIDI.EventType.NOTE_ON) { - // The shift allows storing two intergers in one. - // This way we can store both key and velocity in one int. - // It is reteived in `resend_key ()` function - channel_note_on[channel] = key | (velocity << 16); - } else if (type == MIDI.EventType.NOTE_OFF) { - channel_note_on[channel] = -1; - } - } - - // Modify tonal channels with chord - if (channel != 9 && channel != 10 && - (type == MIDI.EventType.NOTE_ON || type == MIDI.EventType.NOTE_OFF)) { - new_event.set_key (StyleMIDIModifers.modify_key_by_chord (key, chord, - style.scale_type, alt_channels_active)); - } - else { - new_event.set_key (key); - } - - // Send data to synth - Application.event_bus.style_midi_event (new_event); - - return Fluid.OK; - } - - private void resend_key (int value, int channel) { - var new_event = new Fluid.MIDIEvent (); - new_event.set_channel (channel); - new_event.set_type (MIDI.EventType.NOTE_ON); - // Decode key and velocity from the integer value - new_event.set_key (StyleMIDIModifers.modify_key_by_chord (value & 0xFFFF, - chord, style.scale_type, alt_channels_active)); - new_event.set_velocity ((value >> 16) & 0xFFFF); - - Application.event_bus.style_midi_event (new_event); - } - - /** - * Starts style playback if not already playing. - */ - public void play () { - if (style_player.get_status () != Fluid.PlayerStatus.PLAYING) { - next_part = current_part; - Application.event_bus.synth_sounds_off (); - style_player.seek (part_bounds_map.get (current_part).start); - style_player.play (); - } - } - - /** - * Stops the style playback if already playing. - */ - public void stop () { - if (style_player.get_status () == Fluid.PlayerStatus.PLAYING) { - style_player.stop (); - halt_continuous_notes (); - Application.event_bus.beat_reset (); - } - } - - /** - * Plays the style if not already playing - * or stops the style if playing. - */ - public void toggle_play () { - if (style_player.get_status () != Fluid.PlayerStatus.PLAYING) { - play (); - } else { - stop (); - } - - sync_start = false; - sync_stop = false; - Application.event_bus.style_sync_changed (false); - } - - /** - * Change the style variation level or trigger a fill-in. - * - * @param part The style part to queue - */ - public void queue_next_part (StylePartType part) { - // Wait for measure end if already playing else instantly change part - if (style_player.get_status () == Fluid.PlayerStatus.PLAYING) { - if (part != StylePartType.INTRO_1 && - part != StylePartType.INTRO_2 && - part != StylePartType.INTRO_3 && - part != StylePartType.ENDING_1 && - part != StylePartType.ENDING_2 && - part != StylePartType.ENDING_3 && - current_part != StylePartType.INTRO_1 && - current_part != StylePartType.INTRO_2 && - current_part != StylePartType.INTRO_3 && - current_part != StylePartType.ENDING_1 && - current_part != StylePartType.ENDING_2 && - current_part != StylePartType.ENDING_3) { - if (next_part == part || Ensembles.settings.autofill) { - queue_fill = true; - } - } - - if (next_part != part) { - next_part = part; - } else if ( - current_part == StylePartType.INTRO_1 || - current_part == StylePartType.INTRO_2 || - current_part == StylePartType.INTRO_3 || - current_part == StylePartType.ENDING_1 || - current_part == StylePartType.ENDING_2 || - current_part == StylePartType.ENDING_3 - ) { - next_part = part; - force_change_part = true; - } - } else { - current_part = part; - if (part == StylePartType.VARIATION_A || - part == StylePartType.VARIATION_B || - part == StylePartType.VARIATION_C || - part == StylePartType.VARIATION_D) { - next_part = part; - current_variation = part; - } - } - - queue_break = false; - } - - /** - * Inserts a minimum voice section during playback. It could be a short - * build-up or a drop. - */ - public void break_play () { - if (style_player.get_status () == Fluid.PlayerStatus.PLAYING) { - queue_break = true; - Application.event_bus.style_break_changed (true); - } - } - - /** - * Start the style playback with chord input or stop the style - * playback on the next measure. - */ - public void sync () { - if (style_player.get_status () == Fluid.PlayerStatus.PLAYING) { - sync_start = false; - sync_stop = !sync_stop; - } else { - sync_start = !sync_start; - sync_stop = false; - } - - Application.event_bus.style_sync_changed (sync_start || sync_stop); - } - - /** - * Ask the style player to stop and wait. - * - * **Note:** This is a blocking call, meaning the function will wait until the - * style player is done playing the current measure. - * - * @param current_tempo Variable to store the current tempo - */ - public bool stop_and_wait (out uint8 current_tempo) { - current_tempo = 0; - if (style_player.get_status () == Fluid.PlayerStatus.PLAYING) { - sync_stop = true; - current_tempo = (uint8) style_player.get_bpm (); - style_player.join (); - Application.event_bus.style_sync_changed (false); - return true; - } - - return false; - } - - /** - * Change the chord of the style. - * - * This will stop all voices that are playing the current chord - * and restart them selectively with the new chord. - * - * @param chord The chord to change to - */ - public void change_chord (Chord chord) { - if (chord.root != ChordRoot.NONE) { - queue_chord_change = true; - } - - if (sync_start) { - sync_start = false; - Application.event_bus.style_sync_changed (false); - play (); - } - } - } -} diff --git a/src/Core/Plugins/AudioPlugins/AudioPlugin.vala b/src/Core/Plugins/AudioPlugins/AudioPlugin.vala deleted file mode 100644 index dba6fed1..00000000 --- a/src/Core/Plugins/AudioPlugins/AudioPlugin.vala +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Core.Plugins.AudioPlugins { - /** - * The base audio plugin type. - * - * An audio plugin can be used for DSP or as voices, expanding - * the standard set of sampled voices that Ensembles come with. - */ - public abstract class AudioPlugin : Plugin { - public enum Category { - DSP, - VOICE, - UNSUPPORTED - } - - public enum Protocol { - NATIVE, - LADSPA, - LV2, - CARLA - } - - // Plugin Information - /** - * The technology this plugin is based on - */ - public Protocol protocol { get; protected set; } - public Category category { get; protected set; } - - public bool stereo_source { get; protected set; } - public bool stereo_sink { get; protected set; } - - protected float _mix_gain = 1; - public float mix_gain { - get { - return _mix_gain; - } - set { - _mix_gain = value; - } - } - - protected Port[] audio_in_ports; - protected Port[] audio_out_ports; - - /** - * Whether the audio plugin can process stereo audio. - */ - public bool stereo { get; protected set; } - - protected AudioPlugin () { - base (); - } - - public abstract void connect_source_buffer (void* in_l, void* in_r); - - public abstract void connect_sink_buffer (void* out_l, void* out_r); - - public abstract int send_midi_event (Fluid.MIDIEvent midi_event); - - /** - * Connect a port to local variable. Connect all ports before activating - * plugin - */ - public abstract void connect_port (Port port, void* data_pointer); - - /** - * Running this function will fill the sink buffers with processed audio - * as per the functionality defined in this function - */ - public abstract void process (uint32 sample_count); - - public abstract AudioPlugin duplicate () throws PluginError; - } -} diff --git a/src/Core/Plugins/AudioPlugins/Lv2/LV2EvBuf.vala b/src/Core/Plugins/AudioPlugins/Lv2/LV2EvBuf.vala deleted file mode 100644 index c5bb5113..00000000 --- a/src/Core/Plugins/AudioPlugins/Lv2/LV2EvBuf.vala +++ /dev/null @@ -1,253 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ -/* - * This file incorporates work covered by the following copyright and - * permission notices: - * - * --- - * - Copyright 2008-2016 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * --- - */ - -// This is a vala gobject port of LV2 evbuf.c code written by David Robillard. - -using LV2; -using LV2.URID; - -namespace Ensembles.Core.Plugins.AudioPlugins.Lv2 { - public class LV2EvBuf : Object { - public uint32 capacity { get; protected set; } - private Urid atom_chunk; - private Urid atom_sequence; - // Unlike the original implementation, it was not possible to allocate - // the EvBuf struct with a custom capacity in Vala. So using a pointer - // to dynamically allocate just the buffer instead. - private Atom.Sequence* buf; - - /** - * Size of the atom event sequence - */ - public uint32 size { - get { - if (buf.atom.type != atom_sequence) { - return 0; - } - - return buf.atom.size - (uint32) sizeof (Atom.SequenceBody); - } - } - - /** - * Creates a new event buffer instance. - * - * @param capacity maximum capacity of event buffer - * @param atom_chunk URID of an atom chunk - * @param atom_sequence URID of an atom sequence - */ - public LV2EvBuf (uint32 capacity, Urid atom_chunk, Urid atom_sequence) { - return_if_fail (capacity > 0); - - Object ( - capacity: capacity - ); - - this.atom_chunk = atom_chunk; - this.atom_sequence = atom_sequence; - buf = (Atom.Sequence*) Aligned.alloc0 (sizeof (Atom.Sequence) + capacity, 1, 64); - - reset (true); - } - - /** - * "Clears" the event buffer by resetting it's size. - * - * @param input whether the buffer is associated with an input port - */ - public void reset (bool input) { - if (input) { - buf.atom.size = (uint32) sizeof (Atom.SequenceBody); - buf.atom.type = (uint32) atom_sequence; - } else { - buf.atom.size = (uint32) capacity; - buf.atom.type = (uint32) atom_chunk; - } - } - - /** - * Returns a pointer to the event sequence. - */ - public Atom.Sequence* get_buffer () { - return buf; - } - - /** - * Returns an iterator which can be used to iterate through - * the event sequence from the beginning. - */ - public Iter begin () { - return Iter () { - evbuf = this, - offset = 0 - }; - } - - /** - * Returns an iterator which can be used to iterate through - * the event sequence from the end. - */ - public Iter end () { - return Iter () { - evbuf = this, - offset = pad_size (this.size) - }; - } - - /** - * Iterator which allows iterating through the event sequence. - */ - public struct Iter { - /** - * The event buffer which this iterator is associated with. - */ - unowned LV2EvBuf evbuf; - /** - * Current position of the iterator. - */ - uint32 offset; - - /** - * If the iterator position is within the buffer size. - */ - public bool is_valid () { - return offset < evbuf.size; - } - - /** - * Get the iterator to the next event in the sequence. - */ - public Iter next () { - if (!is_valid ()) { - return this; - } - - Atom.Event* aev = atom_sequence_contents (evbuf.buf, offset); - - return Iter () { - evbuf = evbuf, - offset = offset + pad_size ( - (uint32) sizeof (Atom.Event) + aev->body.size - ) - }; - } - - /** - * Retrieve event data from the current iterator position in the - * sequence. - * - * @param frames MIDI clock times when the event is to be activated - * @param subframes MIDI clock time subdivisions - * @param size length of the event sequence - * @param data pointer to the event sequence data - */ - public bool get ( - out uint32 frames, - out uint32 subframes, - out uint32 type, - out uint32 size, - out uint8* data - ) { - frames = subframes = type = size = 0; - data = null; - - if (!is_valid ()) { - return false; - } - - Atom.Event* aev = atom_sequence_contents (evbuf.buf, offset); - - frames = (uint32) aev->time_frames; - subframes = 0; - type = aev->body.type; - size = aev->body.size; - data = atom_body (&aev->body); - return true; - } - - /** - * Wrties event data in the current iterator position in the - * sequence. - * - * @param frames MIDI clock times when the event is to be activated - * @param subframes MIDI clock time subdivisions - * @param size length of the event sequence - * @param data pointer to the event sequence data - */ - public bool write ( - uint32 frames, - uint32 subframes, - uint32 type, - uint32 size, - uint8* data - ) { - if ( - (evbuf.capacity - sizeof (Atom.Atom) - evbuf.buf.atom.size) - < (sizeof (Atom.Event) + size) - ) { - return false; - } - - Atom.Event* aev = atom_sequence_contents (evbuf.buf, offset); - aev->time_frames = frames; - aev->body.type = type; - aev->body.size = size; - - // print("writing: %ld\n", (long) aev.time_frames); - - Memory.copy (atom_body (&aev->body), data, size); - - var _size = pad_size ((uint32) sizeof (Atom.Event) + size); - evbuf.buf.atom.size += _size; - offset += _size; - - return true; - } - } - - /** - * Round up the value of "size" to the nearest multiple of 8. - */ - public static uint32 pad_size (uint32 size) { - return (size + 7) & (~7); - } - - /** - * Extract the contents of an atom sequene. - */ - public static Atom.Event* atom_sequence_contents (Atom.Sequence* atom, uint32 offset) { - return (Atom.Event*) (((uint8*) atom) + sizeof (Atom.Sequence) + offset); - } - - /** - * Extract the body of an atom. - */ - public static void* atom_body (Atom.Atom* atom) { - return (void*) (((uint8*) atom) + sizeof (Atom.Atom)); - } - } -} diff --git a/src/Core/Plugins/AudioPlugins/Lv2/LV2Manager.vala b/src/Core/Plugins/AudioPlugins/Lv2/LV2Manager.vala deleted file mode 100644 index 7a32f5af..00000000 --- a/src/Core/Plugins/AudioPlugins/Lv2/LV2Manager.vala +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ -/* - * This file incorporates work covered by the following copyright and - * permission notices: - * - * --- - * - Copyright 2007-2022 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * --- - */ - -namespace Ensembles.Core.Plugins.AudioPlugins.Lv2 { - /** - * The LV2 Manager object manages LV2 Plugins. - */ - public class LV2Manager : Object { - internal static Lilv.World world = new Lilv.World (); - - internal static SyMap symap = new SyMap (); - internal static Mutex symap_lock = Mutex (); - - internal static HashTable node_map = - new HashTable ( - str_hash, - (k1, k2) => { - return k1 == k2; - } - ); - - public void load_plugins (PluginManager plugin_manager) { - assert (world != null); - - Console.log ("Loading LV2 Plugins…"); - world.load_all (); - - var plugins = world.get_all_plugins (); - - for (var iter = plugins.begin (); !plugins.is_end (iter); iter = plugins.next (iter)) { - var lilv_plugin = plugins.get (iter); - - if (lilv_plugin != null) { - try { - var plugin = new LV2Plugin (lilv_plugin, this); - plugin_manager.audio_plugins.append (plugin); - - Application.event_bus.send_initial_status (_("Loading LV2 plugin: ") + plugin.name + "…"); - } catch (PluginError e) { - Console.log ( - "Skipped LV2 plugin: " + - lilv_plugin.get_uri ().as_uri (), - Console.LogLevel.WARNING - ); - } - - Thread.usleep (20000); - } - } - - Console.log ( - "LV2 Plugins Loaded Successfully!", - Console.LogLevel.SUCCESS - ); - } - - // LV2 Feature Implementations - - // URI -> Lilv Node Mapping - internal static unowned Lilv.Node get_node_by_uri (string uri) { - if (node_map.contains (uri)) { - return node_map.get (uri); - } - - return add_node_uri (uri); - } - - internal static unowned Lilv.Node add_node_uri (string uri) { - node_map.insert (uri, new Lilv.Node.uri (world, uri)); - return node_map.get (uri); - } - - // LV2 URID - public LV2.URID.Urid map_uri (string uri) { - Lv2.LV2Manager.symap_lock.lock (); - LV2.URID.Urid urid = Lv2.LV2Manager.symap.map (uri); - Lv2.LV2Manager.symap_lock.unlock (); - return urid; - } - - public string unmap_uri (LV2.URID.Urid urid) { - Lv2.LV2Manager.symap_lock.lock (); - string uri = Lv2.LV2Manager.symap.unmap ((uint32)urid); - Lv2.LV2Manager.symap_lock.unlock (); - return uri; - } - - } -} diff --git a/src/Core/Plugins/AudioPlugins/Lv2/LV2Plugin.vala b/src/Core/Plugins/AudioPlugins/Lv2/LV2Plugin.vala deleted file mode 100644 index f4734780..00000000 --- a/src/Core/Plugins/AudioPlugins/Lv2/LV2Plugin.vala +++ /dev/null @@ -1,525 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ -/* - * This file incorporates work covered by the following copyright and - * permission notices: - * - * --- - * - Copyright 2007-2016 David Robillard - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --- - * Copyright (C) 2008-2012 Carl Hetherington - * Copyright (C) 2008-2017 Paul Davis - * Copyright (C) 2008-2019 David Robillard - * Copyright (C) 2012-2019 Robin Gareus - * Copyright (C) 2013-2018 John Emmas - * Copyright (C) 2013 Michael R. Fisher - * Copyright (C) 2014-2016 Tim Mayberry - * Copyright (C) 2016-2017 Damien Zammit - * Copyright (C) 2016 Nick Mainsbridge - * Copyright (C) 2017 Johannes Mueller - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * --- - */ - -namespace Ensembles.Core.Plugins.AudioPlugins.Lv2 { - /** - * An LV2 Plugin that can be used for DSP or as voices, expanding - * the standard set of sampled voices that Ensembles come with. - * - * LV2 is an extensible open standard for audio plugins. - * LV2 has a simple core interface, which is accompanied by extensions - * that add more advanced functionality. - */ - public class LV2Plugin : Plugins.AudioPlugins.AudioPlugin { - public string plugin_uri { get; private set; } - public string plugin_class { get; private set; } - - // LV2 Features //////////////////////////////////////////////////////// - private LV2.Feature*[] features; - private const string[] SUPPORTED_FEATURE_URIS = { - LV2.URID._map, - LV2.URID._unmap - // LV2.Worker._schedule - }; - - LV2.Feature urid_map_feature; - LV2.Feature urid_unmap_feature; - // LV2.Feature scheduler_feature; - // LV2.Feature options_feature; - - // Feature Maps - LV2.URID.UridMap urid_map; - LV2.URID.UridUnmap urid_unmap; - // LV2.Worker.Schedule schedule; - - // Plugin Worker Thread - LV2Worker worker; - Zix.Sem plugin_sem_lock; - - // Plugin Instances //////////////////////////////////////////////////// - private Lilv.Instance lv2_instance_l; // Stereo audio / Mono L Processor - private Lilv.Instance lv2_instance_r; // Mono R Processor - - // Ports /////////////////////////////////////////////////////////////// - // Control ports - public LV2ControlPort[] control_in_ports; - public float[] control_in_variables; - - // Atom ports - // MIDI - public LV2AtomPort[] atom_midi_in_ports; - public Fluid.MIDIEvent[] midi_event_buffer; - public LV2EvBuf[] atom_midi_in_variables; - public uint8 midi_input_event_count; - - public unowned Lilv.Plugin? lilv_plugin { get; protected set; } - public unowned LV2Manager? lv2_manager { get; protected set; } - - public LV2Plugin (Lilv.Plugin? lilv_plugin, LV2Manager? manager) throws PluginError { - Object ( - lilv_plugin: lilv_plugin, - lv2_manager: manager - ); - - if (!features_are_supported ()) { - throw new PluginError.UNSUPPORTED_FEATURE ("Feature not supported"); - } - - name = lilv_plugin.get_name ().as_string (); - plugin_uri = lilv_plugin.get_uri ().as_uri (); - plugin_class = lilv_plugin.get_class ().get_label ().as_string (); - author_name = lilv_plugin.get_author_name ().as_string (); - author_email = lilv_plugin.get_author_email ().as_string (); - author_homepage = lilv_plugin.get_author_homepage ().as_string (); - - protocol = Protocol.LV2; - - // Get all ports from plugin - category = get_category (); - } - - private Category get_category () { - var port_analyser = new LV2PortAnalyser (lilv_plugin); - if ( // Check if it is DSP (effect) plugin - ( - plugin_class.contains ("Amplifier") || - plugin_class.contains ("Utility") || - plugin_class.contains ("Reverb") - ) && ( - port_analyser.audio_in_port_list.length () > 0 && - port_analyser.audio_out_port_list.length () > 0 - ) - ) { - return Category.DSP; - } else if ( // Check if it is Voice (instrument) plugin - plugin_class == "Instrument Plugin" || - ( - port_analyser.n_atom_midi_in_ports > 0 && - port_analyser.audio_in_port_list.length () > 0 && - port_analyser.audio_out_port_list.length () > 0 - ) - ) { - return Category.VOICE; - } - - return Category.UNSUPPORTED; - } - - /** - * Creates a workable instance of the lv2 plugin. - * Instantiate must be called on this object before connecting any ports - * or running the plugin. - */ - public override void instantiate () { - if (lv2_instance_l == null) { - Console.log("Instantiating LV2 Plugin %s, with URI: %s".printf(name, plugin_uri)); - active = false; - setup_workers (); - create_features (); - - lv2_instance_l = lilv_plugin.instantiate (AudioEngine.Synthesizer.sample_rate, features); - // Check if plugin is mono - if (!stereo) { - lv2_instance_r = lilv_plugin.instantiate (AudioEngine.Synthesizer.sample_rate, features); - } - - create_ports (); - allocate_control_ports (); - allocate_midi_port_buffers (); - build_ui (); - } - } - - private void allocate_control_ports () { - control_in_variables = new float[control_in_ports.length]; - for (uint32 i = 0; i < control_in_ports.length; i++) { - control_in_variables[i] = control_in_ports[i].default_value; - connect_port (control_in_ports[i], &control_in_variables[i]); - } - } - - private void allocate_midi_port_buffers () { - atom_midi_in_variables = new LV2EvBuf [atom_midi_in_ports.length]; - - for (uint8 i = 0; i < atom_midi_in_ports.length; i++) { - atom_midi_in_variables[i] = new LV2EvBuf ( - AudioEngine.Synthesizer.get_buffer_size (), - lv2_manager.map_uri (LV2.Atom._Chunk), - lv2_manager.map_uri (LV2.Atom._Sequence) - ); - - atom_midi_in_variables[i].reset (true); - - connect_port (atom_midi_in_ports[i], atom_midi_in_variables[i].get_buffer ()); - } - } - - public override AudioPlugin duplicate () throws PluginError { - return new LV2Plugin (lilv_plugin, lv2_manager); - } - - protected override void activate () { - if (lv2_instance_l != null) { - lv2_instance_l.activate (); - } - - if (lv2_instance_r != null) { - lv2_instance_r.activate (); - } - } - - protected override void deactivate () { - if (lv2_instance_l != null) { - lv2_instance_l.deactivate (); - } - - if (lv2_instance_r != null) { - lv2_instance_r.deactivate (); - } - } - - public override void connect_source_buffer (void* in_l, void* in_r) { - if (stereo) { - // Stereo plugin - for (uint8 i = 0; i < audio_in_ports.length; i++) { - if ((i & 1) == 0) { // If even - if (lv2_instance_l != null) { - lv2_instance_l.connect_port ( - audio_in_ports[i].index, - in_l - ); - } - } else { - if (lv2_instance_l != null) { - lv2_instance_l.connect_port ( - audio_in_ports[i].index, - in_r - ); - } - } - } - } else { - lv2_instance_l.connect_port ( - audio_in_ports[0].index, - in_l - ); - - lv2_instance_r.connect_port ( - audio_in_ports[0].index, - in_r - ); - } - } - - public override void connect_sink_buffer (void* out_l, void* out_r) { - if (stereo) { - for (uint8 i = 0; i < audio_out_ports.length; i++) { - if ((i & 1) == 0) { // If even - if (lv2_instance_l != null) { - lv2_instance_l.connect_port ( - audio_out_ports[i].index, - out_l - ); - } - } else { - if (lv2_instance_l != null) { - lv2_instance_l.connect_port ( - audio_out_ports[i].index, - out_r - ); - } - } - } - } else { - lv2_instance_l.connect_port ( - audio_out_ports[0].index, - out_l - ); - - lv2_instance_r.connect_port ( - audio_out_ports[0].index, - out_r - ); - } - } - - public override void connect_port (Port port, void* data_pointer) { - if (lv2_instance_l != null) { - lv2_instance_l.connect_port (port.index, data_pointer); - } - - if (lv2_instance_r != null) { - lv2_instance_r.connect_port (port.index, data_pointer); - } - } - - public override int send_midi_event (Fluid.MIDIEvent midi_event) { - if (active) { - // print ("midi, %d\n", midi_event.get_key ()); - if (midi_event_buffer == null) { - midi_event_buffer = new Fluid.MIDIEvent [AudioEngine.Synthesizer.get_buffer_size ()]; - } - - midi_event_buffer[midi_input_event_count] = new Fluid.MIDIEvent (); - midi_event_buffer[midi_input_event_count].set_type (midi_event.get_type ()); - midi_event_buffer[midi_input_event_count].set_key (midi_event.get_key ()); - midi_event_buffer[midi_input_event_count++].set_velocity (midi_event.get_velocity ()); - - return Fluid.OK; - } - - return Fluid.FAILED; - } - - private void fill_event_buffers () { - for (uint16 p = 0; p < atom_midi_in_ports.length; p++) { - // unowned LV2AtomPort port = atom_midi_in_ports[p]; - unowned LV2EvBuf evbuf = atom_midi_in_variables[p]; - evbuf.reset (true); - var iter = evbuf.begin (); - - // print ("midi buffer size %d\n", midi_event_buffer.length); - - for (uint8 i = 0; i < midi_input_event_count; i++) { - unowned Fluid.MIDIEvent midi_event = midi_event_buffer[i]; - var buffer = new uint8[3]; - buffer[0] = (uint8) midi_event.get_type (); - buffer[1] = (uint8) midi_event.get_key (); - buffer[2] = (uint8) midi_event.get_velocity (); - iter.write ( - (uint32) ( - new DateTime.now_utc ().to_unix () - AudioEngine.Synthesizer.get_process_start_time () - ), - 0, - (uint32) lv2_manager.map_uri (LV2.MIDI._MidiEvent), - 3, - buffer - ); - } - } - - midi_input_event_count = 0; - } - - public override void process (uint32 sample_count) { - fill_event_buffers (); - - if (lv2_instance_l != null) { - lv2_instance_l.run (sample_count); - } - - if (lv2_instance_r != null) { - lv2_instance_r.run (sample_count); - } - } - - private void setup_workers () { - Zix.Sem.init (out plugin_sem_lock, 1); - worker = new LV2Worker (plugin_sem_lock, true); - worker.handle = (LV2.Handle) this; - } - - /** - * Create plugin features - */ - private void create_features () { - urid_map = LV2.URID.UridMap (); - urid_map.map = lv2_manager.map_uri; - - urid_unmap = LV2.URID.UridUnmap (); - urid_unmap.unmap = lv2_manager.unmap_uri; - - // schedule = LV2.Worker.Schedule (); - // schedule.schedule_work = worker.schedule; - - features = new LV2.Feature* [2]; - urid_map_feature = register_feature (LV2.URID._map, &urid_map); - urid_unmap_feature = register_feature (LV2.URID._unmap, &urid_unmap); - // scheduler_feature = register_feature (LV2.Worker._schedule, &schedule); - - features[0] = &urid_map_feature; - features[1] = &urid_unmap_feature; - // features[2] = &scheduler_feature; - } - - private bool features_are_supported () { - var lilv_features = lilv_plugin.get_required_features (); - for (var iter = lilv_features.begin (); !lilv_features.is_end (iter); - iter = lilv_features.next (iter)) { - string required_feature = lilv_features.get (iter).as_uri (); - print ("checking: %s\n", required_feature); - if (!feature_supported (required_feature)) { - return false; - } - } - - return true; - } - - private bool feature_supported (string feature) { - for (uint8 i = 0; i < SUPPORTED_FEATURE_URIS.length; i++) { - if (feature == SUPPORTED_FEATURE_URIS[i]) { - return true; - } - } - - return false; - } - - private LV2.Feature register_feature (string uri, void* data) { - return LV2.Feature () { - URI = uri, - data = data - }; - } - - private void create_ports () { - var port_analyser = new LV2PortAnalyser (lilv_plugin); - - var n_audio_in_ports = port_analyser.audio_in_port_list.length (); - audio_in_ports = new Port[n_audio_in_ports]; - - // If there's more than one audio in port then presume that - // the plugin is stereo - stereo = n_audio_in_ports > 1; - for (uint32 p = 0; p < n_audio_in_ports; p++) { - unowned LV2Port _port = - port_analyser.audio_in_port_list.nth_data (p); - audio_in_ports[p] = new LV2Port ( - _port.name, - _port.index, - _port.properties, - _port.symbol, - _port.turtle_token - ); - } - - var n_audio_out_ports = port_analyser.audio_out_port_list.length (); - audio_out_ports = new Port[n_audio_out_ports]; - for (uint32 p = 0; p < n_audio_out_ports; p++) { - unowned LV2Port _port = - port_analyser.audio_out_port_list.nth_data (p); - audio_out_ports[p] = new LV2Port ( - _port.name, - _port.index, - _port.properties, - _port.symbol, - _port.turtle_token - ); - } - - var n_control_in_ports = port_analyser.control_in_port_list.length (); - control_in_ports = new LV2ControlPort[n_control_in_ports]; - for (uint32 p = 0; p < n_control_in_ports; p++) { - unowned LV2ControlPort _port = - port_analyser.control_in_port_list.nth_data (p); - control_in_ports[p] = new LV2ControlPort ( - _port.name, - _port.index, - _port.properties, - _port.symbol, - _port.turtle_token, - _port.min_value, - _port.max_value, - _port.default_value, - _port.step - ); - } - - var n_atom_in_ports = port_analyser.atom_in_port_list.length (); - // MIDI Ports - atom_midi_in_ports = new LV2AtomPort[port_analyser.n_atom_midi_in_ports]; - - for (uint32 p = 0, i = 0; p < n_atom_in_ports; p++) { - unowned LV2AtomPort _port = - port_analyser.atom_in_port_list.nth_data (p); - if ((_port.flags & LV2AtomPort.Flags.SUPPORTS_MIDI_EVENT) > LV2AtomPort.Flags.NONE) { - atom_midi_in_ports[i++] = new LV2AtomPort ( - _port.name, - _port.index, - _port.properties, - _port.symbol, - _port.turtle_token, - _port.flags - ); - } - } - } - - private void build_ui () { - var box = new Gtk.Box ( - Gtk.Orientation.HORIZONTAL, - 8 - ) { - spacing = 4, - valign = Gtk.Align.CENTER, - homogeneous = control_in_ports.length < 4 - }; - - bool is_ui_required = false; - - if (control_in_ports.length > 0) { - for (uint i = 0; i < control_in_ports.length; i++) { - var plugin_control = new Shell.Plugins.AudioPlugins.Widgets.AudioPluginControl ( - control_in_ports[i], - & (control_in_variables[i]), - control_in_ports.length > 3 ? Gtk.IconSize.NORMAL : Gtk.IconSize.LARGE - ); - box.append (plugin_control); - } - - is_ui_required = true; - } - - if (is_ui_required) { - ui = box; - } - } - } -} diff --git a/src/Core/Plugins/AudioPlugins/Lv2/LV2PortAnalyser.vala b/src/Core/Plugins/AudioPlugins/Lv2/LV2PortAnalyser.vala deleted file mode 100644 index e288fe5c..00000000 --- a/src/Core/Plugins/AudioPlugins/Lv2/LV2PortAnalyser.vala +++ /dev/null @@ -1,279 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ -/* - * This file incorporates work covered by the following copyright and - * permission notices: - * - * --- - * - Copyright 2007-2016 David Robillard - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - --- - * Copyright (C) 2008-2012 Carl Hetherington - * Copyright (C) 2008-2017 Paul Davis - * Copyright (C) 2008-2019 David Robillard - * Copyright (C) 2012-2019 Robin Gareus - * Copyright (C) 2013-2018 John Emmas - * Copyright (C) 2013 Michael R. Fisher - * Copyright (C) 2014-2016 Tim Mayberry - * Copyright (C) 2016-2017 Damien Zammit - * Copyright (C) 2016 Nick Mainsbridge - * Copyright (C) 2017 Johannes Mueller - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - * - * --- - */ - -namespace Ensembles.Core.Plugins.AudioPlugins.Lv2 { - /** - * The LV2PortAnalyser object is used to analyse LV2 ports - * and provide port descriptors which the plugin object can the use to - * create the ports. - */ - public class LV2PortAnalyser : Object { - /** - * The Lilv Plugin whose ports are being described. - */ - unowned Lilv.Plugin lilv_plugin { get; protected set; } - - /** - * These ports represents a buffer for storing dry audio. - */ - public List audio_in_port_list; - /** - * These ports represents a buffer for storing wet audio. - */ - public List audio_out_port_list; - /** - * These ports represents basic control input ports. - */ - public List control_in_port_list; - /** - * These ports represents basic control output ports. - */ - public List control_out_port_list; - /** - * These ports represents atom input ports. - */ - public List atom_in_port_list; - /** - * These ports represents atom output ports. - */ - public List atom_out_port_list; - - // Atom ports classifications - public uint16 n_atom_midi_in_ports { get; private set; } - public uint16 n_atom_midi_out_ports { get; private set; } - - /** - * Creates a new `LV2PortAnalyser` instance. - * - * @param lilv_plugin the lilv plugin object whose ports to describe - */ - public LV2PortAnalyser (Lilv.Plugin lilv_plugin) { - this.lilv_plugin = lilv_plugin; - fetch_ports (); - } - - private void fetch_ports () { - audio_in_port_list = new List (); - audio_out_port_list = new List (); - control_in_port_list = new List (); - atom_in_port_list = new List (); - atom_out_port_list = new List (); - - var n_ports = lilv_plugin.get_num_ports (); - for (uint32 i = 0; i < n_ports; i++) { - // Get port from plugin - unowned Lilv.Port port = lilv_plugin.get_port_by_index (i); - - var name = lilv_plugin.port_get_name (port).as_string (); - print ("port: " + name + "\n"); - var symbol = lilv_plugin.port_get_symbol (port).as_string (); - var turtle_token = lilv_plugin.port_get_symbol (port).get_turtle_token (); - var properties = get_port_properties (port); - - // Plugin class flags - bool is_audio_port = false; - bool is_input_port = false; - bool is_output_port = false; - bool is_control_port = false; - bool is_atom_port = false; - - // Get all classes associated with this port - unowned Lilv.Nodes port_classes = lilv_plugin.port_get_classes (port); - - for (var class_iter = port_classes.begin (); - !port_classes.is_end (class_iter); - class_iter = port_classes.next (class_iter)) { - switch (port_classes.get (class_iter).as_string ()) { - case LV2.Core._AudioPort: - is_audio_port = true; - break; - case LV2.Core._ControlPort: - is_control_port = true; - break; - case LV2.Atom._AtomPort: - is_atom_port = true; - break; - case LV2.Core._InputPort: - is_input_port = true; - break; - case LV2.Core._OutputPort: - is_output_port = true; - break; - } - } - - if (is_audio_port) { - if (is_input_port) { - audio_in_port_list.append (new LV2Port ( - name, - i, - properties, - symbol, - turtle_token - )); - } else if (is_output_port) { - audio_out_port_list.append (new LV2Port ( - name, - i, - properties, - symbol, - turtle_token - )); - } - } else if (is_control_port) { - Lilv.Node default_value; - Lilv.Node min_value; - Lilv.Node max_value; - - lilv_plugin.port_get_range (port, out default_value, out min_value, out max_value); - - if (is_input_port) { - control_in_port_list.append (new LV2ControlPort ( - name, - i, - properties, - symbol, - turtle_token, - min_value.as_float (), - max_value.as_float (), - default_value.as_float (), - 0.1f - )); - } - } else if (is_atom_port) { - var flags = LV2AtomPort.Flags.NONE; - Lilv.Nodes buffer_types = lilv_plugin.port_get_value ( - port, - LV2Manager.get_node_by_uri (LV2.Atom._bufferType) - ); - - Lilv.Nodes atom_supports = lilv_plugin.port_get_value ( - port, - LV2Manager.get_node_by_uri (LV2.Atom._supports) - ); - - if ( - buffer_types.contains ( - LV2Manager.get_node_by_uri (LV2.Atom._Sequence) - ) - ) { - flags |= LV2AtomPort.Flags.SEQUENCE; - - if (atom_supports.contains ( - LV2Manager.get_node_by_uri (LV2.MIDI._MidiEvent) - )) { - flags |= LV2AtomPort.Flags.SUPPORTS_MIDI_EVENT; - } - } - - if (is_input_port) { - atom_in_port_list.append ( - new LV2AtomPort ( - name, - i, - properties, - symbol, - turtle_token, - flags - ) - ); - - if ( - (flags & LV2AtomPort.Flags.SUPPORTS_MIDI_EVENT) > - LV2AtomPort.Flags.NONE - ) { - n_atom_midi_in_ports++; - } - } else if (is_output_port) { - atom_out_port_list.append ( - new LV2AtomPort ( - name, - i, - properties, - symbol, - turtle_token, - flags - ) - ); - - if ( - (flags & LV2AtomPort.Flags.SUPPORTS_MIDI_EVENT) > - LV2AtomPort.Flags.NONE - ) { - n_atom_midi_out_ports++; - } - } - } - } - } - - - private string[] get_port_properties (Lilv.Port port) { - var prop_list = new List (); - - var properties = lilv_plugin.port_get_properties (port); - - for (var props_iter = properties.begin (); - !properties.is_end (props_iter); - props_iter = properties.next (props_iter)) { - var prop = properties.get (props_iter).as_string (); - print ("port prop:" + prop + "\n"); - prop_list.append (prop); - } - - var n = prop_list.length (); - - var props = new string[n]; - for (uint32 i = 0; i < n; i++) { - props[i] = prop_list.nth_data (i) + ""; // Make owned - } - return props; - } - } -} diff --git a/src/Core/Plugins/AudioPlugins/Lv2/LV2SyMap.vala b/src/Core/Plugins/AudioPlugins/Lv2/LV2SyMap.vala deleted file mode 100644 index 201b23e2..00000000 --- a/src/Core/Plugins/AudioPlugins/Lv2/LV2SyMap.vala +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ -/* - * This file incorporates work covered by the following copyright and - * permission notices: - * - * --- - * - Copyright 2011-2022 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * --- - */ - -namespace Ensembles.Core.Plugins.AudioPlugins.Lv2 { - public class SyMap { - private List symbols; - public SyMap () { - symbols = new List (); - } - - public uint32 map (string sym) { - int index = search (sym); - - if (index < 0) { - symbols.append (sym); - return symbols.length () - 1; - } - - return (uint32) index; - } - - public string unmap (uint32 index) { - return symbols.nth_data (index); - } - - private int search (string sym) { - int index = -1; - for (int i = 0; i < symbols.length (); i++) { - if (symbols.nth_data (i) == sym) { - index = i; - } - } - - return index; - } - } -} diff --git a/src/Core/Plugins/AudioPlugins/Lv2/LV2Worker.vala b/src/Core/Plugins/AudioPlugins/Lv2/LV2Worker.vala deleted file mode 100644 index 672d9a31..00000000 --- a/src/Core/Plugins/AudioPlugins/Lv2/LV2Worker.vala +++ /dev/null @@ -1,217 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ -/* - * This file incorporates work covered by the following copyright and - * permission notices: - * - * --- - * - Copyright 2008-2016 David Robillard - - Permission to use, copy, modify, and/or distribute this software for any - purpose with or without fee is hereby granted, provided that the above - copyright notice and this permission notice appear in all copies. - - THIS SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES - WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF - MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR - ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES - WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN - ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF - OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. - * - * --- - */ - -// This is a vala gobject port of Jalv worker.c code written by David Robillard. - -using LV2; - -namespace Ensembles.Core.Plugins.AudioPlugins.Lv2 { - public class LV2Worker : Object { - private Zix.Ring requests; ///< Requests to the worker - private Zix.Ring responses; ///< Responses from the worker - private void* response; - private unowned Zix.Sem plugin_instance_lock; - private bool queue_exit; - private Zix.Sem sem; - private Zix.Thread thread; - public Handle handle; - private unowned Worker.Interface? iface; - public bool threaded { get; private set; } - - private const uint MAX_PACKET_SIZE = 4096U; - - public LV2Worker (Zix.Sem? plugin_instance_lock, bool threaded) { - this.threaded = threaded; - responses = new Zix.Ring (null, MAX_PACKET_SIZE);; - response = Posix.calloc (1, MAX_PACKET_SIZE);; - this.plugin_instance_lock = plugin_instance_lock; - queue_exit = false; - - responses.mlock (); - - if (threaded && launch () != SUCCESS) { - free (response); - } - } - - ~LV2Worker () { - exit (); - free (response); - } - - private static Worker.Status write_packet (Zix.Ring target, [CCode (type="const uint32_t")] uint32 size, [CCode (type="const void*")] void* data) { - Zix.Ring.Transaction tx = target.begin_write (); - if (target.amend_write (tx, &size, (uint32) sizeof(uint32)) != Zix.Status.SUCCESS || - target.amend_write (tx, data, size) != Zix.Status.SUCCESS) { - return Worker.Status.ERR_NO_SPACE; - } - - target.commit_write (tx); - return Worker.Status.SUCCESS; - } - - private static Worker.Status respond (Worker.RespondHandle handle, [CCode (type="const uint32_t")] uint32 size, [CCode (type="const void*")] void* data) { - return write_packet (((LV2Worker) handle).responses, size, data); - } - - public Zix.ThreadResult func () { - void* buf = null; - - while (true) { - // Wait for a request - sem.wait (); - if (queue_exit) { - break; - } - - // Read the size header of request - uint32 size = 0; - requests.read (&size, (uint32) sizeof(uint32)); - - // Reallocate buffer to allocate request if necessary - void* new_buf = realloc (buf, size); - if (new_buf != null) { - // Read request into buffer - buf = new_buf; - requests.read (buf, size); - - // Lock and dispatch request to plugin's work handler - plugin_instance_lock.wait (); - iface.work ( - handle, - respond, - (LV2.Worker.RespondHandle) this, - size, buf - ); - plugin_instance_lock.post (); - } else { - // Reallocation failed, skip request to avoid corrupting ring - requests.skip (size); - } - } - - free (buf); - return (Zix.ThreadResult) null; - } - - public Zix.Status launch () { - var st = Zix.Sem.init (out sem, 0); - - if (st != Zix.Status.SUCCESS) { - return st; - } else { - st = Zix.Thread.create (out thread, MAX_PACKET_SIZE, func); - - if (st != Zix.Status.SUCCESS) { - return st; - } - } - - var _requests = new Zix.Ring (null, MAX_PACKET_SIZE); - - if (_requests == null) { - thread.join (); - sem.destroy (); - st = Zix.Status.NO_MEM; - return st; - } - - _requests.mlock (); - requests = (owned) _requests; - return st; - } - - public void start (Worker.Interface iface, Handle handle) { - this.iface = iface; - this.handle = handle; - } - - public void exit () { - if (threaded) { - queue_exit = true; - sem.post (); - thread.join (); - threaded = false; - } - } - - public Worker.Status schedule (uint32 size, void* data) { - var st = Worker.Status.SUCCESS; - - if (size == 0) { - st = Worker.Status.ERR_UNKNOWN; - } - - if (threaded) { - // Schedule a request to be executed by the worker thread - st = write_packet (requests, size, data); - if (st == Worker.Status.SUCCESS) { - sem.post (); - } - } else { - plugin_instance_lock.wait (); - st = iface.work ( - handle, - respond, - (LV2.Worker.RespondHandle) this, - size, - data - ); - plugin_instance_lock.post (); - } - - return st; - } - - public void emit_responses (Handle lv2_handle) { - const uint32 size_size = (uint32) sizeof(uint32); - - if (responses != null) { - uint32 size = 0U; - while (responses.read (&size, size_size) == size_size) { - if (responses.read (response, size) == size) { - iface.work_response (lv2_handle, size, response); - } - } - } - } - - public void end_run () { - if (iface != null && iface.end_run != null) { - iface.end_run (handle); - } - } - } -} - -// These are required as the library Worker doesn't yet have typedefs for these function pointers in Interface -[CCode (cname = " interface_work_t", has_target = false)] -extern delegate Worker.Status InterfaceWorkFunc (Handle instance, Worker.RespondFunc respond, Worker.RespondHandle handle, uint32 size, void* data); -[CCode (cname = " interface_work_reponse_t", has_target = false)] -extern delegate Worker.Status InterfaceWorkResponseFunc (Handle instance, uint32 size, [CCode (type="const void*")] void* body); -[CCode (cname = " interface_end_run_t", has_target = false)] -extern delegate Worker.Status InterfaceEndRunFunc (Handle instance); diff --git a/src/Core/Plugins/AudioPlugins/Lv2/Ports/LV2AtomPort.vala b/src/Core/Plugins/AudioPlugins/Lv2/Ports/LV2AtomPort.vala deleted file mode 100644 index e9b222c6..00000000 --- a/src/Core/Plugins/AudioPlugins/Lv2/Ports/LV2AtomPort.vala +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Core.Plugins.AudioPlugins.Lv2 { - public class LV2AtomPort : LV2Port { - [Flags] - public enum Flags { - NONE, - SEQUENCE, - SUPPORTS_MIDI_EVENT - } - - public Flags flags { get; private set; } - - public LV2AtomPort (string name, uint32 index, owned string[] properties, - string symbol, string turtle_token = "", Flags flags) { - base (name, index, properties, symbol, turtle_token); - this.flags = flags; - } - } -} diff --git a/src/Core/Plugins/AudioPlugins/Lv2/Ports/LV2ControlPort.vala b/src/Core/Plugins/AudioPlugins/Lv2/Ports/LV2ControlPort.vala deleted file mode 100644 index c950b74f..00000000 --- a/src/Core/Plugins/AudioPlugins/Lv2/Ports/LV2ControlPort.vala +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - - namespace Ensembles.Core.Plugins.AudioPlugins.Lv2 { - public class LV2ControlPort : LV2Port { - public float default_value { get; private set; } - public float min_value { get; private set; } - public float max_value { get; private set; } - public float step { get; private set; } - - public LV2ControlPort (string name, uint32 index, owned string[] properties, - string symbol, string turtle_token = "", float min_value = 0, float max_value = 1, - float default_value = 0, float step = 0.1f) { - base (name, index, properties, symbol, turtle_token); - this.default_value = default_value; - this.min_value = min_value; - this.max_value = max_value; - this.step = step; - } - } -} diff --git a/src/Core/Plugins/AudioPlugins/Lv2/Ports/LV2Port.vala b/src/Core/Plugins/AudioPlugins/Lv2/Ports/LV2Port.vala deleted file mode 100644 index 5edc48a8..00000000 --- a/src/Core/Plugins/AudioPlugins/Lv2/Ports/LV2Port.vala +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Core.Plugins.AudioPlugins.Lv2 { - public class LV2Port : Port { - public string[] properties { get; private set; } - public string symbol { get; private set; } - public string turtle_token { get; private set; } - - public LV2Port (string name, uint32 index, owned string[] properties, - string symbol, string turtle_token = "") { - base (name, index); - this.symbol = symbol; - this.turtle_token = turtle_token; - } - } -} diff --git a/src/Core/Plugins/AudioPlugins/Port.vala b/src/Core/Plugins/AudioPlugins/Port.vala deleted file mode 100644 index 5fafee73..00000000 --- a/src/Core/Plugins/AudioPlugins/Port.vala +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Core.Plugins.AudioPlugins { - public class Port : Object { - public string name { get; private set; } - public uint32 index { get; private set; } - - public Port (string name, uint32 index) { - this.name = name; - this.index = index; - } - } -} diff --git a/src/Core/Plugins/Plugin.vala b/src/Core/Plugins/Plugin.vala deleted file mode 100644 index 4a74e7a8..00000000 --- a/src/Core/Plugins/Plugin.vala +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Core.Plugins { - /** - * The base plugin type. - * - * A plugin is used to add additional functionality - * or features to ensembles. - */ - public abstract class Plugin : Object { - /** - * Name of the plugin. - */ - public string name { get; protected set; } - /** - * Name of the author of this plugin. - */ - public string author_name { get; protected set; } - /** - * Email address of the author of this plugin. - */ - public string author_email { get; protected set; } - /** - * Homepage or the main URL of the plugin. - */ - public string author_homepage { get; protected set; } - /** - * The license associated with this plugin. - */ - public string license { get; protected set; } - - private bool _active; - - /** - * The plugin will only work if it's active. - */ - public bool active { - get { - return _active; - } - set { - _active = value; - if (value) { - activate (); - } else { - deactivate (); - } - } - } - - private Gtk.Widget _ui = null; - - /** - * Plugin's own UI which can be displayed inside the window management - * framework of Ensembles. - * - * If the plugin doesn't come with an UI then this value will be `null`. - */ - public Gtk.Widget ui { - get { - return _ui; - } - protected set { - _ui = value; - } - } - - protected Plugin () { - active = false; - instantiate (); - } - - ~Plugin () { - active = false; - } - - /** - * This function is called when the plugin is instantiated. - * This just means that the plugin data is created. A Plugin cannot be - * used without instantiation. - */ - public abstract void instantiate (); - - protected abstract void activate (); - - protected abstract void deactivate (); - } -} diff --git a/src/Core/Plugins/PluginManager.vala b/src/Core/Plugins/PluginManager.vala deleted file mode 100644 index 96d46b73..00000000 --- a/src/Core/Plugins/PluginManager.vala +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Core.Plugins { - /** - * ## Plugin Manager - * - * Plugins add additional functionality to Ensembles externally. - * - * The following types of plugins may be supported: - * - Audio Plugins - * - Style Plugins - * - Display Theme Plugins - * - Functional Plugins - */ - public class PluginManager : Object { - /** - * Audio Plugins (Voices and DSP) - */ - public List audio_plugins; - - private AudioPlugins.Lv2.LV2Manager lv2_audio_plugin_manager; - - construct { - // Load Audio Plugins ////////////////////////////////////////////// - audio_plugins = new List (); - - // Load LADSPA Plugins - - // Load LV2 Plugins - lv2_audio_plugin_manager = new AudioPlugins.Lv2.LV2Manager (); - lv2_audio_plugin_manager.load_plugins (this); - - // Load Carla Plugins - - // Load Native Plugins - } - } -} diff --git a/src/Core/Racks/DSPRack.vala b/src/Core/Racks/DSPRack.vala deleted file mode 100644 index c5df3ad9..00000000 --- a/src/Core/Racks/DSPRack.vala +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Core.Plugins.AudioPlugins; - -namespace Ensembles.Core.Racks { - /** - * ## DSP Rack - * - * This defines a rack which gets populated with DSP plugins. - * The final output of the synthesizer / voice plugin is processed by all - * the plugins in this rack. - * - * _**Note:** DSP - Digital Signal Processing_ - */ - public class DSPRack : Rack { - public DSPRack () { - Object ( - rack_type: AudioPlugin.Category.DSP - ); - } - } -} diff --git a/src/Core/Racks/Rack.vala b/src/Core/Racks/Rack.vala deleted file mode 100644 index 6581b764..00000000 --- a/src/Core/Racks/Rack.vala +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Core.Plugins.AudioPlugins; - -namespace Ensembles.Core.Racks { - /** - * Racks can be populated with plugins which are then used to - * process audio - */ - public abstract class Rack : Object { - protected List plugins; - - public bool active = true; - - public AudioPlugin.Category rack_type { get; protected set; } - - // Sound buffers - float[] aud_buf_dry_l; - float[] aud_buf_dry_r; - float[] aud_buf_mix_l; - float[] aud_buf_mix_r; - - construct { - plugins = new List (); - } - - public unowned List get_plugins () { - return plugins; - } - - /** - * Add a plugin to the end of the rack - * - * @param plugin AudioPlugin to append to the rack - */ - public void append (AudioPlugin plugin) throws PluginError { - if (plugin.category != rack_type) { - throw new PluginError.INVALID_CATEGORY ("Attempted to add plugin of different category"); - } - - plugins.append (plugin); - plugin.instantiate (); - - connect_audio_ports ((int) plugins.length () - 1); - } - - /** - * Add a plugin to the specified position - * - * @param plugin AudioPlugin to add to the rack - * @param position The position in the stack where the plugin must - * be added - */ - public void insert (AudioPlugin plugin, int position) throws PluginError { - if (plugin.category != rack_type) { - throw new PluginError.INVALID_CATEGORY ("Attempted to add plugin of different category"); - } - - plugins.insert (plugin, position); - plugin.instantiate (); - - connect_audio_ports (position); - } - - /** - * Remove a plugin from a given position on the rack - * - * @param position position in the stack from where the plugin will - * be removed - */ - public void remove (int position) { - AudioPlugin plugin = plugins.nth_data (position); - plugin.active = false; - plugins.remove (plugin); - - connect_audio_ports (); - } - - /** - * Remove a plugin from the rack - * - * @param plugin plugin to remove - */ - public void remove_data (AudioPlugin plugin) { - plugin.active = false; - plugins.remove (plugin); - - connect_audio_ports (); - } - - /** - * Activate or deactivate a plugin - * - * A plugin will not process audio if it's not active - * - * @param position The position of the plugin in the rack - * @param active Whether the plugin should be enabled or not - */ - public virtual void set_plugin_active (int position, bool active = true) { - AudioPlugin plugin = plugins.nth_data (position); - plugin.active = active; - } - - /** - * Process a given stereo audio buffer using plugins - * - * @param len Length of buffer to process - * @param buffer_in_l Audio input buffer for left channel - * @param buffer_in_r Audio input buffer for right channel - * @param buffer_out_l Audio output buffer for left channel - * @param buffer_out_r Audio output buffer for right channel - */ - public void process_audio (int len, float* buffer_in_l, float* buffer_in_r, - float** buffer_out_l, float** buffer_out_r) { - // If the main buffers aren't initialised - // initialize them - if (aud_buf_dry_l == null || aud_buf_dry_r == null || - aud_buf_mix_l == null || aud_buf_mix_r == null) { - aud_buf_dry_l = new float[len]; - aud_buf_dry_r = new float[len]; - aud_buf_mix_l = new float[len]; - aud_buf_mix_r = new float[len]; - } - - // Fill main dry buffers with audio data - for (int i = 0; i < len; i++) { - aud_buf_dry_l[i] = buffer_in_l[i]; - aud_buf_dry_r[i] = buffer_in_r[i]; - } - - // Process audio using plugins - run_plugins (len); - - // Fill out buffers using wet mix; - // Wet mix has been copied to the dry buffer; See below - for (int i = 0; i < len; i++) { - * (* buffer_out_l + i) = aud_buf_dry_l[i]; - * (* buffer_out_r + i) = aud_buf_dry_r[i]; - } - } - - protected void run_plugins (uint32 sample_count) { - if (active) { - var rack_thread = new Thread ("rack_thread", () => { - foreach (AudioPlugin plugin in plugins) { - if (plugin.active) { - // Have the plugin process the audio buffer - plugin.process (sample_count); - - // Copy wet audio to dry buffer as per mix amount - for (uint32 j = 0; j < sample_count; j++) { - aud_buf_dry_l[j] = Utils.Math.map_range_unclampedf ( - plugin.mix_gain, - 0, - 1, - aud_buf_dry_l[j], - aud_buf_mix_l[j] - ); - - aud_buf_dry_r[j] = Utils.Math.map_range_unclampedf ( - plugin.mix_gain, - 0, - 1, - aud_buf_dry_r[j], - aud_buf_mix_r[j] - ); - } - - // Next plugin ready to run - } - } - }); - - rack_thread.join (); - } - } - - protected void connect_audio_ports (int change_index = -1) { - var was_active = active; - active = false; - - foreach (AudioPlugin plugin in plugins) { - plugin.connect_source_buffer (aud_buf_dry_l, aud_buf_dry_r); - plugin.connect_sink_buffer (aud_buf_mix_l, aud_buf_mix_r); - } - - active = was_active; - Application.event_bus.rack_reconnected (this, change_index); - } - } -} diff --git a/src/Core/Racks/VoiceRack.vala b/src/Core/Racks/VoiceRack.vala deleted file mode 100644 index d61d3f14..00000000 --- a/src/Core/Racks/VoiceRack.vala +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Core.Plugins.AudioPlugins; - -namespace Ensembles.Core.Racks { - /** - * ## Voice Rack - * - * This rack supports voice / instrument plugins. - * - * Every individual voice plugin can be associated with an instance - * of DSP Rack. - */ - public class VoiceRack : Rack { - private List dsp_racks; - - /** - * Whether only a single instance of a plugin is allowed to process audio. - */ - public bool exclusive_mode { get; set; } - - public VoiceRack () { - Object ( - rack_type: AudioPlugin.Category.VOICE, - exclusive_mode: true - ); - - dsp_racks = new List (); - } - - public int send_midi_event (Fluid.MIDIEvent event) { - if (!active) { - return Fluid.FAILED; - } - - bool handled = false; - foreach (var plugin in plugins) { - if (plugin.active && plugin.send_midi_event (event) == Fluid.OK) { - handled = true; - } - } - - return handled ? Fluid.OK : Fluid.FAILED; - } - - public override void set_plugin_active (int position, bool active = true) { - base.set_plugin_active (position, active); - - if (active && exclusive_mode) { - uint n = plugins.length (); - for (uint i = 0; i < n; i++) { - if (i != position) { - plugins.nth_data (i).active = false; - } - } - } - } - } -} diff --git a/src/Core/SamplingPads/SamplePlayer.vala b/src/Core/SamplingPads/SamplePlayer.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Core/SamplingPads/SampleRecorder.vala b/src/Core/SamplingPads/SampleRecorder.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Core/StateManager/RegistryManager.vala b/src/Core/StateManager/RegistryManager.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Interfaces/MediaKeyListener.vala b/src/Interfaces/MediaKeyListener.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Interfaces/SoundIndicator.vala b/src/Interfaces/SoundIndicator.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Main.vala b/src/Main.vala index 50a650aa..d34e2eef 100644 --- a/src/Main.vala +++ b/src/Main.vala @@ -3,12 +3,45 @@ * SPDX-License-Identifier: GPL-3.0-or-later */ +using Ensembles; + public static int main (string[] args) { Environment.set_application_name (Constants.APP_NAME); Environment.set_prgname (Constants.APP_NAME); - var application = new Ensembles.Application (); - application.init (args); + Console.greet (Constants.VERSION, Constants.DISPLAYVER); + + Services.di_container = new Vinject.Injector (); + + try { + // Arranger Workstation Service + Services.configure_aw_service ((aw_builder) => { + aw_builder.use_driver ( + Ensembles.ArrangerWorkstation.AudioEngine.ISynthEngine.Driver.ALSA + ) + .load_soundfont_with_name ("EnsemblesGM") + .load_soundfont_from_dir (Constants.SF2DATADIR) + .add_style_search_path (StyleRepository.get_style_dir ()) + .add_style_search_path (Environment.get_user_special_dir ( + GLib.UserDirectory.DOCUMENTS) + + "/ensembles" + + "/styles" + ); + }); + + // GTK 4 + Services.configure_gtkshell_service ((shell_builder) => { + shell_builder.with_app_id (Constants.APP_ID) + .with_name ("Ensembles") + .with_icon_name ("com.github.ensemblesaw.ensembles") + .has_version (Constants.VERSION, Constants.DISPLAYVER); + }); + + Console.log ("Starting application"); + return Services.di_container.obtain (Services.st_application).run (args); - return application.run (args); + // Windows UI 3 + } catch (Vinject.VinjectErrors e) { + error (e.message); + } } diff --git a/src/Models/Chord.vala b/src/Models/Chord.vala deleted file mode 100644 index 8eff8031..00000000 --- a/src/Models/Chord.vala +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Models { - /** - * Represents root note of chord - */ - public enum ChordRoot { - C = 0, - CS = 1, - D = 2, - EF = 3, - E = 4, - F = 5, - FS = 6, - G = -5, - AF = -4, - A = -3, - BF = -2, - B = -1, - NONE = -6; - } - - /** - * Represents the type of chord - */ - public enum ChordType { - MAJOR = 0, - MINOR = 1, - DIMINISHED = 2, - SUSPENDED_2 = 3, - SUSPENDED_4 = 4, - AUGMENTED = 5, - SIXTH = 6, - SEVENTH = 7, - MAJOR_7TH = 8, - MINOR_7TH = 9, - ADD_9TH = 10, - NINTH = 11 - } - - /** - * Represents musical chords - */ - public struct Chord { - public ChordRoot root; - public ChordType type; - } -} diff --git a/src/Models/Registry.vala b/src/Models/Registry.vala deleted file mode 100644 index 7725e61e..00000000 --- a/src/Models/Registry.vala +++ /dev/null @@ -1,30 +0,0 @@ - -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Models { - public struct Registry { - public Voice voice_r1; - public Voice voice_r2; - public Voice voice_l; - public Style style; - public uint8 tempo; - public int8 transpose; - public bool transpose_active; - public int8 octave_shift; - public bool octave_shift_active; - public uint8 reverb_level; - public bool reverb_active; - public uint8 chorus_level; - public bool chorus_active; - public bool accomp_active; - public bool layer_active; - public bool split_active; - public uint8 harmonizer_type; - public bool harmnonizer_active; - public uint8 arpeggiator_type; - public bool arperggiator_active; - } -} diff --git a/src/Models/Style.vala b/src/Models/Style.vala deleted file mode 100644 index 5190639e..00000000 --- a/src/Models/Style.vala +++ /dev/null @@ -1,85 +0,0 @@ - -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Models { - /** - * Data structure representing auto accompaniment styles - */ - public struct Style { - public string name; - public string genre; - public uint8 tempo; - public uint8 time_signature_n; - public uint8 time_signature_d; - public uint32 time_resolution; - public string enstl_path; - public string copyright_notice; - public ChordType scale_type; - public StylePart[] parts; - - public string to_string () { - string output = "Style Object ->\n╭──────────────────────────────────────────────────────────╮\n"; - output += "│ \x1B[1m%s\x1B[0m, Genre: %s".printf (name, genre); - for (uint8 i = 0; i < 48 - (name.length + genre.length); i++) {output += " ";} - output += "│\n"; - output += "│ Tempo: %u BPM, Time Signature: %u/%u".printf (tempo, time_signature_n, time_signature_d); - for ( - uint8 i = 0; - i < 27 - (tempo.to_string ().length + time_signature_n.to_string ().length - + time_signature_d.to_string ().length); - i++ - ) { output += " "; } - output += "│\n"; - output += "│ " + copyright_notice; - if (copyright_notice.length < 60) { - for ( - uint8 i = 0; - i < 57 - copyright_notice.length; - i++ - ) { output += " "; } - output += "│"; - } - - output += "\n┢━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━┯━━━━━━━━━━━┪\n"; - output += "┃PART │ 1 │ 2 │ 3 │ 4 ┃\n"; - output += "┡┅┅┅┅┅┅┅┅┅┅┿┅┅┅┅┅┅┅┅┅┅┅┿┅┅┅┅┅┅┅┅┅┅┅┿┅┅┅┅┅┅┅┅┅┅┅┿┅┅┅┅┅┅┅┅┅┅┅┩\n"; - output += "│INTRO │ %07u │ %07u │ %07u │ N/A │\n".printf ( - 2 * parts[0].time_stamp, 2 * parts[1].time_stamp, 2 * parts[2].time_stamp - ); - output += "│VARIATION │ %07u │ %07u │ %07u │ %07u │\n".printf ( - 2 * parts[4].time_stamp, 2 * parts[6].time_stamp, 2 * parts[8].time_stamp, 2 * parts[10].time_stamp - ); - output += "│FILL-IN │ %07u │ %07u │ %07u │ %07u │\n".printf ( - 2 * parts[5].time_stamp, 2 * parts[7].time_stamp, 2 * parts[9].time_stamp, 2 * parts[11].time_stamp - ); - output += "│BREAK │ %07u │ N/A │ N/A │ N/A │\n".printf ( - 2 * parts[3].time_stamp - ); - output += "│ENDING │ %07u │ %07u │ %07u │ N/A │\n".printf ( - 2 * parts[12].time_stamp, 2 * parts[14].time_stamp, 2 * parts[16].time_stamp - ); - output += "│EOS │ %07u │ %07u │ %07u │ N/A │\n".printf ( - 2 * parts[13].time_stamp, 2 * parts[15].time_stamp, 2 * parts[17].time_stamp - ); - output += "╰──────────┴───────────┴───────────┴───────────┴───────────╯"; - - return output; - } - - /** - * Updates a given hash table with `StylePartType` as the key and the - * part bounds as the value. - */ - public void update_part_hash_table (HashTable? hash_table) { - for (uint8 i = 0; i < parts.length; i++) { - hash_table.insert (parts[i].style_part_type, StylePartBounds () { - start = (int)parts[i].time_stamp, - end = (int)parts[i + 1].time_stamp - }); - } - } - } -} diff --git a/src/Models/StylePart.vala b/src/Models/StylePart.vala deleted file mode 100644 index 974945b1..00000000 --- a/src/Models/StylePart.vala +++ /dev/null @@ -1,31 +0,0 @@ - -namespace Ensembles.Models { - public enum StylePartType { - INTRO_1, - INTRO_2, - INTRO_3, - BREAK, - VARIATION_A, - VARIATION_B, - VARIATION_C, - VARIATION_D, - FILL_A, - FILL_B, - FILL_C, - FILL_D, - ENDING_1, - ENDING_2, - ENDING_3, - EOS - } - - public struct StylePart { - public uint time_stamp; - public StylePartType style_part_type; - } - - public struct StylePartBounds { - public int start; - public int end; - } -} diff --git a/src/Models/Voice.vala b/src/Models/Voice.vala deleted file mode 100644 index fabfb761..00000000 --- a/src/Models/Voice.vala +++ /dev/null @@ -1,33 +0,0 @@ - -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles { - /** - * Describes which hand is playing the voice - */ - public enum VoiceHandPosition { - /** Playing on left hand of split */ - LEFT, - /** Playing on right hand of split as the main voice*/ - RIGHT, - /** Playing on the right side of split layered with main voice */ - RIGHT_LAYERED - } - - namespace Models { - /** - * Data structure representing voice or timbre data in soundfont - */ - public struct Voice { - public uint index; - public uint8 bank; - public uint8 preset; - public string name; - public string category; - public string sf_path; - } - } -} diff --git a/src/Services.vala b/src/Services.vala new file mode 100644 index 00000000..980c8ff1 --- /dev/null +++ b/src/Services.vala @@ -0,0 +1,10 @@ +using Vinject; +using Ensembles.ArrangerWorkstation; + +/* + * What's happening here is that `Services` is a namespace shared among + * all the modules. It's where all the dependency injection stuff lives. + */ +namespace Ensembles.Services { + static Injector di_container; +} diff --git a/src/Services/EventBus.vala b/src/Services/EventBus.vala deleted file mode 100644 index 196888be..00000000 --- a/src/Services/EventBus.vala +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Models; - -namespace Ensembles.Services { - public class EventBus : Object { - // Shell Events - public signal void size_change (); - public signal bool show_menu (bool show); - public signal void menu_shown (bool shown); - public signal void send_initial_status (string status); - - // Homescreen - public signal void voice_chosen (VoiceHandPosition position, string name, uint8 bank, uint8 preset); - - // Core Events - public signal void arranger_ready (); - - public signal void beat (bool measure, uint8 time_signature_n, uint8 time_signature_d); - public signal void beat_reset (); - - // Style Player Events - public signal void style_change (Style style); - public signal void style_chord_changed (Ensembles.Models.Chord chord); - public signal int style_midi_event (Fluid.MIDIEvent event); - public signal void style_play_toggle (); - public signal void style_set_part (StylePartType part); - public signal void style_current_part_changed (StylePartType part_type); - public signal void style_next_part_changed (StylePartType part_type); - public signal void style_sync (); - public signal void style_sync_changed (bool active); - public signal void style_break (); - public signal void style_break_changed (bool active); - - // Synthesizer - public signal int synth_send_event (Fluid.MIDIEvent event); - public signal void synth_received_note (uint8 note_number, bool on); - public signal void synth_halt_notes (bool except_drums = false); - public signal void synth_sounds_off (); - public signal int synth_midi_reroute (int channel, Fluid.MIDIEvent event); - - // Plugins - public signal void rack_reconnected (Core.Racks.Rack rack, int change_index); - public signal void show_plugin_ui (Core.Plugins.AudioPlugins.AudioPlugin plugin); - } -} diff --git a/src/Services/Settings.vala b/src/Services/Settings.vala deleted file mode 100644 index 2cdbcc7c..00000000 --- a/src/Services/Settings.vala +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Services { - public class Settings : GLib.Settings { - public Settings () { - Object (schema_id: Constants.APP_ID); - } - - public string version { - owned get { return get_string ("version"); } - set { set_string ("version", value); } - } - - // Main Window ///////////////////////////////////////////////////////// - /** The saved x-position of the window. */ - public int window_x { - get { return get_int ("window-x"); } - set { set_int ("window-x", value); } - } - - /** The saved y-position of the window. */ - public int window_y { - get { return get_int ("window-y"); } - set { set_int ("window-y", value); } - } - - /** The saved width of the window. */ - public int window_w { - get { return get_int ("window-w"); } - set { set_int ("window-w", value); } - } - - /** The saved height of the window. */ - public int window_h { - get { return get_int ("window-h"); } - set { set_int ("window-h", value); } - } - - /** If window should be maximized */ - public bool window_maximized { - get { return get_boolean ("window-maximized"); } - set { set_boolean ("window-maximized", value); } - } - - /** Info Display theme */ - public string display_theme { - owned get { return get_string ("display-theme"); } - set { set_string ("display-theme", value); } - } - - // Arranger Core /////////////////////////////////////////////////////// - /** Enstl style path of the last used style*/ - public string style_path { - owned get { return get_string ("style-path"); } - set { set_string ("style-path", value); } - } - - // Style Engine //////////////////////////////////////////////////////// - /** - * If autofill is `true`, then style engine automatically adds a fill-in - * when switching between variations. - */ - public bool autofill { - get { return get_boolean ("autofill"); } - set { set_boolean ("autofill", value); } - } - - /** - * How chord should be interpreted from the keyboard input. - * - * - `SPLIT_LONG`: Determine chord from multiple keys only on left side - * of split point - * - `SPLIT_SHORT`: Determine chord from two fingers only on left side - * of split point - * - `FULL_RANGE`: Determine chord from multiple fingers from any place - * on the keyboard - */ - public Core.Analysers.ChordAnalyser.ChordDetectionMode chord_detection_mode { - get { return get_enum ("chord-detection-mode"); } - set { set_enum ("chord-detection-mode", value); } - } - } -} diff --git a/src/Services/Theme.vala b/src/Services/Theme.vala deleted file mode 100644 index c5373b9c..00000000 --- a/src/Services/Theme.vala +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Services { - public class Theme { - static Gtk.CssProvider main_css_provider; - static Gtk.CssProvider complimentary_css_provider; - - public static string theme_color = "blueberry"; - - public static void init_theme () { - weak Gtk.IconTheme default_theme = Gtk.IconTheme.get_for_display (Gdk.Display.get_default ()); - default_theme.add_resource_path ("/com/github/subhadeepjasu/ensembles/icons"); - - GLib.Value theme_value = GLib.Value (GLib.Type.STRING); - - var gtk_settings = Gtk.Settings.get_default (); - var granite_settings = Granite.Settings.get_default (); - - gtk_settings.get_property ("gtk-theme-name", ref theme_value); - - var system_theme = theme_value.get_string (); - - if (system_theme.has_prefix ("io.elementary.")) { - theme_color = theme_value.get_string ().replace ("io.elementary.stylesheet.", ""); - } else { - gtk_settings.set_property ("gtk-icon-theme-name", "elementary"); - } - - if (main_css_provider == null) { - main_css_provider = new Gtk.CssProvider (); - main_css_provider.load_from_resource ("/com/github/subhadeepjasu/ensembles/theme/Application.css"); - Gtk.StyleContext.add_provider_for_display ( - Gdk.Display.get_default (), - main_css_provider, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - } - - // Set colors that are complimentary to the accent color for special cases - if (complimentary_css_provider == null) { - complimentary_css_provider = new Gtk.CssProvider (); - complimentary_css_provider.load_from_data (AccentColors.get_complementary (theme_color)); - - Gtk.StyleContext.add_provider_for_display ( - Gdk.Display.get_default (), - complimentary_css_provider, - Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - ); - } - - gtk_settings.gtk_application_prefer_dark_theme = ( - granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK - ); - - granite_settings.notify["prefers-color-scheme"].connect (() => { - gtk_settings.gtk_application_prefer_dark_theme = ( - granite_settings.prefers_color_scheme == Granite.Settings.ColorScheme.DARK - ); - }); - } - } -} diff --git a/src/Shell/Dialogs/PluginWindow.vala b/src/Shell/Dialogs/PluginWindow.vala deleted file mode 100644 index e69de29b..00000000 diff --git a/src/Shell/Dialogs/PowerDialog.vala b/src/Shell/Dialogs/PowerDialog.vala deleted file mode 100644 index 7e767bae..00000000 --- a/src/Shell/Dialogs/PowerDialog.vala +++ /dev/null @@ -1,91 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Dialog { - public class PowerDialog : Gtk.Window { - private Gtk.Image power_icon; - private Gtk.Label header; - private Gtk.Label message; - private Gtk.Button log_out_button; - private Gtk.Button cancel_button; - private Gtk.Button shutdown_button; - - construct { - build_ui (); - build_events (); - } - - public PowerDialog (Gtk.Window main_window) { - Object ( - modal: true, - transient_for: main_window, - decorated: false - ); - } - - private void build_ui () { - add_css_class ("pseudowindow-actual"); - - var main_grid = new Gtk.Grid () { - row_spacing = 8, - column_spacing = 8, - halign = Gtk.Align.CENTER, - valign = Gtk.Align.CENTER - }; - main_grid.add_css_class ("pseudowindow"); - main_grid.add_css_class ("opaque"); - - set_child (main_grid); - - power_icon = new Gtk.Image.from_icon_name ("system-shutdown") { - width_request = 48, - height_request = 48, - icon_size = Gtk.IconSize.LARGE - }; - main_grid.attach (power_icon, 0, 0, 1, 2); - - header = new Gtk.Label (_("Are you sure you want to Shut Down?")) { - halign = Gtk.Align.START - }; - header.add_css_class (Granite.STYLE_CLASS_H3_LABEL); - main_grid.attach (header, 1, 0, 4); - - message = new Gtk.Label (_("This will turn off this device")) { - halign = Gtk.Align.START - }; - main_grid.attach (message, 1, 1, 4); - - log_out_button = new Gtk.Button.with_label (_("Log Out Instead…")); - main_grid.attach (log_out_button, 1, 2, 2); - - cancel_button = new Gtk.Button.with_label (_("Cancel")); - main_grid.attach (cancel_button, 3, 2); - - shutdown_button = new Gtk.Button.with_label (_("Shut Down")); - shutdown_button.add_css_class (Granite.STYLE_CLASS_DESTRUCTIVE_ACTION); - main_grid.attach (shutdown_button, 4, 2); - } - - private void build_events () { - cancel_button.clicked.connect (() => { - this.close (); - }); - - log_out_button.clicked.connect (() => { - Application.main_window.close (); - }); - - shutdown_button.clicked.connect (() => { - Application.main_window.close (); - }); - - ((Gtk.Widget) this).realize.connect (() => { - var display = Gdk.Display.get_default (); - var monitor = display.get_monitor_at_surface (get_surface ()); - set_default_size (monitor.geometry.width, monitor.geometry.height); - }); - } - } -} diff --git a/src/Shell/Layouts/AssignablesBoard.vala b/src/Shell/Layouts/AssignablesBoard.vala deleted file mode 100644 index 9efdf056..00000000 --- a/src/Shell/Layouts/AssignablesBoard.vala +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Layouts { - public class AssignablesBoard : Gtk.Grid { - construct { - add_css_class ("panel"); - } - - public AssignablesBoard () { - Object ( - hexpand: true, - vexpand: true - ); - } - } -} diff --git a/src/Shell/Layouts/DesktopLayout.vala b/src/Shell/Layouts/DesktopLayout.vala deleted file mode 100644 index 9b9ee985..00000000 --- a/src/Shell/Layouts/DesktopLayout.vala +++ /dev/null @@ -1,126 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Layouts { - public class DesktopLayout : Gtk.Grid { - private weak Layouts.AssignablesBoard assignables_board; - private weak Layouts.InfoDisplay info_display; - private weak Layouts.SynthControlPanel synth_control_panel; - private weak Layouts.VoiceNavPanel voice_nav_panel; - private weak Layouts.MixerBoard mixer_board; - private weak Layouts.SamplerPadsPanel sampler_pads_panel; - private weak Layouts.StyleControlPanel style_control_panel; - private weak Layouts.RegistryPanel registry_panel; - private weak Layouts.KeyboardPanel keyboard; - private Gtk.Button start_button; - - private Gtk.CenterBox top_row; - private Gtk.CenterBox middle_row; - private Gtk.Grid bottom_row; - private Gtk.CenterBox bottom_row_box; - private Gtk.Revealer bottom_row_revealer; - - construct { - build_ui (); - } - - public DesktopLayout (Layouts.AssignablesBoard? assignables_board, - Layouts.InfoDisplay? info_display, - Layouts.SynthControlPanel? synth_control_panel, - Layouts.VoiceNavPanel? voice_nav_panel, - Layouts.MixerBoard? mixer_board, - Layouts.SamplerPadsPanel? sampler_pads_panel, - Layouts.StyleControlPanel? style_control_panel, - Layouts.RegistryPanel? registry_panel, - Layouts.KeyboardPanel? keyboard) { - Object ( - width_request: 812, - height_request: 600, - hexpand: true, - vexpand: true - ); - this.assignables_board = assignables_board; - this.info_display = info_display; - this.synth_control_panel = synth_control_panel; - this.voice_nav_panel = voice_nav_panel; - this.mixer_board = mixer_board; - this.sampler_pads_panel = sampler_pads_panel; - this.style_control_panel = style_control_panel; - this.registry_panel = registry_panel; - this.keyboard = keyboard; - } - - private void build_ui () { - top_row = new Gtk.CenterBox () { - hexpand = true, - vexpand = true - }; - attach (top_row, 0, 0); - - middle_row = new Gtk.CenterBox () { - hexpand = true, - vexpand = true - }; - attach (middle_row, 0, 1); - - - bottom_row_revealer = new Gtk.Revealer () { - reveal_child = true, - hexpand = true - }; - attach (bottom_row_revealer, 0, 2); - - bottom_row = new Gtk.Grid () { - hexpand = true - }; - bottom_row_revealer.set_child (bottom_row); - - bottom_row_box = new Gtk.CenterBox (); - bottom_row.attach (bottom_row_box, 0, 0); - - var start_button_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 2); - start_button_box.add_css_class ("panel"); - bottom_row_box.set_center_widget (start_button_box); - - start_button = new Gtk.Button.from_icon_name ("media-playback-start-symbolic") { - width_request = 64, - height_request = 32 - }; - start_button.add_css_class (Granite.STYLE_CLASS_DESTRUCTIVE_ACTION); - start_button.remove_css_class ("image-button"); - start_button.clicked.connect (() => { - Application.event_bus.style_play_toggle (); - }); - - start_button_box.append (start_button); - start_button_box.append (new Gtk.Label (_("START/STOP")) { opacity = 0.5 }); - } - - public void reparent () { - assignables_board.unparent (); - info_display.unparent (); - synth_control_panel.unparent (); - voice_nav_panel.unparent (); - mixer_board.unparent (); - sampler_pads_panel.unparent (); - style_control_panel.unparent (); - registry_panel.unparent (); - keyboard.unparent (); - - top_row.set_start_widget (assignables_board); - top_row.set_center_widget (info_display); - info_display.fill_screen = false; - top_row.set_end_widget (synth_control_panel); - - middle_row.set_start_widget (voice_nav_panel); - middle_row.set_center_widget (mixer_board); - middle_row.set_end_widget (sampler_pads_panel); - - bottom_row_box.set_start_widget (style_control_panel); - bottom_row_box.set_end_widget (registry_panel); - bottom_row.attach (keyboard, 0, 1); - } - } -} diff --git a/src/Shell/Layouts/Display/AudioPluginPicker.vala b/src/Shell/Layouts/Display/AudioPluginPicker.vala deleted file mode 100644 index 906922d6..00000000 --- a/src/Shell/Layouts/Display/AudioPluginPicker.vala +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Core.Plugins.AudioPlugins; -using Ensembles.Shell.Widgets.Display; - -namespace Ensembles.Shell.Layouts.Display { - public class AudioPluginPicker : WheelScrollableWidget { - public AudioPlugin.Category category { - get; - private set; - } - private Gtk.ListBox main_list_box; - - public AudioPluginPicker (AudioPlugin.Category category) { - Object ( - width_request: 500, - hexpand: false, - vexpand: true, - orientation: Gtk.Orientation.VERTICAL, - spacing: 8 - ); - this.category = category; - - build_ui (); - build_events (); - populate (Application.arranger_workstation.get_audio_plugins ()); - } - - public void build_ui () { - var plugin_picker_header = new Gtk.Label (_("A U D I O P L U G I N S")) { - halign = Gtk.Align.END, - opacity = 0.5, - margin_end = 14, - margin_top = 24 - }; - plugin_picker_header.add_css_class (Granite.STYLE_CLASS_H3_LABEL); - append (plugin_picker_header); - - var scrollable = new Gtk.ScrolledWindow () { - hexpand = true, - vexpand = true - }; - append (scrollable); - - main_list_box = new Gtk.ListBox () { - selection_mode = Gtk.SelectionMode.NONE - }; - main_list_box.add_css_class ("plugin-list"); - scrollable.set_child (main_list_box); - } - - private void build_events () { - - } - - public void populate (List plugins) { - for (uint16 i = 0; i < plugins.length (); i++) { - if (plugins.nth_data (i).category == category) { - var menu_item = new DSPMenuItem (plugins.nth_data (i), - Application.arranger_workstation.get_main_dsp_rack ()); - main_list_box.insert (menu_item, -1); - } - } - - min_value = 0; - max_value = (int) plugins.length () - 1; - } - } -} diff --git a/src/Shell/Layouts/Display/DSPScreen.vala b/src/Shell/Layouts/Display/DSPScreen.vala deleted file mode 100644 index 9eb76eb8..00000000 --- a/src/Shell/Layouts/Display/DSPScreen.vala +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Shell.Widgets.Display; -using Ensembles.Models; -using Ensembles.Core.Plugins.AudioPlugins; -using Ensembles.Core.Racks; - -namespace Ensembles.Shell.Layouts.Display { - public class DSPScreen : DisplayWindow { - private Gtk.Button plugin_picker_button; - private Gtk.Switch dsp_switch; - private Adw.Flap main_flap; - private Gtk.ListBox main_list_box; - private AudioPluginPicker plugin_picker; - - private unowned DSPRack rack; - - public DSPScreen (DSPRack rack) { - base (_("Main DSP Rack"), _("Add Effects to the Rack to apply them globally")); - - this.rack = rack; - } - - construct { - build_ui (); - build_events (); - } - - private void build_ui () { - dsp_switch = new Gtk.Switch () { - valign = Gtk.Align.CENTER, - halign = Gtk.Align.CENTER - }; - dsp_switch.active = true; - add_to_header (dsp_switch); - - plugin_picker_button = new Gtk.Button.from_icon_name ("plugin-add-symbolic") { - width_request = 36, - tooltip_text = _("Add plugin to DSP Rack") - }; - add_to_header (plugin_picker_button); - - main_flap = new Adw.Flap () { - fold_policy = Adw.FlapFoldPolicy.ALWAYS, - flap_position = Gtk.PackType.END - }; - main_flap.add_css_class ("plugin-flap"); - append (main_flap); - - plugin_picker = new AudioPluginPicker (Core.Plugins.AudioPlugins.AudioPlugin.Category.DSP); - main_flap.set_flap (plugin_picker); - - var scrollable = new Gtk.ScrolledWindow () { - hexpand = true, - vexpand = true, - margin_start = 8, - margin_end = 8, - margin_top = 8, - margin_bottom = 8 - }; - scrollable.add_css_class ("can-be-blurred"); - main_flap.set_content (scrollable); - - main_list_box = new Gtk.ListBox () { - selection_mode = Gtk.SelectionMode.NONE - }; - main_list_box.add_css_class ("menu-box"); - scrollable.set_child (main_list_box); - } - - private void build_events () { - dsp_switch.notify["active"].connect (() => { - rack.active = dsp_switch.active; - }); - - plugin_picker_button.clicked.connect (() => { - main_flap.reveal_flap = !main_flap.reveal_flap; - }); - - main_flap.notify.connect ((param) => { - if (param.name == "reveal-flap") { - Idle.add (() => { - if (main_flap.reveal_flap) { - main_flap.get_content ().add_css_class ("blurred"); - } else { - main_flap.get_content ().remove_css_class ("blurred"); - } - - return false; - }); - } - }); - - Application.event_bus.rack_reconnected.connect ((rack, change_index) => { - if (rack.rack_type == AudioPlugin.Category.DSP) { - populate (rack.get_plugins (), change_index); - } - - main_flap.reveal_flap = false; - }); - } - - public void populate (List plugins, int highlight_index) { - while (main_list_box.get_first_child () != null) { - main_list_box.remove (main_list_box.get_first_child ()); - } - - for (uint16 i = 0; i < plugins.length (); i++) { - var menu_item = new DSPInstanceMenuItem (plugins.nth_data (i), this); - main_list_box.insert (menu_item, -1); - - if (highlight_index == i) { - menu_item.capture_attention (); - } - } - - min_value = 0; - max_value = (int) plugins.length () - 1; - } - - public void delete_plugin_item (DSPInstanceMenuItem item) { - unowned AudioPlugin plugin = item.plugin; - main_list_box.remove (item); - rack.remove_data (plugin); - } - } -} diff --git a/src/Shell/Layouts/Display/HomeScreen.vala b/src/Shell/Layouts/Display/HomeScreen.vala deleted file mode 100644 index ebe9549f..00000000 --- a/src/Shell/Layouts/Display/HomeScreen.vala +++ /dev/null @@ -1,341 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Layouts.Display { - public class HomeScreen : Gtk.Box { - private Gtk.Button power_button; - private Gtk.Button style_button; - private Gtk.Button voice_l_button; - private Gtk.Button voice_r1_button; - private Gtk.Button voice_r2_button; - - private Gtk.Button dsp_button; - private Gtk.Label dsp_status; - private Gtk.Button recorder_button; - private Gtk.Label recorder_status; - - private Gtk.Label selected_style_label; - private Gtk.Label selected_voice_l_label; - private Gtk.Label selected_voice_r1_label; - private Gtk.Label selected_voice_r2_label; - - private Gtk.Label tempo_label; - private Gtk.Label measure_label; - private Gtk.Label beat_label; - private Gtk.Label transpose_label; - private Gtk.Label octave_label; - private Gtk.Label chord_label; - private Gtk.Label chord_flat_label; - private Gtk.Label chord_type_label; - - public signal void change_screen (string screen_name); - - public HomeScreen () { - Object ( - orientation: Gtk.Orientation.VERTICAL, - spacing: 0 - ); - } - - construct { - build_ui (); - build_events (); - } - - private void build_ui () { - add_css_class ("homescreen"); - - var links_section = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { - height_request = 200 - }; - links_section.add_css_class ("homescreen-links-section"); - append(links_section); - - // Top Links /////////////////////////////////////////////////////////////////////////////////////////////// - - var top_link_panel = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - height_request = 56, - hexpand = true - }; - top_link_panel.add_css_class ("homescreen-link-panel-top"); - links_section.append (top_link_panel); - - if (Application.kiosk_mode) { - power_button = new Gtk.Button.from_icon_name ("system-shutdown-symbolic") { - height_request = 48, - width_request = 32 - }; - power_button.add_css_class ("homescreen-link-panel-top-button"); - top_link_panel.append (power_button); - } - - style_button = new Gtk.Button (); - top_link_panel.append (style_button); - style_button.add_css_class ("homescreen-link-panel-top-button"); - - var style_button_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { - height_request = 48, - hexpand = true - }; - style_button.set_child (style_button_box); - - var style_label = new Gtk.Label (_("Style")) { - halign = Gtk.Align.CENTER - }; - style_button_box.append (style_label); - style_label.add_css_class ("homescreen-link-panel-top-button-header"); - - selected_style_label = new Gtk.Label (_("Undefined")) { - ellipsize = Pango.EllipsizeMode.MIDDLE, - halign = Gtk.Align.CENTER - }; - style_button_box.append (selected_style_label); - selected_style_label.add_css_class ("homescreen-link-panel-top-button-subheader"); - - voice_l_button = new Gtk.Button (); - top_link_panel.append (voice_l_button); - voice_l_button.add_css_class ("homescreen-link-panel-top-button"); - - var voice_l_button_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { - height_request = 48, - hexpand = true - }; - voice_l_button.set_child (voice_l_button_box); - - var voice_l_label = new Gtk.Label (_("Voice L")) { - halign = Gtk.Align.CENTER - }; - voice_l_button_box.append (voice_l_label); - voice_l_label.add_css_class ("homescreen-link-panel-top-button-header"); - - selected_voice_l_label = new Gtk.Label (_("Undefined")) { - ellipsize = Pango.EllipsizeMode.MIDDLE, - halign = Gtk.Align.CENTER - }; - voice_l_button_box.append (selected_voice_l_label); - selected_voice_l_label.add_css_class ("homescreen-link-panel-top-button-subheader"); - - voice_r1_button = new Gtk.Button (); - top_link_panel.append (voice_r1_button); - voice_r1_button.add_css_class ("homescreen-link-panel-top-button"); - - var voice_r1_button_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { - height_request = 48, - hexpand = true - }; - voice_r1_button.set_child (voice_r1_button_box); - - var voice_r1_label = new Gtk.Label (_("Voice R1")) { - halign = Gtk.Align.CENTER - }; - voice_r1_button_box.append (voice_r1_label); - voice_r1_label.add_css_class ("homescreen-link-panel-top-button-header"); - - selected_voice_r1_label = new Gtk.Label (_("Undefined")) { - ellipsize = Pango.EllipsizeMode.MIDDLE, - halign = Gtk.Align.CENTER - }; - voice_r1_button_box.append (selected_voice_r1_label); - selected_voice_r1_label.add_css_class ("homescreen-link-panel-top-button-subheader"); - - voice_r2_button = new Gtk.Button (); - top_link_panel.append (voice_r2_button); - voice_r2_button.add_css_class ("homescreen-link-panel-top-button"); - - var voice_r2_button_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { - height_request = 48, - hexpand = true - }; - voice_r2_button.set_child (voice_r2_button_box); - - var voice_r2_label = new Gtk.Label (_("Voice R2")) { - halign = Gtk.Align.CENTER - }; - voice_r2_button_box.append (voice_r2_label); - voice_r2_label.add_css_class ("homescreen-link-panel-top-button-header"); - - selected_voice_r2_label = new Gtk.Label (_("Undefined")) { - ellipsize = Pango.EllipsizeMode.MIDDLE, - halign = Gtk.Align.CENTER - }; - voice_r2_button_box.append (selected_voice_r2_label); - selected_voice_r2_label.add_css_class ("homescreen-link-panel-top-button-subheader"); - - // Bottom Links //////////////////////////////////////////////////////////////////////////////////////////// - var bottom_links_panel = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { - vexpand = true, - hexpand = true, - valign = Gtk.Align.END - }; - links_section.append (bottom_links_panel); - bottom_links_panel.add_css_class ("homescreen-link-panel-bottom"); - - dsp_button = new Gtk.Button () { - valign = Gtk.Align.END, - halign = Gtk.Align.START - }; - dsp_button.add_css_class ("homescreen-link-panel-bottom-button"); - bottom_links_panel.append (dsp_button); - - var dsp_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); - dsp_button.set_child (dsp_box); - - dsp_box.append (new Gtk.Separator (Gtk.Orientation.VERTICAL)); - dsp_box.append (new Gtk.Label (_("Main Effect Rack - "))); - - dsp_status = new Gtk.Label (_("0 Effects in Use")); - dsp_status.add_css_class ("homescreen-link-panel-bottom-button-status"); - dsp_box.append (dsp_status); - - recorder_button = new Gtk.Button () { - valign = Gtk.Align.END, - halign = Gtk.Align.START - }; - recorder_button.add_css_class ("homescreen-link-panel-bottom-button"); - bottom_links_panel.append (recorder_button); - - var recorder_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); - recorder_button.set_child (recorder_box); - - recorder_box.append (new Gtk.Separator (Gtk.Orientation.VERTICAL)); - recorder_box.append (new Gtk.Label (_("Recorder - "))); - - recorder_status = new Gtk.Label (_("No Project Open")); - recorder_status.add_css_class ("homescreen-link-panel-bottom-button-status"); - recorder_box.append (recorder_status); - - // Bottom Panel //////////////////////////////////////////////////////////////////////////////////////////// - var status_panel = new Gtk.Grid () { - vexpand = true, - hexpand = true, - column_homogeneous = true, - height_request = 175 - }; - append (status_panel); - status_panel.add_css_class ("homescreen-panel-status"); - - var tempo_header = new Gtk.Label(_("Tempo")); - tempo_header.add_css_class ("homescreen-panel-status-header"); - status_panel.attach (tempo_header, 0, 0); - - var measure_header = new Gtk.Label(_("Measure")); - measure_header.add_css_class ("homescreen-panel-status-header"); - status_panel.attach (measure_header, 1, 0); - - var beat_header = new Gtk.Label(_("Time Signature")); - beat_header.add_css_class ("homescreen-panel-status-header"); - status_panel.attach (beat_header, 2, 0); - - var transpose_header = new Gtk.Label(_("Transpose")); - transpose_header.add_css_class ("homescreen-panel-status-header"); - status_panel.attach (transpose_header, 3, 0); - - var octave_header = new Gtk.Label(_("Octave")); - octave_header.add_css_class ("homescreen-panel-status-header"); - status_panel.attach (octave_header, 4, 0); - - var chord_header = new Gtk.Label(_("Chord")); - chord_header.add_css_class ("homescreen-panel-status-header"); - status_panel.attach (chord_header, 5, 0); - - var tempo_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 1) { - halign = Gtk.Align.CENTER - }; - status_panel.attach (tempo_box, 0, 1); - - tempo_label = new Gtk.Label ("120"); - tempo_label.add_css_class ("homescreen-panel-status-label"); - tempo_box.append (tempo_label); - - var tempo_unit_label = new Gtk.Label ("BPM") { - margin_bottom = 8 - }; - tempo_unit_label.add_css_class ("homescreen-panel-status-label-small"); - tempo_box.append (tempo_unit_label); - - measure_label = new Gtk.Label("0"); - measure_label.add_css_class ("homescreen-panel-status-label"); - status_panel.attach (measure_label, 1, 1); - - beat_label = new Gtk.Label("4 / 4"); - beat_label.add_css_class ("homescreen-panel-status-label"); - status_panel.attach (beat_label, 2, 1); - - transpose_label = new Gtk.Label("0"); - transpose_label.add_css_class ("homescreen-panel-status-label"); - status_panel.attach (transpose_label, 3, 1); - - octave_label = new Gtk.Label("0"); - octave_label.add_css_class ("homescreen-panel-status-label"); - status_panel.attach (octave_label, 4, 1); - - var chord_grid = new Gtk.Grid () { - halign = Gtk.Align.CENTER - }; - status_panel.attach (chord_grid, 5, 1); - - chord_label = new Gtk.Label(_("C")); - chord_label.add_css_class ("homescreen-panel-status-label"); - chord_grid.attach (chord_label, 0, 0, 1, 2); - - chord_flat_label = new Gtk.Label ("#"); - chord_flat_label.add_css_class ("homescreen-panel-status-label-small"); - chord_grid.attach (chord_flat_label, 1, 0); - - chord_type_label = new Gtk.Label ("m"); - chord_type_label.add_css_class ("homescreen-panel-status-label-small"); - chord_grid.attach (chord_type_label, 1, 1); - } - - private void build_events () { - style_button.clicked.connect (() => { - change_screen ("style"); - }); - - voice_l_button.clicked.connect (() => { - change_screen ("voice-l"); - }); - - voice_r1_button.clicked.connect (() => { - change_screen ("voice-r1"); - }); - - voice_r2_button.clicked.connect (() => { - change_screen ("voice-r2"); - }); - - dsp_button.clicked.connect (() => { - change_screen ("dsp"); - }); - - if (Application.kiosk_mode) { - power_button.clicked.connect (() => { - var power_dialog = new Dialog.PowerDialog (Application.main_window); - power_dialog.present (); - power_dialog.show (); - }); - } - - Application.event_bus.style_change.connect ((style) => { - print ("%s\n", style.name); - selected_style_label.set_text (style.name); - }); - - Application.event_bus.voice_chosen.connect ((position, name) => { - switch (position) { - case VoiceHandPosition.LEFT: - selected_voice_l_label.set_text (name); - break; - case VoiceHandPosition.RIGHT: - selected_voice_r1_label.set_text (name); - break; - case VoiceHandPosition.RIGHT_LAYERED: - selected_voice_r2_label.set_text (name); - break; - } - }); - } - } -} diff --git a/src/Shell/Layouts/Display/PluginScreen.vala b/src/Shell/Layouts/Display/PluginScreen.vala deleted file mode 100644 index c1d6473c..00000000 --- a/src/Shell/Layouts/Display/PluginScreen.vala +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Shell.Widgets.Display; -using Ensembles.Core.Plugins.AudioPlugins; - -namespace Ensembles.Shell.Layouts.Display { - /** - * Shows the plugin UI. - */ - public class PluginScreen : DisplayWindow { - public unowned AudioPlugin plugin { get; private set; } - public string? history { get; set; } - - private Gtk.Switch active_switch; - private Widgets.Knob gain_knob; - - public PluginScreen (AudioPlugin plugin) { - var protocol_name = ""; - switch (plugin.protocol) { - case AudioPlugin.Protocol.LV2: - protocol_name += "L V 2"; - break; - case AudioPlugin.Protocol.CARLA: - protocol_name += "C A R L A"; - break; - case AudioPlugin.Protocol.LADSPA: - protocol_name += "L A D S P A"; - break; - case AudioPlugin.Protocol.NATIVE: - protocol_name += "E N S E M B L E S G T K"; - break; - } - - base (_(plugin.name), _(protocol_name)); - this.plugin = plugin; - - build_ui (); - build_events (); - } - - private void build_ui () { - gain_knob = new Widgets.Knob.with_range (-12, 0, 1) { - width_request = 40, - height_request = 40, - halign = Gtk.Align.CENTER, - valign = Gtk.Align.CENTER, - tooltip_text = _("Dry / Wet Mix") - }; - gain_knob.add_css_class ("small"); - - gain_knob.value = Utils.Math.convert_gain_to_db (plugin.mix_gain); - gain_knob.add_mark (-12); - gain_knob.add_mark (0); - add_to_header (gain_knob); - - active_switch = new Gtk.Switch () { - halign = Gtk.Align.CENTER, - valign = Gtk.Align.CENTER, - margin_end = 8 - }; - active_switch.active = plugin.active; - add_to_header (active_switch); - - var scrollable = new Gtk.ScrolledWindow () { - vexpand = true, - hexpand = true - }; - append (scrollable); - - var plugin_ui = plugin.ui; - if (plugin_ui != null) { - scrollable.set_child (plugin_ui); - } - } - - private void build_events () { - active_switch.notify["active"].connect (() => { - plugin.active = active_switch.active; - }); - - gain_knob.value_changed.connect ((db) => { - plugin.mix_gain = (float) Utils.Math.convert_db_to_gain (db); - }); - } - } -} diff --git a/src/Shell/Layouts/Display/StyleScreen.vala b/src/Shell/Layouts/Display/StyleScreen.vala deleted file mode 100644 index 96e55a1c..00000000 --- a/src/Shell/Layouts/Display/StyleScreen.vala +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Shell.Widgets.Display; -using Ensembles.Models; - -namespace Ensembles.Shell.Layouts.Display { - /** - * Shows a list of styles. - */ - public class StyleScreen : DisplayWindow { - private Gtk.ListBox main_list_box; - - public StyleScreen () { - base (_("Style"), _("Pick a Rhythm to accompany you")); - } - - construct { - build_ui (); - build_events (); - } - - private void build_ui () { - var scrollable = new Gtk.ScrolledWindow () { - hexpand = true, - vexpand = true, - margin_start = 8, - margin_end = 8, - margin_top = 8, - margin_bottom = 8 - }; - append (scrollable); - - main_list_box = new Gtk.ListBox () { - selection_mode = Gtk.SelectionMode.SINGLE - }; - main_list_box.add_css_class ("menu-box"); - scrollable.set_child (main_list_box); - } - - public void build_events () { - main_list_box.row_activated.connect ((item) => { - var style_item = (StyleMenuItem) item; - - Application.event_bus.style_change (style_item.style); - }); - - Application.event_bus.arranger_ready.connect (() => { - Timeout.add (1000, () => { - Idle.add (() => { - populate (Application.arranger_workstation.get_styles ()); - var row_to_select = main_list_box.get_row_at_index (0); - main_list_box.select_row (row_to_select); - Application.event_bus.style_change (((StyleMenuItem) row_to_select).style); - return false; - }); - return false; - }); - }); - } - - public void populate (Style[] styles) { - Console.log ("Populating style list…"); - - var temp_category = ""; - for (uint16 i = 0; i < styles.length; i++) { - var show_category = false; - if (temp_category != styles[i].genre) { - temp_category = styles[i].genre; - show_category = true; - } - - var menu_item = new StyleMenuItem (styles[i], show_category); - main_list_box.insert (menu_item, -1); - } - - min_value = 0; - max_value = styles.length - 1; - } - - public void scroll_to_selected_row () { - var selected_item = main_list_box.get_selected_row (); - if (selected_item != null) { - selected_item.grab_focus (); - - // var adj = main_list_box.get_adjustment (); - // if (adj != null) { - // int height, _htemp; - // height = selected_item.get_allocated_height (); - - // Timeout.add (200, () => { - // adj.set_value (_selected_index * height); - // return false; - // }); - // } - } - } - } -} diff --git a/src/Shell/Layouts/Display/VoiceScreen.vala b/src/Shell/Layouts/Display/VoiceScreen.vala deleted file mode 100644 index 5abcb600..00000000 --- a/src/Shell/Layouts/Display/VoiceScreen.vala +++ /dev/null @@ -1,147 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Shell.Widgets.Display; -using Ensembles.Models; -using Ensembles.Core.Plugins.AudioPlugins; -using Ensembles.Core.Racks; - -namespace Ensembles.Shell.Layouts.Display { - /** - * Shows a list of voices from SoundFont and Voice plugins - */ - public class VoiceScreen : DisplayWindow { - public VoiceHandPosition hand_position { get; private set; } - private Gtk.ListBox main_list_box; - - private uint16 last_voice_index = 0; - private uint16 plugin_start_index = 0; - - public VoiceScreen (VoiceHandPosition hand_position) { - var title_by_position = ""; - var subtitle_by_position = ""; - switch (hand_position) { - case VoiceHandPosition.LEFT: - title_by_position = _("Left (Split)"); - subtitle_by_position = _("Pick a Voice to play on the left hand side of split"); - break; - case VoiceHandPosition.RIGHT: - title_by_position = _("Right 1 (Main)"); - subtitle_by_position = _("Pick a Voice to play"); - break; - case VoiceHandPosition.RIGHT_LAYERED: - title_by_position = _("Right 2 (Layered)"); - subtitle_by_position = _("Pick a Voice to play on another layer"); - break; - } - - base ( - _("Voice - %s").printf (title_by_position), - subtitle_by_position - ); - this.hand_position = hand_position; - } - - construct { - build_ui (); - build_events (); - } - - private void build_ui () { - var scrollable = new Gtk.ScrolledWindow () { - hexpand = true, - vexpand = true - }; - append (scrollable); - - main_list_box = new Gtk.ListBox () { - selection_mode = Gtk.SelectionMode.SINGLE - }; - main_list_box.add_css_class ("menu-box"); - scrollable.set_child (main_list_box); - } - - public void build_events () { - main_list_box.row_selected.connect ((item) => { - var voice_item = (VoiceMenuItem) item; - if (voice_item.is_plugin) { - Application.event_bus.voice_chosen (hand_position, voice_item.plugin.name, 0, 0); - Application.arranger_workstation.get_voice_rack (hand_position).active = true; - Application.arranger_workstation.get_voice_rack (hand_position) - .set_plugin_active (item.get_index () - plugin_start_index, true); - } else { - Application.arranger_workstation.get_voice_rack (hand_position).active = false; - Application.event_bus.voice_chosen ( - hand_position, voice_item.voice.name, voice_item.voice.bank, voice_item.voice.preset - ); - } - }); - Application.event_bus.arranger_ready.connect (() => { - populate (Application.arranger_workstation.get_voices ()); - populate_plugins (Application.arranger_workstation.get_voice_rack (hand_position).get_plugins ()); - }); - } - - public void populate (Voice[] voices) { - var temp_category = ""; - for (uint16 i = 0; i < voices.length; i++) { - var show_category = false; - if (temp_category != voices[i].category) { - temp_category = voices[i].category; - show_category = true; - } - - var menu_item = new VoiceMenuItem ( - last_voice_index++, - voices[i], - null, - show_category - ); - main_list_box.insert (menu_item, -1); - } - - plugin_start_index = last_voice_index; - } - - public void populate_plugins (List plugins) { - var temp_category = AudioPlugin.Protocol.NATIVE; - for (uint16 i = 0; i < plugins.length (); i++) { - if (plugins.nth_data (i).category == AudioPlugin.Category.VOICE) { - var show_category = false; - if (temp_category != plugins.nth_data (i).protocol) { - temp_category = plugins.nth_data (i).protocol; - show_category = true; - } - - var menu_item = new VoiceMenuItem ( - last_voice_index++, - Voice (), - plugins.nth_data (i), - show_category - ); - main_list_box.insert (menu_item, -1); - } - } - } - - public void scroll_to_selected_row () { - var selected_item = main_list_box.get_selected_row (); - if (selected_item != null) { - selected_item.grab_focus (); - - // var adj = main_list_box.get_adjustment (); - // if (adj != null) { - // int height, _htemp; - // height = selected_item.get_allocated_height (); - - // Timeout.add (200, () => { - // adj.set_value (_selected_index * height); - // return false; - // }); - // } - } - } - } -} diff --git a/src/Shell/Layouts/InfoDisplay.vala b/src/Shell/Layouts/InfoDisplay.vala deleted file mode 100644 index cf0c9418..00000000 --- a/src/Shell/Layouts/InfoDisplay.vala +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Shell.Layouts.Display; - -namespace Ensembles.Shell.Layouts { - public class InfoDisplay : Gtk.Box { - private Gtk.Overlay main_overlay; - private Gtk.Box splash_screen; - private Gtk.Label splash_screen_label; - private Gtk.Stack main_stack; - - private bool _fill_screen; - public bool fill_screen { - get { - return _fill_screen; - } - set { - _fill_screen = value; - if (value) { - remove_css_class ("panel"); - main_overlay.add_css_class ("fill"); - } else { - add_css_class ("panel"); - main_overlay.remove_css_class ("fill"); - } - } - } - - // Screens - private HomeScreen home_screen; - private StyleScreen style_screen; - private VoiceScreen voice_l_screen; - private VoiceScreen voice_r1_screen; - private VoiceScreen voice_r2_screen; - private DSPScreen dsp_screen; - private PluginScreen plugin_screen; - - construct { - build_ui (); - build_events (); - } - - public InfoDisplay () { - Object ( - hexpand: true, - vexpand: true, - width_request: 480, - height_request: 360 - ); - } - - private void build_ui () { - add_css_class ("panel"); - - main_overlay = new Gtk.Overlay () { - hexpand = true, - vexpand = true, - overflow = Gtk.Overflow.HIDDEN - }; - main_overlay.add_css_class ("display"); - append (main_overlay); - - splash_screen = new Gtk.Box (Gtk.Orientation.VERTICAL, 0); - splash_screen.add_css_class ("splash-screen-background"); - main_overlay.add_overlay (splash_screen); - - var splash_banner = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - hexpand = true, - vexpand = true - }; - splash_banner.add_css_class ("ensembles-logo-splash"); - splash_screen.append (splash_banner); - - splash_screen_label = new Gtk.Label (_("Initializing…")) { - xalign = 0, - margin_start = 8, - margin_bottom = 8, - margin_end = 8, - margin_top = 8, - opacity = 0.5 - }; - splash_screen_label.add_css_class ("splash-screen-label"); - splash_screen.append (splash_screen_label); - - main_stack = new Gtk.Stack () { - transition_type = Gtk.StackTransitionType.OVER_UP_DOWN - }; - main_stack.add_css_class ("display-stack"); - main_stack.add_css_class ("fade-black"); - main_overlay.set_child (main_stack); - - home_screen = new HomeScreen (); - main_stack.add_named (home_screen, "home"); - - style_screen = new StyleScreen (); - main_stack.add_named (style_screen, "style"); - - voice_l_screen = new VoiceScreen (Ensembles.VoiceHandPosition.LEFT); - main_stack.add_named (voice_l_screen, "voice-l"); - - voice_r1_screen = new VoiceScreen (Ensembles.VoiceHandPosition.RIGHT); - main_stack.add_named (voice_r1_screen, "voice-r1"); - - voice_r2_screen = new VoiceScreen (Ensembles.VoiceHandPosition.RIGHT_LAYERED); - main_stack.add_named (voice_r2_screen, "voice-r2"); - } - - private void build_events () { - Application.event_bus.arranger_ready.connect (() => { - splash_screen.add_css_class ("fade-black"); - - Timeout.add (1000, () => { - main_overlay.remove_overlay (splash_screen); - if (splash_screen != null) { - splash_screen.unref (); - } - - Timeout.add (200, () => { - main_stack.remove_css_class ("fade-black"); - return false; - }); - - Timeout.add (400, () => { - dsp_screen = new DSPScreen (Application.arranger_workstation.get_main_dsp_rack ()); - dsp_screen.close.connect (navigate_to_home); - main_stack.add_named (dsp_screen, "dsp"); - return false; - }); - return false; - }); - - }); - - home_screen.change_screen.connect ((screen_name) => { - main_stack.set_visible_child_name (screen_name); - }); - - Application.event_bus.send_initial_status.connect (update_status); - - style_screen.close.connect (navigate_to_home); - voice_l_screen.close.connect (navigate_to_home); - voice_r1_screen.close.connect (navigate_to_home); - voice_r2_screen.close.connect (navigate_to_home); - - Application.event_bus.show_plugin_ui.connect (show_plugin_screen); - } - - public void navigate_to_home () { - main_stack.set_visible_child_name ("home"); - } - - public void show_plugin_screen (Core.Plugins.AudioPlugins.AudioPlugin plugin) { - if (plugin_screen != null) { - main_stack.remove (plugin_screen); - plugin_screen = null; - } - - plugin_screen = new PluginScreen (plugin) { - history = main_stack.get_visible_child_name () - }; - plugin_screen.close.connect (() => { - main_stack.set_visible_child_name (plugin_screen.history); - }); - main_stack.add_named (plugin_screen, "plugin"); - main_stack.set_visible_child_name ("plugin"); - } - - public void update_status (string status) { - Idle.add (() => { - splash_screen_label.set_text (status); - return false; - }); - } - } -} diff --git a/src/Shell/Layouts/KeyboardPanel.vala b/src/Shell/Layouts/KeyboardPanel.vala deleted file mode 100644 index 7077daa9..00000000 --- a/src/Shell/Layouts/KeyboardPanel.vala +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Shell.Widgets; - -namespace Ensembles.Shell.Layouts { - public class KeyboardPanel : Gtk.Grid { - private Gtk.Overlay keyboard_info_bar; - private Keyboard keyboard; - - public KeyboardPanel () { - Object ( - hexpand: true, - vexpand: true, - height_request: 128 - ); - } - - construct { - add_css_class ("keyboard"); - build_ui (); - build_events (); - } - - private void build_ui () { - keyboard_info_bar = new Gtk.Overlay () { - hexpand = true, - height_request = 32 - }; - keyboard_info_bar.add_css_class ("keyboard-info-bar"); - attach (keyboard_info_bar, 0, 0); - - var keyboard_button_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 8) { - halign = Gtk.Align.END - }; - keyboard_info_bar.set_child (keyboard_button_box); - - var zoom_in_button = new Gtk.Button.from_icon_name ("zoom-in-symbolic"); - zoom_in_button.clicked.connect (() => { - keyboard.zoom_level += 48; - }); - keyboard_button_box.append (zoom_in_button); - - var zoom_out_button = new Gtk.Button.from_icon_name ("zoom-out-symbolic"); - zoom_out_button.clicked.connect (() => { - keyboard.zoom_level -= 48; - }); - keyboard_button_box.append (zoom_out_button); - - var zoom_reset_button = new Gtk.Button.from_icon_name ("zoom-fit-best-symbolic"); - zoom_reset_button.clicked.connect (() => { - keyboard.zoom_level = 0; - }); - keyboard_button_box.append (zoom_reset_button); - - var keyboard_scrollable = new Gtk.ScrolledWindow () { - hexpand = true, - vexpand = true, - kinetic_scrolling = false, - has_frame = false, - - }; - - keyboard_scrollable.set_placement (Gtk.CornerType.BOTTOM_LEFT); - attach (keyboard_scrollable, 0, 1); - - keyboard = new Keyboard (5) { - octave_offset = 3 - }; - keyboard_scrollable.set_child (keyboard); - } - - private void build_events () { - keyboard.key_event.connect ((event) => { - Application.event_bus.synth_send_event (event); - }); - Application.event_bus.synth_received_note.connect ((note, on) => { - keyboard.set_key_illumination (note, on); - }); - } - } -} diff --git a/src/Shell/Layouts/KioskLayout.vala b/src/Shell/Layouts/KioskLayout.vala deleted file mode 100644 index 14ba6e97..00000000 --- a/src/Shell/Layouts/KioskLayout.vala +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - - namespace Ensembles.Shell.Layouts { - public class KioskLayout : Gtk.Grid { - private unowned InfoDisplay info_display; - private unowned MixerBoard mixer_board; - - construct { - add_css_class ("panel"); - } - - public KioskLayout (InfoDisplay info_display, MixerBoard mixer_board) { - Object ( - hexpand: true, - vexpand: true - ); - - this.info_display = info_display; - this.mixer_board = mixer_board; - - build_ui (); - } - - private void build_ui () { - attach (info_display, 0, 0); - attach (mixer_board, 0, 1); - } - } -} diff --git a/src/Shell/Layouts/MixerBoard.vala b/src/Shell/Layouts/MixerBoard.vala deleted file mode 100644 index 5ecd19f2..00000000 --- a/src/Shell/Layouts/MixerBoard.vala +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Layouts { - public class MixerBoard : Gtk.Grid { - construct { - add_css_class ("panel"); - } - } -} diff --git a/src/Shell/Layouts/MobileLayout.vala b/src/Shell/Layouts/MobileLayout.vala deleted file mode 100644 index 027534be..00000000 --- a/src/Shell/Layouts/MobileLayout.vala +++ /dev/null @@ -1,175 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Layouts { - public class MobileLayout : Gtk.Grid { - private weak Layouts.AssignablesBoard assignables_board; - private weak Layouts.InfoDisplay info_display; - private weak Layouts.SynthControlPanel synth_control_panel; - private weak Layouts.VoiceNavPanel voice_nav_panel; - private weak Layouts.MixerBoard mixer_board; - private weak Layouts.SamplerPadsPanel sampler_pads_panel; - private weak Layouts.StyleControlPanel style_control_panel; - private weak Layouts.RegistryPanel registry_panel; - private weak Layouts.KeyboardPanel keyboard; - - private Gtk.Grid infoview; - private Gtk.Grid keyboardview; - private Gtk.Box style_registry_box; - private Gtk.Box style_controller_socket; - private Gtk.Box registry_socket; - private Gtk.Button start_button; - - private Gtk.ScrolledWindow scrolled_window; - private Adw.Flap flap; - private Gtk.Stack main_stack; - - private Gtk.ListBox menu_box; - - construct { - build_ui (); - build_events (); - } - - public MobileLayout (Layouts.AssignablesBoard? assignables_board, - Layouts.InfoDisplay? info_display, - Layouts.SynthControlPanel? synth_control_panel, - Layouts.VoiceNavPanel? voice_nav_panel, - Layouts.MixerBoard? mixer_board, - Layouts.SamplerPadsPanel? sampler_pads_panel, - Layouts.StyleControlPanel? style_control_panel, - Layouts.RegistryPanel? registry_panel, - Layouts.KeyboardPanel? keyboard) { - Object ( - width_request: 812, - height_request: 375 - ); - this.assignables_board = assignables_board; - this.info_display = info_display; - this.synth_control_panel = synth_control_panel; - this.voice_nav_panel = voice_nav_panel; - this.mixer_board = mixer_board; - this.sampler_pads_panel = sampler_pads_panel; - this.style_control_panel = style_control_panel; - this.registry_panel = registry_panel; - this.keyboard = keyboard; - } - - private void build_ui () { - flap = new Adw.Flap (); - attach (flap, 0, 0); - - // Make menu - menu_box = new Gtk.ListBox () { - width_request = 200 - }; - flap.set_flap (menu_box); - menu_box.add_css_class ("adw-listbox"); - - var info_entry = new Adw.ActionRow () { - title = "Info Display", - subtitle = "View interactive infomation display", - name = "info" - }; - menu_box.append (info_entry); - - var keyboard_entry = new Adw.ActionRow () { - title = "Keyboard", - subtitle = "Show the keys, style control buttons and registry buttons", - name = "keyboard" - }; - menu_box.append (keyboard_entry); - - main_stack = new Gtk.Stack () { - width_request = 800, - transition_type = Gtk.StackTransitionType.SLIDE_UP_DOWN, - transition_duration = 300 - }; - flap.set_content (main_stack); - - // Make Content - infoview = new Gtk.Grid (); - main_stack.add_named (infoview, "info-view"); - - keyboardview = new Gtk.Grid (); - main_stack.add_named (keyboardview, "keyboard-view"); - - scrolled_window = new Gtk.ScrolledWindow () { - height_request = 62, - vscrollbar_policy = Gtk.PolicyType.NEVER - }; - keyboardview.attach (scrolled_window, 0, 0); - style_registry_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); - scrolled_window.set_child (style_registry_box); - - style_controller_socket = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); - style_registry_box.append (style_controller_socket); - - var start_button_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 2); - start_button_box.add_css_class ("panel"); - style_registry_box.append (start_button_box); - - start_button = new Gtk.Button.from_icon_name ("media-playback-start-symbolic") { - width_request = 64, - height_request = 32 - }; - start_button.add_css_class (Granite.STYLE_CLASS_DESTRUCTIVE_ACTION); - start_button.remove_css_class ("image-button"); - start_button.clicked.connect (() => { - Application.event_bus.style_play_toggle (); - }); - - start_button_box.append (start_button); - start_button_box.append (new Gtk.Label (_("START/STOP")) { opacity = 0.5 }); - - registry_socket = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0); - style_registry_box.append (registry_socket); - } - - public void reparent () { - assignables_board.unparent (); - info_display.unparent (); - synth_control_panel.unparent (); - voice_nav_panel.unparent (); - mixer_board.unparent (); - sampler_pads_panel.unparent (); - style_control_panel.unparent (); - registry_panel.unparent (); - keyboard.unparent (); - - infoview.attach (info_display, 0, 0); - info_display.fill_screen = true; - - style_controller_socket.append (style_control_panel); - registry_socket.append (registry_panel); - keyboardview.attach (keyboard, 0, 1); - } - - private void build_events () { - menu_box.row_selected.connect ((row) => { - main_stack.set_visible_child_name (row.name + "-view"); - }); - - Application.event_bus.show_menu.connect ((show) => { - flap.set_reveal_flap (show); - return !show; - }); - - flap.notify.connect ((param) => { - if (param.name == "reveal-flap") { - Application.event_bus.menu_shown (flap.reveal_flap); - Idle.add (() => { - if (flap.reveal_flap && flap.folded) { - main_stack.add_css_class ("dimmed"); - } else { - main_stack.remove_css_class ("dimmed"); - } - return false; - }); - } - }); - } - } -} diff --git a/src/Shell/Layouts/PluginView.vala b/src/Shell/Layouts/PluginView.vala deleted file mode 100644 index eb772f0f..00000000 --- a/src/Shell/Layouts/PluginView.vala +++ /dev/null @@ -1,15 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Layouts { - public class PluginView : Gtk.Box { - public weak Display.DisplayWindow plugin_ui { get; set; } - - public void reparent () { - plugin_ui.unparent (); - append (plugin_ui); - } - } -} diff --git a/src/Shell/Layouts/RegistryPanel.vala b/src/Shell/Layouts/RegistryPanel.vala deleted file mode 100644 index 354355c1..00000000 --- a/src/Shell/Layouts/RegistryPanel.vala +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Layouts { - public class RegistryPanel : Gtk.Grid { - construct { - add_css_class ("panel"); - } - } -} diff --git a/src/Shell/Layouts/SamplerPadsPanel.vala b/src/Shell/Layouts/SamplerPadsPanel.vala deleted file mode 100644 index 3c724d51..00000000 --- a/src/Shell/Layouts/SamplerPadsPanel.vala +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Layouts { - public class SamplerPadsPanel : Gtk.Grid { - construct { - add_css_class ("panel"); - } - } -} diff --git a/src/Shell/Layouts/StyleControlPanel.vala b/src/Shell/Layouts/StyleControlPanel.vala deleted file mode 100644 index 76750612..00000000 --- a/src/Shell/Layouts/StyleControlPanel.vala +++ /dev/null @@ -1,591 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Models; - -namespace Ensembles.Shell.Layouts { - public class StyleControlPanel : Gtk.Box { - private Gtk.Button intro_1_button; - private Gtk.Button intro_2_button; - private Gtk.Button intro_3_button; - private Gtk.Button break_button; - private Gtk.Button variation_a_button; - private Gtk.Button variation_b_button; - private Gtk.Button variation_c_button; - private Gtk.Button variation_d_button; - private Gtk.Button ending_1_button; - private Gtk.Button ending_2_button; - private Gtk.Button ending_3_button; - private Gtk.Button sync_start_button; - - private StylePartType current_part = StylePartType.VARIATION_A; - private StylePartType next_part = StylePartType.VARIATION_A; - - public StyleControlPanel () { - Object ( - orientation: Gtk.Orientation.HORIZONTAL, - spacing: 4, - hexpand: true - ); - } - - construct { - build_ui (); - build_events (); - } - - private void build_ui () { - add_css_class ("panel"); - - var intro_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 2); - append (intro_box); - - var intro_button_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - hexpand = true, - homogeneous = true - }; - intro_button_box.add_css_class (Granite.STYLE_CLASS_LINKED); - intro_box.append (intro_button_box); - intro_box.append (new Gtk.Label (_("INTRO")) { opacity = 0.5 } ); - - var variation_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 2); - append (variation_box); - - var variation_button_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - hexpand = true, - homogeneous = true - }; - variation_button_box.add_css_class (Granite.STYLE_CLASS_LINKED); - variation_box.append (variation_button_box); - variation_box.append (new Gtk.Label (_("VARIATION/FILL-IN")) { opacity = 0.5 } ); - - var break_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 2); - append (break_box); - - break_button = new Gtk.Button.from_icon_name ("style-break-symbolic") { - tooltip_text = "Break", - has_tooltip = true, - hexpand = true, - height_request = 32 - }; - break_button.remove_css_class ("image-button"); - break_box.append (break_button); - break_box.append (new Gtk.Label (_("BREAK")) { opacity = 0.5 } ); - - var ending_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 2); - append (ending_box); - - var ending_button_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - hexpand = true, - homogeneous = true - }; - ending_button_box.add_css_class (Granite.STYLE_CLASS_LINKED); - ending_box.append (ending_button_box); - ending_box.append (new Gtk.Label (_("ENDING")) { opacity = 0.5 } ); - - intro_1_button = new Gtk.Button.with_label (_("1")) { - height_request = 32 - }; - intro_button_box.append (intro_1_button); - intro_2_button = new Gtk.Button.with_label (_("2")) { - height_request = 32 - }; - intro_button_box.append (intro_2_button); - intro_3_button = new Gtk.Button.with_label (_("3")) { - height_request = 32 - }; - intro_button_box.append (intro_3_button); - - variation_a_button = new Gtk.Button.with_label (_("A")) { - height_request = 32 - }; - variation_button_box.append (variation_a_button); - variation_b_button = new Gtk.Button.with_label (_("B")) { - height_request = 32 - }; - variation_button_box.append (variation_b_button); - variation_c_button = new Gtk.Button.with_label (_("C")) { - height_request = 32 - }; - variation_button_box.append (variation_c_button); - variation_d_button = new Gtk.Button.with_label (_("D")) { - height_request = 32 - }; - variation_button_box.append (variation_d_button); - - ending_1_button = new Gtk.Button.with_label (_("1")) { - height_request = 32 - }; - ending_button_box.append (ending_1_button); - ending_2_button = new Gtk.Button.with_label (_("2")) { - height_request = 32 - }; - ending_button_box.append (ending_2_button); - ending_3_button = new Gtk.Button.with_label (_("3")) { - height_request = 32 - }; - ending_button_box.append (ending_3_button); - - var sync_start_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 2); - append (sync_start_box); - sync_start_button = new Gtk.Button.from_icon_name ("style-sync-start-symbolic") { - tooltip_text = "Sync Start / Stop", - has_tooltip = true, - hexpand = true, - height_request = 32 - }; - sync_start_button.remove_css_class ("image-button"); - sync_start_box.append (sync_start_button); - sync_start_box.append (new Gtk.Label (_("SYNC")) { opacity = 0.5 } ); - - highlight_part (); - } - - private void build_events () { - intro_1_button.clicked.connect (() => { - Application.event_bus.style_set_part (StylePartType.INTRO_1); - }); - - intro_2_button.clicked.connect (() => { - Application.event_bus.style_set_part (StylePartType.INTRO_2); - }); - - intro_3_button.clicked.connect (() => { - Application.event_bus.style_set_part (StylePartType.INTRO_3); - }); - - variation_a_button.clicked.connect (() => { - Application.event_bus.style_set_part (StylePartType.VARIATION_A); - }); - - variation_b_button.clicked.connect (() => { - Application.event_bus.style_set_part (StylePartType.VARIATION_B); - }); - - variation_c_button.clicked.connect (() => { - Application.event_bus.style_set_part (StylePartType.VARIATION_C); - }); - - variation_d_button.clicked.connect (() => { - Application.event_bus.style_set_part (StylePartType.VARIATION_D); - }); - - ending_1_button.clicked.connect (() => { - Application.event_bus.style_set_part (StylePartType.ENDING_1); - }); - - ending_2_button.clicked.connect (() => { - Application.event_bus.style_set_part (StylePartType.ENDING_2); - }); - - ending_3_button.clicked.connect (() => { - Application.event_bus.style_set_part (StylePartType.ENDING_3); - }); - - Application.event_bus.style_current_part_changed.connect ((part) => { - current_part = part; - highlight_part (); - }); - - Application.event_bus.style_next_part_changed.connect ((part) => { - next_part = part; - highlight_part (); - }); - - sync_start_button.clicked.connect (() => { - Application.event_bus.style_sync (); - }); - - Application.event_bus.style_sync_changed.connect ((active) => { - if (active) { - sync_start_button.add_css_class ("pulse"); - } else { - sync_start_button.remove_css_class ("pulse"); - } - }); - - break_button.clicked.connect (() => { - Application.event_bus.style_break (); - }); - - Application.event_bus.style_break_changed.connect ((active) => { - if (active) { - break_button.add_css_class ("pulse"); - } else { - break_button.remove_css_class ("pulse"); - } - }); - } - - private void highlight_part () { - switch (current_part) { - case StylePartType.INTRO_1: - intro_1_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.INTRO_2: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.INTRO_3: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.ENDING_1: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.ENDING_2: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.ENDING_3: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.VARIATION_A: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.VARIATION_B: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.VARIATION_C: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.VARIATION_D: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.add_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.FILL_A: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.add_css_class ("pulse-fill"); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.FILL_B: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.add_css_class ("pulse-fill"); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.FILL_C: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.add_css_class ("pulse-fill"); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.remove_css_class ("pulse-fill"); - break; - case StylePartType.FILL_D: - intro_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - intro_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_1_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_2_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - ending_3_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_a_button.remove_css_class ("pulse-fill"); - variation_b_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_b_button.remove_css_class ("pulse-fill"); - variation_c_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_c_button.remove_css_class ("pulse-fill"); - variation_d_button.remove_css_class (Granite.STYLE_CLASS_SUGGESTED_ACTION); - variation_d_button.add_css_class ("pulse-fill"); - break; - default: - break; - } - - if (current_part != next_part) { - switch (next_part) { - case StylePartType.INTRO_1: - intro_1_button.add_css_class ("pulse"); - intro_2_button.remove_css_class ("pulse"); - intro_3_button.remove_css_class ("pulse"); - ending_1_button.remove_css_class ("pulse"); - ending_2_button.remove_css_class ("pulse"); - ending_3_button.remove_css_class ("pulse"); - variation_a_button.remove_css_class ("pulse"); - variation_b_button.remove_css_class ("pulse"); - variation_c_button.remove_css_class ("pulse"); - variation_d_button.remove_css_class ("pulse"); - break; - case StylePartType.INTRO_2: - intro_1_button.remove_css_class ("pulse"); - intro_2_button.add_css_class ("pulse"); - intro_3_button.remove_css_class ("pulse"); - ending_1_button.remove_css_class ("pulse"); - ending_2_button.remove_css_class ("pulse"); - ending_3_button.remove_css_class ("pulse"); - variation_a_button.remove_css_class ("pulse"); - variation_b_button.remove_css_class ("pulse"); - variation_c_button.remove_css_class ("pulse"); - variation_d_button.remove_css_class ("pulse"); - break; - case StylePartType.INTRO_3: - intro_1_button.remove_css_class ("pulse"); - intro_2_button.add_css_class ("pulse"); - intro_3_button.remove_css_class ("pulse"); - ending_1_button.remove_css_class ("pulse"); - ending_2_button.remove_css_class ("pulse"); - ending_3_button.remove_css_class ("pulse"); - variation_a_button.remove_css_class ("pulse"); - variation_b_button.remove_css_class ("pulse"); - variation_c_button.remove_css_class ("pulse"); - variation_d_button.remove_css_class ("pulse"); - break; - case StylePartType.ENDING_1: - intro_1_button.remove_css_class ("pulse"); - intro_2_button.remove_css_class ("pulse"); - intro_3_button.remove_css_class ("pulse"); - ending_1_button.add_css_class ("pulse"); - ending_2_button.remove_css_class ("pulse"); - ending_3_button.remove_css_class ("pulse"); - variation_a_button.remove_css_class ("pulse"); - variation_b_button.remove_css_class ("pulse"); - variation_c_button.remove_css_class ("pulse"); - variation_d_button.remove_css_class ("pulse"); - break; - case StylePartType.ENDING_2: - intro_1_button.remove_css_class ("pulse"); - intro_2_button.remove_css_class ("pulse"); - intro_3_button.remove_css_class ("pulse"); - ending_1_button.remove_css_class ("pulse"); - ending_2_button.add_css_class ("pulse"); - ending_3_button.remove_css_class ("pulse"); - variation_a_button.remove_css_class ("pulse"); - variation_b_button.remove_css_class ("pulse"); - variation_c_button.remove_css_class ("pulse"); - variation_d_button.remove_css_class ("pulse"); - break; - case StylePartType.ENDING_3: - intro_1_button.remove_css_class ("pulse"); - intro_2_button.remove_css_class ("pulse"); - intro_3_button.remove_css_class ("pulse"); - ending_1_button.remove_css_class ("pulse"); - ending_2_button.remove_css_class ("pulse"); - ending_3_button.add_css_class ("pulse"); - variation_a_button.remove_css_class ("pulse"); - variation_b_button.remove_css_class ("pulse"); - variation_c_button.remove_css_class ("pulse"); - variation_d_button.remove_css_class ("pulse"); - break; - case StylePartType.VARIATION_A: - intro_1_button.remove_css_class ("pulse"); - intro_2_button.remove_css_class ("pulse"); - intro_3_button.remove_css_class ("pulse"); - ending_1_button.remove_css_class ("pulse"); - ending_2_button.remove_css_class ("pulse"); - ending_3_button.remove_css_class ("pulse"); - variation_a_button.add_css_class ("pulse"); - variation_b_button.remove_css_class ("pulse"); - variation_c_button.remove_css_class ("pulse"); - variation_d_button.remove_css_class ("pulse"); - break; - case StylePartType.VARIATION_B: - intro_1_button.remove_css_class ("pulse"); - intro_2_button.remove_css_class ("pulse"); - intro_3_button.remove_css_class ("pulse"); - ending_1_button.remove_css_class ("pulse"); - ending_2_button.remove_css_class ("pulse"); - ending_3_button.remove_css_class ("pulse"); - variation_a_button.remove_css_class ("pulse"); - variation_b_button.add_css_class ("pulse"); - variation_c_button.remove_css_class ("pulse"); - variation_d_button.remove_css_class ("pulse"); - break; - case StylePartType.VARIATION_C: - intro_1_button.remove_css_class ("pulse"); - intro_2_button.remove_css_class ("pulse"); - intro_3_button.remove_css_class ("pulse"); - ending_1_button.remove_css_class ("pulse"); - ending_2_button.remove_css_class ("pulse"); - ending_3_button.remove_css_class ("pulse"); - variation_a_button.remove_css_class ("pulse"); - variation_b_button.remove_css_class ("pulse"); - variation_c_button.add_css_class ("pulse"); - variation_d_button.remove_css_class ("pulse"); - break; - case StylePartType.VARIATION_D: - intro_1_button.remove_css_class ("pulse"); - intro_2_button.remove_css_class ("pulse"); - intro_3_button.remove_css_class ("pulse"); - ending_1_button.remove_css_class ("pulse"); - ending_2_button.remove_css_class ("pulse"); - ending_3_button.remove_css_class ("pulse"); - variation_a_button.remove_css_class ("pulse"); - variation_b_button.remove_css_class ("pulse"); - variation_c_button.remove_css_class ("pulse"); - variation_d_button.add_css_class ("pulse"); - break; - default: - break; - } - } else { - intro_1_button.remove_css_class ("pulse"); - intro_2_button.remove_css_class ("pulse"); - intro_3_button.remove_css_class ("pulse"); - ending_1_button.remove_css_class ("pulse"); - ending_2_button.remove_css_class ("pulse"); - ending_3_button.remove_css_class ("pulse"); - variation_a_button.remove_css_class ("pulse"); - variation_b_button.remove_css_class ("pulse"); - variation_c_button.remove_css_class ("pulse"); - variation_d_button.remove_css_class ("pulse"); - } - } - } -} diff --git a/src/Shell/Layouts/SynthControlPanel.vala b/src/Shell/Layouts/SynthControlPanel.vala deleted file mode 100644 index 9f6e77d7..00000000 --- a/src/Shell/Layouts/SynthControlPanel.vala +++ /dev/null @@ -1,19 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Layouts { - public class SynthControlPanel : Gtk.Grid { - construct { - add_css_class ("panel"); - } - - public SynthControlPanel () { - Object ( - hexpand: true, - vexpand: true - ); - } - } -} diff --git a/src/Shell/Layouts/VoiceNavPanel.vala b/src/Shell/Layouts/VoiceNavPanel.vala deleted file mode 100644 index 9bf37e0f..00000000 --- a/src/Shell/Layouts/VoiceNavPanel.vala +++ /dev/null @@ -1,12 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Layouts { - public class VoiceNavPanel : Gtk.Grid { - construct { - add_css_class ("panel"); - } - } -} diff --git a/src/Shell/MainWindow.vala b/src/Shell/MainWindow.vala deleted file mode 100644 index 8aa5d5d6..00000000 --- a/src/Shell/MainWindow.vala +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - - namespace Ensembles.Shell { - public class MainWindow : Gtk.ApplicationWindow { - // Event Handling - private Gtk.EventControllerKey event_controller_key; - - // Headerbar - private Gtk.HeaderBar headerbar; - - // Responsive UI - private Adw.Squeezer squeezer; - private Gtk.ToggleButton flap_button; - private bool flap_revealed = true; - - // Various major layouts - private Layouts.DesktopLayout desktop_layout; - private Layouts.MobileLayout mobile_layout; - private Layouts.KioskLayout kiosk_layout; - - // Sub-layouts - private Layouts.AssignablesBoard assignables_board; - private Layouts.InfoDisplay info_display; - private Layouts.SynthControlPanel synth_control_panel; - private Layouts.VoiceNavPanel voice_nav_panel; - private Layouts.MixerBoard mixer_board; - private Layouts.SamplerPadsPanel sampler_pads_panel; - private Layouts.StyleControlPanel style_control_panel; - private Layouts.RegistryPanel registry_panel; - private Layouts.KeyboardPanel keyboard; - - // Headerbar - private Widgets.BeatVisualization beat_visualization; - - public MainWindow (Ensembles.Application? ensembles_app) { - Object ( - application: ensembles_app, - icon_name: Constants.APP_ID, - title: "Ensembles", - default_height: 700 - ); - } - - construct { - build_ui (); - build_events (); - } - - private void build_ui () { - if (Application.kiosk_mode) { - decorated = false; - fullscreened = true; - - info_display = new Layouts.InfoDisplay (); - info_display.fill_screen = true; - mixer_board = new Layouts.MixerBoard (); - - kiosk_layout = new Layouts.KioskLayout (info_display, mixer_board); - set_child (kiosk_layout); - return; - } - - // Make headerbar - headerbar = new Gtk.HeaderBar () { - show_title_buttons = true, - }; - - set_titlebar (headerbar); - - flap_button = new Gtk.ToggleButton () { - visible = false - }; - flap_button.set_icon_name ("view-continuous-symbolic"); - flap_button.remove_css_class ("image-button"); - flap_button.clicked.connect (() => { - flap_revealed = Application.event_bus.show_menu (flap_revealed); - }); - headerbar.pack_start (flap_button); - - beat_visualization = new Widgets.BeatVisualization (); - headerbar.pack_start (beat_visualization); - - squeezer = new Adw.Squeezer () { - orientation = Gtk.Orientation.VERTICAL, - transition_type = Adw.SqueezerTransitionType.CROSSFADE, - transition_duration = 400 - }; - set_child (squeezer); - - assignables_board = new Layouts.AssignablesBoard (); - info_display = new Layouts.InfoDisplay (); - synth_control_panel = new Layouts.SynthControlPanel (); - voice_nav_panel = new Layouts.VoiceNavPanel (); - mixer_board = new Layouts.MixerBoard (); - sampler_pads_panel = new Layouts.SamplerPadsPanel (); - style_control_panel = new Layouts.StyleControlPanel (); - registry_panel = new Layouts.RegistryPanel (); - keyboard = new Layouts.KeyboardPanel (); - - desktop_layout = new Layouts.DesktopLayout (assignables_board, - info_display, - synth_control_panel, - voice_nav_panel, - mixer_board, - sampler_pads_panel, - style_control_panel, - registry_panel, - keyboard); - squeezer.add (desktop_layout); - desktop_layout.reparent (); - - - mobile_layout = new Layouts.MobileLayout (assignables_board, - info_display, - synth_control_panel, - voice_nav_panel, - mixer_board, - sampler_pads_panel, - style_control_panel, - registry_panel, - keyboard); - squeezer.add (mobile_layout); - } - - public void show_ui () { - present (); - show (); - } - - private void build_events () { - event_controller_key = new Gtk.EventControllerKey (); - ((Gtk.Widget)this).add_controller (event_controller_key); - - event_controller_key.key_pressed.connect ((keyval, keycode, state) => { - Console.log ("key: %u".printf (keyval)); - - return false; - }); - - Application.event_bus.arranger_ready.connect (() => { - Console.log ("Arranger Workstation Initialized!", Console.LogLevel.SUCCESS); - }); - - notify["default-height"].connect (() => { - if (!Application.kiosk_mode) { - flap_button.visible = squeezer.get_visible_child () == mobile_layout; - - if (squeezer.get_visible_child () == desktop_layout) { - desktop_layout.reparent (); - } else { - mobile_layout.reparent (); - } - } - - Application.event_bus.size_change (); - }); - - notify["default-width"].connect (() => { - Application.event_bus.size_change (); - }); - - notify["maximized"].connect (() => { - fullscreen (); - Timeout.add (100, () => { - if (!Application.kiosk_mode) { - flap_button.visible = squeezer.get_visible_child () == mobile_layout; - - if (squeezer.get_visible_child () == desktop_layout) { - desktop_layout.reparent (); - } else { - mobile_layout.reparent (); - } - } - - Application.event_bus.size_change (); - return false; - }); - }); - - Application.event_bus.menu_shown.connect ((shown) => { - flap_revealed = !shown; - flap_button.active = shown; - }); - - ((Gtk.Widget) this).realize.connect (() => { - if (Application.kiosk_mode) { - var display = Gdk.Display.get_default (); - var monitor = display.get_monitor_at_surface (get_surface ()); - set_default_size (monitor.geometry.width, monitor.geometry.height); - kiosk_layout.width_request = monitor.geometry.width; - kiosk_layout.height_request = monitor.geometry.height; - } - }); - } - } - } diff --git a/src/Shell/Plugins/AudioPlugins/Widgets/AudioPluginControl.vala b/src/Shell/Plugins/AudioPlugins/Widgets/AudioPluginControl.vala deleted file mode 100644 index e3a58b85..00000000 --- a/src/Shell/Plugins/AudioPlugins/Widgets/AudioPluginControl.vala +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Core.Plugins.AudioPlugins; - -namespace Ensembles.Shell.Plugins.AudioPlugins.Widgets { - public class AudioPluginControl : Gtk.Box { - private Gtk.IconSize widget_size; - private float* variable; - private unowned Port port; - - private Gtk.Label control_label; - - public AudioPluginControl (Port port, float* variable, Gtk.IconSize widget_size = Gtk.IconSize.NORMAL) { - Object ( - margin_start: 8, - margin_bottom: 8, - margin_top: 8, - margin_end: 8, - halign: Gtk.Align.CENTER, - orientation: Gtk.Orientation.VERTICAL - ); - - this.widget_size = widget_size; - this.variable = variable; - this.port = port; - - build_ui (); - } - - private void build_ui () { - add_css_class (Granite.STYLE_CLASS_CARD); - - control_label = new Gtk.Label (port.name) { - margin_top = 16, - margin_start = 16, - margin_end = 16 - }; - control_label.add_css_class (Granite.STYLE_CLASS_H3_LABEL); - append (control_label); - - if (widget_size == Gtk.IconSize.LARGE) { - var knob = new Shell.Widgets.Knob () { - width_request = 150, - height_request = 150, - margin_start = 16, - margin_end = 16, - margin_top = 16, - margin_bottom = 16, - draw_value = true - }; - - append (knob); - - if (port is Core.Plugins.AudioPlugins.Lv2.LV2ControlPort) { - var lv2_control_port = (Core.Plugins.AudioPlugins.Lv2.LV2ControlPort) port; - knob.adjustment.lower = lv2_control_port.min_value; - knob.adjustment.upper = lv2_control_port.max_value; - knob.adjustment.step_increment = lv2_control_port.step; - knob.value = *variable; - - knob.add_mark (lv2_control_port.min_value); - knob.add_mark (lv2_control_port.default_value); - knob.add_mark (lv2_control_port.max_value); - } - - knob.value_changed.connect ((value) => { - *variable = (float) value; - }); - } else { - var scale = new Gtk.Scale (Gtk.Orientation.VERTICAL, null) { - height_request = 150, - margin_start = 16, - margin_end = 16, - margin_top = 16, - margin_bottom = 16, - inverted = true - }; - - append (scale); - - if (port is Core.Plugins.AudioPlugins.Lv2.LV2ControlPort) { - var lv2_control_port = (Core.Plugins.AudioPlugins.Lv2.LV2ControlPort) port; - scale.adjustment.lower = lv2_control_port.min_value; - scale.adjustment.upper = lv2_control_port.max_value; - scale.adjustment.step_increment = lv2_control_port.step; - scale.adjustment.value = *variable; - - scale.add_mark ( - lv2_control_port.min_value, Gtk.PositionType.RIGHT, - null - ); - scale.add_mark ( - lv2_control_port.default_value, - Gtk.PositionType.RIGHT, - null - ); - scale.add_mark ( - lv2_control_port.max_value, - Gtk.PositionType.RIGHT, - null - ); - } - - scale.value_changed.connect ((range) => { - *variable = (float) range.get_value (); - }); - } - } - } -} diff --git a/src/Shell/Widgets/BeatVisualization.vala b/src/Shell/Widgets/BeatVisualization.vala deleted file mode 100644 index 9308a001..00000000 --- a/src/Shell/Widgets/BeatVisualization.vala +++ /dev/null @@ -1,101 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Widgets { - public class BeatVisualization : Gtk.Box { - Gtk.Fixed beat_counter_visual; - private uint beat_count = 0; - private uint8 tempo = 120; - private uint8 beats_per_bar = 4; - private uint8 beat_duration = 4; - - construct { - build_ui (); - } - - private void build_ui () { - beat_counter_visual = new Gtk.Fixed () { - width_request = 108, - height_request = 32, - valign = Gtk.Align.CENTER - }; - - beat_counter_visual.add_css_class ("beat-counter-0"); - append (beat_counter_visual); - - Application.event_bus.beat.connect ((measure, time_sig_n, time_sig_d) => { - beats_per_bar = time_sig_n; - beat_duration = time_sig_d; - beat (measure); - }); - - Application.event_bus.beat_reset.connect (() => { - beat_count = 0; - }); - } - - private void beat (bool measure) { - if (measure) { - beat_count = 1; - } - - if (beat_count < 5) { - set_beat_graphic (beat_count); - Timeout.add (120000 / (tempo * beat_duration), () => { - set_beat_graphic (0); - return false; - }); - } else { - beat_count = 1; - } - - beat_count++; - } - - private void set_beat_graphic (uint val) { - Idle.add (() => { - switch (val) { - case 0: - beat_counter_visual.add_css_class ("beat-counter-0"); - beat_counter_visual.remove_css_class ("beat-counter-1"); - beat_counter_visual.remove_css_class ("beat-counter-2"); - beat_counter_visual.remove_css_class ("beat-counter-3"); - beat_counter_visual.remove_css_class ("beat-counter-4"); - break; - case 1: - beat_counter_visual.remove_css_class ("beat-counter-0"); - beat_counter_visual.add_css_class ("beat-counter-1"); - beat_counter_visual.remove_css_class ("beat-counter-2"); - beat_counter_visual.remove_css_class ("beat-counter-3"); - beat_counter_visual.remove_css_class ("beat-counter-4"); - break; - case 2: - beat_counter_visual.remove_css_class ("beat-counter-0"); - beat_counter_visual.remove_css_class ("beat-counter-1"); - beat_counter_visual.add_css_class ("beat-counter-2"); - beat_counter_visual.remove_css_class ("beat-counter-3"); - beat_counter_visual.remove_css_class ("beat-counter-4"); - break; - case 3: - beat_counter_visual.remove_css_class ("beat-counter-0"); - beat_counter_visual.remove_css_class ("beat-counter-1"); - beat_counter_visual.remove_css_class ("beat-counter-2"); - beat_counter_visual.add_css_class ("beat-counter-3"); - beat_counter_visual.remove_css_class ("beat-counter-4"); - break; - case 4: - beat_counter_visual.remove_css_class ("beat-counter-0"); - beat_counter_visual.remove_css_class ("beat-counter-1"); - beat_counter_visual.remove_css_class ("beat-counter-2"); - beat_counter_visual.remove_css_class ("beat-counter-3"); - beat_counter_visual.add_css_class ("beat-counter-4"); - break; - } - - return false; - }); - } - } -} diff --git a/src/Shell/Widgets/Display/DSPInstanceMenuItem.vala b/src/Shell/Widgets/Display/DSPInstanceMenuItem.vala deleted file mode 100644 index c37ecc9b..00000000 --- a/src/Shell/Widgets/Display/DSPInstanceMenuItem.vala +++ /dev/null @@ -1,129 +0,0 @@ -/* -* Copyright 2020-2023 Subhadeep Jasu -* SPDX-License-Identifier: GPL-3.0-or-later -*/ - -using Ensembles.Models; -using Ensembles.Core.Plugins.AudioPlugins; - -namespace Ensembles.Shell.Widgets.Display { - public class DSPInstanceMenuItem : Gtk.ListBoxRow { - public unowned AudioPlugin plugin { get; set; } - protected unowned Layouts.Display.DSPScreen rack_shell { get; set; } - public bool show_category { get; set; } - public Knob gain_knob; - public Gtk.CheckButton active_switch; - public Gtk.Button show_ui_button; - public Gtk.Button delete_instance_button; - - public DSPInstanceMenuItem (AudioPlugin plugin, Layouts.Display.DSPScreen rack_shell) { - Object ( - plugin: plugin, - rack_shell: rack_shell - ); - - build_ui (); - build_events (); - } - - private void build_ui () { - add_css_class ("menu-item"); - add_css_class ("p-8"); - - var menu_item_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12); - set_child (menu_item_box); - - active_switch = new Gtk.CheckButton () { - valign = Gtk.Align.CENTER, - halign = Gtk.Align.CENTER, - margin_end = 16 - }; - active_switch.add_css_class ("audio-switch"); - active_switch.active = plugin.active; - menu_item_box.append (active_switch); - - var plugin_name_label = new Gtk.Label (plugin.name) { - halign = Gtk.Align.START, - hexpand = true - }; - plugin_name_label.add_css_class ("menu-item-name"); - menu_item_box.append (plugin_name_label); - - gain_knob = new Shell.Widgets.Knob.with_range (-12, 0, 1) { - width_request = 40, - height_request = 40, - tooltip_text = _("Dry / Wet Mix") - }; - gain_knob.add_css_class ("small"); - gain_knob.value = Utils.Math.convert_gain_to_db (plugin.mix_gain); - gain_knob.add_mark (-12); - gain_knob.add_mark (0); - menu_item_box.append (gain_knob); - - var button_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - homogeneous = true, - height_request = 36, - width_request = 80 - }; - button_box.add_css_class (Granite.STYLE_CLASS_LINKED); - menu_item_box.append (button_box); - - if (plugin.ui != null) { - show_ui_button = new Gtk.Button.from_icon_name ( - "preferences-other-symbolic" - ) { - tooltip_text = _("Show Plugin UI") - }; - button_box.append (show_ui_button); - } - - delete_instance_button = new Gtk.Button.from_icon_name ( - "edit-delete-symbolic" - ) { - tooltip_text = _("Remove Plugin from Rack") - }; - button_box.append (delete_instance_button); - } - - private void build_events () { - gain_knob.value_changed.connect ((db) => { - plugin.mix_gain = (float) Utils.Math.convert_db_to_gain (db); - }); - - active_switch.notify["active"].connect (() => { - plugin.active = active_switch.active; - }); - - if (plugin.ui != null) { - show_ui_button.clicked.connect (() => { - Application.event_bus.show_plugin_ui (plugin); - }); - } - - delete_instance_button.clicked.connect (() => { - rack_shell.delete_plugin_item (this); - }); - - plugin.notify["active"].connect (() => { - active_switch.active = plugin.active; - }); - - plugin.notify["mix-gain"].connect (() => { - gain_knob.value = Utils.Math.convert_gain_to_db (plugin.mix_gain); - }); - } - - public void capture_attention () { - Timeout.add (100, () => { - add_css_class ("capture-attention"); - - Timeout.add_seconds (1, () => { - remove_css_class ("capture-attention"); - return false; - }); - - return false; - }); - } - } -} diff --git a/src/Shell/Widgets/Display/DSPMenuItem.vala b/src/Shell/Widgets/Display/DSPMenuItem.vala deleted file mode 100644 index 678385f1..00000000 --- a/src/Shell/Widgets/Display/DSPMenuItem.vala +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - - using Ensembles.Core.Plugins.AudioPlugins; - -namespace Ensembles.Shell.Widgets.Display { - public class DSPMenuItem : Gtk.ListBoxRow { - public unowned AudioPlugin plugin { get; set; } - - private Gtk.Button insert_button; - - public DSPMenuItem (AudioPlugin plugin, Core.Racks.DSPRack dsp_rack) { - Object ( - plugin: plugin, - height_request: 68 - ); - - build_ui (); - - insert_button.clicked.connect (() => { - try { - dsp_rack.append (plugin.duplicate ()); - } catch (PluginError e) { - Console.log ("Failed to add plugin %s with error %s".printf (plugin.name, e.message), - Console.LogLevel.WARNING); - } - }); - } - - private void build_ui () { - add_css_class ("plugin-item"); - - var menu_item_grid = new Gtk.Grid (); - set_child (menu_item_grid); - - var plugin_name_label = new Gtk.Label (plugin.name) { - halign = Gtk.Align.START, - hexpand = true - }; - plugin_name_label.add_css_class ("plugin-item-name"); - menu_item_grid.attach (plugin_name_label, 0, 0); - - var extra_info_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 4); - extra_info_box.add_css_class ("plugin-item-info"); - menu_item_grid.attach (extra_info_box, 0, 1); - - var extra_info_labels = new string[0]; - if (plugin.author_name != null && plugin.author_name.length > 0) { - extra_info_labels.resize (1); - if (plugin.author_name.length > 32) { - extra_info_labels[0] = plugin.author_name.substring (0, 32) + "…"; - } else { - extra_info_labels[0] = plugin.author_name; - } - } - - if (plugin.author_homepage != null && plugin.author_homepage.length > 0) { - extra_info_labels.resize (extra_info_labels.length + 1); - - if (plugin.author_homepage.length > 36) { - extra_info_labels[extra_info_labels.length - 1] = - plugin.author_homepage.substring (0, 36) + "…"; - } else { - extra_info_labels[extra_info_labels.length - 1] = plugin.author_homepage; - } - - } - - if (extra_info_labels.length > 0) { - extra_info_box.append ( - new Gtk.Label (string.joinv (" ⏺ ", extra_info_labels)) { - opacity = 0.5 - } - ); - } - - var plugin_protocol_icon = ""; - switch (plugin.protocol) { - case AudioPlugin.Protocol.LV2: - plugin_protocol_icon = "lv2"; - break; - case AudioPlugin.Protocol.CARLA: - plugin_protocol_icon = "carla"; - break; - case AudioPlugin.Protocol.LADSPA: - plugin_protocol_icon = "ladspa"; - break; - case AudioPlugin.Protocol.NATIVE: - plugin_protocol_icon = "native"; - break; - } - - if (plugin_protocol_icon.length > 0) { - plugin_protocol_icon = - "/com/github/subhadeepjasu/ensembles/icons/scalable/emblems/plugin-audio-" + - plugin_protocol_icon + "-symbolic.svg"; - - var icon = new Gtk.Image.from_resource (plugin_protocol_icon); - icon.add_css_class ("plugin-item-protocol"); - extra_info_box.append (icon); - } - - insert_button = new Gtk.Button.from_icon_name ("insert-object-symbolic") { - valign = Gtk.Align.START - }; - insert_button.add_css_class ("plugin-item-insert-button"); - menu_item_grid.attach (insert_button, 1, 0, 1, 2); - } - } -} diff --git a/src/Shell/Widgets/Display/DisplayWindow.vala b/src/Shell/Widgets/Display/DisplayWindow.vala deleted file mode 100644 index 1c31f7a6..00000000 --- a/src/Shell/Widgets/Display/DisplayWindow.vala +++ /dev/null @@ -1,129 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Shell.Widgets.Display; - -namespace Ensembles.Shell.Layouts.Display { - /** - * Display Window is a window that may contain other widgets - * that are to be displayed inside the info display of Ensembles - */ - public class DisplayWindow : WheelScrollableWidget { - private Gtk.Button close_button; - private Gtk.Box header_bar; - private Gtk.Box window_title_box; - private Gtk.Label title_label; - private Gtk.Label subtitle_label; - private Gtk.Box header_container; - - private string _title; - public string title { - get { - return _title; - } - set { - _title = value; - if (title_label != null) { - title_label.set_text (value); - } - } - } - - private string _subtitle; - public string subtitle { - get { - return _subtitle; - } - set { - _subtitle = value; - if (subtitle_label != null) { - subtitle_label.set_text (value); - } - } - } - - private Gtk.Widget _header_addon_widget; - public Gtk.Widget header_addon_widget { - get { - return _header_addon_widget; - } - set { - _header_addon_widget = value; - } - } - - public signal void close (); - - construct { - build_ui (); - } - - public DisplayWindow (string title = "", string subtitle = "") { - Object ( - title: title, - subtitle: subtitle - ); - } - - private void build_ui () { - add_css_class ("display-window-background"); - orientation = Gtk.Orientation.VERTICAL; - - header_bar = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - spacing = 16 - }; - append (header_bar); - header_bar.add_css_class ("display-window-header-bar"); - - close_button = new Gtk.Button.from_icon_name ("application-exit-symbolic") { - halign = Gtk.Align.START, - valign = Gtk.Align.CENTER, - width_request = 36, - height_request = 36 - }; - close_button.add_css_class ("accented"); - close_button.clicked.connect (() => { close (); }); - header_bar.append (close_button); - - window_title_box = new Gtk.Box (Gtk.Orientation.VERTICAL, 0) { - halign = Gtk.Align.START, - valign = Gtk.Align.CENTER - }; - - title_label = new Gtk.Label (title) { - xalign = 0 - }; - title_label.add_css_class ("title"); - window_title_box.append (title_label); - - subtitle_label = new Gtk.Label (subtitle) { - xalign = 0 - }; - subtitle_label.add_css_class ("subtitle"); - window_title_box.append (subtitle_label); - - if (Application.kiosk_mode) { - header_bar.append (window_title_box); - } else { - var window_handle = new Gtk.WindowHandle () { - hexpand = true - }; - header_bar.append (window_handle); - window_handle.set_child (window_title_box); - } - - header_container = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 12); - header_bar.append (header_container); - } - - public void set_child (Gtk.Widget widget) { - append (widget); - } - - public void add_to_header (Gtk.Widget widget) { - header_container.append (widget); - } - } -} diff --git a/src/Shell/Widgets/Display/StyleMenuItem.vala b/src/Shell/Widgets/Display/StyleMenuItem.vala deleted file mode 100644 index 9f0c95a5..00000000 --- a/src/Shell/Widgets/Display/StyleMenuItem.vala +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Models; - -namespace Ensembles.Shell.Widgets.Display { - public class StyleMenuItem : Gtk.ListBoxRow { - public Style style { get; set; } - public bool show_category { get; set; } - - public StyleMenuItem (Style style, bool show_category = false) { - Object ( - style: style, - show_category: show_category - ); - - build_ui (); - } - - private void build_ui () { - add_css_class ("menu-item"); - - var menu_item_grid = new Gtk.Grid (); - set_child (menu_item_grid); - - var style_name_label = new Gtk.Label (style.name) { - halign = Gtk.Align.START, - hexpand = true - }; - style_name_label.add_css_class ("menu-item-name"); - menu_item_grid.attach (style_name_label, 0, 0, 1, 2); - - var tempo_label = new Gtk.Label (style.time_signature_n.to_string () + - "/" + - style.time_signature_d.to_string () + - "\t" + - (((double)style.tempo / 100.0 >= 1) ? "" : " ") + - "♩ = " + style.tempo.to_string ()) { - halign = Gtk.Align.END - }; - tempo_label.add_css_class ("menu-item-description"); - menu_item_grid.attach (tempo_label, 1, 1, 1, 1); - - var category_label = new Gtk.Label (""); - if (show_category) { - category_label.set_text (style.genre); - category_label.add_css_class ("menu-item-category"); - } - - menu_item_grid.attach (category_label, 1, 0, 2, 1); - - if (style.copyright_notice != null && style.copyright_notice != "") { - var copyright_button = new Gtk.Button.from_icon_name ("text-x-copying-symbolic") { - margin_top = 6, - margin_start = 4, - margin_end = 4, - tooltip_text = style.copyright_notice - }; - copyright_button.add_css_class ("menu-item-icon"); - menu_item_grid.attach (copyright_button, 2, 1, 1, 1); - } - } - } -} diff --git a/src/Shell/Widgets/Display/VoiceMenuItem.vala b/src/Shell/Widgets/Display/VoiceMenuItem.vala deleted file mode 100644 index 618a3958..00000000 --- a/src/Shell/Widgets/Display/VoiceMenuItem.vala +++ /dev/null @@ -1,108 +0,0 @@ -/* -* Copyright 2020-2023 Subhadeep Jasu -* SPDX-License-Identifier: GPL-3.0-or-later -*/ - -using Ensembles.Models; -using Ensembles.Core.Plugins.AudioPlugins; - -namespace Ensembles.Shell.Widgets.Display { - public class VoiceMenuItem : Gtk.ListBoxRow { - public uint16 index { get; protected set; } - - /** Whether this voice item is a plugin or the SoundFont */ - public bool is_plugin { get; protected set; } - - // If the voice is a plugin - public unowned AudioPlugin plugin { get; protected set; } - protected unowned Layouts.Display.VoiceScreen rack_shell { get; protected set; } - public Gtk.Button show_ui_button; - - // If the voice is from the SoundFont - public Voice voice { get; protected set; } - - public bool show_category { get; set; } - - public VoiceMenuItem ( - uint16 index, - Voice voice, - AudioPlugin? plugin = null, - bool show_category = false - ) { - Object ( - index: index, - voice: voice, - plugin: plugin, - is_plugin: plugin != null, - show_category: show_category - ); - - build_ui (); - } - - private void build_ui () { - add_css_class ("menu-item"); - - var menu_item_grid = new Gtk.Grid () { - column_spacing = 16, - row_spacing = 0 - }; - set_child (menu_item_grid); - - if (show_category) { - var category_label = new Gtk.Label ("") { - xalign = 0 - }; - var protocol_name = ""; - if (is_plugin) { - switch (plugin.protocol) { - case AudioPlugin.Protocol.LV2: - protocol_name = "LV2"; - break; - case AudioPlugin.Protocol.CARLA: - protocol_name = "Carla"; - break; - case AudioPlugin.Protocol.LADSPA: - protocol_name = "LADSPA"; - break; - case AudioPlugin.Protocol.NATIVE: - protocol_name = "GTK"; - break; - } - } - - category_label.set_text ( - is_plugin ? protocol_name.up () + " PLUGINS" : voice.category.up () - ); - category_label.add_css_class ("menu-item-category"); - menu_item_grid.attach (category_label, 0, 0, 3, 1); - } - - var index_label = new Gtk.Label ("%03d".printf (index)) { - width_chars = 3, - xalign = 0 - }; - index_label.add_css_class ("menu-item-index"); - menu_item_grid.attach (index_label, 0, 1); - - var voice_name_label = new Gtk.Label (is_plugin ? plugin.name : voice.name) { - halign = Gtk.Align.START, - hexpand = true, - height_request = 48 - }; - voice_name_label.add_css_class ("menu-item-name"); - menu_item_grid.attach (voice_name_label, 1, 1); - - if (is_plugin && plugin.ui != null) { - show_ui_button = new Gtk.Button.from_icon_name ("preferences-other-symbolic") { - margin_top = 6, - margin_start = 4, - margin_end = 4, - width_request = 80, - tooltip_text = _("Show Plugin UI") - }; - menu_item_grid.attach (show_ui_button, 2, 1, 1, 1); - } - } - } -} diff --git a/src/Shell/Widgets/Display/WheelScrollableWidget.vala b/src/Shell/Widgets/Display/WheelScrollableWidget.vala deleted file mode 100644 index 4f71b800..00000000 --- a/src/Shell/Widgets/Display/WheelScrollableWidget.vala +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - - namespace Ensembles.Shell.Widgets.Display { - /** - * Widget that responds to the Ensembles Scroll Wheel widget - */ - public abstract class WheelScrollableWidget : Gtk.Box { - public int scroll_wheel_location; - public int max_value = -1; - public int min_value = -1; - public signal void wheel_scrolled_absolute (int value); - public signal void wheel_scrolled_relative (bool direction, int amount); - - public void scroll_wheel_scroll (bool direction, int amount) { - if (max_value != -1 && min_value != -1) { - if (direction) { - if (scroll_wheel_location + amount < max_value) { - scroll_wheel_location += amount; - } else if (scroll_wheel_location != max_value) { - scroll_wheel_location = max_value; - } - } else { - if (scroll_wheel_location - amount > min_value) { - scroll_wheel_location -= amount; - } else if (scroll_wheel_location != min_value) { - scroll_wheel_location = min_value; - } - } - - wheel_scrolled_absolute (scroll_wheel_location); - } else { - wheel_scrolled_relative (direction, amount); - } - } - } -} diff --git a/src/Shell/Widgets/Key.vala b/src/Shell/Widgets/Key.vala deleted file mode 100644 index a34270ad..00000000 --- a/src/Shell/Widgets/Key.vala +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Widgets { - public class Key : Gtk.Box { - public uint8 index { get; protected set; } - public bool is_black { get; protected set; } - private Gtk.GestureDrag motion_controller; - private Gtk.GestureClick click_gesture; - - private bool _active; - public bool active { - get { - return _active; - } - set { - _active = value; - if (value) { - add_css_class ("activated"); - } else { - remove_css_class ("activated"); - } - } - } - - public signal void pressed (uint8 index); - public signal void released (uint8 index); - public signal void motion (uint8 index, double x, double y); - - public Key (uint8 index, bool is_black) { - Object ( - index: index, - is_black: is_black - ); - - if (is_black) { - add_css_class ("black"); - } - } - - construct { - build_ui (); - build_event (); - } - - private void build_ui () { - add_css_class ("key"); - } - - private void build_event () { - motion_controller = new Gtk.GestureDrag (); - add_controller (motion_controller); - - click_gesture = new Gtk.GestureClick (); - click_gesture.pressed.connect ((n_press, x, y) => { - pressed (index); - }); - click_gesture.released.connect (() => { - released (index); - }); - - motion_controller.drag_update.connect ((x, y) => { - if (active) { - this.motion (index, x / get_allocated_width (), y / get_allocated_height ()); - } - }); - add_controller (click_gesture); - } - - public bool inside (Octave parent, double x, double y) { - double _x, _y; - parent.translate_coordinates (this, x, y, out _x, out _y); - return contains (_x, _y); - } - } -} diff --git a/src/Shell/Widgets/Keyboard.vala b/src/Shell/Widgets/Keyboard.vala deleted file mode 100644 index cc2c0f66..00000000 --- a/src/Shell/Widgets/Keyboard.vala +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Widgets { - public class Keyboard : Gtk.Widget, Gtk.Accessible { - public uint8 n_octaves { get; protected set; } - private Octave[] octaves; - private bool[] key_pressed; - - private double[] motion_x; - private double[] motion_y; - - private bool update = true; - private int width; - private int height; - - public uint8 motion_x_control = MIDI.Control.EXPLICIT_PITCH; - public uint8 motion_y_control = MIDI.Control.CUT_OFF; - public bool motion_control_enabled = false; - - private int control_x = 64; - private int previous_control_y = 64; - private int control_y = 40; - - private uint8 _zoom_level; - public uint8 zoom_level { - get { - return _zoom_level; - } - set { - _zoom_level = value.clamp (0, 255); - if (_zoom_level == 0) { - width_request = -1; - } else { - width_request = value * 16 + 1000; - } - } - } - - public int8 octave_offset { get; set; } - - public signal void key_event (Fluid.MIDIEvent midi_event); - - public Keyboard (uint8 n_octaves) { - Object ( - accessible_role: Gtk.AccessibleRole.TABLE, - name: "keyboard", - css_name: "keyboard", - layout_manager: new Gtk.BoxLayout (Gtk.Orientation.HORIZONTAL), - height_request: 100, - n_octaves: n_octaves - ); - - build_ui (); - } - - ~Keyboard () { - update = false; - } - - construct { - build_events (); - } - - private void build_ui () { - octaves = new Octave[n_octaves]; - key_pressed = new bool[n_octaves * 12]; - motion_x = new double[n_octaves]; - motion_y = new double[n_octaves]; - for (uint8 i = 0; i < n_octaves; i++) { - var octave = new Octave (this, i); - octave.key_pressed.connect (handle_key_press); - octave.key_released.connect (handle_key_release); - octave.key_motion.connect (handle_key_motion); - octave.set_parent (this); - octaves[i] = (owned) octave; - - motion_x[i] = 0; - motion_y[i] = 0; - } - - Timeout.add (80, () => { - Idle.add (() => { - if (width != get_allocated_width () || height != get_allocated_height ()) { - for (uint8 i = 0; i < n_octaves; i++) { - octaves[i].draw_keys (); - } - - width = get_allocated_width (); - height = get_allocated_height (); - } - - return false; - }, Priority.LOW); - return update; - }, Priority.LOW); - } - - private void build_events () { - this.destroy.connect (() => { - update = false; - }); - } - - private void handle_key_press (uint8 key_index) { - var event = new Fluid.MIDIEvent (); - event.set_channel (17); // Channel 17 handles user key events - event.set_type (MIDI.EventType.NOTE_ON); - event.set_key (key_index + 12 * octave_offset); - event.set_velocity (100); - - key_event (event); - - key_pressed[key_index] = true; - } - - private void handle_key_release (uint8 key_index) { - var event = new Fluid.MIDIEvent (); - event.set_channel (17); // Channel 17 handles user key events - event.set_type (MIDI.EventType.NOTE_OFF); - event.set_key (key_index + 12 * octave_offset); - - key_event (event); - - previous_control_y = control_y; - key_pressed[key_index] = false; - - if (motion_control_enabled) { - var any_pressed = false; - for (int i = 0; i < key_pressed.length; i++) { - any_pressed = any_pressed || key_pressed[i]; - } - - if (!any_pressed) { - var event_x = new Fluid.MIDIEvent (); - event_x.set_channel (17); - event_x.set_type (MIDI.EventType.CONTROL_CHANGE); - event_x.set_control (motion_x_control); - event_x.set_value (64); - key_event (event_x); - } - } - } - - private void handle_key_motion (uint8 octave_index, double x, double y) { - if (motion_control_enabled) { - motion_x[octave_index] = x; - motion_y[octave_index] = y; - - double avg_x = 0; - double avg_y = 0; - uint8 n = (uint8) octaves.length; - - for (uint8 i = 0; i < n; i++) { - avg_x += motion_x[i]; - avg_y += motion_y[i]; - } - - var event_x = new Fluid.MIDIEvent (); - event_x.set_channel (17); // Channel 17 handles user key events - event_x.set_type (MIDI.EventType.CONTROL_CHANGE); - event_x.set_control (motion_x_control); - control_x = (64 + (int) (127 * avg_x / n)); - event_x.set_value (control_x); - if (control_x > 127) { - control_x = 127; - } else if (control_x < 0) { - control_x = 0; - } - - key_event (event_x); - - var event_y = new Fluid.MIDIEvent (); - event_y.set_channel (17); // Channel 17 handles user key events - event_y.set_type (MIDI.EventType.CONTROL_CHANGE); - event_y.set_control (motion_y_control); - control_y = previous_control_y + (int) (127 * avg_y / n); - if (control_y > 127) { - control_y = 127; - } else if (control_y < 0) { - control_y = 0; - } - - event_y.set_value (control_y); - - key_event (event_y); - } - } - - public void set_key_illumination (uint8 key_index, bool active) { - uint8 octave_index = (key_index / 12) - octave_offset; - octaves[octave_index].set_key_illumination (key_index - (octave_offset * 12), active); - } - } -} diff --git a/src/Shell/Widgets/Knob.vala b/src/Shell/Widgets/Knob.vala deleted file mode 100644 index 1b477af3..00000000 --- a/src/Shell/Widgets/Knob.vala +++ /dev/null @@ -1,368 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Widgets { - /** - * A `Knob` is a rotary control used to select a numeric value - */ - public class Knob : Gtk.Widget, Gtk.Accessible { - /** - * The adjustment that is controlled by the knob. - */ - public Gtk.Adjustment adjustment { get; set; } - /** - * Current value of the knob. - */ - public double value { - get { - return adjustment.value; - } - set { - pointing_angle = Utils.Math.map_range_unclamped ( - value, - adjustment.lower, - adjustment.upper, - pointing_angle_lower, - pointing_angle_lower + pointing_angle_upper - ); - - if (pointing_angle < pointing_angle_lower) { - pointing_angle = pointing_angle_lower; - } else if (pointing_angle > pointing_angle_upper + pointing_angle_lower) { - pointing_angle = pointing_angle_upper + pointing_angle_lower; - } - - adjustment.value = value; - } - } - - // Knob UI - private Gtk.BinLayout bin_layout; - protected Gtk.Box knob_socket_graphic; - protected Gtk.Box knob_cover; - protected Gtk.DrawingArea knob_meter; - protected Gtk.Box knob_background; - - protected List marks; - - private Gtk.GestureRotate touch_rotation_gesture; - private Gtk.GestureDrag drag_gesture; - private Gtk.EventControllerScroll wheel_gesture; - - /** - * The current angle in degrees towards which the knob is pointing. - */ - public double pointing_angle { get; private set; } - /** - * The angle in degrees which the knob will point towards - * when `value` is minimum. - */ - public double pointing_angle_lower { get; protected set; } - /** - * The angle in degrees which the knob will point towards - * when `value` is maximum. - */ - public double pointing_angle_upper { get; protected set; } - private double current_deg; - private double previous_deg; - - /** - * Number of decimal places that are displayed in the value. - */ - public uint8 digits { get; set; } - /** - * Whether the current value is displayed as a string inside the knob. - */ - public bool draw_value { get; set; } - - private uint radius = 0; - - public signal void value_changed (double value); - - /** - * Creates a new `Knob` widget. - * - * @param adjustment the [class@Gtk.Adjustment] which sets the range of - * the knob, or null to create a new adjustment. - */ - public Knob (Gtk.Adjustment? adjustment = null) { - Object ( - name: "knob", - accessible_role: Gtk.AccessibleRole.SPIN_BUTTON - ); - - if (adjustment != null) { - this.adjustment.lower = adjustment.lower; - this.adjustment.upper = adjustment.upper; - this.adjustment.step_increment = adjustment.step_increment; - } - - pointing_angle = pointing_angle_lower; - } - - /** - * Creates a new `Knob` widget with a range from min to max. - * - * Let's the user input a number between min and max (including min and - * max) with the increment step. step must be nonzero; it’s the distance - * the meter moves to adjust the knob value. - * - * @param min minimum value - * @param max maximum value - * @param step increment (tick size) - */ - public Knob.with_range (double min, double max, double step) { - Object ( - name: "knob", - accessible_role: Gtk.AccessibleRole.SPIN_BUTTON - ); - this.adjustment.lower = min; - this.adjustment.upper = max; - this.adjustment.step_increment = step; - pointing_angle = pointing_angle_lower; - } - - construct { - adjustment = new Gtk.Adjustment (0, 0, 100, - 1, 0, 0); - marks = new List (); - pointing_angle_upper = 275; - pointing_angle_lower = 135; - build_layout (); - realize.connect (() => { - build_ui (); - }); - build_events (); - } - - private void build_layout () { - bin_layout = new Gtk.BinLayout (); - set_layout_manager (bin_layout); - } - - private void build_ui () { - add_css_class ("knob"); - - var width = get_allocated_width () | width_request; - var height = get_allocated_height () | height_request; - - var diameter = width < height ? width : height; - - radius = diameter / 2; - - if (knob_background == null) { - knob_background = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - halign = Gtk.Align.CENTER, - valign = Gtk.Align.CENTER - }; - knob_background.add_css_class ("knob-background"); - knob_background.set_parent (this); - } - knob_background.width_request = diameter; - knob_background.height_request = diameter; - - if (knob_cover == null) { - knob_cover = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - halign = Gtk.Align.CENTER, - valign = Gtk.Align.CENTER - }; - knob_cover.add_css_class ("knob-cover"); - knob_cover.set_parent (this); - } - - knob_cover.width_request = diameter; - knob_cover.height_request = diameter; - - if (knob_meter == null) { - knob_meter = new Gtk.DrawingArea () { - halign = Gtk.Align.CENTER, - valign = Gtk.Align.CENTER, - width_request = diameter, - height_request = diameter - }; - knob_meter.set_parent (this); - - knob_meter.set_draw_func (draw_meter); - } - - knob_meter.width_request = diameter; - knob_meter.height_request = diameter; - } - - protected void draw_meter (Gtk.DrawingArea meter, Cairo.Context ctx, int width, int height) { - var gb = Utils.Math.map_range_unclamped ( - adjustment.value, - adjustment.lower, - adjustment.upper, - 0, - 1 - ); - // Draw meter - ctx.arc (radius + 0.2, radius, radius - 7, - pointing_angle_lower * (Math.PI / 180.0), - pointing_angle * (Math.PI / 180.0)); - ctx.set_line_width (2); - ctx.set_source_rgba (1 - gb, gb, gb, 1); - ctx.stroke (); - - // Draw marks - foreach (var mark in marks) { - var mark_angle = Utils.Math.map_range_unclamped ( - mark, - adjustment.lower, - adjustment.upper, - pointing_angle_lower, - pointing_angle_lower + pointing_angle_upper - ); - ctx.arc ( - radius + 0.2, radius, radius - 2, - (mark_angle - 1) * (Math.PI / 180.0), - (mark_angle + 1) * (Math.PI / 180.0) - ); - - ctx.set_source_rgba (1, 1, 1, adjustment.value == mark ? 1 : 0.3); - ctx.stroke (); - } - - if (draw_value) { - string text = (adjustment.step_increment >= 1 ? "%.lf" : "%.1lf").printf (adjustment.value); - ctx.select_font_face ("Michroma", Cairo.FontSlant.NORMAL, Cairo.FontWeight.NORMAL); - ctx.set_font_size (Math.fmax (10, radius / 3)); - - Cairo.TextExtents extents; - ctx.text_extents (text, out extents); - ctx.move_to (radius - (extents.width / 2), radius + (extents.height / 2)); - ctx.set_source_rgb (0.8, 0.8, 0.8); - ctx.show_text (text); - } - } - - private void build_events () { - drag_gesture = new Gtk.GestureDrag () { - propagation_phase = Gtk.PropagationPhase.CAPTURE, - name = "drag-rotation-capture" - }; - add_controller (drag_gesture); - - drag_gesture.drag_begin.connect ((x, y) => { - previous_deg = Math.atan2 (x - radius, y - radius) * (180 / Math.PI); - }); - - drag_gesture.drag_update.connect ((x, y) => { - double start_x; - double start_y; - drag_gesture.get_start_point (out start_x, out start_y); - - double relative_x = start_x + x; - double relative_y = start_y + y; - - current_deg = Math.atan2 (relative_x - radius, relative_y - radius) * (180 / Math.PI); - - var delta_deg = previous_deg - current_deg; - - if (delta_deg < 270 && delta_deg > -270) { - pointing_angle += delta_deg; - - if (pointing_angle < pointing_angle_lower) { - pointing_angle = pointing_angle_lower; - } else if (pointing_angle > pointing_angle_upper + pointing_angle_lower) { - pointing_angle = pointing_angle_upper + pointing_angle_lower; - } - - adjustment.value = Utils.Math.map_range_unclamped ( - pointing_angle, - pointing_angle_lower, - pointing_angle_lower + pointing_angle_upper, - adjustment.lower, - adjustment.upper - ); - value_changed (adjustment.value); - } - - previous_deg = current_deg; - }); - - touch_rotation_gesture = new Gtk.GestureRotate (); - add_controller (touch_rotation_gesture); - - wheel_gesture = new Gtk.EventControllerScroll (Gtk.EventControllerScrollFlags.VERTICAL); - add_controller (wheel_gesture); - - wheel_gesture.scroll.connect ((dx, dy) => { - var value = adjustment.value - adjustment.step_increment * dy; - pointing_angle = Utils.Math.map_range_unclamped ( - value, - adjustment.lower, - adjustment.upper, - pointing_angle_lower, - pointing_angle_lower + pointing_angle_upper - ); - - if (value > adjustment.upper) { - value = adjustment.upper; - } else if (value < adjustment.lower) { - value = adjustment.lower; - } - - if (pointing_angle < pointing_angle_lower) { - pointing_angle = pointing_angle_lower; - } else if (pointing_angle > pointing_angle_upper + pointing_angle_lower) { - pointing_angle = pointing_angle_upper + pointing_angle_lower; - } - - adjustment.value = value; - value_changed (value); - return true; - }); - - touch_rotation_gesture.angle_changed.connect ((angle, angle_delta) => { - pointing_angle += angle_delta; - - if (pointing_angle < pointing_angle_lower) { - pointing_angle = pointing_angle_lower; - } else if (pointing_angle > pointing_angle_upper + pointing_angle_lower) { - pointing_angle = pointing_angle_upper + pointing_angle_lower; - } - - adjustment.value = Utils.Math.map_range_unclamped ( - pointing_angle, - pointing_angle_lower, - pointing_angle_lower + pointing_angle_upper, - adjustment.lower, - adjustment.upper - ); - value_changed (adjustment.value); - }); - - adjustment.value_changed.connect (() => { - Idle.add (() => { - knob_meter.queue_draw (); - return false; - }); - }); - } - - /** - * Adds a mark at value. - * - * A mark is indicated visually by drawing a tick mark outside the knob. - * - * @param value the value at which the mark is placed, must be between - * the lower and upper limits of the scales’ adjustment - */ - public void add_mark (double value) { - marks.append (value); - } - - /** - * Removes any marks that have been added. - */ - public void clear_marks () { - foreach (var mark in marks) { - marks.remove (mark); - } - } - } -} diff --git a/src/Shell/Widgets/Octave.vala b/src/Shell/Widgets/Octave.vala deleted file mode 100644 index 4d96285d..00000000 --- a/src/Shell/Widgets/Octave.vala +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Shell.Widgets { - public class Octave : Gtk.Widget, Gtk.Accessible { - public uint8 index { get; protected set; } - public unowned Keyboard keyboard { get; protected set; } - private const uint8[] BLACK_KEYS = { 1, 3, 6, 8, 10 }; - private const uint8[] WHITE_KEYS = { 0, 2, 4, 5, 7, 9, 11 }; - private const double[] BLACK_KEY_OFFSETS = { 0.932, 2.758, 5.56, 7.38, 9.24 }; - - Gtk.Box white_key_box; - private Key[] keys = new Key[12]; - - private double[] motion_x = new double[12]; - private double[] motion_y = new double[12]; - - public signal void key_pressed (uint8 index); - public signal void key_released (uint8 index); - public signal void key_motion (uint8 index, double x, double y); - - public Octave (Keyboard keyboard, uint8 index) { - Object ( - index: index, - name: "octave", - accessible_role: Gtk.AccessibleRole.TABLE, - keyboard: keyboard, - accessible_role: Gtk.AccessibleRole.TABLE, - layout_manager: new Gtk.BinLayout (), - width_request: 200, - height_request: 100, - hexpand: true, - vexpand: true - ); - - for (uint8 i = 0; i < 12; i++) { - motion_x[i] = 0; - motion_y[i] = 0; - } - - build_ui (); - } - - private void build_ui () { - white_key_box = new Gtk.Box (Gtk.Orientation.HORIZONTAL, 0) { - hexpand = true, - vexpand = true, - homogeneous = true - }; - white_key_box.set_parent (this); - - keys = new Key[12]; - // Arrange all the white keys - for (uint8 i = 0; i < 7; i++) { - var key = new Key (WHITE_KEYS[i], false); - key.pressed.connect (handle_key_press); - key.released.connect (handle_key_release); - key.motion.connect (handle_key_motion); - white_key_box.append (key); - keys[WHITE_KEYS[i]] = (owned) key; - } - - // Arrange all the black keys - for (uint8 i = 0; i < 5; i++) { - var key = new Key (BLACK_KEYS[i], true); - key.pressed.connect (handle_key_press); - key.released.connect (handle_key_release); - key.motion.connect (handle_key_motion); - key.set_parent (this); - keys[BLACK_KEYS[i]] = (owned) key; - } - } - - public void draw_keys () { - int w_max = get_allocated_width (); - double offset = w_max * 0.09; - int h_max = get_allocated_height (); - int black_key_width = w_max / 10; - int black_key_height = (int) (h_max / 1.5); - - for (uint8 i = 0; i < 5; i++) { - int left, right, bottom; - box_to_margins ( - (int) (BLACK_KEY_OFFSETS[i] * offset), - 0, - black_key_width, - black_key_height, - w_max, - h_max, - out left, - out right, - out bottom - ); - keys[BLACK_KEYS[i]].margin_start = left; - keys[BLACK_KEYS[i]].margin_end = right; - keys[BLACK_KEYS[i]].margin_bottom = bottom; - } - } - - /** - * Calculate margins based on the given box and parent box dimensions - */ - private void box_to_margins ( - int x, int y, int width, int height, int w_max, int h_max, - out int left, out int right, out int bottom - ) { - left = x; - right = w_max - (x + width); - bottom = h_max - (y + height); - } - - private void handle_key_press (uint8 key_index) { - key_pressed (index * 12 + key_index); - } - - private void handle_key_release (uint8 key_index) { - key_released (index * 12 + key_index); - } - - private void handle_key_motion (uint8 key_index, double x, double y) { - motion_x[key_index] = x; - motion_y[key_index] = y; - - double avg_x = 0; - double avg_y = 0; - - for (uint8 i = 0; i < 12; i++) { - avg_x += motion_x[key_index]; - avg_y += motion_y[key_index]; - } - - key_motion (index, avg_x / 12, avg_y / 12); - } - - public void set_key_illumination (uint8 key_index, bool active) { - uint8 actual_key_index = key_index - (index * 12); - keys[actual_key_index].active = active; - } - } -} diff --git a/src/Utils/AccentColors.vala b/src/Utils/AccentColors.vala deleted file mode 100644 index 572e82ec..00000000 --- a/src/Utils/AccentColors.vala +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles { - public class AccentColors { - private const string COMPLIMENTARY_ACCENT_COLORS_TEMPLATE = - " - @define-color accent_color_complimentary %s; - @define-color accent_color_complimentary_alternate %s; - "; - - private static string complimentary_accent_colors_strawberry - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@BANANA_500", "@ORANGE_500"); - private static string complimentary_accent_colors_orange - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@BLUEBERRY_500", "@MINT_500"); - private static string complimentary_accent_colors_banana - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@MINT_500", "@ORANGE_500"); - private static string complimentary_accent_colors_lime - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@BANANA_500", "@BUBBLEGUM_500"); - private static string complimentary_accent_colors_mint - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@BANANA_500", "@SILVER_500"); - private static string complimentary_accent_colors_blueberry - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@GRAPE_500", "@MINT_500"); - private static string complimentary_accent_colors_bubblegum - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@MINT_500", "@GRAPE_500"); - private static string complimentary_accent_colors_cocoa - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@MINT_500", "@BANANA_500"); - private static string complimentary_accent_colors_grape - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@STRAWBERRY_300", "@BUBBLEGUM_500"); - private static string complimentary_accent_colors_silver - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@BLUEBERRY_300", "@STRAWBERRY_300"); - private static string complimentary_accent_colors_slate - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@MINT_500", "@BANANA_500"); - - public static uint8[]? get_complementary (string theme_color) { - complimentary_accent_colors_strawberry - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@BANANA_500", "@ORANGE_500"); - complimentary_accent_colors_orange - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@BLUEBERRY_500", "@MINT_500"); - complimentary_accent_colors_banana - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@MINT_500", "@ORANGE_500"); - complimentary_accent_colors_lime - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@BANANA_500", "@BUBBLEGUM_500"); - complimentary_accent_colors_mint - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@BANANA_500", "@SILVER_500"); - complimentary_accent_colors_blueberry - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@GRAPE_500", "@MINT_500"); - complimentary_accent_colors_bubblegum - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@MINT_500", "@GRAPE_500"); - complimentary_accent_colors_cocoa - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@MINT_500", "@BANANA_500"); - complimentary_accent_colors_grape - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@STRAWBERRY_300", "@BUBBLEGUM_500"); - complimentary_accent_colors_silver - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@BLUEBERRY_300", "@STRAWBERRY_300"); - complimentary_accent_colors_slate - = COMPLIMENTARY_ACCENT_COLORS_TEMPLATE.printf ("@MINT_500", "@BANANA_500"); - - switch (theme_color) { - case "strawberry": - return complimentary_accent_colors_strawberry.data; - case "orange": - return complimentary_accent_colors_orange.data; - case "banana": - return complimentary_accent_colors_banana.data; - case "lime": - return complimentary_accent_colors_lime.data; - case "mint": - return complimentary_accent_colors_mint.data; - case "blueberry": - return complimentary_accent_colors_blueberry.data; - case "grape": - return complimentary_accent_colors_grape.data; - case "bubblegum": - return complimentary_accent_colors_bubblegum.data; - case "cocoa": - return complimentary_accent_colors_cocoa.data; - case "silver": - return complimentary_accent_colors_silver.data; - case "slate": - case "black": - return complimentary_accent_colors_slate.data; - } - - return complimentary_accent_colors_blueberry.data; - } - } -} diff --git a/src/Utils/Console.vala b/src/Utils/Console.vala deleted file mode 100644 index dc4ffcf5..00000000 --- a/src/Utils/Console.vala +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles { - public class Console { - private const string RED = "\x1B[31m"; - private const string GRN = "\x1B[32m"; - private const string YEL = "\x1B[33m"; - private const string BLU = "\x1B[34m"; - private const string MAG = "\x1B[35m"; - private const string CYN = "\x1B[36m"; - private const string WHT = "\x1B[37m"; - private const string BOLD = "\x1B[1m"; - private const string RESET = "\x1B[0m"; - - public static void get_console_header () { - print (MAG); - print ("███████ ███ ██ ███████ ███████ ███ ███ ██████ ██ ███████ ███████\n"); - print ("██ ████ ██ ██ ██ ████ ████ ██ ██ ██ ██ ██\n"); - print ("█████ ██ ██ ██ ███████ █████ ██ ████ ██ ██████ ██ █████ ███████\n"); - print ("██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██\n"); - print ("███████ ██ ████ ███████ ███████ ██ ██ ██████ ███████ ███████ ███████\n"); - print (RED); - print ("============================================================================\n"); - print (YEL); - print (_("VERSION: %s, DISPLAY VERSION: %s | (c) SUBHADEEP JASU 2020 - 2023\n"), - Constants.VERSION, Constants.DISPLAYVER); - print (RED); - print ("----------------------------------------------------------------------------\n"); - print (RESET); - } - - public enum LogLevel { - SUCCESS, - TRACE, - WARNING, - ERROR, - } - - public static void log (T object, LogLevel log_level = LogLevel.TRACE) { - DateTime date_time = new DateTime.now_utc (); - string message = ""; - if (typeof (T) == Type.STRING) { - message = (string) object; - } else if (typeof (T) == typeof (Error)) { - message = ((Error) object).domain.to_string () - .replace ("-quark", "") - .replace ("-", " ") - .up (); - message += ": " + ((Error) object).message; - } - - switch (log_level) { - case SUCCESS: - if (Application.verbose) { - print ("%s▎%s%sSUCCESS %s[%s%s%s]: %s\n", GRN, WHT, BOLD, - RESET, BLU, date_time.to_string (), RESET, message); - } - break; - case TRACE: - if (Application.verbose) { - print ("%s▎%s%sTRACE %s[%s%s%s]: %s\n", CYN, WHT, BOLD, RESET, BLU, date_time.to_string (), - RESET, message); - } - break; - case WARNING: - if (Application.verbose) { - print ("%s▎%s%sWARNING %s[%s%s%s]: %s%s%s\n", YEL, WHT, BOLD, RESET, BLU, date_time.to_string (), - RESET, YEL, message, RESET); - } - break; - case ERROR: - if (Application.verbose) { - print ("%s▎%s%sERROR %s[%s%s%s]: %s%s%s\n", RED, WHT, BOLD, RESET, BLU, date_time.to_string (), - RESET, RED, message, RESET); - } - GLib.log (Constants.APP_NAME, LogLevelFlags.LEVEL_ERROR, message); - break; - } - } - } -} diff --git a/src/Utils/DisplayTheme.vala b/src/Utils/DisplayTheme.vala deleted file mode 100644 index 00b6a5db..00000000 --- a/src/Utils/DisplayTheme.vala +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles { - // public class Utils { - // static string display_theme_path = ""; - // static Gtk.CssProvider display_theme_provider; - // public static string set_display_theme (string name) { - // display_theme_path = Application.user_config_dir + "/display_themes/"; - // // Update the stylesheets first - // if (DirUtils.create_with_parents (Application.user_config_dir, 2000) != -1) { - // if (DirUtils.create_with_parents (display_theme_path, 2000) != -1) { - // create_file ("DisplayUnit", "Default", "css"); - // create_file ("DisplayUnitElementaryLight", "elementary Light", "css"); - // create_file ("DisplayUnitElementaryDark", "elementary Dark", "css"); - // create_file ("DisplayUnitAurora", "Aurora", "css"); - // } - // } - // // Attempt to set the given theme - // if (display_theme_provider == null) { - // display_theme_provider = new Gtk.CssProvider (); - // } else { - // Gtk.StyleContext.remove_provider_for_display (Gdk.Display.get_default (), display_theme_provider); - // } - // try { - // display_theme_provider.load_from_path (display_theme_path + name + ".css"); - // Gtk.StyleContext.add_provider_for_display ( - // Gdk.Display.get_default (), display_theme_provider, - // Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - // ); - // } catch (Error e) { - // warning (e.message); - // try { - // display_theme_provider.load_from_path (display_theme_path + "Default.css"); - // Gtk.StyleContext.add_provider_for_display ( - // Gdk.Display.get_default (), display_theme_provider, - // Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - // ); - // return "Default"; - // } catch (Error e1) { - // warning (e1.message); - // try { - // display_theme_provider.load_from_path (display_theme_path + "Elementary Light.css"); - // Gtk.StyleContext.add_provider_for_display ( - // Gdk.Display.get_default (), display_theme_provider, - // Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - // ); - // return "Elementary Light"; - // } catch (Error e2) { - // warning (e2.message); - // try { - // display_theme_provider.load_from_path (display_theme_path + "Elementary Dark.css"); - // Gtk.StyleContext.add_provider_for_display ( - // Gdk.Display.get_default (), display_theme_provider, - // Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - // ); - // return "Elementary Dark"; - // } catch (Error e3) { - // warning (e3.message); - // try { - // display_theme_provider.load_from_path (display_theme_path + "Aurora.css"); - // Gtk.StyleContext.add_provider_for_display ( - // Gdk.Display.get_default (), display_theme_provider, - // Gtk.STYLE_PROVIDER_PRIORITY_APPLICATION - // ); - // return "Aurora"; - // } catch (Error e4) { - // warning ("Failed to load any of the default Display Themes: %s", e4.message); - // } - // } - // } - // } - // } - // return name; - // } - // } -} diff --git a/src/Utils/ErrorDomains.vala b/src/Utils/ErrorDomains.vala deleted file mode 100644 index 8165a597..00000000 --- a/src/Utils/ErrorDomains.vala +++ /dev/null @@ -1,20 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles { - protected errordomain FluidError { - INVALID_SF - } - - protected errordomain StyleError { - INVALID_FILE, - INVALID_LAYOUT, - } - - protected errordomain PluginError { - UNSUPPORTED_FEATURE, - INVALID_CATEGORY - } -} diff --git a/src/Utils/MIDI.vala b/src/Utils/MIDI.vala deleted file mode 100644 index 57800f4b..00000000 --- a/src/Utils/MIDI.vala +++ /dev/null @@ -1,85 +0,0 @@ -namespace Ensembles.MIDI { - public enum EventType { - /** This event is sent when a note is released (ended). */ - NOTE_OFF = 0x80, - /** This event is sent when a note is depressed (started). */ - NOTE_ON = 0x90, - /** - * Polyphonic Key Pressure (Aftertouch). - * This event is most often sent by pressing down on the key after it - * "bottoms out". - */ - KEY_PRESSURE = 0xA0, - /** This event is sent when a controller value changes. - * Controllers include devices such as pedals and levers. - * Certain controller numbers are reserved for specific purposes. - */ - CONTROL_CHANGE = 0xB0, - /** This event is sent when the patch number changes. */ - PROGRAM_CHANGE = 0xC0, - /** - * Channel Pressure (After-touch). - * This event is most often sent by pressing down on the key after it - * "bottoms out". This event is different from polyphonic after-touch. - * Use this event to send the single greatest pressure value (of all - * the current depressed keys). - */ - CHANNEL_PRESSURE = 0xD0, - /** - * This event is sent to indicate a change in the pitch wheel. - */ - PITCH_BEND = 0xE0, - /** System Exclusive. */ - SYSEX = 0xF0, - /** - * Song Position Pointer. - * This is an internal 14 bit register that holds the number of MIDI - * beats (1 beat= six MIDI clocks) since the start of the song. - */ - SONG_POSITION = 0xF2, - /** - * Song Select. - * The Song Select specifies which sequence or song is to be played. - */ - SONG_SELECT = 0xF3, - /** End of Exclusive (SysEx). - * Used to terminate a System Exclusive. - */ - EOE = 0xF7, - /** - * Timing Clock. - * Sent 24 times per quarter note when synchronisation is required. - */ - CLOCK_TIMER = 0xF8, - /** - * Play the current sequence. - */ - PLAY = 0xFA, - /** Continue at the point the sequence was paused. */ - RESUME = 0xFB, - /** Pause the current sequence. */ - PAUSE = 0xFC, - /** Active Sensing. */ - ACTIVE_SENSING = 0xFE, - /** - * Reset all receivers in the system to power-up status. - * This should be used sparingly, preferably under manual control. - * In particular, it should not be sent on power-up. - */ - RESET = 0xFF - } - - public enum Control { - MODULATION = 0x01, - EXPLICIT_PITCH = 0x03, - GAIN = 0x07, - PAN = 0x0A, - EXPRESSION = 0x0B, - PITCH = 0x42, - RESONANCE = 0x47, - CUT_OFF = 0x4A, - EXPLICIT_BANK_SELECT = 0x55, - REVERB = 0x5B, - CHORUS = 0x5D - } -} diff --git a/src/Utils/Math.vala b/src/Utils/Math.vala deleted file mode 100644 index d21905e9..00000000 --- a/src/Utils/Math.vala +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -namespace Ensembles.Utils { - public class Math { - /** - * Returns a value mapped from one range into another. - * - * @param value the value in input range - * @param in_range_min input range min - * @param in_range_max input range max - * @param out_range_min output range min - * @param out_range_max output range max - * @return mapped value in output range - */ - public static double map_range_unclamped (double value, - double in_range_min, double in_range_max, - double out_range_min, double out_range_max) { - return out_range_min + ( - (out_range_max - out_range_min) / (in_range_max - in_range_min) - ) * (value - in_range_min); - } - - /** - * Returns a value mapped from one range into another. - * - * @param value the value in input range - * @param in_range_min input range min - * @param in_range_max input range max - * @param out_range_min output range min - * @param out_range_max output range max - * @return mapped value in output range - */ - public static float map_range_unclampedf (float value, - float in_range_min, float in_range_max, - float out_range_min, float out_range_max) { - return out_range_min + ( - (out_range_max - out_range_min) / (in_range_max - in_range_min) - ) * (value - in_range_min); - } - - public static double convert_db_to_gain (double db) { - return GLib.Math.pow (10, db / 20); - } - - public static double convert_gain_to_db (double gain) { - return 20 * GLib.Math.log10 (gain); - } - } -} diff --git a/src/Utils/StyleMIDIModifiers.vala b/src/Utils/StyleMIDIModifiers.vala deleted file mode 100644 index 346907e5..00000000 --- a/src/Utils/StyleMIDIModifiers.vala +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright 2020-2023 Subhadeep Jasu - * SPDX-License-Identifier: GPL-3.0-or-later - */ - -using Ensembles.Models; - -namespace Ensembles { - public class StyleMIDIModifers { - public static int modify_key_by_chord (int key, Chord? chord, - ChordType style_scale_type, bool alt_channels_active) { - if (style_scale_type == ChordType.MAJOR) { - switch (chord.type) { - case ChordType.MAJOR: - return key + chord.root; - case ChordType.MINOR: - if ( - !alt_channels_active && ((key - 4) % 12 == 0 || (key - 9) % 12 == 0 || (key - 11) % 12 == 0) - ) { - return (key + chord.root - 1); - } else { - return (key + chord.root); - } - case ChordType.DIMINISHED: - if ((key - 4) % 12 == 0 || (key - 7) % 12 == 0) { - return (key + chord.root - 1); - } else { - return (key + chord.root); - } - case ChordType.SUSPENDED_2: - if ((key - 4) % 12 == 0) { - return (key + chord.root - 2); - } else { - return (key + chord.root); - } - case ChordType.SUSPENDED_4: - if ((key - 4) % 12 == 0) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - case ChordType.AUGMENTED: - if ((key - 2) % 12 == 0 || (key - 7) % 12 == 0) { - return (key + chord.root + 1); - } else if ((key - 5) % 12 == 0 || (key - 9) % 12 == 0) { - return (key + chord.root - 1); - } else { - return (key + chord.root); - } - case ChordType.SIXTH: - if ((key - 4) % 12 == 0) { - if (Random.int_range (0, 3) > 2) { - return (key + chord.root); - } - - return (key + chord.root + 5); - } else { - return (key + chord.root); - } - case ChordType.SEVENTH: - if ((key - 4) % 12 == 0) { - if (Random.int_range (0, 3) > 2) { - return (key + chord.root); - } - - return (key + chord.root + 6); - } else { - return (key + chord.root); - } - case ChordType.MAJOR_7TH: - if ((key - 4) % 12 == 0) { - if (Random.int_range (0, 3) > 2) { - return (key + chord.root); - } - - return (key + chord.root - 5); - } else { - return (key + chord.root); - } - case ChordType.MINOR_7TH: - if ((key - 4) % 12 == 0) { - if (Random.boolean ()) { - return (key + chord.root + 6); - } - - return (key + chord.root - 1); - } else { - return (key + chord.root); - } - case ChordType.ADD_9TH: - if ((key - 4) % 12 == 0) { - if (Random.int_range (0, 3) > 2) { - return (key + chord.root); - } - - return (key + chord.root - 2); - } else { - return (key + chord.root); - } - case ChordType.NINTH: - if ((key - 4) % 12 == 0) { - if (Random.boolean ()) { - return (key + chord.root - 2); - } - - return (key + chord.root); - } else if ((key - 7) % 12 == 0) { - if (Random.boolean ()) { - return (key + chord.root + 3); - } - return (key + chord.root); - } else { - return (key + chord.root); - } - } - } else if (style_scale_type == ChordType.MINOR) { - switch (chord.type) { - case ChordType.MINOR: - return (key + chord.root); - case ChordType.MAJOR: - if ( - !alt_channels_active && ((key - 3) % 12 == 0 || (key - 8) % 12 == 0 || (key - 10) % 12 == 0) - ) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - case ChordType.DIMINISHED: - if ((key - 7) % 12 == 0) { - return (key + chord.root - 1); - } else if ((key - 8) % 12 == 0 || (key - 10) % 12 == 0) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - case ChordType.SUSPENDED_2: - if ((key - 3) % 12 == 0) { - return (key + chord.root - 1); - } else if ((key - 8) % 12 == 0 || (key - 10) % 12 == 0) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - case ChordType.SUSPENDED_4: - if ((key - 3) % 12 == 0) { - return (key + chord.root + 2); - } else if ((key - 8) % 12 == 0 || (key - 10) % 12 == 0) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - case ChordType.AUGMENTED: - if ((key - 7) % 12 == 0) { - return (key + chord.root - 1); - } else if ((key - 8) % 12 == 0 || (key - 10) % 12 == 0) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - case ChordType.SIXTH: - if ((key - 3) % 12 == 0) { - if (Random.int_range (0, 3) > 2) { - return (key + chord.root + 1); - } - - return (key + chord.root + 6); - } else if ((key - 8) % 12 == 0 || (key - 10) % 12 == 0) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - case ChordType.SEVENTH: - if ((key - 3) % 12 == 0) { - if (Random.int_range (0, 3) > 2) { - return (key + chord.root + 1); - } - - return (key + chord.root + 7); - } else if ((key - 8) % 12 == 0) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - case ChordType.MAJOR_7TH: - if ((key - 3) % 12 == 0) { - if (Random.int_range (0, 3) > 2) { - return (key + chord.root + 1); - } - - return (key + chord.root + 8); - } else if ((key - 8) % 12 == 0 || (key - 10) % 12 == 0) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - case ChordType.MINOR_7TH: - if ((key - 3) % 12 == 0) { - if (Random.int_range (0, 3) > 2) { - return (key + chord.root); - } - - return (key + chord.root + 7); - } else if ((key - 8) % 12 == 0) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - case ChordType.ADD_9TH: - if ((key - 3) % 12 == 0) { - if (Random.int_range (0, 3) > 2) { - return (key + chord.root + 1); - } - - return (key + chord.root - 2); - } else if ((key - 8) % 12 == 0 || (key - 10) % 12 == 0) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - case ChordType.NINTH: - if ((key - 3) % 12 == 0) { - if (Random.boolean ()) { - return (key + chord.root - 1); - } - return (key + chord.root + 1); - } else if ((key - 7) % 12 == 0) { - if (Random.boolean ()) { - return (key + chord.root + 3); - } - - return (key + chord.root); - } else if ((key - 8) % 12 == 0) { - return (key + chord.root + 1); - } else { - return (key + chord.root); - } - } - } - return 0; - } - } - } diff --git a/src/meson.build b/src/meson.build index 463f5e23..54021ced 100644 --- a/src/meson.build +++ b/src/meson.build @@ -15,105 +15,5 @@ config_header = configure_file ( sources = files ( 'Main.vala', - 'Application.vala', - - # Shell - 'Shell/MainWindow.vala', - - 'Shell/Layouts/DesktopLayout.vala', - 'Shell/Layouts/MobileLayout.vala', - 'Shell/Layouts/KioskLayout.vala', - 'Shell/Layouts/InfoDisplay.vala', - 'Shell/Layouts/KeyboardPanel.vala', - 'Shell/Layouts/MixerBoard.vala', - 'Shell/Layouts/AssignablesBoard.vala', - 'Shell/Layouts/RegistryPanel.vala', - 'Shell/Layouts/SamplerPadsPanel.vala', - 'Shell/Layouts/StyleControlPanel.vala', - 'Shell/Layouts/SynthControlPanel.vala', - 'Shell/Layouts/VoiceNavPanel.vala', - 'Shell/Layouts/PluginView.vala', - - 'Shell/Layouts/Display/HomeScreen.vala', - 'Shell/Layouts/Display/StyleScreen.vala', - 'Shell/Layouts/Display/VoiceScreen.vala', - 'Shell/Layouts/Display/DSPScreen.vala', - 'Shell/Layouts/Display/AudioPluginPicker.vala', - 'Shell/Layouts/Display/PluginScreen.vala', - - 'Shell/Widgets/BeatVisualization.vala', - 'Shell/Widgets/Knob.vala', - 'Shell/Widgets/Key.vala', - 'Shell/Widgets/Octave.vala', - 'Shell/Widgets/Keyboard.vala', - - 'Shell/Widgets/Display/WheelScrollableWidget.vala', - 'Shell/Widgets/Display/DisplayWindow.vala', - 'Shell/Widgets/Display/VoiceMenuItem.vala', - 'Shell/Widgets/Display/StyleMenuItem.vala', - 'Shell/Widgets/Display/DSPMenuItem.vala', - 'Shell/Widgets/Display/DSPInstanceMenuItem.vala', - - 'Shell/Plugins/AudioPlugins/Widgets/AudioPluginControl.vala', - - 'Shell/Dialogs/PowerDialog.vala', - - # Core - 'Core/ArrangerWorkstation.vala', - - 'Core/AudioEngine/Synthesizer.vala', - 'Core/AudioEngine/SynthProvider.vala', - 'Core/AudioEngine/SynthSettingsPresets.vala', - - 'Core/Analysers/ChordAnalyser.vala', - 'Core/Analysers/StyleAnalyser.vala', - 'Core/Analysers/VoiceAnalyser.vala', - - 'Core/MIDIPlayers/StyleEngine.vala', - - 'Core/FileLoaders/StyleFileLoader.vala', - - 'Core/Racks/Rack.vala', - 'Core/Racks/DSPRack.vala', - 'Core/Racks/VoiceRack.vala', - - # Services - 'Services/EventBus.vala', - 'Services/Settings.vala', - 'Services/Theme.vala', - - # Utilities - 'Utils/Console.vala', - 'Utils/ErrorDomains.vala', - 'Utils/AccentColors.vala', - 'Utils/StyleMIDIModifiers.vala', - 'Utils/MIDI.vala', - 'Utils/DisplayTheme.vala', - 'Utils/Math.vala', - - # Models - 'Models/Chord.vala', - 'Models/Registry.vala', - 'Models/Voice.vala', - 'Models/Style.vala', - 'Models/StylePart.vala', - - # Plugins - 'Core/Plugins/Plugin.vala', - 'Core/Plugins/PluginManager.vala', - - # Audio Plugins - 'Core/Plugins/AudioPlugins/AudioPlugin.vala', - 'Core/Plugins/AudioPlugins/Port.vala', - - # LV2 Plugins - 'Core/Plugins/AudioPlugins/Lv2/LV2Manager.vala', - 'Core/Plugins/AudioPlugins/Lv2/LV2Plugin.vala', - 'Core/Plugins/AudioPlugins/Lv2/LV2SyMap.vala', - 'Core/Plugins/AudioPlugins/Lv2/LV2EvBuf.vala', - 'Core/Plugins/AudioPlugins/Lv2/LV2Worker.vala', - 'Core/Plugins/AudioPlugins/Lv2/LV2PortAnalyser.vala', - 'Core/Plugins/AudioPlugins/Lv2/Ports/LV2Port.vala', - 'Core/Plugins/AudioPlugins/Lv2/Ports/LV2ControlPort.vala', - 'Core/Plugins/AudioPlugins/Lv2/Ports/LV2AtomPort.vala' + 'Services.vala' ) diff --git a/subprojects/ens-aw-core.wrap b/subprojects/ens-aw-core.wrap new file mode 100644 index 00000000..58444842 --- /dev/null +++ b/subprojects/ens-aw-core.wrap @@ -0,0 +1,4 @@ +[wrap-git] +url = https://github.com/ensemblesaw/ens-aw-core +depth = 1 +revision = main diff --git a/subprojects/ens-shell-cli.wrap b/subprojects/ens-shell-cli.wrap new file mode 100644 index 00000000..a65e5cbd --- /dev/null +++ b/subprojects/ens-shell-cli.wrap @@ -0,0 +1,4 @@ +[wrap-git] +url = https://github.com/ensemblesaw/ens-shell-cli.git +depth = 1 +revision = main diff --git a/subprojects/ens-shell-gtk.wrap b/subprojects/ens-shell-gtk.wrap new file mode 100644 index 00000000..69e9cf90 --- /dev/null +++ b/subprojects/ens-shell-gtk.wrap @@ -0,0 +1,4 @@ +[wrap-git] +url = https://github.com/ensemblesaw/ens-shell-gtk +depth = 1 +revision = main diff --git a/subprojects/enstl.wrap b/subprojects/enstl.wrap new file mode 100644 index 00000000..61b0ddcb --- /dev/null +++ b/subprojects/enstl.wrap @@ -0,0 +1,4 @@ +[wrap-git] +url = https://github.com/ensemblesaw/styles +depth = 1 +revision = main diff --git a/subprojects/libvinject.wrap b/subprojects/libvinject.wrap new file mode 100644 index 00000000..8148bb69 --- /dev/null +++ b/subprojects/libvinject.wrap @@ -0,0 +1,7 @@ +[wrap-git] +url=https://gitlab.com/geeky_endeavours/vinject.git +revision = main +depth=1 + +[provide] +vinject-0.0.0 = vinject_dep diff --git a/subprojects/zix.wrap b/subprojects/zix.wrap deleted file mode 100644 index 4ba71df3..00000000 --- a/subprojects/zix.wrap +++ /dev/null @@ -1,4 +0,0 @@ -[wrap-git] -url = https://github.com/drobilla/zix -depth = 1 -revision = main diff --git a/vapi/fluidsynth.vapi b/vapi/fluidsynth.vapi index 15b49121..5d8957b3 100644 --- a/vapi/fluidsynth.vapi +++ b/vapi/fluidsynth.vapi @@ -835,7 +835,7 @@ namespace Fluid { [CCode (cname = "fluid_midi_driver_t", cprefix = "fluid_midi_driver_", free_function = "delete_fluid_midi_driver", has_type_id = false)] public class MIDIDriver { [CCode (cname = "new_fluid_midi_driver")] - public MIDIDriver (); + public MIDIDriver (Settings? settings, handle_midi_event_func_t handler, void* event_handler_data); } /** diff --git a/vapi/lilv-0.vapi b/vapi/lilv-0.vapi index 463a7ac4..3142c51b 100644 --- a/vapi/lilv-0.vapi +++ b/vapi/lilv-0.vapi @@ -66,6 +66,7 @@ namespace Lilv { public unowned PluginClass get_class(); public Nodes get_value(Node predicate); public bool has_feature(Node feature_uri); + public bool has_extension_data(Node uri); public Nodes get_supported_features(); public Nodes get_required_features(); public Nodes get_optional_features(); @@ -84,28 +85,6 @@ namespace Lilv { public Instance? instantiate(double sample_rate, [CCode (array_length = false, array_null_terminated = true)] LV2.Feature*[] features); public UIs get_uis(); - - // port methods - [CCode (cname = "lilv_port_get_value")] - public Nodes port_get_value(Port port, Node predicate); - [CCode (cname = "lilv_port_get_properties")] - public Nodes port_get_properties(Port port); - [CCode (cname = "lilv_port_has_property")] - public bool port_has_property(Port port, Node property_uri); - [CCode (cname = "lilv_port_supports_event")] - public bool port_supports_event(Port port, Node event_uri); - [CCode (cname = "lilv_port_get_symbol")] - public unowned Node port_get_symbol(Port port); - [CCode (cname = "lilv_port_get_name")] - public Node port_get_name(Port port); - [CCode (cname = "lilv_port_get_classes")] - public unowned Nodes port_get_classes(Port port); - [CCode (cname = "lilv_port_is_a")] - public bool port_is_a(Port port, Node port_class); - [CCode (cname = "lilv_port_get_range")] - public void port_get_range(Port port, out Node deflt, out Node min, out Node max); - [CCode (cname = "lilv_port_get_scale_points")] - public ScalePoints port_get_scale_points(Port port); } [Compact] @@ -125,6 +104,32 @@ namespace Lilv { [Immutable] [CCode (free_function = "")] public class Port { + [CCode (instance_pos=1.5)] + public unowned Node get_node (Plugin plugin); + [CCode (instance_pos=1.5)] + public Nodes get_value (Plugin plugin, Node predicate); + [CCode (cname="lilv_plugin_get", instance_pos=1.5)] + public unowned Node get_property (Plugin plugin, Node predicate); + [CCode (instance_pos=1.5)] + public Nodes get_properties (Plugin plugin); + [CCode (instance_pos=1.5)] + public bool has_property (Plugin plugin, Node property); + [CCode (instance_pos=1.5)] + public bool supports_event (Plugin plugin, Node event_type); + [CCode (instance_pos=1.5)] + public uint32 get_index (Plugin plugin); + [CCode (instance_pos=1.5)] + public unowned Node get_symbol (Plugin plugin); + [CCode (instance_pos=1.5)] + public unowned Node get_name (Plugin plugin); + [CCode (instance_pos=1.5)] + public unowned Nodes get_classes (Plugin plugin); + [CCode (instance_pos=1.5)] + public bool is_a (Plugin plugin, Node port_class); + [CCode (instance_pos=1.5)] + public void get_range (Plugin plugin, out Node def, out Node min, out Node max); + [CCode (instance_pos=1.5)] + public ScalePoints get_scale_points (Plugin plugin); } [Compact] diff --git a/vapi/lv2.vapi b/vapi/lv2.vapi index 90443248..ad5af79e 100644 --- a/vapi/lv2.vapi +++ b/vapi/lv2.vapi @@ -142,7 +142,7 @@ namespace LV2 { /** * User interfaces of any type for plugins. * See for details. -*/ + */ [CCode (cheader_filename = "lv2/lv2plug.in/ns/extensions/ui/ui.h")] namespace LV2.UI { public const string URI; @@ -474,7 +474,7 @@ namespace LV2.Worker { public const string PREFIX; - public const string _Interface; + public const string _interface; public const string _schedule; [CCode (cname = "interface_work_t", has_target = false)] @@ -523,6 +523,7 @@ namespace LV2.Worker { public struct ScheduleHandle { } + [CCode (instance_pos = 0)] public delegate Status SchedulerFunc (uint32 size, void* data); [CCode (cname = "LV2_Worker_Schedule", destroy_function = "")] @@ -534,3 +535,425 @@ namespace LV2.Worker { } } + + +[CCode(cheader_filename="lv2/units/units.h")] +namespace LV2.Units { + public const string URI; + + public const string PREFIX; + + public const string _Conversion; + public const string _Unit; + public const string _bar; + public const string _beat; + public const string _bpm; + public const string _cent; + public const string _cm; + public const string _coef; + public const string _conversion; + public const string _db; + public const string _degree; + public const string _frame; + public const string _hz; + public const string _inch; + public const string _khz; + public const string _km; + public const string _m; + public const string _mhz; + public const string _midiNote; + public const string _mile; + public const string _min; + public const string _mm; + public const string _ms; + public const string _name; + public const string _oct; + public const string _pc; + public const string _prefixConversion; + public const string _render; + public const string _s; + public const string _semitone12TET; + public const string _symbol; + public const string _unit; +} + + +[CCode(cheader_filename="lv2/options/options.h")] +namespace LV2.Options { + public const string URI; + + public const string PREFIX; + + public const string _Option; + public const string _interface; + public const string _options; + public const string _requiredOption; + public const string _supportedOption; + + /** + * The context of an Option, which defines the subject it applies to. + */ + [CCode (cname = "LV2_Options_Context", has_type_id = false, cprefix = "LV2_OPTIONS_")] + public enum Context { + /** + * This option applies to the instance itself. + * + * The subject must be ignored. + */ + INSTANCE, + /** + * This option applies to some named resource. + * + * The subject is a URI mapped to an integer (a LV2_URID, like the key) + */ + RESOURCE, + /** + * This option applies to some blank node. + * + * The subject is a blank node identifier, which is valid only within the current local scope. + */ + BLANK, + /** + * This option applies to a port on the instance. + * + * The subject is the port's index. + */ + PORT + } + + /** + * A status code for option functions. + */ + [CCode (cname = "LV2_Options_Status", has_type_id = false, cprefix = "LV2_OPTIONS_")] + public enum Status { + SUCCESS, + ERR_UNKNOWN, + ERR_BAD_SUBJECT, + ERR_BAD_KEY, + ERR_BAD_VALUE + } + + /** + * An option. + * + * ---------- + * This is a property with a subject, also known as a triple or statement. + * + * This struct is useful anywhere a statement needs to be passed where no memory ownership issues are present + * (since the value is a const pointer). + * + * Options can be passed to an instance via the feature `LV2_OPTIONS__options` with data pointed to an array of + * options terminated by a zeroed option, or accessed/manipulated using `LV2_Options_Interface`. + */ + [SimpleType] + [CCode (cname = "LV2_Options_Option")] + public struct Option { + public Context context; + public uint32 subject; + public URID.Urid key; + public uint32 size; + public URID.Urid type; + public void* value; + } + + [CCode (cname = "lv2_options_interface_get_t", has_target = false)] + public delegate uint32 InterfaceGetFunc (LV2.Handle instance, out Option options); + + [CCode (cname = "lv2_options_interface_set_t", has_target = false)] + public delegate uint32 InterfaceSetFunc (LV2.Handle instance, Option options); + + /** + * Interface for dynamically setting options `(LV2_OPTIONS__interface)`. + */ + [Compact] + [SimpleType] + [CCode (cname = "LV2_Options_Interface", has_type_id = false, free_function = "")] + public class Interface { + /** + * Get the given options. + * + * ---------------------- + * Each element of the passed options array MUST have type, subject, and key set. All other fields (size, type, + * value) MUST be initialised to zero, and are set to the option value if such an option is found. + * + * This function is in the "instantiation" LV2 threading class, so no other instance functions may be called + * concurrently. + * + * @returns Bitwise OR of LV2_Options_Status values. + */ + [CCode (cname = "get", has_target = false, delegate_target_cname = "", simple_generics = true)] + public unowned InterfaceGetFunc get; + /** + * Set the given options. + * + * ---------------------- + * This function is in the "instantiation" LV2 threading class, so no other instance functions may be called concurrently. + * + * @returns Bitwise OR of LV2_Options_Status values. + */ + [CCode (cname = "set", has_target = false, delegate_target_cname = "", simple_generics = true)] + public unowned InterfaceSetFunc set; + } +} + + +[CCode(cheader_filename="lv2/parameters/parameters.h")] +namespace LV2.Parameters { + public const string URI; + + public const string PREFIX; + + public const string _CompressorControls; + public const string _ControlGroup; + public const string _EnvelopeControls; + public const string _FilterControls; + public const string _OscillatorControls; + public const string _amplitude; + public const string _attack; + public const string _bypass; + public const string _cutoffFrequency; + public const string _decay; + public const string _delay; + public const string _dryLevel; + public const string _frequency; + public const string _gain; + public const string _hold; + public const string _pulseWidth; + public const string _ratio; + public const string _release; + public const string _resonance; + public const string _sampleRate; + public const string _sustain; + public const string _threshold; + public const string _waveform; + public const string _wetDryRatio; + public const string _wetLevel; +} + + +[CCode(cheader_filename="lv2/buf-size/buf-size.h")] +namespace LV2.BufSize { + public const string URI; + + public const string PREFIX; + + public const string _boundedBlockLength; + public const string _coarseBlockLength; + public const string _fixedBlockLength; + public const string _maxBlockLength; + public const string _minBlockLength; + public const string _nominalBlockLength; + public const string _powerOf2BlockLength; + public const string _sequenceSize; +} + + +[CCode(cheader_filename="lv2/log/log.h")] +namespace LV2.Log { + public const string URI; + + public const string PREFIX; + + public const string _Entry; + public const string _Error; + public const string _Note; + public const string _Trace; + public const string _Warning; + public const string _log; + + [SimpleType] + [CCode (cname = "LV2_Log_Handle")] + public struct LogHandle { + } + + [CCode (instance_pos = 0)] + public delegate int PrintFunc (URID.Urid type, string fmt, ...); + + [CCode (instance_pos = 0)] + public delegate int VPrintFunc (URID.Urid type, string fmt, va_list ap); + + [CCode (cname = "LV2_Log_Log", destroy_function = "")] + public struct Log { + [CCode (cname = "handle")] + public LogHandle handle; + [CCode (cname = "printf", has_target = false, delegate_target_cname = "handle")] + public unowned PrintFunc printf; + [CCode (cname = "vprintf", has_target = false, delegate_target_cname = "handle")] + public unowned VPrintFunc vprintf; + } +} + + +[CCode(cheader_filename="lv2/patch/patch.h")] +namespace LV2.Patch { + public const string URI; + + public const string PREFIX; + + public const string _Ack; + public const string _Delete; + public const string _Copy; + public const string _Error; + public const string _Get; + public const string _Message; + public const string _Move; + public const string _Patch; + public const string _Post; + public const string _Put; + public const string _Request; + public const string _Response; + public const string _Set; + public const string _accept; + public const string _add; + public const string _body; + public const string _context; + public const string _destination; + public const string _property; + public const string _readable; + public const string _remove; + public const string _request; + public const string _subject; + public const string _sequenceNumber; + public const string _value; + public const string _wildcard; + public const string _writable; +} + + +[CCode(cheader_filename="lv2/time/time.h")] +namespace LV2.Time { + public const string URI; + + public const string PREFIX; + + public const string _Time; + public const string _Position; + public const string _Rate; + public const string _position; + public const string _barBeat; + public const string _bar; + public const string _beat; + public const string _beatUnit; + public const string _beatsPerBar; + public const string _beatsPerMinute; + public const string _frame; + public const string _framesPerSecond; + public const string _speed; +} + + +[CCode(cheader_filename="lv2/port-groups/port-groups.h")] +namespace LV2.PortGroups { + public const string URI; + + public const string PREFIX; + + public const string _DiscreteGroup; + public const string _Element; + public const string _FivePointOneGroup; + public const string _FivePointZeroGroup; + public const string _FourPointZeroGroup; + public const string _Group; + public const string _InputGroup; + public const string _MidSideGroup; + public const string _MonoGroup; + public const string _OutputGroup; + public const string _SevenPointOneGroup; + public const string _SevenPointOneWideGroup; + public const string _SixPointOneGroup; + public const string _StereoGroup; + public const string _ThreePointZeroGroup; + public const string _center; + public const string _centerLeft; + public const string _centerRight; + public const string _element; + public const string _group; + public const string _left; + public const string _lowFrequencyEffects; + public const string _mainInput; + public const string _mainOutput; + public const string _rearCenter; + public const string _rearLeft; + public const string _rearRight; + public const string _right; + public const string _side; + public const string _sideChainOf; + public const string _sideLeft; + public const string _sideRight; + public const string _source; + public const string _subGroupOf; +} + + +[CCode(cheader_filename="lv2/port-props/port-props.h")] +namespace LV2.PortProps { + public const string URI; + + public const string PREFIX; + + public const string _causesArtifacts; + public const string _continuousCV; + public const string _discreteCV; + public const string _displayProperty; + public const string _expensive; + public const string _hasStrictBounds; + public const string _logarithmic; + public const string _notAutomatic; + public const string _notOnGUI; + public const string _rangeSteps; + public const string _supportsStrictBounds; + public const string _trigger; +} + + +[CCode(cheader_filename="lv2/presets/presets.h")] +namespace LV2.Presets { + public const string URI; + + public const string PREFIX; + + public const string _Bank; + public const string _Preset; + public const string _bank; + public const string _preset; + public const string _value; +} + + +[CCode(cheader_filename="lv2/resize-port/resize-port.h")] +namespace LV2.ResizePort { + public const string URI; + + public const string PREFIX; + + public const string _asLargeAs; + public const string _minimumSize; + public const string _resize; + + /** + * A status code for state functions. + */ + [CCode (cname = "LV2_Resize_Port_Status", has_type_id = false, cprefix = "LV2_RESIZE_PORT_")] + public enum Status { + SUCCESS, + ERR_UNKNOWN, + ERR_NO_SPACE + } + + [SimpleType] + [CCode (cname = "LV2_Resize_Port_Feature_Data")] + public struct FeatureData { + } + + [CCode (cname = "lv2_port_resize_func_t", has_target = false)] + public delegate Status ResizeFunc (FeatureData data, uint32 index, size_t size); + + [Compact] + [SimpleType] + [CCode (cname = "LV2_Resize_Port_Resize", has_type_id = false, free_function = "")] + public class PortResize { + FeatureData data; + [CCode (cname = "resize", has_target = false, delegate_target_cname = "", simple_generics = true)] + public unowned ResizeFunc resize; + } +} diff --git a/vapi/portmidi.vapi b/vapi/portmidi.vapi new file mode 100644 index 00000000..2038da2c --- /dev/null +++ b/vapi/portmidi.vapi @@ -0,0 +1,193 @@ +/* + Copyright (C) 2013 Roman Soumin + All rights reserved. + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + + - Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN + ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + POSSIBILITY OF SUCH DAMAGE. +*/ + +[CCode (cprefix = "Pm", lower_case_cprefix = "", cheader_filename = "portmidi.h")] +namespace PortMidi { + + public struct DeviceID: int {} + public struct Timestamp: long {} + + [CCode (cname = "pmNoDevice")] + public const DeviceID NO_DEVICE; + + [Compact] + public class DeviceInfo { + [CCode (cname = "Pm_GetDeviceInfo")] + public static unowned DeviceInfo from_id(DeviceID id); + [CCode (cname = "structVersion")] + public int struct_version; + public string interf; + public string name; + public bool input; + public bool output; + public bool opened; + } + + public enum Error { + [CCode (cname = "FALSE")] FALSE, + [CCode (cname = "TRUE")] TRUE, + [CCode (cname = "pmNoError")] NO_ERROR, + [CCode (cname = "pmNoData")] NO_DATA, + [CCode (cname = "pmGotData")] GOT_DATA, + [CCode (cname = "pmHostError")] HOST_ERROR, + [CCode (cname = "pmInvalidDeviceId")] INVALID_DEVICE_ID, + [CCode (cname = "pmInsufficientMemory")] INSUFFICIENT_MEMORY, + [CCode (cname = "pmBufferTooSmall")] BUFFER_TOO_SMALL, + [CCode (cname = "pmBufferOverflow")] BUFFER_OVERFLOW, + [CCode (cname = "pmBadPtr")] BAD_PTR, + [CCode (cname = "pmBadData")] BAD_DATA, + [CCode (cname = "pmInternalError")] INTERNAL_ERROR, + [CCode (cname = "pmBufferMaxSize")] BUFFER_MAX_SIZE + } + + public struct Message: long { + [CCode (cname = "Pm_Message")] + public Message(int status, int data1, int data2); + [CCode (cname = "Pm_MessageStatus")] + public int status(); + [CCode (cname = "Pm_MessageData1")] + public int data1(); + [CCode (cname = "Pm_MessageData2")] + public int data2(); + } + + public struct Event { + Message message; + Timestamp timestamp; + } + + [Compact] + [CCode (free_function = "Pm_Close")] + class Stream { + public struct Filters: ulong {} + + [CCode (cname = "PM_FILT_ACTIVE")] + public const Filters FILT_ACTIVE; + [CCode (cname = "PM_FILT_SYSEX")] + public const Filters FILT_SYSEX; + [CCode (cname = "PM_FILT_CLOCK")] + public const Filters FILT_CLOCK; + [CCode (cname = "PM_FILT_PLAY")] + public const Filters FILT_PLAY; + [CCode (cname = "PM_FILT_TICK")] + public const Filters FILT_TICK; + [CCode (cname = "PM_FILT_FD")] + public const Filters FILT_FD; + [CCode (cname = "PM_FILT_UNDEFINED")] + public const Filters FILT_UNDEFINED; + [CCode (cname = "PM_FILT_RESET")] + public const Filters FILT_RESET; + [CCode (cname = "PM_FILT_REALTIME")] + public const Filters FILT_REALTIME; + [CCode (cname = "PM_FILT_NOTE")] + public const Filters FILT_NOTE; + [CCode (cname = "PM_FILT_CHANNEL_AFTERTOUCH")] + public const Filters FILT_CHANNEL_AFTERTOUCH; + [CCode (cname = "PM_FILT_POLY_AFTERTOUCH")] + public const Filters FILT_POLY_AFTERTOUCH; + [CCode (cname = "PM_FILT_AFTERTOUCH")] + public const Filters FILT_AFTERTOUCH; + [CCode (cname = "PM_FILT_PROGRAM")] + public const Filters PM_FILT_PROGRAM; + [CCode (cname = "PM_FILT_CONTROL")] + public const Filters FILT_CONTROL; + [CCode (cname = "PM_FILT_PITCHBEND")] + public const Filters FILT_PITCHBEND; + [CCode (cname = "PM_FILT_MTC")] + public const Filters FILT_MTC; + [CCode (cname = "PM_FILT_SONG_POSITION")] + public const Filters FILT_SONG_POSITION; + [CCode (cname = "PM_FILT_SONG_SELECT")] + public const Filters FILT_SONG_SELECT; + [CCode (cname = "PM_FILT_TUNE")] + public const Filters FILT_TUNE; + [CCode (cname = "PM_FILT_SYSTEMCOMMON")] + public const Filters FILT_SYSTEMCOMMON; + + public delegate Timestamp TimeProc(); + + [CCode (cname = "Pm_OpenInput")] + public static Error open_input(out Stream stream, + DeviceID inputDevice, + void* inputDriverInfo, + long bufferSize, + TimeProc? time_proc); + + [CCode (cname = "Pm_OpenOutput")] + public static Error open_output(out Stream stream, + DeviceID outputDevice, + void* outputDriverInfo, + long bufferSize, + TimeProc? time_proc, + long latency); + + [CCode (cname = "Pm_HasHostError")] + bool has_host_error(); + + [CCode (cname = "Pm_SetFilter")] + public Error set_filter(Filters filters); + + [CCode (cname = "Pm_SetChannelMask")] + public Error set_channel_mask(int mask); + + [CCode (cname = "Pm_Abort")] + public Error abort(); + + [CCode (cname = "Pm_Read")] + public int read(Event[] buffer); + + [CCode (cname = "Pm_Poll")] + public Error poll(); + + [CCode (cname = "Pm_Write")] + public Error write(Event[] buffer); + + [CCode (cname = "Pm_WriteShort")] + public Error write_short(Timestamp when, long msg); + + [CCode (cname = "Pm_WriteSysEx")] + public Error write_sys_ex(Timestamp when, string msg); + } + + + [CCode (cname = "Pm_Initialize")] + public Error initialize(); + [CCode (cname = "Pm_Terminate")] + public Error terminate(); + [CCode (cname = "Pm_GetErrorText")] + public string get_error_text(Error errorNum); + [CCode (cname = "Pm_CountDevices")] + public int count_devices(); + [CCode (cname = "Pm_GetDefaultInputDeviceID")] + public DeviceID get_default_input_device_id(); + [CCode (cname = "Pm_GetDefaultOutputDeviceID")] + public DeviceID get_default_output_device_id(); + [CCode (cname = "Pm_Channel")] + public int channel_mask(uint channel); +}