Files
dmxconnect/hardware/MIDIDriver.go

133 lines
3.9 KiB
Go
Raw Normal View History

2024-12-15 13:45:46 +01:00
package hardware
import (
"context"
"fmt"
"regexp"
"strconv"
"strings"
"github.com/mattrtaylor/go-rtmidi"
)
/*
DMXConnect
DMXUSBProtocol.go
Copyright (c) Valentin Boulanger
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0.txt
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
2024-12-23 17:22:37 +01:00
// MIDIDriver represents how the protocol is defined
type MIDIDriver struct {
2024-12-15 13:45:46 +01:00
peripherals map[string]Peripheral // The list of peripherals
}
2024-12-23 17:22:37 +01:00
// NewMIDIDriver creates a new DMXUSB protocol
func NewMIDIDriver() *MIDIDriver {
return &MIDIDriver{
2024-12-15 13:45:46 +01:00
peripherals: make(map[string]Peripheral),
}
}
2024-12-23 17:22:37 +01:00
// Initialize initializes the MIDI driver
func (d *MIDIDriver) Initialize() error {
fmt.Println("MIDI driver initialized")
2024-12-15 13:45:46 +01:00
return nil
}
2024-12-23 17:22:37 +01:00
// GetName returns the name of the driver
func (d *MIDIDriver) GetName() string {
2024-12-15 13:45:46 +01:00
return "MIDI"
}
2024-12-20 17:18:57 +01:00
// GetPeripheral gets the peripheral that correspond to the specified ID
2024-12-23 17:22:37 +01:00
func (d *MIDIDriver) GetPeripheral(peripheralID string) (Peripheral, bool) {
2024-12-20 17:18:57 +01:00
// Return the specified peripheral
2024-12-23 17:22:37 +01:00
peripheral := d.peripherals[peripheralID]
2024-12-20 17:18:57 +01:00
if peripheral == nil {
return nil, false
}
return peripheral, true
}
2024-12-15 13:45:46 +01:00
func splitStringAndNumber(input string) (string, int, error) {
// Regular expression to match the text part and the number at the end
re := regexp.MustCompile(`^(.*?)(\d+)$`)
matches := re.FindStringSubmatch(input)
// Check if the regex found both a text part and a number
if len(matches) == 3 {
// matches[1]: text part (might contain trailing spaces)
// matches[2]: numeric part as a string
textPart := strings.TrimSpace(matches[1]) // Remove any trailing spaces from the text
numberPart, err := strconv.Atoi(matches[2])
if err != nil {
return "", 0, err // Return error if the number conversion fails
}
return textPart, numberPart, nil
}
// Return an error if no trailing number is found
return "", 0, fmt.Errorf("no number found at the end of the string")
}
// Scan scans the interfaces compatible with the MIDI protocol
2024-12-23 17:22:37 +01:00
func (d *MIDIDriver) Scan(ctx context.Context) error {
2024-12-15 13:45:46 +01:00
midiPeripherals := make(map[string]Peripheral)
fmt.Println("Opening MIDI scanner port...")
midiScanner, err := rtmidi.NewMIDIInDefault()
if err != nil {
return fmt.Errorf("Error when opening the MIDI scanner: %s", err)
}
defer midiScanner.Close()
fmt.Println("Scanning MIDI devices...")
devicesCount, err := midiScanner.PortCount()
if err != nil {
return fmt.Errorf("Error when scanning MIDI devices: %s", err)
}
for i := 0; i < devicesCount; i++ {
portName, err := midiScanner.PortName(i)
if err != nil {
portName = "Unknown device 0"
}
// Separate data
name, location, err := splitStringAndNumber(portName)
if err != nil {
return fmt.Errorf("Unable to get information from the string: %s", err)
}
fmt.Printf("New MIDI device found: %s on %i\n", name, location)
// Add the peripheral to the temporary list
2024-12-23 17:22:37 +01:00
midiPeripherals[portName] = NewMIDIPeripheral(name, location)
2024-12-15 13:45:46 +01:00
}
// Compare with the current peripherals to detect arrivals/removals
2024-12-23 17:22:37 +01:00
removedList, addedList := comparePeripherals(d.peripherals, midiPeripherals)
2024-12-15 13:45:46 +01:00
// Emit the events
emitPeripheralsEvents(ctx, removedList, PeripheralRemoval)
emitPeripheralsEvents(ctx, addedList, PeripheralArrival)
// Store the new peripherals list
2024-12-23 17:22:37 +01:00
d.peripherals = midiPeripherals
return nil
}
// CreatePeripheral is not implemented here
func (d *MIDIDriver) CreatePeripheral(context.Context) (Peripheral, error) {
return nil, nil
}
// RemovePeripheral is not implemented here
func (d *MIDIDriver) RemovePeripheral(serialNumber string) error {
2024-12-15 13:45:46 +01:00
return nil
}