diff --git a/app.go b/app.go
index 5886487..8532918 100644
--- a/app.go
+++ b/app.go
@@ -7,20 +7,8 @@ import (
"io"
"log"
"os"
- "path/filepath"
"strings"
"sync"
- "time"
-
- "github.com/wailsapp/wails/v2/pkg/runtime"
-
- "gopkg.in/yaml.v2"
-)
-
-const (
- projectsDirectory = "projects" // The directory were are stored all the projects
- avatarsDirectory = "frontend/public" // The directory were are stored all the avatars
- projectExtension = ".dmxproj" // The extension of a DMX Connect project
)
// App struct
@@ -38,8 +26,9 @@ type App struct {
func NewApp() *App {
// Create a new hadware manager
hardwareManager := hardware.NewHardwareManager()
- hardwareManager.RegisterFinder(hardware.NewMIDIFinder())
- hardwareManager.RegisterFinder(hardware.NewFTDIFinder())
+ hardwareManager.RegisterDriver(hardware.NewMIDIDriver())
+ hardwareManager.RegisterDriver(hardware.NewFTDIDriver())
+ hardwareManager.RegisterDriver(hardware.NewOS2LDriver())
return &App{
hardwareManager: hardwareManager,
projectSave: "",
@@ -60,174 +49,6 @@ func (a *App) startup(ctx context.Context) {
}
}
-// CreateProject creates a new blank project
-func (a *App) CreateProject() ShowInfo {
- date := time.Now()
- a.projectSave = ""
- a.projectInfo.ShowInfo = ShowInfo{
- Name: "My new show",
- Date: fmt.Sprintf("%04d-%02d-%02dT%02d:%02d", date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute()),
- Avatar: "appicon.png",
- Comments: "Write your comments here",
- }
- return a.projectInfo.ShowInfo
-}
-
-// GetPeripherals gets all the peripherals connected
-func (a *App) GetPeripherals() error {
- return a.hardwareManager.Scan(a.ctx)
-}
-
-// GetProjects gets all the projects in the projects directory
-func (a *App) GetProjects() ([]ProjectMetaData, error) {
- projects := []ProjectMetaData{}
-
- f, err := os.Open(projectsDirectory)
- if err != nil {
- log.Fatalf("Unable to open the projects directory: %v", err)
- return nil, err
- }
-
- files, err := f.Readdir(0)
- if err != nil {
- log.Fatalf("Unable to read the projects directory: %v", err)
- return nil, err
- }
-
- for _, fileInfo := range files {
- // Open the file and get the show name
- fileData, err := os.ReadFile(filepath.Join(projectsDirectory, fileInfo.Name()))
- if err == nil {
- projectObject := ProjectInfo{}
- err = yaml.Unmarshal(fileData, &projectObject)
- if err == nil {
- // Add the SaveFile property
- projects = append(projects, ProjectMetaData{
- Name: projectObject.ShowInfo.Name,
- Save: fileInfo.Name(),
- })
- }
- }
- }
- return projects, nil
-}
-
-// GetProjectInfo returns the information of the saved project
-func (a *App) GetProjectInfo(projectFile string) (ProjectInfo, error) {
- // Open the project file
- projectPath := filepath.Join(projectsDirectory, projectFile)
- content, err := os.ReadFile(projectPath)
- if err != nil {
- log.Fatalf("Unable to read the project file: %v", err)
- return ProjectInfo{}, err
- }
- a.projectInfo = ProjectInfo{}
- err = yaml.Unmarshal(content, &a.projectInfo)
- if err != nil {
- log.Fatalf("Unable to get the project information: %v", err)
- return ProjectInfo{}, err
- }
- // Load it into the app
- a.projectSave = projectFile
- // Return the show information
- return a.projectInfo, nil
-}
-
-// ChooseAvatarPath opens a filedialog to choose the show avatar
-func (a *App) ChooseAvatarPath() (string, error) {
- // Open the file dialog box
- filePath, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{
- Title: "Choose your show avatar",
- Filters: []runtime.FileFilter{
- {
- DisplayName: "Images",
- Pattern: "*.png;*.jpg;*.jpeg",
- },
- },
- })
- if err != nil {
- return "", err
- }
- // Copy the avatar to the application avatars path
- avatarPath := filepath.Join(avatarsDirectory, filepath.Base(filePath))
- _, err = copy(filePath, avatarPath)
- if err != nil {
- return "", err
- }
- return filepath.Base(filePath), nil
-}
-
-// UpdateShowInfo updates the show information
-func (a *App) UpdateShowInfo(showInfo ShowInfo) {
- fmt.Printf("%s\n", showInfo)
- a.projectInfo.ShowInfo = showInfo
-}
-
-// AddPeripheral adds a peripheral to the project
-func (a *App) AddPeripheral(protocolName string, peripheralID string) error {
- // Get the device from its finder
- p, found := a.hardwareManager.GetPeripheral(protocolName, peripheralID)
- if !found {
- return fmt.Errorf("Unable to localize the peripheral %s", peripheralID)
- }
- // Add the peripheral ID to the project
- a.projectInfo.PeripheralsInfo[peripheralID] = p.GetInfo()
- // TODO: Connect the peripheral
- return nil
-}
-
-// RemovePeripheral adds a peripheral to the project
-func (a *App) RemovePeripheral(protocolName string, peripheralID string) error {
- // TODO: Disconnect the peripheral
- // Remove the peripheral ID from the project
- delete(a.projectInfo.PeripheralsInfo, peripheralID)
- return nil
-}
-
-// SaveProject saves the project
-func (a *App) SaveProject() (string, error) {
- log.Printf("Saving the project %s to %s", a.projectInfo.ShowInfo.Name, a.projectSave)
- // If there is no save file, create a new one with the show name
- if a.projectSave == "" {
- date := time.Now()
- a.projectSave = fmt.Sprintf("%04d%02d%02d%02d%02d%02d%s", date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), projectExtension)
- }
- data, err := yaml.Marshal(a.projectInfo)
- if err != nil {
- return "", err
- }
- // Create the project directory if not exists
- err = os.MkdirAll(projectsDirectory, os.ModePerm)
- if err != nil {
- return "", err
- }
- err = os.WriteFile(filepath.Join(projectsDirectory, a.projectSave), data, os.ModePerm)
- if err != nil {
- return "", err
- }
- return a.projectSave, nil
-}
-
-// ShowInfo defines the information of the show
-type ShowInfo struct {
- Name string `yaml:"name"`
- Date string `yaml:"date"`
- Avatar string `yaml:"avatar"`
- Comments string `yaml:"comments"`
-}
-
-// ProjectMetaData defines all the minimum information for a lighting project
-type ProjectMetaData struct {
- Name string // Show name
- Save string // The save file of the project
-}
-
-// ProjectInfo defines all the information for a lighting project
-type ProjectInfo struct {
- ShowInfo ShowInfo `yaml:"show"` // Show information
- PeripheralsInfo map[string]hardware.PeripheralInfo `yaml:"peripherals"` // Peripherals information
-}
-
func formatString(input string) string {
// Convertir en minuscules
lowerCaseString := strings.ToLower(input)
@@ -260,31 +81,3 @@ func copy(src, dst string) (int64, error) {
nBytes, err := io.Copy(destination, source)
return nBytes, err
}
-
-// FOR TESTING PURPOSE ONLY
-
-func (a *App) ConnectFTDI() error {
- // Create a new FTDI object
- var err error
- a.ftdi, err = hardware.NewFTDIPeripheral("FTDI TEST INTERFACE", "A50825I", 0, "Virtual FTDI finder")
- if err != nil {
- return err
- }
- return a.ftdi.Connect()
-}
-
-func (a *App) ActivateFTDI() error {
- return a.ftdi.Activate()
-}
-
-func (a *App) SetDeviceFTDI(channelValue byte) error {
- return a.ftdi.SetDeviceProperty(0, 0, channelValue)
-}
-
-func (a *App) DeactivateFTDI() error {
- return a.ftdi.Deactivate()
-}
-
-func (a *App) DisconnectFTDI() error {
- return a.ftdi.Disconnect()
-}
diff --git a/frontend/src/components/General/NavigationBar.svelte b/frontend/src/components/General/NavigationBar.svelte
index bd05ec7..3c6e315 100644
--- a/frontend/src/components/General/NavigationBar.svelte
+++ b/frontend/src/components/General/NavigationBar.svelte
@@ -41,12 +41,12 @@
-
-
-
-
-
-
+
+
+
+
+
+
diff --git a/frontend/src/components/Settings/InputsOutputsContent.svelte b/frontend/src/components/Settings/InputsOutputsContent.svelte
index e1c73e9..60792a8 100644
--- a/frontend/src/components/Settings/InputsOutputsContent.svelte
+++ b/frontend/src/components/Settings/InputsOutputsContent.svelte
@@ -4,7 +4,8 @@
import { _ } from 'svelte-i18n'
import { needProjectSave, peripherals } from "../../stores";
import { get } from "svelte/store"
- import { RemovePeripheral, ConnectFTDI, ActivateFTDI, DeactivateFTDI, DisconnectFTDI, SetDeviceFTDI, AddPeripheral } from "../../../wailsjs/go/main/App";
+ import { AddOS2LPeripheral, RemovePeripheral, ConnectFTDI, ActivateFTDI, DeactivateFTDI, DisconnectFTDI, SetDeviceFTDI, AddPeripheral } from "../../../wailsjs/go/main/App";
+ import RoundedButton from "../General/RoundedButton.svelte";
function ftdiConnect(){
ConnectFTDI().then(() =>
@@ -86,6 +87,20 @@
console.log("Unable to remove the peripheral from the project: " + error)
})
}
+
+ // Create the OS2L peripheral
+ function createOS2L(){
+ AddOS2LPeripheral().then(os2lDevice => {
+ peripherals.update(currentPeriph => {
+ os2lDevice.isSaved = true
+ os2lDevice.isDetected = true
+ currentPeriph[os2lDevice.SerialNumber] = os2lDevice
+ return {...currentPeriph}
+ })
+ }).catch(error => {
+ console.log("Unable to add the OS2L peripheral: " + error)
+ })
+ }
@@ -103,9 +118,7 @@
{/if}
{/each}
Others
-
console.log("Edit the OS2L hardware")} title="OS2L device" type="OS2L" line1="Add to configure" addable on:add={() => console.log("Add an OS2L device")}/>
- console.log("Edit the OSC hardware")} title="OSC device" type="OSC" line1="Add to configure" addable on:add={() => console.log("Add an OSC device")}/>
- console.log("Edit the ArtNet hardware")} title="ArtNet device" type="ArtNet" line1="Add to configure" addable on:add={() => console.log("Add an ArtNet device")}/>
+
diff --git a/frontend/src/lang/en.json b/frontend/src/lang/en.json
index 9194a1f..a97cb8f 100644
--- a/frontend/src/lang/en.json
+++ b/frontend/src/lang/en.json
@@ -33,6 +33,6 @@
"projectHardwareShowLabel" : "My Show",
"projectHardwareInputsLabel": "INPUTS",
"projectHardwareOutputsLabel": "OUTPUTS",
- "projectHardwareDeleteTooltip": "Delete this device",
- "projectHardwareAddTooltip": "Add this device to project"
+ "projectHardwareDeleteTooltip": "Delete this peripheral",
+ "projectHardwareAddTooltip": "Add this peripheral to project"
}
diff --git a/hardware/FTDIFinder.go b/hardware/FTDIDriver.go
similarity index 69%
rename from hardware/FTDIFinder.go
rename to hardware/FTDIDriver.go
index 9c5f07d..c7bac99 100644
--- a/hardware/FTDIFinder.go
+++ b/hardware/FTDIDriver.go
@@ -17,41 +17,41 @@ const (
scanDelay = 4 * time.Second // Waiting delay before scanning the FTDI devices
)
-// FTDIFinder represents how the protocol is defined
-type FTDIFinder struct {
+// FTDIDriver represents how the protocol is defined
+type FTDIDriver struct {
peripherals map[string]Peripheral
}
-// NewFTDIFinder creates a new FTDI finder
-func NewFTDIFinder() *FTDIFinder {
- return &FTDIFinder{
+// NewFTDIDriver creates a new FTDI finder
+func NewFTDIDriver() *FTDIDriver {
+ return &FTDIDriver{
peripherals: make(map[string]Peripheral),
}
}
-// Initialize initializes the FTDI finder
-func (f *FTDIFinder) Initialize() error {
+// Initialize initializes the FTDI driver
+func (d *FTDIDriver) Initialize() error {
if goRuntime.GOOS != "windows" {
- return fmt.Errorf(" The FTDI finder is not compatible with your platform yet (%s)", goRuntime.GOOS)
+ return fmt.Errorf(" The FTDI driver is not compatible with your platform yet (%s)", goRuntime.GOOS)
}
- fmt.Println("FTDI finder initialized")
+ fmt.Println("FTDI driver initialized")
return nil
}
-// GetName returns the name of the finder
-func (f *FTDIFinder) GetName() string {
+// GetName returns the name of the driver
+func (d *FTDIDriver) GetName() string {
return "FTDI"
}
// GetPeripheral gets the peripheral that correspond to the specified ID
-func (f *FTDIFinder) GetPeripheral(peripheralID string) (Peripheral, bool) {
+func (d *FTDIDriver) GetPeripheral(peripheralID string) (Peripheral, bool) {
// Return the specified peripheral
- peripheral := f.peripherals[peripheralID]
+ peripheral := d.peripherals[peripheralID]
if peripheral == nil {
- fmt.Println("Unable to get the peripheral in the finder")
+ fmt.Println("Unable to get the peripheral with the driver")
return nil, false
}
- fmt.Println("Peripheral found in the finder")
+ fmt.Println("Peripheral found by the FTDI driver")
return peripheral, true
}
@@ -60,7 +60,7 @@ func (f *FTDIFinder) GetPeripheral(peripheralID string) (Peripheral, bool) {
var findFTDI []byte
// Scan scans the FTDI peripherals
-func (f *FTDIFinder) Scan(ctx context.Context) error {
+func (d *FTDIDriver) Scan(ctx context.Context) error {
time.Sleep(scanDelay)
// Create a temporary file
@@ -113,18 +113,28 @@ func (f *FTDIFinder) Scan(ctx context.Context) error {
location = -1
}
// Add the peripheral to the temporary list
- peripheral, err := NewFTDIPeripheral(deviceInfo[2], deviceInfo[1], location, f.GetName())
+ peripheral, err := NewFTDIPeripheral(deviceInfo[2], deviceInfo[1], location)
if err != nil {
return fmt.Errorf("Unable to create the FTDI peripheral: %v", err)
}
ftdiPeripherals[deviceInfo[1]] = peripheral
}
// Compare with the current peripherals to detect arrivals/removals
- removedList, addedList := comparePeripherals(f.peripherals, ftdiPeripherals)
+ removedList, addedList := comparePeripherals(d.peripherals, ftdiPeripherals)
// Emit the events
emitPeripheralsEvents(ctx, removedList, PeripheralRemoval)
emitPeripheralsEvents(ctx, addedList, PeripheralArrival)
// Store the new peripherals list
- f.peripherals = ftdiPeripherals
+ d.peripherals = ftdiPeripherals
+ return nil
+}
+
+// CreatePeripheral is not implemented here
+func (d *FTDIDriver) CreatePeripheral(context.Context) (Peripheral, error) {
+ return nil, nil
+}
+
+// RemovePeripheral is not implemented here
+func (d *FTDIDriver) RemovePeripheral(serialNumber string) error {
return nil
}
diff --git a/hardware/FTDIPeripheral.go b/hardware/FTDIPeripheral.go
index 9e8ba30..bb01147 100644
--- a/hardware/FTDIPeripheral.go
+++ b/hardware/FTDIPeripheral.go
@@ -26,7 +26,6 @@ type FTDIPeripheral struct {
serialNumber string // The S/N of the FTDI peripheral
location int // The location of the peripheral
universesNumber int // The number of DMX universes handled by this peripheral
- finderName string // The name of the parent finder
programName string // The temp file name of the executable
dmxSender *exec.Cmd // The command to pilot the DMX sender program
stdin io.WriteCloser // For writing in the DMX sender
@@ -38,7 +37,7 @@ type FTDIPeripheral struct {
}
// NewFTDIPeripheral creates a new FTDI peripheral
-func NewFTDIPeripheral(name string, serialNumber string, location int, finderName string) (*FTDIPeripheral, error) {
+func NewFTDIPeripheral(name string, serialNumber string, location int) (*FTDIPeripheral, error) {
// Create a temporary file
tempFile, err := os.CreateTemp("", "dmxSender*.exe")
if err != nil {
@@ -57,7 +56,6 @@ func NewFTDIPeripheral(name string, serialNumber string, location int, finderNam
programName: tempFile.Name(),
serialNumber: serialNumber,
location: location,
- finderName: finderName,
universesNumber: 1,
disconnectChan: make(chan struct{}),
errorsChan: make(chan error, 1),
diff --git a/hardware/MIDIFinder.go b/hardware/MIDIDriver.go
similarity index 75%
rename from hardware/MIDIFinder.go
rename to hardware/MIDIDriver.go
index a8ae141..c6c8629 100644
--- a/hardware/MIDIFinder.go
+++ b/hardware/MIDIDriver.go
@@ -29,33 +29,33 @@ import (
limitations under the License.
*/
-// MIDIFinder represents how the protocol is defined
-type MIDIFinder struct {
+// MIDIDriver represents how the protocol is defined
+type MIDIDriver struct {
peripherals map[string]Peripheral // The list of peripherals
}
-// NewMIDIFinder creates a new DMXUSB protocol
-func NewMIDIFinder() *MIDIFinder {
- return &MIDIFinder{
+// NewMIDIDriver creates a new DMXUSB protocol
+func NewMIDIDriver() *MIDIDriver {
+ return &MIDIDriver{
peripherals: make(map[string]Peripheral),
}
}
-// Initialize initializes the DMX-USB finder
-func (f *MIDIFinder) Initialize() error {
- fmt.Println("MIDI finder initialized")
+// Initialize initializes the MIDI driver
+func (d *MIDIDriver) Initialize() error {
+ fmt.Println("MIDI driver initialized")
return nil
}
-// GetName returns the name of the finder
-func (f *MIDIFinder) GetName() string {
+// GetName returns the name of the driver
+func (d *MIDIDriver) GetName() string {
return "MIDI"
}
// GetPeripheral gets the peripheral that correspond to the specified ID
-func (f *MIDIFinder) GetPeripheral(peripheralID string) (Peripheral, bool) {
+func (d *MIDIDriver) GetPeripheral(peripheralID string) (Peripheral, bool) {
// Return the specified peripheral
- peripheral := f.peripherals[peripheralID]
+ peripheral := d.peripherals[peripheralID]
if peripheral == nil {
return nil, false
}
@@ -84,7 +84,7 @@ func splitStringAndNumber(input string) (string, int, error) {
}
// Scan scans the interfaces compatible with the MIDI protocol
-func (f *MIDIFinder) Scan(ctx context.Context) error {
+func (d *MIDIDriver) Scan(ctx context.Context) error {
midiPeripherals := make(map[string]Peripheral)
fmt.Println("Opening MIDI scanner port...")
midiScanner, err := rtmidi.NewMIDIInDefault()
@@ -109,14 +109,24 @@ func (f *MIDIFinder) Scan(ctx context.Context) error {
}
fmt.Printf("New MIDI device found: %s on %i\n", name, location)
// Add the peripheral to the temporary list
- midiPeripherals[portName] = NewMIDIPeripheral(name, location, f.GetName())
+ midiPeripherals[portName] = NewMIDIPeripheral(name, location)
}
// Compare with the current peripherals to detect arrivals/removals
- removedList, addedList := comparePeripherals(f.peripherals, midiPeripherals)
+ removedList, addedList := comparePeripherals(d.peripherals, midiPeripherals)
// Emit the events
emitPeripheralsEvents(ctx, removedList, PeripheralRemoval)
emitPeripheralsEvents(ctx, addedList, PeripheralArrival)
// Store the new peripherals list
- f.peripherals = midiPeripherals
+ 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 {
return nil
}
diff --git a/hardware/MIDIPeripheral.go b/hardware/MIDIPeripheral.go
index d8af465..a7dd461 100644
--- a/hardware/MIDIPeripheral.go
+++ b/hardware/MIDIPeripheral.go
@@ -4,15 +4,13 @@ package hardware
type MIDIPeripheral struct {
name string // The name of the peripheral
location int // The location of the peripheral
- finderName string // The name of the parent finder
}
// NewMIDIPeripheral creates a new MIDI peripheral
-func NewMIDIPeripheral(name string, location int, finderName string) *MIDIPeripheral {
+func NewMIDIPeripheral(name string, location int) *MIDIPeripheral {
return &MIDIPeripheral{
name: name,
location: location,
- finderName: finderName,
}
}
diff --git a/hardware/OS2LDriver.go b/hardware/OS2LDriver.go
new file mode 100644
index 0000000..7ead8f7
--- /dev/null
+++ b/hardware/OS2LDriver.go
@@ -0,0 +1,60 @@
+package hardware
+
+import (
+ "context"
+ "fmt"
+ "math/rand"
+)
+
+// OS2LDriver represents how the protocol is defined
+type OS2LDriver struct {
+ peripherals map[string]Peripheral // The list of peripherals
+}
+
+// NewOS2LDriver creates a new OS2L driver
+func NewOS2LDriver() *OS2LDriver {
+ return &OS2LDriver{
+ peripherals: make(map[string]Peripheral),
+ }
+}
+
+// Initialize initializes the MIDI driver
+func (d *OS2LDriver) Initialize() error {
+ fmt.Println("OS2L driver initialized")
+ return nil
+}
+
+// CreatePeripheral creates a new OS2L peripheral
+func (d *OS2LDriver) CreatePeripheral(ctx context.Context) (Peripheral, error) {
+ // Create a random serial number for this peripheral
+ randomSerialNumber := fmt.Sprintf("%08x", rand.Intn(1<<32))
+ peripheral := NewOS2LPeripheral("OS2L", randomSerialNumber)
+ d.peripherals[randomSerialNumber] = peripheral
+ return peripheral, nil
+}
+
+// RemovePeripheral removes an OS2L dev
+func (d *OS2LDriver) RemovePeripheral(serialNumber string) error {
+ delete(d.peripherals, serialNumber)
+ return nil
+}
+
+// GetName returns the name of the driver
+func (d *OS2LDriver) GetName() string {
+ return "OS2L"
+}
+
+// GetPeripheral gets the peripheral that correspond to the specified ID
+func (d *OS2LDriver) GetPeripheral(peripheralID string) (Peripheral, bool) {
+ // Return the specified peripheral
+ peripheral := d.peripherals[peripheralID]
+ if peripheral == nil {
+ return nil, false
+ }
+ return peripheral, true
+}
+
+// Scan scans the interfaces compatible with the MIDI protocol
+func (d *OS2LDriver) Scan(ctx context.Context) error {
+ return nil
+}
diff --git a/hardware/OS2LPeripheral.go b/hardware/OS2LPeripheral.go
new file mode 100644
index 0000000..4d62703
--- /dev/null
+++ b/hardware/OS2LPeripheral.go
@@ -0,0 +1,55 @@
+package hardware
+
+import "fmt"
+
+// OS2LPeripheral contains the data of an OS2L peripheral
+type OS2LPeripheral struct {
+ name string // The name of the peripheral
+ serialNumber string // The serial number of the peripheral
+}
+
+// NewOS2LPeripheral creates a new OS2L peripheral
+func NewOS2LPeripheral(name string, serialNumber string) *OS2LPeripheral {
+ return &OS2LPeripheral{
+ name: name,
+ serialNumber: serialNumber,
+ }
+}
+
+// Connect connects the MIDI peripheral
+func (p *OS2LPeripheral) Connect() error {
+ fmt.Println("OS2L peripheral connected")
+ return nil
+}
+
+// Disconnect disconnects the MIDI peripheral
+func (p *OS2LPeripheral) Disconnect() error {
+ fmt.Println("OS2L peripheral disconnected")
+ return nil
+}
+
+// Activate activates the MIDI peripheral
+func (p *OS2LPeripheral) Activate() error {
+ fmt.Println("OS2L peripheral activated")
+ return nil
+}
+
+// Deactivate deactivates the MIDI peripheral
+func (p *OS2LPeripheral) Deactivate() error {
+ fmt.Println("OS2L peripheral deactivated")
+ return nil
+}
+
+// SetDeviceProperty - not implemented for this kind of peripheral
+func (p *OS2LPeripheral) SetDeviceProperty(uint32, uint32, byte) error {
+ return nil
+}
+
+// GetInfo gets the peripheral information
+func (p *OS2LPeripheral) GetInfo() PeripheralInfo {
+ return PeripheralInfo{
+ Name: p.name,
+ SerialNumber: p.serialNumber,
+ ProtocolName: "OS2L",
+ }
+}
diff --git a/hardware/hardware.go b/hardware/hardware.go
index 77e39e6..6c2ada3 100644
--- a/hardware/hardware.go
+++ b/hardware/hardware.go
@@ -29,7 +29,7 @@ var (
// HardwareManager is the class who manages the hardware
type HardwareManager struct {
- finders map[string]PeripheralFinder // The map of peripherals finders
+ drivers map[string]PeripheralDriver // The map of peripherals finders
peripherals []Peripheral // The current list of peripherals
deviceChangedEvent chan struct{} // The event when the devices list changed
ctx context.Context
@@ -38,7 +38,7 @@ type HardwareManager struct {
// NewHardwareManager creates a new HardwareManager
func NewHardwareManager() *HardwareManager {
return &HardwareManager{
- finders: make(map[string]PeripheralFinder),
+ drivers: make(map[string]PeripheralDriver),
peripherals: make([]Peripheral, 0),
deviceChangedEvent: make(chan struct{}),
}
@@ -118,38 +118,45 @@ func (h *HardwareManager) Start(ctx context.Context) error {
return nil
}
-// RegisterFinder registers a new peripherals finder
-func (h *HardwareManager) RegisterFinder(finder PeripheralFinder) {
- h.finders[finder.GetName()] = finder
- fmt.Printf("Success registered the %s finder\n", finder.GetName())
+// GetDriver returns a register driver
+func (h *HardwareManager) GetDriver(driverName string) (PeripheralDriver, error) {
+ driver, exists := h.drivers[driverName]
+ if !exists {
+ return nil, fmt.Errorf("Unable to locate the '%s' driver", driverName)
+ }
+ return driver, nil
}
-// GetPeripheral gets the peripheral object from the parent finder
-func (h *HardwareManager) GetPeripheral(finderName string, peripheralID string) (Peripheral, bool) {
- // Get the parent finder
- parentFinder := h.finders[finderName]
- // If no finder found, return false
- if parentFinder == nil {
- fmt.Println("Unable to get the finder")
+// RegisterDriver registers a new peripherals driver
+func (h *HardwareManager) RegisterDriver(driver PeripheralDriver) {
+ h.drivers[driver.GetName()] = driver
+ fmt.Printf("Success registered the %s driver\n", driver.GetName())
+}
+
+// GetPeripheral gets the peripheral object from the parent driver
+func (h *HardwareManager) GetPeripheral(driverName string, peripheralID string) (Peripheral, bool) {
+ // Get the driver
+ parentDriver := h.drivers[driverName]
+ // If no driver found, return false
+ if parentDriver == nil {
+ fmt.Println("Unable to get the driver")
return nil, false
}
- fmt.Println("Finder ok, returning the peripheral")
-
- // Contact the finder to get the device
- return parentFinder.GetPeripheral(peripheralID)
+ // Contact the driver to get the device
+ return parentDriver.GetPeripheral(peripheralID)
}
// Scan scans all the peripherals for the registered finders
func (h *HardwareManager) Scan(ctx context.Context) error {
- if len(h.finders) == 0 {
- return fmt.Errorf("No peripherals finder registered")
+ if len(h.drivers) == 0 {
+ return fmt.Errorf("No peripherals driver registered")
}
- for _, finder := range h.finders {
- finder := finder
+ for _, driver := range h.drivers {
+ finder := driver
go func() {
- err := finder.Scan(ctx)
+ err := driver.Scan(ctx)
if err != nil {
- fmt.Printf("Unable to scan peripherals with the %s finder: %s\n", finder.GetName(), err)
+ fmt.Printf("Unable to scan peripherals with the %s driver: %s\n", finder.GetName(), err)
return
}
}()
diff --git a/hardware/interfaces.go b/hardware/interfaces.go
index 363f74e..2c1fb15 100644
--- a/hardware/interfaces.go
+++ b/hardware/interfaces.go
@@ -21,10 +21,12 @@ type PeripheralInfo struct {
Settings []interface{} `yaml:"settings"` // Number of DMX universes handled by the peripheral
}
-// PeripheralFinder represents how compatible peripheral finders are implemented
-type PeripheralFinder interface {
- Initialize() error // Initializes the protocol
- GetName() string // Get the name of the finder
- GetPeripheral(string) (Peripheral, bool) // Get the peripheral
- Scan(context.Context) error // Scan for peripherals
+// PeripheralDriver represents how compatible peripheral drivers are implemented
+type PeripheralDriver interface {
+ Initialize() error // Initializes the protocol
+ GetName() string // Get the name of the finder
+ GetPeripheral(string) (Peripheral, bool) // Get the peripheral
+ Scan(context.Context) error // Scan for peripherals
+ CreatePeripheral(ctx context.Context) (Peripheral, error) // Creates a new peripheral
+ RemovePeripheral(serialNumber string) error // Removes a peripheral
}
diff --git a/peripherals.go b/peripherals.go
new file mode 100644
index 0000000..d944aec
--- /dev/null
+++ b/peripherals.go
@@ -0,0 +1,77 @@
+package main
+
+import (
+ "changeme/hardware"
+ "fmt"
+)
+
+// GetPeripherals gets all the peripherals connected
+func (a *App) GetPeripherals() error {
+ return a.hardwareManager.Scan(a.ctx)
+}
+
+// AddPeripheral adds a peripheral to the project
+func (a *App) AddPeripheral(protocolName string, peripheralID string) error {
+ // Get the device from its finder
+ p, found := a.hardwareManager.GetPeripheral(protocolName, peripheralID)
+ if !found {
+ return fmt.Errorf("Unable to localize the peripheral %s", peripheralID)
+ }
+ // Add the peripheral ID to the project
+ a.projectInfo.PeripheralsInfo[peripheralID] = p.GetInfo()
+ // TODO: Connect the peripheral
+ return nil
+}
+
+// RemovePeripheral adds a peripheral to the project
+func (a *App) RemovePeripheral(protocolName string, peripheralID string) error {
+ // TODO: Disconnect the peripheral
+ // Remove the peripheral ID from the project
+ delete(a.projectInfo.PeripheralsInfo, peripheralID)
+ return nil
+}
+
+// AddOS2LPeripheral adds a new OS2L peripheral
+func (a *App) AddOS2LPeripheral() (hardware.PeripheralInfo, error) {
+ // Get the OS2L driver
+ os2lDriver, err := a.hardwareManager.GetDriver("OS2L")
+ if err != nil {
+ return hardware.PeripheralInfo{}, err
+ }
+ // Create a new OS2L peripheral with this driver
+ os2lPeripheral, err := os2lDriver.CreatePeripheral(a.ctx)
+ if err != nil {
+ return hardware.PeripheralInfo{}, nil
+ }
+ os2lInfo := os2lPeripheral.GetInfo()
+ // Add this new peripheral to the project
+ return os2lInfo, a.AddPeripheral(os2lDriver.GetName(), os2lInfo.SerialNumber)
+}
+
+// FOR TESTING PURPOSE ONLY
+
+func (a *App) ConnectFTDI() error {
+ // Create a new FTDI object
+ var err error
+ a.ftdi, err = hardware.NewFTDIPeripheral("FTDI TEST INTERFACE", "A50825I", 0)
+ if err != nil {
+ return err
+ }
+ return a.ftdi.Connect()
+}
+
+func (a *App) ActivateFTDI() error {
+ return a.ftdi.Activate()
+}
+
+func (a *App) SetDeviceFTDI(channelValue byte) error {
+ return a.ftdi.SetDeviceProperty(0, 0, channelValue)
+}
+
+func (a *App) DeactivateFTDI() error {
+ return a.ftdi.Deactivate()
+}
+
+func (a *App) DisconnectFTDI() error {
+ return a.ftdi.Disconnect()
+}
diff --git a/project.go b/project.go
new file mode 100644
index 0000000..dbcd539
--- /dev/null
+++ b/project.go
@@ -0,0 +1,161 @@
+package main
+
+import (
+ "changeme/hardware"
+ "fmt"
+ "log"
+ "os"
+ "path/filepath"
+ "time"
+
+ "github.com/wailsapp/wails/v2/pkg/runtime"
+ "gopkg.in/yaml.v2"
+)
+
+const (
+ projectsDirectory = "projects" // The directory were are stored all the projects
+ avatarsDirectory = "frontend/public" // The directory were are stored all the avatars
+ projectExtension = ".dmxproj" // The extension of a DMX Connect project
+)
+
+// GetProjects gets all the projects in the projects directory
+func (a *App) GetProjects() ([]ProjectMetaData, error) {
+ projects := []ProjectMetaData{}
+
+ f, err := os.Open(projectsDirectory)
+ if err != nil {
+ log.Fatalf("Unable to open the projects directory: %v", err)
+ return nil, err
+ }
+
+ files, err := f.Readdir(0)
+ if err != nil {
+ log.Fatalf("Unable to read the projects directory: %v", err)
+ return nil, err
+ }
+
+ for _, fileInfo := range files {
+ // Open the file and get the show name
+ fileData, err := os.ReadFile(filepath.Join(projectsDirectory, fileInfo.Name()))
+ if err == nil {
+ projectObject := ProjectInfo{}
+ err = yaml.Unmarshal(fileData, &projectObject)
+ if err == nil {
+ // Add the SaveFile property
+ projects = append(projects, ProjectMetaData{
+ Name: projectObject.ShowInfo.Name,
+ Save: fileInfo.Name(),
+ })
+ }
+ }
+ }
+ return projects, nil
+}
+
+// CreateProject creates a new blank project
+func (a *App) CreateProject() ShowInfo {
+ date := time.Now()
+ a.projectSave = ""
+ a.projectInfo.ShowInfo = ShowInfo{
+ Name: "My new show",
+ Date: fmt.Sprintf("%04d-%02d-%02dT%02d:%02d", date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute()),
+ Avatar: "appicon.png",
+ Comments: "Write your comments here",
+ }
+ return a.projectInfo.ShowInfo
+}
+
+// GetProjectInfo returns the information of the saved project
+func (a *App) GetProjectInfo(projectFile string) (ProjectInfo, error) {
+ // Open the project file
+ projectPath := filepath.Join(projectsDirectory, projectFile)
+ content, err := os.ReadFile(projectPath)
+ if err != nil {
+ log.Fatalf("Unable to read the project file: %v", err)
+ return ProjectInfo{}, err
+ }
+ a.projectInfo = ProjectInfo{}
+ err = yaml.Unmarshal(content, &a.projectInfo)
+ if err != nil {
+ log.Fatalf("Unable to get the project information: %v", err)
+ return ProjectInfo{}, err
+ }
+ // Load it into the app
+ a.projectSave = projectFile
+ // Return the show information
+ return a.projectInfo, nil
+}
+
+// ChooseAvatarPath opens a filedialog to choose the show avatar
+func (a *App) ChooseAvatarPath() (string, error) {
+ // Open the file dialog box
+ filePath, err := runtime.OpenFileDialog(a.ctx, runtime.OpenDialogOptions{
+ Title: "Choose your show avatar",
+ Filters: []runtime.FileFilter{
+ {
+ DisplayName: "Images",
+ Pattern: "*.png;*.jpg;*.jpeg",
+ },
+ },
+ })
+ if err != nil {
+ return "", err
+ }
+ // Copy the avatar to the application avatars path
+ avatarPath := filepath.Join(avatarsDirectory, filepath.Base(filePath))
+ _, err = copy(filePath, avatarPath)
+ if err != nil {
+ return "", err
+ }
+ return filepath.Base(filePath), nil
+}
+
+// UpdateShowInfo updates the show information
+func (a *App) UpdateShowInfo(showInfo ShowInfo) {
+ fmt.Printf("%s\n", showInfo)
+ a.projectInfo.ShowInfo = showInfo
+}
+
+// SaveProject saves the project
+func (a *App) SaveProject() (string, error) {
+ log.Printf("Saving the project %s to %s", a.projectInfo.ShowInfo.Name, a.projectSave)
+ // If there is no save file, create a new one with the show name
+ if a.projectSave == "" {
+ date := time.Now()
+ a.projectSave = fmt.Sprintf("%04d%02d%02d%02d%02d%02d%s", date.Year(), date.Month(), date.Day(), date.Hour(), date.Minute(), date.Second(), projectExtension)
+ }
+ data, err := yaml.Marshal(a.projectInfo)
+ if err != nil {
+ return "", err
+ }
+ // Create the project directory if not exists
+ err = os.MkdirAll(projectsDirectory, os.ModePerm)
+ if err != nil {
+ return "", err
+ }
+ err = os.WriteFile(filepath.Join(projectsDirectory, a.projectSave), data, os.ModePerm)
+ if err != nil {
+ return "", err
+ }
+ return a.projectSave, nil
+}
+
+// ShowInfo defines the information of the show
+type ShowInfo struct {
+ Name string `yaml:"name"`
+ Date string `yaml:"date"`
+ Avatar string `yaml:"avatar"`
+ Comments string `yaml:"comments"`
+}
+
+// ProjectMetaData defines all the minimum information for a lighting project
+type ProjectMetaData struct {
+ Name string // Show name
+ Save string // The save file of the project
+}
+
+// ProjectInfo defines all the information for a lighting project
+type ProjectInfo struct {
+ ShowInfo ShowInfo `yaml:"show"` // Show information
+ PeripheralsInfo map[string]hardware.PeripheralInfo `yaml:"peripherals"` // Peripherals information
+}