From dbc8f01adbf6e71580a7df25d726c20c18353a56 Mon Sep 17 00:00:00 2001 From: Olivier Galibert Date: Tue, 29 Oct 2024 00:01:41 +0100 Subject: [PATCH] file selector: Add midi connection selection to midi ports --- scripts/src/mame/frontend.lua | 2 + src/frontend/mame/ui/filesel.cpp | 18 +++++ src/frontend/mame/ui/filesel.h | 5 +- src/frontend/mame/ui/imgcntrl.cpp | 21 ++++++ src/frontend/mame/ui/imgcntrl.h | 5 +- src/frontend/mame/ui/midiinout.cpp | 105 ++++++++++++++++++++++++++ src/frontend/mame/ui/midiinout.h | 44 +++++++++++ src/osd/interface/midiport.h | 10 +++ src/osd/modules/lib/osdobj_common.cpp | 6 ++ src/osd/modules/lib/osdobj_common.h | 1 + src/osd/modules/midi/midi_module.h | 12 +-- src/osd/modules/midi/none.cpp | 2 +- src/osd/modules/midi/portmidi.cpp | 8 +- src/osd/osdepend.h | 2 + 14 files changed, 222 insertions(+), 19 deletions(-) create mode 100644 src/frontend/mame/ui/midiinout.cpp create mode 100644 src/frontend/mame/ui/midiinout.h diff --git a/scripts/src/mame/frontend.lua b/scripts/src/mame/frontend.lua index cee3aa4a7d7..7e1653a10fa 100644 --- a/scripts/src/mame/frontend.lua +++ b/scripts/src/mame/frontend.lua @@ -139,6 +139,8 @@ files { MAME_DIR .. "src/frontend/mame/ui/mainmenu.h", MAME_DIR .. "src/frontend/mame/ui/menu.cpp", MAME_DIR .. "src/frontend/mame/ui/menu.h", + MAME_DIR .. "src/frontend/mame/ui/midiinout.cpp", + MAME_DIR .. "src/frontend/mame/ui/midiinout.h", MAME_DIR .. "src/frontend/mame/ui/miscmenu.cpp", MAME_DIR .. "src/frontend/mame/ui/miscmenu.cpp", MAME_DIR .. "src/frontend/mame/ui/miscmenu.h", diff --git a/src/frontend/mame/ui/filesel.cpp b/src/frontend/mame/ui/filesel.cpp index 5f4dddc65fc..ac780c60d31 100644 --- a/src/frontend/mame/ui/filesel.cpp +++ b/src/frontend/mame/ui/filesel.cpp @@ -24,6 +24,9 @@ #include "util/corestr.h" #include "util/zippath.h" +#include "bus/midi/midiinport.h" +#include "bus/midi/midioutport.h" + #include #include @@ -69,6 +72,7 @@ menu_file_selector::menu_file_selector( , m_has_empty(has_empty) , m_has_softlist(has_softlist) , m_has_create(has_create) + , m_is_midi(image->device().type() == MIDIIN || image->device().type() == MIDIOUT) , m_clicked_directory(std::string::npos, std::string::npos) { (void)m_image; @@ -319,6 +323,10 @@ void menu_file_selector::append_entry_menu_item(const file_selector_entry *entry text = _("[empty slot]"); break; + case SELECTOR_ENTRY_TYPE_MIDI: + text = _("[midi port]"); + break; + case SELECTOR_ENTRY_TYPE_CREATE: text = _("[create]"); break; @@ -360,6 +368,12 @@ void menu_file_selector::select_item(const file_selector_entry &entry) stack_pop(); break; + case SELECTOR_ENTRY_TYPE_MIDI: + // create + m_result = result::MIDI; + stack_pop(); + break; + case SELECTOR_ENTRY_TYPE_CREATE: // create m_result = result::CREATE; @@ -491,6 +505,10 @@ void menu_file_selector::populate() if (m_has_empty) append_entry(SELECTOR_ENTRY_TYPE_EMPTY, "", ""); + // add the "[midi port]" entry if available + if (m_is_midi) + append_entry(SELECTOR_ENTRY_TYPE_MIDI, "", ""); + // add the "[create]" entry if (m_has_create && directory && !directory->is_archive()) append_entry(SELECTOR_ENTRY_TYPE_CREATE, "", ""); diff --git a/src/frontend/mame/ui/filesel.h b/src/frontend/mame/ui/filesel.h index 8c19100259c..653adc77c05 100644 --- a/src/frontend/mame/ui/filesel.h +++ b/src/frontend/mame/ui/filesel.h @@ -37,7 +37,8 @@ public: EMPTY = 0x1000, SOFTLIST, CREATE, - FILE + FILE, + MIDI }; using handler_function = std::function; @@ -65,6 +66,7 @@ private: enum file_selector_entry_type { SELECTOR_ENTRY_TYPE_EMPTY, + SELECTOR_ENTRY_TYPE_MIDI, SELECTOR_ENTRY_TYPE_CREATE, SELECTOR_ENTRY_TYPE_SOFTWARE_LIST, SELECTOR_ENTRY_TYPE_DRIVE, @@ -94,6 +96,7 @@ private: bool const m_has_empty; bool const m_has_softlist; bool const m_has_create; + bool const m_is_midi; std::vector m_entrylist; std::string m_filename; std::pair m_clicked_directory; diff --git a/src/frontend/mame/ui/imgcntrl.cpp b/src/frontend/mame/ui/imgcntrl.cpp index 6dd909f711c..ddcc5b82d7f 100644 --- a/src/frontend/mame/ui/imgcntrl.cpp +++ b/src/frontend/mame/ui/imgcntrl.cpp @@ -13,6 +13,7 @@ #include "ui/filecreate.h" #include "ui/filesel.h" +#include "ui/midiinout.h" #include "ui/swlist.h" #include "ui/ui.h" @@ -274,6 +275,10 @@ void menu_control_device_image::menu_activated() m_state = START_SOFTLIST; break; + case menu_file_selector::result::MIDI: + m_state = START_MIDI; + break; + default: // return to system stack_pop(); break; @@ -287,6 +292,22 @@ void menu_control_device_image::menu_activated() m_state = SELECT_SOFTLIST; break; + case START_MIDI: + m_midi = ""; + menu::stack_push(ui(), container(), m_image.image_interface(), &m_midi); + m_state = SELECT_MIDI; + break; + + case SELECT_MIDI: + if(!m_midi.empty()) + { + auto [err, msg] = m_image.load(m_midi); + if (err) + machine().popmessage(_("Error connecting to midi port: %1$s"), !msg.empty() ? msg : err.message()); + } + stack_pop(); + break; + case START_OTHER_PART: m_submenu_result.swparts = menu_software_parts::result::INVALID; menu::stack_push(ui(), container(), m_swi, m_image.image_interface(), &m_swp, true, m_submenu_result.swparts); diff --git a/src/frontend/mame/ui/imgcntrl.h b/src/frontend/mame/ui/imgcntrl.h index c081291f2e1..c41f6a25993 100644 --- a/src/frontend/mame/ui/imgcntrl.h +++ b/src/frontend/mame/ui/imgcntrl.h @@ -30,9 +30,9 @@ public: protected: enum { - START_FILE, START_OTHER_PART, START_SOFTLIST, + START_FILE, START_OTHER_PART, START_SOFTLIST, START_MIDI, SELECT_PARTLIST, SELECT_ONE_PART, SELECT_OTHER_PART, - CREATE_FILE, CREATE_CONFIRM, CHECK_CREATE, DO_CREATE, SELECT_SOFTLIST, + CREATE_FILE, CREATE_CONFIRM, CHECK_CREATE, DO_CREATE, SELECT_SOFTLIST, SELECT_MIDI, LAST_ID }; @@ -63,6 +63,7 @@ private: const software_part * m_swp; class software_list_device * m_sld; std::string m_software_info_name; + std::string m_midi; // methods virtual void populate() override; diff --git a/src/frontend/mame/ui/midiinout.cpp b/src/frontend/mame/ui/midiinout.cpp new file mode 100644 index 00000000000..28f335c7488 --- /dev/null +++ b/src/frontend/mame/ui/midiinout.cpp @@ -0,0 +1,105 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +/********************************************************************* + + ui/midiinout.cpp + + Midi channel selection + +*********************************************************************/ + +#include "emu.h" +#include "ui/midiinout.h" + +#include "ui/ui.h" + +#include "osdepend.h" + +namespace ui { + +menu_midi_inout::menu_midi_inout(mame_ui_manager &mui, render_container &container, bool is_input, std::string *channel) + : menu(mui, container) + , m_channel(channel) + , m_is_input(is_input) +{ + set_heading(m_is_input ? _("Midi input channel") : _("Midi output channel")); +} + +menu_midi_inout::~menu_midi_inout() +{ +} + +bool menu_midi_inout::handle(event const *ev) +{ + if(!ev) + return false; + + if(ev->iptkey == IPT_UI_SELECT) { + *m_channel = m_port_names[uintptr_t(ev->itemref)]; + stack_pop(); + return true; + } + + return false; +} + + +//------------------------------------------------- +// menu_midi_inout_populate - populate the midi_inout +// menu +//------------------------------------------------- + +void menu_midi_inout::populate() +{ + auto ports = machine().osd().list_midi_ports(); + for(auto &p : ports) + if((m_is_input && p.input) || (!m_is_input && p.output)) { + item_append(p.name, "", 0, (void *)(m_port_names.size())); + m_port_names.push_back(p.name); + } +} + + +//------------------------------------------------- +// recompute_metrics - recompute metrics +//------------------------------------------------- + +void menu_midi_inout::recompute_metrics(uint32_t width, uint32_t height, float aspect) +{ + menu::recompute_metrics(width, height, aspect); + + // set_custom_space(0.0f, 2.0f * line_height() + 2.0f * tb_border()); +} + + +//------------------------------------------------- +// menu_midi_inout_custom_render - perform our special +// rendering +//------------------------------------------------- + +void menu_midi_inout::custom_render(uint32_t flags, void *selectedref, float top, float bottom, float x1, float y1, float x2, float y2) +{ +} + + +//------------------------------------------------- +// menu_activated - handle menu gaining focus +//------------------------------------------------- + +void menu_midi_inout::menu_activated() +{ + // scripts or the other form of the menu could have changed something in the mean time + reset(reset_options::REMEMBER_POSITION); +} + + +//------------------------------------------------- +// menu_deactivated - handle menu losing focus +//------------------------------------------------- + +void menu_midi_inout::menu_deactivated() +{ +} + +} // namespace ui + diff --git a/src/frontend/mame/ui/midiinout.h b/src/frontend/mame/ui/midiinout.h new file mode 100644 index 00000000000..1cc7f360d35 --- /dev/null +++ b/src/frontend/mame/ui/midiinout.h @@ -0,0 +1,44 @@ +// license:BSD-3-Clause +// copyright-holders:Olivier Galibert +/*************************************************************************** + + ui/midiinout.h + + Midi channel selection + +***************************************************************************/ + +#ifndef MAME_FRONTEND_UI_MIDIINOUT_H +#define MAME_FRONTEND_UI_MIDIINOUT_H + +#pragma once + +#include "ui/menu.h" + + +namespace ui { + +class menu_midi_inout : public menu +{ +public: + menu_midi_inout(mame_ui_manager &mui, render_container &container, bool is_input, std::string *channel); + virtual ~menu_midi_inout() override; + +protected: + virtual void recompute_metrics(uint32_t width, uint32_t height, float aspect) override; + virtual void custom_render(uint32_t flags, void *selectedref, float top, float bottom, float x, float y, float x2, float y2) override; + virtual void menu_activated() override; + virtual void menu_deactivated() override; + +private: + std::vector m_port_names; + std::string *m_channel; + bool m_is_input; + + virtual void populate() override; + virtual bool handle(event const *ev) override; +}; + +} // namespace ui + +#endif // MAME_FRONTEND_UI_MIDIINOUT_H diff --git a/src/osd/interface/midiport.h b/src/osd/interface/midiport.h index f4ce04835a1..47c5bbc5c52 100644 --- a/src/osd/interface/midiport.h +++ b/src/osd/interface/midiport.h @@ -13,6 +13,7 @@ #pragma once #include +#include namespace osd { @@ -35,6 +36,15 @@ public: virtual void write(uint8_t data) = 0; }; +struct midi_port_info +{ + std::string name; + bool input; + bool output; + bool default_input; + bool default_output; +}; + } // namespace osd #endif // MAME_OSD_INTERFACE_MIDIPORT_H diff --git a/src/osd/modules/lib/osdobj_common.cpp b/src/osd/modules/lib/osdobj_common.cpp index ca166c3dbd9..e3c8d63b0d6 100644 --- a/src/osd/modules/lib/osdobj_common.cpp +++ b/src/osd/modules/lib/osdobj_common.cpp @@ -782,3 +782,9 @@ std::unique_ptr osd_common_t::create_midi_output(std::str { return m_midi->create_output(name); } + +std::vector osd_common_t::list_midi_ports() +{ + return m_midi->list_midi_ports(); +} + diff --git a/src/osd/modules/lib/osdobj_common.h b/src/osd/modules/lib/osdobj_common.h index 3f044d9d718..820fe3edf21 100644 --- a/src/osd/modules/lib/osdobj_common.h +++ b/src/osd/modules/lib/osdobj_common.h @@ -242,6 +242,7 @@ public: virtual std::unique_ptr create_midi_input(std::string_view name) override; virtual std::unique_ptr create_midi_output(std::string_view name) override; + virtual std::vector list_midi_ports() override; // FIXME: everything below seems to be osd specific and not part of // this INTERFACE but part of the osd IMPLEMENTATION diff --git a/src/osd/modules/midi/midi_module.h b/src/osd/modules/midi/midi_module.h index 6ea7290805b..61eef311aa6 100644 --- a/src/osd/modules/midi/midi_module.h +++ b/src/osd/modules/midi/midi_module.h @@ -26,23 +26,13 @@ class midi_module { public: - struct port_info - { - std::string name; - bool input; - bool output; - bool default_input; - bool default_output; - }; - using port_info_vector = std::vector; - virtual ~midi_module() = default; // specific routines virtual std::unique_ptr create_input(std::string_view name) = 0; virtual std::unique_ptr create_output(std::string_view name) = 0; - virtual port_info_vector list_midi_ports() = 0; + virtual std::vector list_midi_ports() = 0; }; #endif // MAME_OSD_MODULES_MIDI_MIDI_MODULE_H diff --git a/src/osd/modules/midi/none.cpp b/src/osd/modules/midi/none.cpp index c3dd0aaadc5..2a50bf71a84 100644 --- a/src/osd/modules/midi/none.cpp +++ b/src/osd/modules/midi/none.cpp @@ -30,7 +30,7 @@ public: virtual std::unique_ptr create_input(std::string_view name) override { return nullptr; } virtual std::unique_ptr create_output(std::string_view name) override { return nullptr; } - virtual port_info_vector list_midi_ports() override { return port_info_vector(); } + virtual std::vector list_midi_ports() override { return std::vector(); } }; } // anonymous namespace diff --git a/src/osd/modules/midi/portmidi.cpp b/src/osd/modules/midi/portmidi.cpp index 3a1dbf6739d..07372af1469 100644 --- a/src/osd/modules/midi/portmidi.cpp +++ b/src/osd/modules/midi/portmidi.cpp @@ -41,7 +41,7 @@ public: virtual std::unique_ptr create_input(std::string_view name) override; virtual std::unique_ptr create_output(std::string_view name) override; - virtual port_info_vector list_midi_ports() override; + virtual std::vector list_midi_ports() override; }; @@ -177,17 +177,17 @@ std::unique_ptr pm_module::create_output(std::string_view name } } -midi_module::port_info_vector pm_module::list_midi_ports() +std::vector pm_module::list_midi_ports() { int const num_devs = Pm_CountDevices(); int const def_input = Pm_GetDefaultInputDeviceID(); int const def_output = Pm_GetDefaultOutputDeviceID(); - port_info_vector result; + std::vector result; result.reserve(num_devs); for (int i = 0; num_devs > i; ++i) { auto const pm_info = Pm_GetDeviceInfo(i); - result.emplace_back(port_info{ + result.emplace_back(osd::midi_port_info{ pm_info->name, 0 != pm_info->input, 0 != pm_info->output, diff --git a/src/osd/osdepend.h b/src/osd/osdepend.h index 9824f16ebfe..8e9a4be6d7a 100644 --- a/src/osd/osdepend.h +++ b/src/osd/osdepend.h @@ -16,6 +16,7 @@ #include "emufwd.h" #include "bitmap.h" +#include "interface/midiport.h" #include #include @@ -97,6 +98,7 @@ public: // MIDI interface virtual std::unique_ptr create_midi_input(std::string_view name) = 0; virtual std::unique_ptr create_midi_output(std::string_view name) = 0; + virtual std::vector list_midi_ports() = 0; protected: virtual ~osd_interface() { }