Re: [hatari-devel] MIDI support for Windows & OSX (with PortMidi)

[ Thread Index | Date Index | More lists.tuxfamily.org/hatari-devel Archives ]


Hi,

Nicolas:

* Why changing any of the MIDI options requires reset, isn't
  host MIDI interface handling independent of the emulated
  Atari MIDI functionality?

* Or is it because MIDI write failing calls MIDI UnInit() and
  that removes pending MIDI interrupt(s)?  If yes, couldn't
  interrupt removal be moved to be done on write failure instead,
  so that MIDI host option changes could be done without emulation
  reset?


On 10/04/2017 02:29 AM, Simon Iten wrote:
On 4 Oct 2017, at 01:26, Simon Iten <itensimon@xxxxxxxxx> wrote:
after another unplug and replug of the midi-interface and another restart of hatari (with midi emulation enabled in the settings as before) it now shows up on the macbook without installed portmidi! great.

don’t know why the heck i would need 2 restarts of hatari, but it works now.

If there's a write error, the code seems to remove all MIDI inputs and outputs. Maybe in first restart you got such error?


i can access the preferences menu on osx in two ways, via osd or via application menu. could it be that only one works? i tried both and maybe that triggers the bug as well?
to be more precise, now both osd and from menu show my interface. but i tried both when they were not working and they look sligthly different. the menu preferences still has the writing to file for midi in addition to the portmidi stuff while the osd only has the portmidi selection.

Somebody with OSX needs to look at the OSX GUI code.

Attached is new version of the patch that:
* fixes the issue of needing to enable MIDI & reset Hatari before
  one can see the available MIDI interfaces
* fixes not being able to cancel MIDI option changes
* adds command line option for enabling PortMidi MIDI ports from
  command line
* adds "--trace midi" output for things that PortMidi does
  (interface connections etc)


	- Eero



On 4 Oct 2017, at 01:12, Simon Iten <itensimon@xxxxxxxxx <mailto:itensimon@xxxxxxxxx>> wrote:


On 4 Oct 2017, at 00:57, Eero Tamminen <oak@xxxxxxxxxxxxxx <mailto:oak@xxxxxxxxxxxxxx>> wrote:

Hi,

On 10/04/2017 01:50 AM, Simon Iten wrote:
just to confirm, i tried it on another macbook (also 10.12.6) and without the manual install of port midi it does not work. (i can not choose my interface from the menu)

Do you have MIDI enabled when you do that?
yes, it still only has off in the dropdown menu...

(The code has bug that it lists the MIDI interfaces only if you booted emulation with MIDI enabled.  Rebooting emulation should get them visible.  I have fix for that, but are facing other other issues.)


On 3 Oct 2017, at 14:03, Simon Iten <itensimon@xxxxxxxxx <mailto:itensimon@xxxxxxxxx>> wrote:

when i tried without installing portmidi, the new midi device selector popped up, but i could not select my interface. after i installed portmidi and rebooted, the device (fastlane-usb by motu) showed up.

so it seems the dynamic library fails to load here.

I think Hatari would fail to start if library it uses cannot be loaded.

It seems more likely that the (older?) portmidi version included with the build for some reason doesn't support something required for your MIDI interface.


i think it should be the same version since i also used portmidi from homebrew, as troed did for building.

	- Eero

On 3 Oct 2017, at 13:51, Troed Sångberg <troed@xxxxxxxxxxx <mailto:troed@xxxxxxxxxxx> <mailto:troed@xxxxxxxxxxx <mailto:troed@xxxxxxxxxxx>>> wrote:

Thanks for testing! But .. did you need to install portmidi as well? What happened if you didn't?

(My build includes the portmidi dynamic library)

regards,
Troed


Sent from ProtonMail mobile



-------- Original Message --------
On Oct 3, 2017, 13:47, Simon Iten < itensimon@xxxxxxxxx <mailto:itensimon@xxxxxxxxx> <mailto:itensimon@xxxxxxxxx <mailto:itensimon@xxxxxxxxx>>> wrote:

hey,

home early :-)

it works here after an install of portmidi on 10.12.6. at first glance seems much more stable with sysex data then my hatari build on linux with the same interface. horray!! this is great. will have to test further...

thanks

simon

On 2 Oct 2017, at 15:14, Troed Sångberg <troed@xxxxxxxxxxx <mailto:troed@xxxxxxxxxxx> <mailto:troed@xxxxxxxxxxx <mailto:troed@xxxxxxxxxxx>>> wrote:

patch applied and built for macOS: https://troed.ddns.net/f/54ddaa46c16b4c47b878/ <https://troed.ddns.net/f/54ddaa46c16b4c47b878/> <https://troed.ddns.net/f/54ddaa46c16b4c47b878/ <https://troed.ddns.net/f/54ddaa46c16b4c47b878/>>

However, I have not followed the instructions at all ... :P I installed portmidi using Macports to get a universal dylib, like I do with all other non-standard libraries. CoreAudio and CoreMIDI are osx default frameworks so those should exist on end user systems and thus I have not added them to the Hatari binary either.

I have no MIDI equipment to test with myself. If there's a Mac user on the list who has, please try to above binary and let me know what happens.

(Since I didn't do this in a separate build environment my nightly builds will from tonight also get this functionality)

regards,
Troed



-------- Original Message --------
Subject: [hatari-devel] MIDI support for Windows & OSX (with PortMidi)
Local Time: October 1, 2017 11:57 PM
UTC Time: October 1, 2017 9:57 PM
From: oak@xxxxxxxxxxxxxx <mailto:oak@xxxxxxxxxxxxxx> <mailto:oak@xxxxxxxxxxxxxx <mailto:oak@xxxxxxxxxxxxxx>>
To: hatari-devel@xxxxxxxxxxxxxxxxxxx <mailto:hatari-devel@xxxxxxxxxxxxxxxxxxx> <mailto:hatari-devel@xxxxxxxxxxxxxxxxxxx <mailto:hatari-devel@xxxxxxxxxxxxxxxxxxx>>

Hi,

I got from Jari Kleimola code for adding portmidi library support for
Hatari, which means getting Hatari MIDI working also on OSX and Windows
in addition to Linux.

Attached is patch from him with few bug fixes & CMake stuff from me
(those were needed to make it work also on Linux, so that I could test it).


I would appreciate if somebody with a MIDI device or SW synthetizer
using Windows and/or OSX could test whether it makes MIDI work on their
setup.


Attached are also Jari"s instructions on getting portmidi building on
OSX (he didn"t use CMake for building, but XCode).


- Eero

PS. Jari has also some questions about jitter he"s seeing in MIDI output:
http://www.atari-forum.com/viewtopic.php?f=51&t=32344 <http://www.atari-forum.com/viewtopic.php?f=51&t=32344> <http://www.atari-forum.com/viewtopic.php?f=51&t=32344 <http://www.atari-forum.com/viewtopic.php?f=51&t=32344>>



diff -r 3f4adb62da35 .hgignore
--- a/.hgignore	Sun Oct 01 08:09:42 2017 +0200
+++ b/.hgignore	Wed Oct 04 01:32:31 2017 +0300
@@ -45,6 +45,7 @@
 build/*
 Hatari.build/*
 Release/*
+*.DS_Store
 
 # switch to regexp syntax.
 syntax: regexp
diff -r 3f4adb62da35 CMakeLists.txt
--- a/CMakeLists.txt	Sun Oct 01 08:09:42 2017 +0200
+++ b/CMakeLists.txt	Wed Oct 04 01:32:31 2017 +0300
@@ -126,6 +126,11 @@
 	set(HAVE_PORTAUDIO 1)
 endif(PORTAUDIO_FOUND)
 
+find_package(PortMidi)
+if(PORTMIDI_FOUND)
+	set(HAVE_PORTMIDI 1)
+endif(PORTMIDI_FOUND)
+
 find_package(CapsImage)
 if(CAPSIMAGE_FOUND)
 	set(HAVE_CAPSIMAGE 1)
@@ -352,6 +357,12 @@
   message( "  - portaudio :\tnot found, install it to enable the Falcon microphone input" )
 endif(PORTAUDIO_FOUND)
 
+if(PORTMIDI_FOUND)
+  message( "  - portmidi :\tfound, enables the portable MIDI support" )
+else()
+  message( "  - portmidi :\tnot found, install it to enable MIDI on Windows / OSX" )
+endif(PORTMIDI_FOUND)
+
 if(CAPSIMAGE_FOUND)
   message( "  - capsimage :\tv${CAPSIMAGE_VERSION} found, allow to use .IPF, .RAW and .CTR disk images" )
 else()
diff -r 3f4adb62da35 cmake/FindPortMidi.cmake
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cmake/FindPortMidi.cmake	Wed Oct 04 01:32:31 2017 +0300
@@ -0,0 +1,35 @@
+#
+# Find the native PORTMIDI includes and library
+#
+#  PORTMIDI_INCLUDE_DIR  - where to find portmidi.h, etc.
+#  PORTMIDI_LIBRARY      - List of libraries when using portmidi.
+#  PORTAUDIO_FOUND       - True if portmidi found.
+
+include(FindPackageHandleStandardArgs)
+include(CheckFunctionExists)
+
+if(PORTMIDI_INCLUDE_DIR)
+  # Already in cache, be silent
+  set(PORTMIDI_FIND_QUIETLY TRUE)
+endif(PORTMIDI_INCLUDE_DIR)
+
+find_path(PORTMIDI_INCLUDE_DIR portmidi.h)
+
+find_library(PORTMIDI_LIBRARY NAMES portmidi)
+
+# handle the QUIETLY and REQUIRED arguments and set PORTMIDI_FOUND to TRUE if 
+# all listed variables are TRUE
+find_package_handle_standard_args(PORTMIDI DEFAULT_MSG
+                                  PORTMIDI_LIBRARY PORTMIDI_INCLUDE_DIR)
+
+# Check if it's really a portmidi installation...
+if(PORTMIDI_FOUND)
+	set(CMAKE_REQUIRED_LIBRARIES ${PORTMIDI_LIBRARY})
+	check_function_exists(Pm_Initialize HAVE_PM_INITIALIZE)
+	if (NOT HAVE_PM_INITIALIZE)
+		unset (PORTMIDI_FOUND)
+	endif(NOT HAVE_PM_INITIALIZE)
+	set(CMAKE_REQUIRED_LIBRARIES "")
+endif(PORTMIDI_FOUND)
+
+mark_as_advanced(PORTMIDI_LIBRARY PORTMIDI_INCLUDE_DIR)
diff -r 3f4adb62da35 cmake/config-cmake.h
--- a/cmake/config-cmake.h	Sun Oct 01 08:09:42 2017 +0200
+++ b/cmake/config-cmake.h	Wed Oct 04 01:32:31 2017 +0300
@@ -9,6 +9,9 @@
 /* Define if you have the PortAudio library */
 #cmakedefine HAVE_PORTAUDIO 1
 
+/* Define if you have the PortMidi library */
+#cmakedefine HAVE_PORTMIDI 1
+
 /* Define if you have the capsimage library */
 #cmakedefine HAVE_CAPSIMAGE 1
 #cmakedefine CAPSIMAGE_VERSION @CAPSIMAGE_VERSION@
diff -r 3f4adb62da35 src/CMakeLists.txt
--- a/src/CMakeLists.txt	Sun Oct 01 08:09:42 2017 +0200
+++ b/src/CMakeLists.txt	Wed Oct 04 01:32:31 2017 +0300
@@ -166,6 +166,10 @@
 	target_link_libraries(hatari ${PORTAUDIO_LIBRARY})
 endif(PORTAUDIO_FOUND)
 
+if(PORTMIDI_FOUND)
+	target_link_libraries(hatari ${PORTMIDI_LIBRARY})
+endif(PORTMIDI_FOUND)
+
 if(CAPSIMAGE_FOUND)
 	target_link_libraries(hatari ${CAPSIMAGE_LIBRARY})
 endif(CAPSIMAGE_FOUND)
diff -r 3f4adb62da35 src/change.c
--- a/src/change.c	Sun Oct 01 08:09:42 2017 +0200
+++ b/src/change.c	Wed Oct 04 01:32:31 2017 +0300
@@ -332,9 +332,14 @@
 
 	/* Did change MIDI settings? */
 	if (current->Midi.bEnableMidi != changed->Midi.bEnableMidi
-	    || ((strcmp(changed->Midi.sMidiOutFileName, current->Midi.sMidiOutFileName)
-	         || strcmp(changed->Midi.sMidiInFileName, current->Midi.sMidiInFileName))
-	        && changed->Midi.bEnableMidi))
+#ifdef HAVE_PORTMIDI
+	    || strcmp(changed->Midi.sMidiOutPortName, current->Midi.sMidiOutPortName)
+	    || strcmp(changed->Midi.sMidiInPortName, current->Midi.sMidiInPortName)
+#else
+	    || strcmp(changed->Midi.sMidiOutFileName, current->Midi.sMidiOutFileName)
+	    || strcmp(changed->Midi.sMidiInFileName, current->Midi.sMidiInFileName)
+#endif
+	    )
 	{
 		Dprintf("- midi>\n");
 		Midi_UnInit();
diff -r 3f4adb62da35 src/configuration.c
--- a/src/configuration.c	Sun Oct 01 08:09:42 2017 +0200
+++ b/src/configuration.c	Wed Oct 04 01:32:31 2017 +0300
@@ -517,6 +517,8 @@
 	{ "bEnableMidi", Bool_Tag, &ConfigureParams.Midi.bEnableMidi },
 	{ "sMidiInFileName", String_Tag, ConfigureParams.Midi.sMidiInFileName },
 	{ "sMidiOutFileName", String_Tag, ConfigureParams.Midi.sMidiOutFileName },
+	{ "sMidiInPortName", String_Tag, ConfigureParams.Midi.sMidiInPortName },
+	{ "sMidiOutPortName", String_Tag, ConfigureParams.Midi.sMidiOutPortName },
 	{ NULL , Error_Tag, NULL }
 };
 
@@ -730,6 +732,8 @@
 	ConfigureParams.Midi.bEnableMidi = false;
 	strcpy(ConfigureParams.Midi.sMidiInFileName, "/dev/snd/midiC1D0");
 	strcpy(ConfigureParams.Midi.sMidiOutFileName, "/dev/snd/midiC1D0");
+	strcpy(ConfigureParams.Midi.sMidiInPortName, "Off");
+	strcpy(ConfigureParams.Midi.sMidiOutPortName, "Off");
 
 	/* Set defaults for Screen */
 	ConfigureParams.Screen.bFullScreen = false;
diff -r 3f4adb62da35 src/gui-osx/PrefsController.h
--- a/src/gui-osx/PrefsController.h	Sun Oct 01 08:09:42 2017 +0200
+++ b/src/gui-osx/PrefsController.h	Wed Oct 04 01:32:31 2017 +0300
@@ -117,6 +117,8 @@
 	IBOutlet NSTextField *readRS232FromFile;			// T
 	IBOutlet NSButton *enableMidi;
 	IBOutlet NSTextField *writeMidiToFile;				// T
+	__unsafe_unretained IBOutlet NSPopUpButton *midiInPort;
+	__unsafe_unretained IBOutlet NSPopUpButton *midiOutPort;
 
 	// Other
 
diff -r 3f4adb62da35 src/gui-osx/PrefsController.m
--- a/src/gui-osx/PrefsController.m	Sun Oct 01 08:09:42 2017 +0200
+++ b/src/gui-osx/PrefsController.m	Wed Oct 04 01:32:31 2017 +0300
@@ -32,6 +32,7 @@
 #include "paths.h"
 #include "keymap.h"
 #include "joy.h"
+#include "midi.h"
 
 // Macros to transfer data between Cocoa controls and Hatari data structures
 // de l'affichage vers la structure  (saveAllControls)
@@ -559,12 +560,53 @@
 	{
 		SDLKey key = Preferences_KeysForJoysticks[i];
 		const char* szKeyName = SDL_GetKeyName(key);
-		[dropDown addItemWithTitle:[[NSString stringWithCString:szKeyName encoding:NSASCIIStringEncoding] capitalizedString]];	
+		[dropDown addItemWithTitle:[[NSString stringWithCString:szKeyName encoding:NSASCIIStringEncoding] capitalizedString]];
 		dropDown.lastItem.tag = key ;
 	}
 }
 
 
+// ----------------------------------------------------------------------------
+// populate MIDI dropdowns
+//
+- (void)initMidiDropdowns
+{
+	[midiInPort  removeAllItems];
+	[midiOutPort removeAllItems];
+	const char* szinPortName = "Off";
+	[midiInPort  addItemWithTitle:[NSString stringWithCString:szinPortName encoding:NSASCIIStringEncoding]];
+	[midiOutPort addItemWithTitle:[NSString stringWithCString:szinPortName encoding:NSASCIIStringEncoding]];
+	
+	int i = 0;
+	const char* portName;
+	while ((portName = Midi_Host_GetPortName(i++, true)))
+		[midiInPort addItemWithTitle:[NSString stringWithCString:portName encoding:NSASCIIStringEncoding]];
+	i = 0;
+	while ((portName = Midi_Host_GetPortName(i++, false)))
+		[midiOutPort addItemWithTitle:[NSString stringWithCString:portName encoding:NSASCIIStringEncoding]];
+}
+
+// ----------------------------------------------------------------------------
+// ConfigureParams -> GUI controls
+//
+- (void)setMidiDropdowns
+{
+	[midiInPort  selectItemWithTitle:[NSString stringWithCString:ConfigureParams.Midi.sMidiInPortName  encoding:NSASCIIStringEncoding]];
+	[midiOutPort selectItemWithTitle:[NSString stringWithCString:ConfigureParams.Midi.sMidiOutPortName encoding:NSASCIIStringEncoding]];
+}
+
+// ----------------------------------------------------------------------------
+// GUI controls -> ConfigureParams
+//
+- (void)saveMidiDropdowns
+{
+	strncpy(ConfigureParams.Midi.sMidiInPortName,  [[midiInPort  titleOfSelectedItem] UTF8String], FILENAME_MAX);
+	strncpy(ConfigureParams.Midi.sMidiOutPortName, [[midiOutPort titleOfSelectedItem] UTF8String], FILENAME_MAX);
+	ConfigureParams.Midi.sMidiInPortName[FILENAME_MAX-1]  = 0;
+	ConfigureParams.Midi.sMidiOutPortName[FILENAME_MAX-1] = 0;
+}
+
+
 /*----------------------------------------------------------------------*/
 //Displays the Preferences dialog   Ouverture de la fenêtre des préférences
 /*----------------------------------------------------------------------*/
@@ -604,7 +646,10 @@
 			[joystickMode cellWithTag:1].enabled = FALSE ;
 			realJoystick.enabled = FALSE ;
 		}
-		
+
+		// Fill MIDI dropdowns
+		[self initMidiDropdowns];
+
 		bInitialized = true;
 	}
 
@@ -846,10 +891,13 @@
 	{
 		gemdosImage.stringValue = @"" ; [gemdos setString:@""];
 	}
-	
+
 	// Set the per-joystick controls
 	[self setJoystickControls];
-	
+
+	// -- MIDI
+	[self setMidiDropdowns];
+
 	// Update the controls' enabled states
 	[self updateEnabledStates:self];
 }
@@ -1112,6 +1160,9 @@
 
 	// Save the per-joystick controls
 	[self saveJoystickControls];
+
+	// -- MIDI
+	[self saveMidiDropdowns];
 }
 
 /*----------------------------------------------------------------------*/
diff -r 3f4adb62da35 src/gui-osx/en.lproj/SDLMain.xib
--- a/src/gui-osx/en.lproj/SDLMain.xib	Sun Oct 01 08:09:42 2017 +0200
+++ b/src/gui-osx/en.lproj/SDLMain.xib	Wed Oct 04 01:32:31 2017 +0300
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="12118" systemVersion="16A323" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
+<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="12120" systemVersion="16E195" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
     <dependencies>
         <deployment version="1060" identifier="macosx"/>
-        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12118"/>
+        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="12120"/>
         <capability name="box content view" minToolsVersion="7.0"/>
         <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
     </dependencies>
@@ -272,7 +272,7 @@
                                                 <rect key="frame" x="1" y="1" width="628" height="174"/>
                                                 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                                 <subviews>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="4679">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="4679">
                                                         <rect key="frame" x="209" y="32" width="180" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="GEMDOS Write protection" id="4680">
@@ -281,7 +281,7 @@
                                                             <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="491">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="491">
                                                         <rect key="frame" x="62" y="146" width="111" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="ACSI HD image:" id="4479">
@@ -290,7 +290,7 @@
                                                             <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" id="477">
+                                                    <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="477">
                                                         <rect key="frame" x="178" y="145" width="278" height="19"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4466">
@@ -299,7 +299,7 @@
                                                             <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="3735">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="3735">
                                                         <rect key="frame" x="15" y="122" width="158" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="IDE Master HD image:" id="4487">
@@ -330,7 +330,7 @@
                                                             <action selector="chooseIdeMasterHdImage:" target="329" id="4542"/>
                                                         </connections>
                                                     </button>
-                                                    <textField verticalHuggingPriority="750" id="3738">
+                                                    <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="3738">
                                                         <rect key="frame" x="178" y="121" width="278" height="19"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4490">
@@ -339,7 +339,7 @@
                                                             <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="4530">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="4530">
                                                         <rect key="frame" x="27" y="99" width="146" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="IDE Slave HD image:" id="4537">
@@ -359,7 +359,7 @@
                                                             <action selector="ejectIdeSlaveHdImage:" target="329" id="4545"/>
                                                         </connections>
                                                     </button>
-                                                    <textField verticalHuggingPriority="750" id="4533">
+                                                    <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="4533">
                                                         <rect key="frame" x="178" y="98" width="278" height="19"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4534">
@@ -462,7 +462,7 @@
                                                             <action selector="chooseGemdosImage:" target="329" id="542"/>
                                                         </connections>
                                                     </button>
-                                                    <textField verticalHuggingPriority="750" id="502">
+                                                    <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="502">
                                                         <rect key="frame" x="178" y="75" width="278" height="19"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4484">
@@ -471,7 +471,7 @@
                                                             <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="478">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="478">
                                                         <rect key="frame" x="66" y="76" width="107" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="GEMDOS drive:" id="4467">
@@ -509,7 +509,7 @@
                                                 <rect key="frame" x="1" y="1" width="639" height="168"/>
                                                 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                                 <subviews>
-                                                    <textField verticalHuggingPriority="750" id="481">
+                                                    <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="481">
                                                         <rect key="frame" x="104" y="75" width="352" height="19"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4470">
@@ -529,7 +529,7 @@
                                                             <font key="font" metaFont="system"/>
                                                         </buttonCell>
                                                     </button>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="476">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="476">
                                                         <rect key="frame" x="9" y="132" width="95" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Drive A image:" id="4465">
@@ -538,7 +538,7 @@
                                                             <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" id="492">
+                                                    <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="492">
                                                         <rect key="frame" x="107" y="132" width="349" height="19"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4480">
@@ -550,7 +550,7 @@
                                                             <outlet property="nextKeyView" destination="486" id="818"/>
                                                         </connections>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="503">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="503">
                                                         <rect key="frame" x="165" y="44" width="133" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Write Protection" id="4485">
@@ -559,7 +559,7 @@
                                                             <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="473">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="473">
                                                         <rect key="frame" x="9" y="77" width="95" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Drive B image:" id="4462">
@@ -568,7 +568,7 @@
                                                             <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" id="490">
+                                                    <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="490">
                                                         <rect key="frame" x="176" y="15" width="280" height="19"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4478">
@@ -580,7 +580,7 @@
                                                             <outlet property="nextKeyView" destination="485" id="826"/>
                                                         </connections>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="493">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="493">
                                                         <rect key="frame" x="12" y="14" width="158" height="20"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Default images location:" id="4481">
@@ -744,7 +744,7 @@
                                     <rect key="frame" x="10" y="25" width="643" height="384"/>
                                     <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                     <subviews>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="513">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="513">
                                             <rect key="frame" x="91" y="342" width="84" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" id="4493">
@@ -766,7 +766,7 @@
                                                 <action selector="chooseTosImage:" target="329" id="587"/>
                                             </connections>
                                         </button>
-                                        <textField verticalHuggingPriority="750" id="508">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="508">
                                             <rect key="frame" x="180" y="340" width="361" height="19"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4491">
@@ -775,7 +775,7 @@
                                                 <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                             </textFieldCell>
                                         </textField>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="514">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="514">
                                             <rect key="frame" x="17" y="298" width="158" height="34"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" id="4494">
@@ -797,7 +797,7 @@
                                                 <action selector="chooseCartridgeImage:" target="329" id="588"/>
                                             </connections>
                                         </button>
-                                        <textField verticalHuggingPriority="750" id="511">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="511">
                                             <rect key="frame" x="180" y="313" width="361" height="19"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4492">
@@ -806,7 +806,7 @@
                                                 <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                             </textFieldCell>
                                         </textField>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="4547">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="4547">
                                             <rect key="frame" x="201" y="228" width="319" height="23"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" title="A RESET is needed after changing these options." id="4548">
@@ -868,7 +868,7 @@
                                                             </column>
                                                         </cells>
                                                     </matrix>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="451">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="451">
                                                         <rect key="frame" x="355" y="38" width="98" height="34"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="Color depth:" id="4444">
@@ -914,7 +914,7 @@
                                                 <rect key="frame" x="1" y="1" width="595" height="147"/>
                                                 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                                 <subviews>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="433">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="433">
                                                         <rect key="frame" x="150" y="120" width="100" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="Monitor:" id="4437">
@@ -1004,7 +1004,7 @@
                                                             <font key="font" metaFont="system"/>
                                                         </buttonCell>
                                                     </button>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="4632">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="4632">
                                                         <rect key="frame" x="64" y="49" width="80" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="AVI Codec:" id="4633">
@@ -1027,7 +1027,7 @@
                                                             </menu>
                                                         </popUpButtonCell>
                                                     </popUpButton>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="4642">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="4642">
                                                         <rect key="frame" x="64" y="21" width="80" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="AVI FPS:" id="4648">
@@ -1078,7 +1078,7 @@
                                                             <font key="font" metaFont="system"/>
                                                         </buttonCell>
                                                     </button>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="4683">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="4683">
                                                         <rect key="frame" x="346" y="83" width="158" height="22"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Max Zoomed " id="4694">
@@ -1087,7 +1087,7 @@
                                                             <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" id="4686">
+                                                    <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="4686">
                                                         <rect key="frame" x="419" y="58" width="41" height="22"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="1280" drawsBackground="YES" id="4691">
@@ -1096,7 +1096,7 @@
                                                             <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" id="4688">
+                                                    <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="4688">
                                                         <rect key="frame" x="419" y="28" width="41" height="22"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" title="768" drawsBackground="YES" id="4689">
@@ -1105,7 +1105,7 @@
                                                             <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="4684">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="4684">
                                                         <rect key="frame" x="398" y="50" width="22" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="x " id="4693">
@@ -1130,7 +1130,7 @@
                                                             <action selector="setHeight:" target="329" id="4697"/>
                                                         </connections>
                                                     </stepper>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="4552">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="4552">
                                                         <rect key="frame" x="41" y="40" width="86" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="Frame skip:" id="4553">
@@ -1181,7 +1181,7 @@
                                                             <font key="font" metaFont="system"/>
                                                         </buttonCell>
                                                     </button>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="4705">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="4705">
                                                         <rect key="frame" x="312" y="115" width="236" height="23"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="center" title="Falcon/TT Only" id="4706">
@@ -1297,7 +1297,7 @@
                                                 </column>
                                             </cells>
                                         </matrix>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="384">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="384">
                                             <rect key="frame" x="247" y="325" width="114" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Playback quality:" id="4422">
@@ -1306,7 +1306,7 @@
                                                 <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                             </textFieldCell>
                                         </textField>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="4731">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="4731">
                                             <rect key="frame" x="247" y="114" width="114" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="YM Voices Mixing" id="4732">
@@ -1365,7 +1365,7 @@
                                                 </menu>
                                             </popUpButtonCell>
                                         </popUpButton>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" id="1228">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" allowsCharacterPickerTouchBarItem="NO" id="1228">
                                             <rect key="frame" x="170" y="195" width="36" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="DSP:" id="4434">
@@ -1422,7 +1422,7 @@
                                                 <rect key="frame" x="1" y="1" width="180" height="203"/>
                                                 <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                                 <subviews>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" id="811">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" allowsCharacterPickerTouchBarItem="NO" id="811">
                                                         <rect key="frame" x="15" y="176" width="88" height="20"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="ST RAM SIZE" id="4432">
@@ -1431,7 +1431,7 @@
                                                             <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" id="ym5-XQ-zFl">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" allowsCharacterPickerTouchBarItem="NO" id="ym5-XQ-zFl">
                                                         <rect key="frame" x="18" y="48" width="100" height="14"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="TT RAM SIZE" id="gFq-Ih-mzv">
@@ -1440,7 +1440,7 @@
                                                             <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" id="lNG-9l-lLd">
+                                                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" allowsCharacterPickerTouchBarItem="NO" id="lNG-9l-lLd">
                                                         <rect key="frame" x="19" y="26" width="34" height="14"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="left" title="Mib" id="tQK-Ol-65u">
@@ -1449,7 +1449,7 @@
                                                             <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                                         </textFieldCell>
                                                     </textField>
-                                                    <textField verticalHuggingPriority="750" misplaced="YES" id="fWm-1J-m56">
+                                                    <textField verticalHuggingPriority="750" misplaced="YES" allowsCharacterPickerTouchBarItem="NO" id="fWm-1J-m56">
                                                         <rect key="frame" x="51" y="22" width="63" height="22"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" alignment="center" drawsBackground="YES" id="uMb-sS-i1G">
@@ -1769,7 +1769,7 @@
                                                             </menu>
                                                         </popUpButtonCell>
                                                     </popUpButton>
-                                                    <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" id="fed-jL-MEf">
+                                                    <textField horizontalHuggingPriority="251" verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="fed-jL-MEf">
                                                         <rect key="frame" x="490" y="84" width="84" height="17"/>
                                                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                                         <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" allowsUndo="NO" sendsActionOnEndEditing="YES" title="Video Timing" id="7Mc-pN-A0A">
@@ -1810,7 +1810,7 @@
                                                 <action selector="changeViewedJoystick:" target="329" id="753"/>
                                             </connections>
                                         </popUpButton>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="460">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="460">
                                             <rect key="frame" x="177" y="347" width="114" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" title="Settings for:" id="4448">
@@ -1862,7 +1862,7 @@
                                                 </menu>
                                             </popUpButtonCell>
                                         </popUpButton>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="711">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="711">
                                             <rect key="frame" x="222" y="202" width="98" height="34"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" id="4451">
@@ -1888,7 +1888,7 @@
                                                 </menu>
                                             </popUpButtonCell>
                                         </popUpButton>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="717">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="717">
                                             <rect key="frame" x="222" y="174" width="98" height="34"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" id="4453">
@@ -1914,7 +1914,7 @@
                                                 </menu>
                                             </popUpButtonCell>
                                         </popUpButton>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="723">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="723">
                                             <rect key="frame" x="222" y="146" width="98" height="34"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" id="4455">
@@ -1940,7 +1940,7 @@
                                                 </menu>
                                             </popUpButtonCell>
                                         </popUpButton>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="729">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="729">
                                             <rect key="frame" x="222" y="132" width="98" height="20"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" id="4457">
@@ -1966,7 +1966,7 @@
                                                 </menu>
                                             </popUpButtonCell>
                                         </popUpButton>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="735">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="735">
                                             <rect key="frame" x="264" y="107" width="56" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" id="4459">
@@ -2008,7 +2008,7 @@
                                     <rect key="frame" x="10" y="25" width="643" height="384"/>
                                     <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                     <subviews>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="376">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="376">
                                             <rect key="frame" x="150" y="347" width="160" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Keyboard mapping:" id="4419">
@@ -2055,7 +2055,7 @@
                                                 <action selector="chooseKeyboardMappingFile:" target="329" id="589"/>
                                             </connections>
                                         </button>
-                                        <textField verticalHuggingPriority="750" id="585">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="585">
                                             <rect key="frame" x="101" y="259" width="411" height="19"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4421">
@@ -2080,7 +2080,7 @@
                                     <rect key="frame" x="10" y="25" width="643" height="384"/>
                                     <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                                     <subviews>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="355">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="355">
                                             <rect key="frame" x="17" y="325" width="158" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Print to file:" id="4405">
@@ -2100,7 +2100,7 @@
                                                 <action selector="choosePrintToFile:" target="329" id="590"/>
                                             </connections>
                                         </button>
-                                        <textField verticalHuggingPriority="750" id="364">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="364">
                                             <rect key="frame" x="180" y="323" width="361" height="19"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4414">
@@ -2121,7 +2121,7 @@
                                             <rect key="frame" x="12" y="309" width="619" height="5"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                         </box>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="362">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="362">
                                             <rect key="frame" x="17" y="264" width="158" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Write RS232 output to:" id="4412">
@@ -2141,7 +2141,7 @@
                                                 <action selector="chooseRS232OutputFile:" target="329" id="591"/>
                                             </connections>
                                         </button>
-                                        <textField verticalHuggingPriority="750" id="358">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="358">
                                             <rect key="frame" x="180" y="262" width="361" height="19"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4408">
@@ -2162,7 +2162,7 @@
                                             <rect key="frame" x="12" y="218" width="619" height="5"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                         </box>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="361">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="361">
                                             <rect key="frame" x="17" y="234" width="158" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Read RS232 input from:" id="4411">
@@ -2182,7 +2182,7 @@
                                                 <action selector="chooseRS232InputFile:" target="329" id="592"/>
                                             </connections>
                                         </button>
-                                        <textField verticalHuggingPriority="750" id="357">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="357">
                                             <rect key="frame" x="180" y="232" width="361" height="19"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4407">
@@ -2191,7 +2191,7 @@
                                                 <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                             </textFieldCell>
                                         </textField>
-                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="363">
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="363">
                                             <rect key="frame" x="17" y="173" width="158" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Write MIDI output to:" id="4413">
@@ -2211,7 +2211,7 @@
                                                 <action selector="chooseMidiOutputFile:" target="329" id="593"/>
                                             </connections>
                                         </button>
-                                        <textField verticalHuggingPriority="750" id="359">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="359">
                                             <rect key="frame" x="180" y="171" width="361" height="19"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" controlSize="small" scrollable="YES" lineBreakMode="clipping" selectable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4409">
@@ -2228,6 +2228,50 @@
                                                 <font key="font" metaFont="system"/>
                                             </buttonCell>
                                         </button>
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" allowsCharacterPickerTouchBarItem="NO" id="SUz-3M-0Mn">
+                                            <rect key="frame" x="89" y="140" width="86" height="17"/>
+                                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                                            <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Input port:" id="5dl-wP-t2V">
+                                                <font key="font" metaFont="system"/>
+                                                <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                                                <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                                            </textFieldCell>
+                                        </textField>
+                                        <popUpButton verticalHuggingPriority="750" misplaced="YES" id="SwM-mD-0bD" userLabel="Input port">
+                                            <rect key="frame" x="178" y="133" width="233" height="26"/>
+                                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                                            <popUpButtonCell key="cell" type="push" title="Off" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" inset="2" arrowPosition="arrowAtCenter" preferredEdge="maxY" selectedItem="bf7-2j-2tZ" id="cCF-CI-aTG" userLabel="inport">
+                                                <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
+                                                <font key="font" metaFont="menu"/>
+                                                <menu key="menu" title="OtherViews" id="ZbA-qz-7WK">
+                                                    <items>
+                                                        <menuItem title="Off" state="on" id="bf7-2j-2tZ"/>
+                                                    </items>
+                                                </menu>
+                                            </popUpButtonCell>
+                                        </popUpButton>
+                                        <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" misplaced="YES" allowsCharacterPickerTouchBarItem="NO" id="4r9-TN-AIq">
+                                            <rect key="frame" x="89" y="111" width="86" height="17"/>
+                                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                                            <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Output port:" id="jHe-EH-hz0">
+                                                <font key="font" metaFont="system"/>
+                                                <color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
+                                                <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
+                                            </textFieldCell>
+                                        </textField>
+                                        <popUpButton verticalHuggingPriority="750" misplaced="YES" id="hIV-ek-Dyl" userLabel="Output port">
+                                            <rect key="frame" x="178" y="104" width="233" height="26"/>
+                                            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
+                                            <popUpButtonCell key="cell" type="push" title="Off" bezelStyle="rounded" alignment="left" lineBreakMode="truncatingTail" state="on" borderStyle="borderAndBezel" inset="2" arrowPosition="arrowAtCenter" preferredEdge="maxY" selectedItem="NC6-Qt-SwN" id="cUW-JF-8ep" userLabel="outport">
+                                                <behavior key="behavior" lightByBackground="YES" lightByGray="YES"/>
+                                                <font key="font" metaFont="menu"/>
+                                                <menu key="menu" title="OtherViews" id="5QK-D8-a3U">
+                                                    <items>
+                                                        <menuItem title="Off" state="on" id="NC6-Qt-SwN"/>
+                                                    </items>
+                                                </menu>
+                                            </popUpButtonCell>
+                                        </popUpButton>
                                     </subviews>
                                 </view>
                             </tabViewItem>
@@ -2244,7 +2288,7 @@
                                                 <font key="font" metaFont="system"/>
                                             </buttonCell>
                                         </button>
-                                        <textField verticalHuggingPriority="750" id="2933">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="2933">
                                             <rect key="frame" x="79" y="246" width="108" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" enabled="NO" sendsActionOnEndEditing="YES" title="Trace parameter" id="4498">
@@ -2253,7 +2297,7 @@
                                                 <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                             </textFieldCell>
                                         </textField>
-                                        <textField verticalHuggingPriority="750" id="2935">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="2935">
                                             <rect key="frame" x="193" y="241" width="378" height="22"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" enabled="NO" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4499">
@@ -2262,7 +2306,7 @@
                                                 <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                             </textFieldCell>
                                         </textField>
-                                        <textField verticalHuggingPriority="750" id="2937">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="2937">
                                             <rect key="frame" x="79" y="221" width="327" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" enabled="NO" sendsActionOnEndEditing="YES" title="Hatari reads options from given socket at run-time" id="4500">
@@ -2271,7 +2315,7 @@
                                                 <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                             </textFieldCell>
                                         </textField>
-                                        <textField verticalHuggingPriority="750" id="2939">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="2939">
                                             <rect key="frame" x="412" y="216" width="159" height="22"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" enabled="NO" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4501">
@@ -2280,7 +2324,7 @@
                                                 <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                             </textFieldCell>
                                         </textField>
-                                        <textField verticalHuggingPriority="750" id="2941">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="2941">
                                             <rect key="frame" x="79" y="196" width="120" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" enabled="NO" sendsActionOnEndEditing="YES" title="Save log output to" id="4502">
@@ -2289,7 +2333,7 @@
                                                 <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                             </textFieldCell>
                                         </textField>
-                                        <textField verticalHuggingPriority="750" id="2947">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="2947">
                                             <rect key="frame" x="76" y="171" width="120" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" enabled="NO" sendsActionOnEndEditing="YES" title=" Log Level" id="4505">
@@ -2298,7 +2342,7 @@
                                                 <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                                             </textFieldCell>
                                         </textField>
-                                        <textField verticalHuggingPriority="750" id="2943">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="2943">
                                             <rect key="frame" x="202" y="191" width="369" height="22"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" enabled="NO" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" drawsBackground="YES" id="4503">
@@ -2307,7 +2351,7 @@
                                                 <color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
                                             </textFieldCell>
                                         </textField>
-                                        <comboBox verticalHuggingPriority="750" id="2945">
+                                        <comboBox verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="2945">
                                             <rect key="frame" x="202" y="164" width="99" height="26"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <comboBoxCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" enabled="NO" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" completes="NO" numberOfVisibleItems="5" id="4504">
@@ -2324,7 +2368,7 @@
                                                 </objectValues>
                                             </comboBoxCell>
                                         </comboBox>
-                                        <comboBox verticalHuggingPriority="750" id="3473">
+                                        <comboBox verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="3473">
                                             <rect key="frame" x="393" y="111" width="99" height="26"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <comboBoxCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" enabled="NO" sendsActionOnEndEditing="YES" borderStyle="bezel" drawsBackground="YES" completes="NO" numberOfVisibleItems="5" id="4507">
@@ -2341,7 +2385,7 @@
                                                 </objectValues>
                                             </comboBoxCell>
                                         </comboBox>
-                                        <textField verticalHuggingPriority="750" id="2949">
+                                        <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="2949">
                                             <rect key="frame" x="79" y="118" width="309" height="17"/>
                                             <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                                             <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" enabled="NO" sendsActionOnEndEditing="YES" title="Show dialog for log messages above given level " id="4506">
@@ -2455,6 +2499,8 @@
                 <outlet property="machineType" destination="406" id="568"/>
                 <outlet property="maxZoomedHeight" destination="4688" id="4715"/>
                 <outlet property="maxZoomedWidth" destination="4686" id="4714"/>
+                <outlet property="midiInPort" destination="SwM-mD-0bD" id="UdC-iP-EpD"/>
+                <outlet property="midiOutPort" destination="hIV-ek-Dyl" id="qiK-5h-087"/>
                 <outlet property="monitor" destination="422" id="559"/>
                 <outlet property="nGemdosDrive" destination="lss-lT-hdM" id="L6w-Ya-ZIk"/>
                 <outlet property="partage" destination="4743" id="4744"/>
@@ -2486,7 +2532,7 @@
                 <rect key="frame" x="0.0" y="0.0" width="323" height="302"/>
                 <autoresizingMask key="autoresizingMask"/>
                 <subviews>
-                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="617">
+                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="617">
                         <rect key="frame" x="36" y="208" width="114" height="17"/>
                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" id="4511">
@@ -2555,7 +2601,7 @@
                             </column>
                         </cells>
                     </matrix>
-                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="643">
+                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="643">
                         <rect key="frame" x="35" y="170" width="115" height="17"/>
                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Sectors:" id="4512">
@@ -2564,7 +2610,7 @@
                             <color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
                         </textFieldCell>
                     </textField>
-                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" id="644">
+                    <textField verticalHuggingPriority="750" horizontalCompressionResistancePriority="250" allowsCharacterPickerTouchBarItem="NO" id="644">
                         <rect key="frame" x="36" y="265" width="114" height="17"/>
                         <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                         <textFieldCell key="cell" sendsActionOnEndEditing="YES" alignment="right" title="Sides:" id="4513">
@@ -2641,7 +2687,7 @@
                         <action selector="aller:" target="329" id="4760"/>
                     </connections>
                 </button>
-                <textField verticalHuggingPriority="750" id="4747">
+                <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="4747">
                     <rect key="frame" x="103" y="13" width="153" height="17"/>
                     <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                     <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="to default folder" id="4748">
@@ -2667,7 +2713,7 @@
                         <action selector="halle:" target="329" id="4759"/>
                     </connections>
                 </button>
-                <textField verticalHuggingPriority="750" id="4751">
+                <textField verticalHuggingPriority="750" allowsCharacterPickerTouchBarItem="NO" id="4751">
                     <rect key="frame" x="103" y="13" width="153" height="17"/>
                     <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                     <textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="to default folder" id="4754">
diff -r 3f4adb62da35 src/gui-sdl/dlgDevice.c
--- a/src/gui-sdl/dlgDevice.c	Sun Oct 01 08:09:42 2017 +0200
+++ b/src/gui-sdl/dlgDevice.c	Wed Oct 04 01:32:31 2017 +0300
@@ -8,6 +8,7 @@
 */
 const char DlgDevice_fileid[] = "Hatari dlgDevice.c : " __DATE__ " " __TIME__;
 
+#include <assert.h>
 #include "main.h"
 #include "configuration.h"
 #include "dialog.h"
@@ -25,11 +26,21 @@
 #define DEVDLG_RS232INBROWSE   13
 #define DEVDLG_RS232INNAME     14
 #define DEVDLG_MIDIENABLE      16
+#ifndef HAVE_PORTMIDI
 #define DEVDLG_MIDIINBROWSE    18
 #define DEVDLG_MIDIINNAME      19
 #define DEVDLG_MIDIOUTBROWSE   21
 #define DEVDLG_MIDIOUTNAME     22
 #define DEVDLG_EXIT            23
+#else
+#define DEVDLG_PREVIN          18
+#define DEVDLG_NEXTIN          19
+#define DEVDLG_MIDIINNAME      21
+#define DEVDLG_PREVOUT         23
+#define DEVDLG_NEXTOUT         24
+#define DEVDLG_MIDIOUTNAME     26
+#define DEVDLG_EXIT            27
+#endif
 
 
 #define MAX_DLG_FILENAME 46+1
@@ -62,18 +73,48 @@
 
 	{ SGBOX, 0, 0, 1,15, 50,6, NULL },
  	{ SGCHECKBOX, 0, 0, 2,15, 23,1, "Enable _MIDI emulation" },
+#ifndef HAVE_PORTMIDI
  	{ SGTEXT, 0, 0, 2,17, 26,1, "Read MIDI input from file:" },
  	{ SGBUTTON,   0, 0, 42,17, 8,1, "Brow_se" },
  	{ SGTEXT, 0, 0, 3,18, 46,1, dlgMidiInName },
  	{ SGTEXT, 0, 0, 2,19, 26,1, "Write MIDI output to file:" },
  	{ SGBUTTON,   0, 0, 42,19, 8,1, "Brows_e" },
  	{ SGTEXT, 0, 0, 3,20, 46,1, dlgMidiOutName },
-
+#else
+ 	{ SGTEXT, 0, 0, 5,17, 7,1, "input:" },
+	{ SGBUTTON, 0, 0,  12,17, 3,1, "\x04", SG_SHORTCUT_LEFT },
+	{ SGBUTTON, 0, 0, 15,17, 3,1, "\x03", SG_SHORTCUT_RIGHT },
+	{ SGBOX, 0, 0, 18,17, 32,1, NULL },
+	{ SGTEXT, 0, 0, 19,17, 30,1, dlgMidiInName },
+ 	{ SGTEXT, 0, 0, 4,19, 7,1, "output:" },
+	{ SGBUTTON, 0, 0,  12,19, 3,1, "\x04", SG_SHORTCUT_LEFT },
+	{ SGBUTTON, 0, 0, 15,19, 3,1, "\x03", SG_SHORTCUT_RIGHT },
+	{ SGBOX, 0, 0, 18,19, 32,1, NULL },
+	{ SGTEXT, 0, 0, 19,19, 30,1, dlgMidiOutName },
+#endif
  	{ SGBUTTON, SG_DEFAULT, 0, 16,22, 20,1, "Back to main menu" },
 	{ SGSTOP, 0, 0, 0,0, 0,0, NULL }
 };
 
 
+#ifdef HAVE_PORTMIDI
+#include "midi.h"
+static int midiInput  = -1;
+static int midiOutput = -1;
+
+static void setupMidiControls(void)
+{
+	const char *inportName,*outportName;
+	midiInput  = Midi_Host_GetPortIndex(ConfigureParams.Midi.sMidiInPortName,  true);
+	midiOutput = Midi_Host_GetPortIndex(ConfigureParams.Midi.sMidiOutPortName, false);
+	inportName  = (midiInput  < 0) ? "Off" : ConfigureParams.Midi.sMidiInPortName;
+	outportName = (midiOutput < 0) ? "Off" : ConfigureParams.Midi.sMidiOutPortName;
+	File_ShrinkName(dlgMidiInName,  inportName,  devicedlg[DEVDLG_MIDIINNAME].w);
+	File_ShrinkName(dlgMidiOutName, outportName, devicedlg[DEVDLG_MIDIOUTNAME].w);
+}
+#endif
+
+
 /*-----------------------------------------------------------------------*/
 /**
  * Show and process the "Device" dialog.
@@ -81,6 +122,9 @@
 void Dialog_DeviceDlg(void)
 {
 	int but;
+#ifdef HAVE_PORTMIDI
+	const char* portName;
+#endif
 
 	SDLGui_CenterDlg(devicedlg);
 
@@ -103,8 +147,12 @@
 		devicedlg[DEVDLG_MIDIENABLE].state |= SG_SELECTED;
 	else
 		devicedlg[DEVDLG_MIDIENABLE].state &= ~SG_SELECTED;
+#ifndef HAVE_PORTMIDI
 	File_ShrinkName(dlgMidiInName, ConfigureParams.Midi.sMidiInFileName, devicedlg[DEVDLG_MIDIINNAME].w);
 	File_ShrinkName(dlgMidiOutName, ConfigureParams.Midi.sMidiOutFileName, devicedlg[DEVDLG_MIDIOUTNAME].w);
+#else
+	setupMidiControls();
+#endif
 
 	/* The devices dialog main loop */
 	do
@@ -131,6 +179,7 @@
                                               devicedlg[DEVDLG_RS232INNAME].w,
                                               true);
 			break;
+#ifndef HAVE_PORTMIDI
 		 case DEVDLG_MIDIINBROWSE:              /* Choose a new MIDI file */
 			SDLGui_FileConfSelect("MIDI input:", dlgMidiInName,
                                               ConfigureParams.Midi.sMidiInFileName,
@@ -143,6 +192,42 @@
                                               devicedlg[DEVDLG_MIDIOUTNAME].w,
                                               true);
 			break;
+#else
+		case DEVDLG_PREVIN:
+			if (midiInput >= 0)
+			{
+				midiInput--;
+				portName = (midiInput == -1) ? "Off" : Midi_Host_GetPortName(midiInput, true);
+				if (portName)
+					File_ShrinkName(dlgMidiInName, portName, devicedlg[DEVDLG_MIDIINNAME].w);
+			}
+			break;
+		case DEVDLG_NEXTIN:
+			portName = Midi_Host_GetPortName(midiInput + 1, true);
+			if (portName)
+			{
+				midiInput++;
+				File_ShrinkName(dlgMidiInName, portName, devicedlg[DEVDLG_MIDIINNAME].w);
+			}
+			break;
+		case DEVDLG_PREVOUT:
+			if (midiOutput >= 0)
+			{
+				midiOutput--;
+				portName = (midiOutput == -1) ? "Off" : Midi_Host_GetPortName(midiOutput, false);
+				if (portName)
+					File_ShrinkName(dlgMidiOutName, portName, devicedlg[DEVDLG_MIDIOUTNAME].w);
+			}
+			break;
+		case DEVDLG_NEXTOUT:
+			portName = Midi_Host_GetPortName(midiOutput + 1, false);
+			if (portName)
+			{
+				midiOutput++;
+				File_ShrinkName(dlgMidiOutName, portName, devicedlg[DEVDLG_MIDIOUTNAME].w);
+			}
+			break;
+#endif
 		}
 	}
 	while (but != DEVDLG_EXIT && but != SDLGUI_QUIT
@@ -152,4 +237,10 @@
 	ConfigureParams.Printer.bEnablePrinting = (devicedlg[DEVDLG_PRNENABLE].state & SG_SELECTED);
 	ConfigureParams.RS232.bEnableRS232 = (devicedlg[DEVDLG_RS232ENABLE].state & SG_SELECTED);
 	ConfigureParams.Midi.bEnableMidi = (devicedlg[DEVDLG_MIDIENABLE].state & SG_SELECTED);
+#ifdef HAVE_PORTMIDI
+	assert(sizeof(dlgMidiInName) <= sizeof(ConfigureParams.Midi.sMidiInPortName));
+	strcpy(ConfigureParams.Midi.sMidiInPortName, dlgMidiInName);
+	assert(sizeof(dlgMidiOutName) <= sizeof(ConfigureParams.Midi.sMidiOutPortName));
+	strcpy(ConfigureParams.Midi.sMidiOutPortName, dlgMidiOutName);
+#endif
 }
diff -r 3f4adb62da35 src/includes/configuration.h
--- a/src/includes/configuration.h	Sun Oct 01 08:09:42 2017 +0200
+++ b/src/includes/configuration.h	Wed Oct 04 01:32:31 2017 +0300
@@ -295,6 +295,8 @@
   bool bEnableMidi;
   char sMidiInFileName[FILENAME_MAX];
   char sMidiOutFileName[FILENAME_MAX];
+  char sMidiInPortName[FILENAME_MAX];
+  char sMidiOutPortName[FILENAME_MAX];
 } CNF_MIDI;
 
 
diff -r 3f4adb62da35 src/includes/midi.h
--- a/src/includes/midi.h	Sun Oct 01 08:09:42 2017 +0200
+++ b/src/includes/midi.h	Wed Oct 04 01:32:31 2017 +0300
@@ -19,4 +19,7 @@
 extern void Midi_Data_WriteByte(void);
 extern void Midi_InterruptHandler_Update(void);
 
+extern const char* Midi_Host_GetPortName(int index, bool forInput);
+extern int Midi_Host_GetPortIndex(const char* portName, bool forInput);
+
 #endif
diff -r 3f4adb62da35 src/midi.c
--- a/src/midi.c	Sun Oct 01 08:09:42 2017 +0200
+++ b/src/midi.c	Wed Oct 04 01:32:31 2017 +0300
@@ -53,8 +53,6 @@
 #define	MIDI_TRANSFER_BYTE_CYCLE	(MIDI_TRANSFER_BIT_CYCLE * 10)
 #endif
 
-static FILE *pMidiFhIn  = NULL;        /* File handle used for Midi input */
-static FILE *pMidiFhOut = NULL;        /* File handle used for Midi output */
 static Uint8 MidiControlRegister;
 static Uint8 MidiStatusRegister;
 static Uint8 nRxDataByte;
@@ -63,42 +61,43 @@
 static Uint64 TSR_Complete_Time;	/* Time when TSR will be completely transferred */
 
 
+/*
+** Host MIDI I/O
+*/
+static bool Midi_Host_Open(void);
+static void Midi_Host_Close(void);
+static int  Midi_Host_ReadByte(void);
+static bool Midi_Host_WriteByte(Uint8 byte);
+
+#ifndef HAVE_PORTMIDI
+static FILE *pMidiFhIn  = NULL;    /* File handle used for Midi input */
+static FILE *pMidiFhOut = NULL;    /* File handle used for Midi output */
+#else
+#include "portmidi.h"
+#define INPUT_BUFFER_SIZE  1024		 // PortMidi handles buffering
+static PmStream* midiIn  = NULL;	 // current midi input port
+static PmStream* midiOut = NULL;	 // current midi output port
+static int numInputs  = 0;				 // number of available input ports
+static int numOutputs = 0;				 // number of available output ports
+static const PmDeviceInfo** inports  = NULL;	// array of available input ports
+static const PmDeviceInfo** outports = NULL;	// array of available output ports
+
+static bool Midi_Host_SwitchPort(const char* portName, bool forInput);
+static int Midi_GetDataLength(Uint8 status);
+static int Midi_SplitEvent(PmEvent* midiEvent, Uint8* msg);
+static PmEvent* Midi_BuildEvent(Uint8 byte);
+#endif
+
 
 /**
  * Initialization: Open MIDI device.
  */
 void Midi_Init(void)
 {
-	if (!ConfigureParams.Midi.bEnableMidi)
-		return;
-
-	if (ConfigureParams.Midi.sMidiOutFileName[0])
+	if (!Midi_Host_Open())
 	{
-		/* Open MIDI output file */
-		pMidiFhOut = File_Open(ConfigureParams.Midi.sMidiOutFileName, "wb");
-		if (!pMidiFhOut)
-		{
-			Log_AlertDlg(LOG_ERROR, "MIDI output file open failed. MIDI support disabled.");
-			ConfigureParams.Midi.bEnableMidi = false;
-			return;
-		}
-		setvbuf(pMidiFhOut, NULL, _IONBF, 0);    /* No output buffering! */
-		LOG_TRACE(TRACE_MIDI, "MIDI: Opened file '%s' for output\n",
-			 ConfigureParams.Midi.sMidiOutFileName);
-	}
-	if (ConfigureParams.Midi.sMidiInFileName[0])
-	{
-		/* Try to open MIDI input file */
-		pMidiFhIn = File_Open(ConfigureParams.Midi.sMidiInFileName, "rb");
-		if (!pMidiFhIn)
-		{
-			Log_AlertDlg(LOG_ERROR, "MIDI input file open failed. MIDI support disabled.");
-			ConfigureParams.Midi.bEnableMidi = false;
-			return;
-		}
-		setvbuf(pMidiFhIn, NULL, _IONBF, 0);    /* No input buffering! */
-		LOG_TRACE(TRACE_MIDI, "MIDI: Opened file '%s' for input\n",
-			 ConfigureParams.Midi.sMidiInFileName);
+		Log_AlertDlg(LOG_ERROR, "MIDI i/o open failed. MIDI support disabled.");
+		ConfigureParams.Midi.bEnableMidi = false;
 	}
 }
 
@@ -108,9 +107,7 @@
  */
 void Midi_UnInit(void)
 {
-	pMidiFhIn = File_Close(pMidiFhIn);
-	pMidiFhOut = File_Close(pMidiFhOut);
-
+	Midi_Host_Close();
 	CycInt_RemovePendingInterrupt(INTERRUPT_MIDI);
 }
 
@@ -257,7 +254,8 @@
 void Midi_Data_WriteByte(void)
 {
 	Uint8 nTxDataByte;
-
+	bool ok;
+	
 	ACIA_AddWaitCycles ();						/* Additional cycles when accessing the ACIA */
 
 	nTxDataByte = IoMem[0xfffc06];
@@ -287,20 +285,14 @@
 	if (!ConfigureParams.Midi.bEnableMidi)
 		return;
 
-	if (pMidiFhOut)
+	ok = Midi_Host_WriteByte(nTxDataByte);
+
+	/* If there was an error then stop the midi emulation */
+	if (!ok)
 	{
-		int ret;
-
-		/* Write the character to the output file: */
-		ret = fputc(nTxDataByte, pMidiFhOut);
-
-		/* If there was an error then stop the midi emulation */
-		if (ret == EOF)
-		{
-			LOG_TRACE(TRACE_MIDI, "MIDI: write error -> stop MIDI\n");
-			Midi_UnInit();
-			return;
-		}
+		LOG_TRACE(TRACE_MIDI, "MIDI: write error -> stop MIDI\n");
+		Midi_UnInit();
+		return;
 	}
 }
 
@@ -331,25 +323,24 @@
 	}
 
 	/* Read the bytes in, if we have any */
-	if (pMidiFhIn && File_InputAvailable(pMidiFhIn))
+	nInChar = Midi_Host_ReadByte();
+	if (nInChar != EOF)
 	{
-		nInChar = fgetc(pMidiFhIn);
-		if (nInChar != EOF)
-		{
-			LOG_TRACE(TRACE_MIDI, "MIDI: Read character -> $%x\n", nInChar);
-			/* Copy into our internal queue */
-			nRxDataByte = nInChar;
-			MidiStatusRegister |= ACIA_SR_RX_FULL;
+		LOG_TRACE(TRACE_MIDI, "MIDI: Read character -> $%x\n", nInChar);
+		/* Copy into our internal queue */
+		nRxDataByte = nInChar;
+		MidiStatusRegister |= ACIA_SR_RX_FULL;
 
-			/* Do we need to generate a receive interrupt? */
-			MIDI_UpdateIRQ ();
-		}
-		else
-		{
-			LOG_TRACE(TRACE_MIDI, "MIDI: read error (doesn't stop MIDI)\n");
-			clearerr(pMidiFhIn);
-		}
+		/* Do we need to generate a receive interrupt? */
+		MIDI_UpdateIRQ ();
 	}
+#ifndef HAVE_PORTMIDI
+	else if (pMidiFhIn)
+	{
+		LOG_TRACE(TRACE_MIDI, "MIDI: read error (doesn't stop MIDI)\n");
+		clearerr(pMidiFhIn);
+	}
+#endif
 
 	/* Set timer */
 #ifdef OLD_CPU_SHIFT
@@ -359,3 +350,452 @@
 #endif
 }
 
+
+// ============================================================================
+// Host MIDI I/O
+// ============================================================================
+
+/**
+ * open MIDI streams
+ * return true for no errors
+ */
+static bool Midi_Host_Open(void)
+{
+#ifndef HAVE_PORTMIDI
+	if (!ConfigureParams.Midi.bEnableMidi)
+		return true;
+
+	if (ConfigureParams.Midi.sMidiOutFileName[0])
+	{
+		/* Open MIDI output file */
+		pMidiFhOut = File_Open(ConfigureParams.Midi.sMidiOutFileName, "wb");
+		if (!pMidiFhOut)
+			return false;
+		setvbuf(pMidiFhOut, NULL, _IONBF, 0);    /* No output buffering! */
+		LOG_TRACE(TRACE_MIDI, "MIDI: Opened file '%s' for output\n",
+			 ConfigureParams.Midi.sMidiOutFileName);
+	}
+	if (ConfigureParams.Midi.sMidiInFileName[0])
+	{
+		/* Try to open MIDI input file */
+		pMidiFhIn = File_Open(ConfigureParams.Midi.sMidiInFileName, "rb");
+		if (!pMidiFhIn)
+			return false;
+		setvbuf(pMidiFhIn, NULL, _IONBF, 0);    /* No input buffering! */
+		LOG_TRACE(TRACE_MIDI, "MIDI: Opened file '%s' for input\n",
+			 ConfigureParams.Midi.sMidiInFileName);
+	}
+
+#else
+	/* Need to always get MIDI device info, for MIDI setup dialog */
+	int i;
+	int iindex = 0;
+	int oindex = 0;
+	int numPorts = 0;
+	
+	if (Pm_Initialize() != pmNoError)
+	{
+		LOG_TRACE(TRACE_MIDI, "MIDI: PortMidi initialization failed\n");
+		return false;
+	}
+	// -- get rid of earlier portmidi descriptor arrays (if allocated)
+	// -- the information may be stale (USB Midi etc)
+	if (inports)
+		free (inports);
+	if (outports)
+		free (outports);
+	inports = outports = NULL;
+	numInputs = numOutputs = 0;
+
+	// -- count number of input and output ports
+	numPorts = Pm_CountDevices();
+	for (i = 0; i < numPorts; i++)
+	{
+		const PmDeviceInfo *info = Pm_GetDeviceInfo(i);
+		if (info->input)
+			numInputs++;
+		else if (info->output)
+			numOutputs++;
+	}
+
+	// -- allocate descriptor arrays
+	inports  = malloc(numInputs  * sizeof(PmDeviceInfo*));
+	outports = malloc(numOutputs * sizeof(PmDeviceInfo*));
+	
+	// -- populate descriptor arrays
+	for (i = 0; i < numPorts; i++)
+	{
+		const PmDeviceInfo* info = Pm_GetDeviceInfo(i);
+		if (info)
+		{
+			LOG_TRACE(TRACE_MIDI, "MIDI: device %d: '%s'\n", i, info->name);
+			if (info->input)
+				inports[iindex++] = info;
+			if (info->output)
+				outports[oindex++] = info;
+		}
+		else
+			LOG_TRACE(TRACE_MIDI, "MIDI: info disappeared for device %d!\n", i);
+	}
+
+	// -- open input and output ports according to configuration
+	if (ConfigureParams.Midi.sMidiInPortName[0])
+		Midi_Host_SwitchPort(ConfigureParams.Midi.sMidiInPortName, true);
+	if (ConfigureParams.Midi.sMidiOutPortName[0])
+		Midi_Host_SwitchPort(ConfigureParams.Midi.sMidiOutPortName, false);
+#endif
+
+	return true;
+}
+
+
+/* ---------------------------------------------------------------------------- */
+/**
+ * close MIDI streams
+ */
+static void Midi_Host_Close(void)
+{
+#ifndef HAVE_PORTMIDI
+	pMidiFhIn = File_Close(pMidiFhIn);
+	pMidiFhOut = File_Close(pMidiFhOut);
+#else
+	if (midiIn)
+		Pm_Close(midiIn);
+	if (midiOut)
+		Pm_Close(midiOut);
+	midiIn = midiOut = NULL;
+
+	// Can't terminate PM or free descriptor arrays as this gets
+	// called by any write errors and GUI won't then work.
+	// Pm_Terminate();
+#endif
+}
+
+
+
+/* ---------------------------------------------------------------------------- */
+/**
+ * returns port name for input or output port at 'index'
+ */
+const char* Midi_Host_GetPortName(int index, bool forInput)
+{
+#ifdef HAVE_PORTMIDI
+	if (forInput && index < numInputs)
+		return inports[index]->name;
+	else if (!forInput && index < numOutputs)
+		return outports[index]->name;
+#endif
+
+	return NULL;
+}
+
+/* ---------------------------------------------------------------------------- */
+/**
+ * returns port descriptor array index for input or output 'portName'
+ */
+int Midi_Host_GetPortIndex(const char* portName, bool forInput)
+{
+#ifdef HAVE_PORTMIDI
+	int i = 0;
+	int numPorts = forInput ? numInputs : numOutputs;
+	const PmDeviceInfo** ports = forInput ? inports : outports;
+
+	if (ports)
+	{
+		for (i = 0; i < numPorts; i++)
+			if (!strcmp(portName, ports[i]->name))
+				return i;
+	}
+#endif
+
+	return -1;
+}
+
+/**
+ * closes current midi port (if any) and opens 'portName' if MIDI enabled
+ * returns true if successful, false otherwise
+ */
+static bool Midi_Host_SwitchPort(const char* portName, bool forInput)
+{	
+#ifdef HAVE_PORTMIDI
+	int i, count;
+	bool err;
+
+	if (!ConfigureParams.Midi.bEnableMidi)
+		return false;
+
+	// -- find PortMidi index for 'portName'
+	count = Pm_CountDevices();
+	for (i = 0; i < count; i++)
+	{
+		const PmDeviceInfo* info = Pm_GetDeviceInfo(i);
+		if (info)
+		{
+			if (forInput && !info->input)
+				continue;
+			else if (!forInput && info->input)
+				continue;
+			if (!strcmp(info->name, portName))
+				break;
+		}
+	}
+	if (i >= count)
+		return false;
+
+	// -- close current port in any case, then try open new one
+	if (forInput == true)
+	{
+		if (midiIn) {
+			Pm_Close(midiIn);
+			midiIn = NULL;
+		}
+		err = (Pm_OpenInput(&midiIn, i, NULL, INPUT_BUFFER_SIZE, NULL, NULL) == pmNoError);
+		LOG_TRACE(TRACE_MIDI, "MIDI: input port %d '%s' open %s\n", i, portName, err ? "succeeded" : "failed");
+		return err;
+	}
+	else
+	{
+		if (midiOut) {
+			Pm_Close(midiOut);
+			midiOut = NULL;
+		}
+		err = (Pm_OpenOutput(&midiOut, i, NULL, 0, NULL, NULL, 0) == pmNoError);
+		LOG_TRACE(TRACE_MIDI, "MIDI: output port %d '%s' open %s\n", i, portName, err ? "succeeded" : "failed");
+		return err;
+	}
+#endif
+	return false;
+}
+
+
+/**
+ * returns byte from input stream, or EOF if it is empty
+ */
+static int Midi_Host_ReadByte(void)
+{
+#ifndef HAVE_PORTMIDI
+	if (pMidiFhIn && File_InputAvailable(pMidiFhIn))
+		return fgetc(pMidiFhIn);
+	else return EOF;
+#else
+	static Uint8 msg[4];
+	static Uint8 ibyte = 0;
+	static int bytesAvailable = 0;
+
+	if (midiIn)
+	{
+		// -- we have not yet returned all bytes from previous event
+		if (bytesAvailable > 0)
+		{
+			bytesAvailable--;
+			return msg[ibyte++];
+		}
+
+		// -- read new event (if any)
+		else if (Pm_Poll(midiIn) == TRUE) {
+			PmEvent midiEvent;
+			if (Pm_Read(midiIn, &midiEvent, 1) != 1)
+				return EOF;
+			if ((bytesAvailable = Midi_SplitEvent(&midiEvent, msg)) > 0)
+			{
+				bytesAvailable--;
+				ibyte = 1;
+				return msg[0];
+			}
+		}
+	}
+
+	// -- no more midi data
+	return EOF;
+#endif
+}
+
+
+/**
+ * writes 'byte' into output stream, returns true on success
+ */
+static bool Midi_Host_WriteByte(Uint8 byte)
+{
+#ifndef HAVE_PORTMIDI
+	if (pMidiFhOut)
+	{
+		/* Write the character to the output file: */
+		int ret = fputc(byte, pMidiFhOut);
+		return (ret != EOF);
+	}
+#else
+	if (midiOut)
+	{
+		PmEvent* midiEvent = Midi_BuildEvent(byte);
+		if (midiEvent)
+		{
+			PmError error = Pm_Write(midiOut, midiEvent, 1);
+			if (error == pmNoError)
+				return true;
+			LOG_TRACE(TRACE_MIDI, "MIDI: PortMidi write error %d\n", error);
+			return false;
+		}
+		return true;
+	}
+#endif
+
+	return false;
+}
+
+
+#ifdef HAVE_PORTMIDI
+// ============================================================================
+// PortMidi utils
+//
+// PortMidi (as most native MIDI APIs) operate on complete MIDI messages
+// we need therefore handle running status, variable number of data bytes
+// and sysex correctly.
+//
+// ============================================================================
+
+/**
+ * return number of databytes that should accompany 'status' byte
+ * four bytes for sysex is a special case to simplify Midi_BuildEvent()
+ */
+static int Midi_GetDataLength(Uint8 status)
+{
+	static const Uint8 dataLength[] = { 2,2,2,2,1,2,2, 4,1,2,1,0,0,0,0 };
+
+	if (status >= 0xF8 || status == 0)
+		return 0;
+	if (status >= 0xF0)
+		return dataLength[(status & 0x0F) + 7];
+	return dataLength[(status >> 4) - 8];
+}
+
+/**
+ * collect bytes until valid MIDI event has been formed / four bytes of sysex data has been gathered
+ * returns PmEvent when done, or NULL if it needs still more data
+ * see MIDI 1.0 Detailed Spec 4.2, pages A-1..A-2 for discussion on running status
+ */
+static PmEvent* Midi_BuildEvent(Uint8 byte)
+{
+	static const Uint8 shifts[] = { 0,8,16,24 };
+	static PmEvent midiEvent = { 0,0 };
+	static Uint32 midimsg;
+	static Uint8 runningStatus = 0;
+	static Uint8 bytesToWait = 0;
+	static Uint8 bytesCollected = 0;
+	static bool processingSysex = false;
+
+	// -- status byte
+	if (byte & 0x80)
+	{
+		if (byte >= 0xF8)
+		{
+			midiEvent.message = Pm_Message(byte,0,0);
+			return &midiEvent;
+		}
+		else
+		{
+			processingSysex = false;
+			if (byte >= 0xF0)
+			{
+				runningStatus = 0;
+				if (byte == 0xF0)
+				{
+					processingSysex = true;
+					bytesCollected = 1;
+				}
+				else if (byte == 0xF7)
+				{
+					midiEvent.message = midimsg | (((Uint32)byte) << shifts[bytesCollected]);
+					midimsg = bytesToWait = bytesCollected = 0;
+					return &midiEvent;
+				}
+				else
+					bytesCollected = 0;
+			}
+			else
+			{
+				runningStatus = byte;
+				bytesCollected = 0;
+			}
+		}
+		midimsg = byte;
+		bytesToWait = Midi_GetDataLength(byte);
+	}
+
+	// -- data byte
+	else
+	{
+		if (processingSysex)
+			midimsg |= ((Uint32)byte) << shifts[bytesCollected++];
+		else
+			midimsg |= ((Uint32)byte) << shifts[++bytesCollected];
+		if (bytesCollected >= bytesToWait)
+		{
+			midiEvent.message = midimsg;
+			midimsg = 0;
+			bytesCollected = 0;
+			bytesToWait = processingSysex ? 4 : 0;
+			return &midiEvent;
+		}
+	}
+	
+	return NULL;
+}
+
+
+/**
+ * extracts raw bytes from 'midiEvent' into 'msg'
+ * returns number of bytes available in 'msg'
+ *
+ * this method is required for sysex handling
+ * native framework has already handled running status
+ */
+static int Midi_SplitEvent(PmEvent* midiEvent, Uint8* msg)
+{
+	static bool processingSysex = false;
+	PmMessage midiMessage = midiEvent->message;
+	int i, bytesAvailable = 0;
+
+	msg[0] = Pm_MessageStatus(midiMessage);
+
+	// -- sysex start or continuation
+	if ((msg[0] == 0xF0) || (msg[0] < 0x80))
+	{
+		if (msg[0] == 0xF0)
+			processingSysex = true;
+
+		if (processingSysex)
+		{
+			for (i = 0; i <= 3; i++)
+			{
+				msg[i] = midiMessage & 0xFF;
+				bytesAvailable = i;
+				if (msg[i] == 0xF7)
+				{
+					processingSysex = false;
+					break;
+				}
+				midiMessage >>= 8;
+			}
+		}
+		else bytesAvailable = -1;
+	}
+
+	// -- non-sysex
+	else
+	{
+		if (msg[0] < 0xF8) // non-realtime
+		{
+			processingSysex = false;
+			midiMessage >>= 8;
+			bytesAvailable = Midi_GetDataLength(msg[0]);
+			for (i = 1; i <= bytesAvailable; i++)
+			{
+				msg[i] = midiMessage & 0xFF;
+				midiMessage >>= 8;
+			}
+		}
+	}
+
+	return bytesAvailable + 1;
+}
+#endif
diff -r 3f4adb62da35 src/options.c
--- a/src/options.c	Sun Oct 01 08:09:42 2017 +0200
+++ b/src/options.c	Wed Oct 04 01:32:31 2017 +0300
@@ -107,8 +107,12 @@
 	OPT_JOYSTICK4,
 	OPT_JOYSTICK5,
 	OPT_PRINTER,
+#ifdef HAVE_PORTMIDI
+	OPT_MIDI,
+#else
 	OPT_MIDI_IN,
 	OPT_MIDI_OUT,
+#endif
 	OPT_RS232_IN,
 	OPT_RS232_OUT,
 	OPT_DRIVEA,		/* disk options */
@@ -308,10 +312,15 @@
 	  "<type>", "Set joystick type (none/keys/real) for given port" },
 	{ OPT_PRINTER,   NULL, "--printer",
 	  "<file>", "Enable printer support and write data to <file>" },
+#ifdef HAVE_PORTMIDI
+	{ OPT_MIDI,   NULL, "--midi",
+	  "<bool>", "Whether to use MIDI (with PortMidi devices)" },
+#else
 	{ OPT_MIDI_IN,   NULL, "--midi-in",
 	  "<file>", "Enable MIDI and use <file> as the input device" },
 	{ OPT_MIDI_OUT,  NULL, "--midi-out",
 	  "<file>", "Enable MIDI and use <file> as the output device" },
+#endif
 	{ OPT_RS232_IN,  NULL, "--rs232-in",
 	  "<file>", "Enable serial port and use <file> as the input device" },
 	{ OPT_RS232_OUT, NULL, "--rs232-out",
@@ -1376,6 +1385,11 @@
 					&ConfigureParams.Printer.bEnablePrinting);
 			break;
 
+#ifdef HAVE_PORTMIDI
+		case OPT_MIDI:
+			ok = Opt_Bool(argv[++i], OPT_MIDI, &ConfigureParams.Midi.bEnableMidi);
+			break;
+#else
 		case OPT_MIDI_IN:
 			i += 1;
 			ok = Opt_StrCpy(OPT_MIDI_IN, true, ConfigureParams.Midi.sMidiInFileName,
@@ -1389,7 +1403,8 @@
 					argv[i], sizeof(ConfigureParams.Midi.sMidiOutFileName),
 					&ConfigureParams.Midi.bEnableMidi);
 			break;
-      
+#endif
+
 		case OPT_RS232_IN:
 			i += 1;
 			ok = Opt_StrCpy(OPT_RS232_IN, true, ConfigureParams.RS232.szInFileName,


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/