Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Osc in Mixxx + ARM64/2.6 (20241104) #13835

Open
wants to merge 25 commits into
base: main
Choose a base branch
from

Conversation

Eve00000
Copy link
Contributor

@Eve00000 Eve00000 commented Nov 4, 2024

***** This PR is created after crash reports on ARM64 of PR #13714 *******
***** If tests are all ok, this PR can replace the old one ******

Now with rebase from 2.6 + ARM64 problem should be solved

  • Soundsourceffmpeg correction for Stem location

OSC working in Mixxx (also Epic, my first real PR )

Preferences: Enabled / Receivers / Ports
Sending Track Info / Title / Duration ...

Receiving in thread and executing all CO's + Stems + FX + .... (everything)
CMakeLists.txt is also adapted.
Bi-directional  // sync knob / timers elapsed & remain
Switch decks 1-3 & 2-4

Q1: now 5 clients can be configured in settings, should I make it 10?

Open for feedback
Test with MixxxInTouchOSCv50.tosc.txt -> rename: drop the .txt

corrected in #49 : jog channels (deckswitch was lost in updates)
added: slowstart & brake

added in #50 : unescape TrackArtist & TrackTitle json \uXXXX
MixxxInTouchOSCv50.tosc.txt

afbeelding

OSC in Mixxx
Why?
There are different user cases where OSC-functionality in Mixxx is an added value:

  • If the user's hardware controller doesn't have enough knobs / encoders / potmeters to control all control objects of Mixxx, fi Stem controls on a tablet
  • If the user want to have a remote controller
  • If the user's hardware controller doesn't haven sceens that can give information or needed functionality a tablet can be added to display info of a deck or for all decks
  • If a user wants to receive information from Mixxx in a light controller
  • If a user want"s to extract information from Mixxx to display on a screen for the audience or on a website
  • IF a user want a combination of previous listed items
    The example enclosed has the functionality of a combination of an extra controller, an info screen and a remote controller.

Environment
Different to hardware controllers that are in general connected to the Mixxx-machine through USB (Midi / HID) OSC works over the network (LAN). Networkconnections can be wired or wireless. Keep in mind that the user needs to provide a LAN connection between the Mixxx-machine and the OSC-Receivers. There are many reasons why a DJ doesn't want to connect it's Mixxx-machine to a public network. Preferable the DJ sets up a private LAN: a hardware or software wireless accesspoint, to connect tablets or smartphones, a small switch to connect machines with a LAN-connector or in case only one other machine needs to be connected to Mixxx a crossed-cable can be used. (all tested).

Mixxx Ecosystem
The integration of OSC in Mixxx needed to respect Mixxx's Ecosystem, OSC had to work by analogy to the hardware controllers Midi/Hid integration. Some remarks:

  • mapping a basic OSC controller must be easy accessible for everyone, advanced scripting can require some basic programming skills.
  • a control object can be controlled by a 'simple' mapping like it can be mapped as 'normal' in the XML for a Midi controller
  • a control object can be controlled through a script like control objects can be mapped as 'script' and through a JS script in the midi.js file for a Midi controller.
  • a logic and simple translation is needed between the Mixxx control object names and the OSC controller
  • to write script functions the OSC controller must be able to 'pull' information from Mixxx when needed like 'getValue / getParameter in Midi-scripting.
  • for particular functions in the OSC-controller the information needs to be accurate, so a solution similar to engine.makeConnection needed to be found.
  • some controllers can only be configured as 'receivers' (fi when they don't have scripting possibilities), Mixxx needs to be able to 'push' information to update these receivers.
  • the information must be accurate on all connected OSC-receivers, even if only a part of the information is used.

Remark: as TouchOSC is seen as the 'standard' OSC-editor, all following OSC functions, scripts ... are created and tested in TouchOSC.

The OSC - object.
OSC is a protocol to send/receive small commands and informationspackages over a network.
That package is constructed of severl parts:

  • The address and the port of the machine to which the package is addressed
  • a path
  • a value and it's type

The address and port of the machine to which the package is addressed is configured in the connections.
The path starts always with a slash, followed with a 1st address-part, a slash, a 2nd adress-part .... a slash, a x-th address-part, a slash and the name of the object.
(in Mixxx we don't use all the address-parts, just a slash and the name of the object: /name)
A value can be a String, Int, Boolean or Float.
(in Mixxx we'll use only the float)

There a different types of OSC-Controls
General:
A control has a type, shape, value, orientation, color... and can contain a script form.
A control can send information when touched/pressed/released or with a script.
with Momentary (on the moment of the action) if 'press' and 'release' are selected touching the control will send information and releasing the button will send information as well.
With 'Toggle Press' you only send information on the moment that you press the button (with Toggle Realease on the moment that you release the button)
A control has also a value, this can be a text (in case of a label) or a key. The key can be x or touch.
Touch is a Boolean: you touch the control or you don't. fi in case you touch the button you want to change the color of the button.
The value of x can be defined in the scale of the OSC-message or can be given in a script.

Main Types used to control Mixxx:

  • a Label: can be the descriving text overlay on a button or a 'standalone field' used to give some information, or even an 'receiving control' (to receive text =string information)

  • a Button: serves to send an instruction (information) when touched or to activate a script.
    *when the information is send can be defined: Momentary (on the moment of the action): if 'press' and 'release' are selected touching the button will send information and releasing the button will send information as well.
    If you're defining a 'play-button' you don't want this because in the same action (press-release) you start (send 1) and pause (send 0) the track.
    With 'Toggle Press' you only send information on the moment that you press the button (with Toggle Realease on the moment that you release the button)

  • a Radial: can be used to control an encoder fi high / mid / low eq, gain. The information send is the value on the scale where the control is last touched (can be through a script), a Radial has a minimum and maximum value.

  • a Fader: can be used to control a fader (rate / volume / crossfader), The information send is the value on the scale where the control is last touched (can be through a script), a Fader has a minimum and maximum value.

  • an Encoder: can be used to control a jogwheel, to browse, in the library.. The information send is calulated relative to the previous position of the control.

A control has different properties:
name, tag, size, color, shape.
These properties can be changed through scripting.
Fi change the color of a playbutton when it's pressed to start the plaing.

function update()
  if key == 'x' and self.values.x == 0 then
    self.color = Color.fromHexString("0000FFAA")
  elseif key == 'x' and self.values.x == 1 then
    self.color = Color.fromHexString("0000FFFF")
  end
end

Fi the play-button '(Channel2)@play' can be changed to '(Channel4)@play' when a 'deckswitchbutton' to switch to deck 4 is activated. When pressing the 'deckswitchbutton' again to return to deck 2 the name of the control can be changed back to
'(Channel2)@play'.

function onValueChanged(key)
  if key == "x" and self.values.x == 1 then
    self.parent.children['(Channel2)@play'].properties.name = '(Channel4)@play'
  end
  if key == "x" and self.values.x == 0 then
    self.parent.children['(Channel4)@play'].properties.name = '(Channel2)@play'
  end
end

Remark:
In the duration that the button is renamed to '(Channel4)@play' the controller can't receive messages for '(Channel2)@play',
if the deck 2 player is started meanwhile the OSC controller does not know. You'lll need to cover this issue with scripting after changing the deck fi;

if self.values.x == 0 then
  sendOSC('/GetP#(Channel2)@play', 1)
end
if  self.values.x == 1 then
  sendOSC('/GetP#(Channel4)@play', 1)
end

A OSC-Controller can be devided in parts to create more space or to devide controls in groups.
This can be done with a 'pager'. A pager contains different 'pages'.
Properties of controls on another 'page' can be called using the 'parent' and 'children' instructions.
fi: if you want to use the value of a 'Shift-button' that is located on another page, you can start from the 'root' of the document:

if root.children.Stems.children.Controller.children['Shift'].values.x == 0
if root.children['Stems'].children['Controller'].children['Shift'].values.x == 0

Remark: both lines are valid and call the value of the same 'Shift-Button'
To change the name of a control that is located in a 'sub-pager' on the same main 'page':

self.parent.children['Controller_Ch2'].children.P5.children['(EqualizerRack1_(Channel2)_Effect1)@button_parameter2'].properties.name = '(EqualizerRack1_(Channel4)_Effect1)@button_parameter2

Remark: you can see both addressing methods can be used.

Controls on different pages can have the same name (OSC uses an internal ID system to identify the controls),
so you can have the same control in different forms or on diferent 'pages'.
If the 'naming' and 'path' rules are respected all controls will receive the same information.
fi: If you have a 1st 'page' called 'Stems' on which you created controls for stems in [Channel1] (Mixxx CO group is between [ ] ):

name: (Channel1Stem1)@mute
path: /name

and on a 2nd 'page' you created a virtual controller on which you want to control the stems of [Channel1] as well, you just create a new control with the same name and path.
if you send a scripted instruction like

sendOSC('/GetP#(Channel1Stem1)@mute', 1)

both controls will be receive the information and will be updated.

OSC integration in Mixxx

  • in Mixxx Preferences:
    In OSC the terms OSC Server and Client are used, the machine sending information is the server, the machine receiving information is the client. In a system where both machines send and receive information I prefer to talk about Receivers (the OSC Controllers and the Mixxx-Machine)
  • OSC enabled (or not)
  • OSC Port-In: the UDP port on which Mixxx receives OSC packages, this port should be configured as Port-Out on the receiver.
  • OSC Port-Out: the UDP port on which Mixxx sends OSC packages, at the moment 1 standard port for all receivers. This port should be configured as Port-In on the receiver.
  • OSC Receivers, at the moment there's the possibility to configure 5 clients (maybe this should be 10) of which the IP-Address needs to be entered. The IP-address needs to be reachable from the Mixxx-Machine. Each Receiver can be set Active, which means that Mixxx will send a copy of the OSC packages to this address.
  • If 5 Receivers are set Active, Mixxx will send all outgoing information to these 5 machines.
  • A time value for a periodic 'syns push' can be entered in milliseconds.This value tells Mixxx the interval between 'sync push'-triggers.
  • In general:
  • OSC uses the '[' and ']' (square brackets) internally, so all square brackets are replaced with normal brackets '(' and ')'
  • In OSC all control objects are written with an @-symbol between the group and the key in the name, fi (Channel1)@play, (Master)@crossfader, (QuickEffectRack1_(Channel1Stem2))@super1
  • All OSC-addresses in the OSC-messaging system on the controller are rooted in the path, this means they are written as
    '/name' (so NOT as '/page/subpage/whatever/name'
  • Attention for capital letters!
  • At the moment OSC doe not standard support Double values (as all control object values are in Mixxx), so all values are sent and received as Float

Simple mapping of Control Object in TouchOSC:

  • create an object (button), name it as the CO fi (Channel1)@play
  • set the button properties, fi Toggle Press, Check Press, Check Receive
  • add the OSC Message in messaging, change the path so it's only '/name', click on the x, set the value on float, and the scale to 0 - 1
  • press the 'play' function in the OSC editor so the contoller gets executed
  • try your button, an OSC message is sent when you press play with value 1, when you release the button nothiong is send.
    when you press again an OSC message is sent with the value 0.

OSC functions on Mixxx Machine

  • As written earlier the Mixxx-Machine will send all OSC packages to all active Receivers.
  • Some basic information information is send 'on value change' in Mixxx, some information is sent as a new 'pseudo control object'
  • Trackinfo : (Group)@Trackartist, (Group)@TrackTitle (should be preferably received in a 'label'-object; will be expanded, unfortunately OSC does not support transferring images at the moment)
  • (Group)@track_loaded, (Group)@duration, (Group)@play, (Group)@eject

Scripting

  • An object does not have to be configured to send a standard OSC message, OSC messages can be send with a script.
  • In TouchOSC scripts can be written in LUA (very simple)
  • TouchOSC does not have the possibility to define global variables, local variable in functions can be defined but these can not be addressed in other functions. If you want to interchange information between functions / objects you need to store the values in (hidden) objects. It's recommended to create (define) all Control Objects so all information can be received, even if you don't need it at the moment.
  • Mixxx can be (periodically) triggered to send information with a '/GetP#' or '/GetV#' prefix before the control object's path. (a future change in these is possible), 'GetV#' requests Mixxx to send the value of the CO (Control Object) and 'GetP#' requests Mixxx to send the parameterized value of the CO (Control Object).
    Used as: 'sendOSC('/GetP#(Master)@crossfader', 1)', 'sendOSC('/GetV#(EqualizerRack1_(Channel1)Effect1)@Parameter3', 1)' ...
    When Mixxx receives these requests, Mixxx will send the values of these CO's instantly to all Active Receivers. These values will be received in the configured objects fi '(Master)@crossfader' and '(EqualizerRack1
    (Channel1)_Effect1)@Parameter3' if these are configured, else they'll be ignored.
  • There are some standard functions you can use to write scripts
  • update(), onValueChanged(key), onReceiveOSC, onReceiveNotify()...
    fi function to select the behaviour of key depending on the chosen deck to control (value of Ch2_Deckswitch- and the value of the Shift button.
function onValueChanged(key)
  if key == "x" and self.values.x == 1 then
    if self.parent.children['Ch2_Deckswitch'].values.x == 0 then
      if self.parent.children['Shift'].values.x == 0 then
        sendOSC('/(Channel2)@hotcue_1_activate', 1)    
      end 
      if self.parent.children['Shift'].values.x == 1 then
        sendOSC('/(Channel2)@hotcue_1_clear', 1)    
      end 
    end
    if self.parent.children['Ch2_Deckswitch'].values.x == 1 then
      if self.parent.children['Shift'].values.x == 0 then
        sendOSC('/(Channel4)@hotcue_1_activate', 1)    
      end 
      if self.parent.children['Shift'].values.x == 1 then
        sendOSC('/(Channel4)@hotcue_1_clear', 1)    
      end 
    end
  end    
end
  • Periodically (see earlier) Mixxx wil send a 'sync push'-trigger. This is a message to the object name '(Osc)@oscsync'.
    You can define an object with this name or a global 'onReceiveOSC'function for the correspondinf path ' if path == '/Osc@OscSync' then' ... in which you can list all objects for which you want to request an update:
    fi:
function onReceiveOSC(message, connections)
  local path = message[1]
  local arguments = message[2]
  if path == '/Osc@OscSync' then
    sendOSC('/GetP#(Master)@balance', 1)
    sendOSC('/GetP#(Master)@volume', 1)

Remark: in TouchOSC you can also create a (global) periodical function, fi to update a control like playposition. Herefor you need to call the 'time'-element of the device:

local time = getTime()
local miilisecs = getMillis()

In the next example we swant to receive the actual playpostion to calculate the elapsed and remain time of the track in Deck 1. If the Deck is not playing the interval between the updates can be longer than when the track is playing.
In the same example you can see the conversion of a string to a number 'tonumber())', the conversion of a number to a string 'tostring()', and the concatenate function ( .. ) as well as marking text as comment '--'
This script can be stored in a (Channel1)@playposition ' label coontrol.

local delay = 500
-- 500 = 1/2 second, 1000 = 1 second
local last = 0
local duration
local position 
local elapsed
local elapsedmin
local elapsedsec
local remain
local remainmin
local remainsec

function update()
  if self.parent.children['Ch1_Deckswitch'].values.x == 0 then
    if self.parent.children['(Channel1)@track_loaded'].values.text == '1' then
      local now = getMillis()
      if self.parent.children['(Channel1)@play'].values.x == 1 then
        if(now - last > delay) then
          last = now
          sendOSC('/GetP#(Channel1)@playposition', 1)
        end
      else
        if(now - last > delay * 5) then
          last = now
          --sendOSC('/GetP#(Channel1)@track_loaded', 1)
          sendOSC('/GetP#(Channel1)@playposition', 1)
        end 
      end
      self.parent.children['Ch1_position'].values.x = tonumber(self.values.text)
      duration = tonumber(self.parent.children['(Channel1)@duration'].values.text)
      position = tonumber(self.values.text)
  
      elapsed = duration * position
      elapsedmin = math.floor(elapsed / 60)
      elapsedsec = math.floor(elapsed - (elapsedmin * 60))
    
      remain = duration * (1 - position)
      remainmin = math.floor(remain / 60)
      remainsec = math.floor(remain - (remainmin * 60))
    else
      elapsedmin = 0
      elapsedsec = 0
      remainmin = 0
      remainsec = 0
    end

    if elapsedsec < 10 then
      self.parent.children['Ch1_Elapsed'].values.text = tostring(elapsedmin) .. ':0' .. tostring(elapsedsec)
    else 
      self.parent.children['Ch1_Elapsed'].values.text = tostring(elapsedmin) .. ':' .. tostring(elapsedsec)
    end
    if remainsec < 10 then
      self.parent.children['Ch1_Remain'].values.text = tostring(remainmin) .. ':0' .. tostring(remainsec)
    else 
      self.parent.children['Ch1_Remain'].values.text = tostring(remainmin) .. ':' .. tostring(remainsec)
    end   
  end 
end

Example: combination of print (to view received values in script window combined with a loo:

function onReceiveOSC(message, connections)
  local path = message[1]
  local arguments = message[2]
  for i=1,#arguments do
    print('\t path        =', path)
    print('\t argument    =', arguments[i .tag, arguments[i].value)
  end
end

Remark: in Mixxx we only send one argument in each OSC message (package), in other words: we send a new package for each value. So the example above will have only 1 argument in Mixxx - OSC.

This was referenced Nov 5, 2024
@Michael-Z-Freeman
Copy link

Michael-Z-Freeman commented Nov 5, 2024

Still crashes.

Relevant line?:

9 Mixxx 0x103beb31c UdpSocket::Implementation::Bind(IpEndpointName const&) + 208

I did try making sure the port numbers matched TouchOSC.

-------------------------------------
Translated Report (Full Report Below)
-------------------------------------

Process:               Mixxx [40028]
Path:                  /Applications/Mixxx.app/Contents/MacOS/Mixxx
Identifier:            org.mixxx.mixxx
Version:               2.6.0 (2.6.0)
Code Type:             ARM-64 (Native)
Parent Process:        launchd [1]
User ID:               501

Date/Time:             2024-11-05 15:19:37.3767 +0000
OS Version:            macOS 15.1 (24B83)
Report Version:        12
Anonymous UUID:        F8168C04-52A7-BAA0-BB7C-E4B896C8C75D

Sleep/Wake UUID:       8BFA3751-3622-49E7-9F66-BCE233E3340B

Time Awake Since Boot: 390000 seconds
Time Since Wake:       2082 seconds

System Integrity Protection: enabled

Crashed Thread:        5

Exception Type:        EXC_CRASH (SIGABRT)
Exception Codes:       0x0000000000000000, 0x0000000000000000

Termination Reason:    Namespace SIGNAL, Code 6 Abort trap: 6
Terminating Process:   Mixxx [40028]

Application Specific Information:
abort() called


Thread 0::  Dispatch queue: com.apple.main-thread
0   dyld                          	       0x183ec4640 invocation function for block in dyld4::RuntimeState::setUpTLVs(dyld3::MachOAnalyzer const*) + 44
1   dyld                          	       0x183f0bf40 void dyld3::MachOAnalyzer::forEachThreadLocalVariableInSection<long long>(Diagnostics&, dyld3::MachOFile::SectionInfo const&, void (void* (*)(dyld3::MachOAnalyzer::TLV_Thunk*) __ptrauth<0u, false, 0u>*, unsigned long*) block_pointer) const + 104
2   dyld                          	       0x183efdc38 invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 496
3   dyld                          	       0x183eb02dc dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const + 300
4   dyld                          	       0x183efcbcc dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const + 192
5   dyld                          	       0x183f0bda0 dyld3::MachOAnalyzer::forEachThreadLocalVariable(Diagnostics&, void (void* (*)(dyld3::MachOAnalyzer::TLV_Thunk*) __ptrauth<0u, false, 0u>*, unsigned long*) block_pointer) const + 208
6   dyld                          	       0x183ec4578 dyld4::RuntimeState::setUpTLVs(dyld3::MachOAnalyzer const*) + 308
7   dyld                          	       0x183eecd28 dyld4::APIs::dlopen_from(char const*, int, void*)::$_0::operator()() const + 1716
8   dyld                          	       0x183ee4360 dyld4::APIs::dlopen_from(char const*, int, void*) + 1092
9   SoftLinking                   	       0x191cfabd8 _sl_dlopen + 100
10  AppKit                        	       0x18866d7c0 WritingToolsUILibraryCore + 156
11  AppKit                        	       0x18866318c +[NSTextView(NSTextView_WritingTools) _supportsWritingTools] + 28
12  AppKit                        	       0x187e3c270 -[NSApplication(NSMenuUpdating) _addTextInputMenuItems:] + 124
13  AppKit                        	       0x187e3c198 -[NSApplication(NSMenuUpdating) _customizeMainMenu] + 36
14  AppKit                        	       0x187e3ae84 -[NSApplication finishLaunching] + 588
15  AppKit                        	       0x187e3a9fc -[NSApplication run] + 252
16  Mixxx                         	       0x1038cd884 QCocoaEventDispatcherPrivate::ensureNSAppInitialized() + 300
17  Mixxx                         	       0x1038cc87c QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>) + 576
18  Mixxx                         	       0x102b50038 main + 3124

Thread 1:
0   libsystem_pthread.dylib       	       0x1842320e8 start_wqthread + 0

Thread 2:
0   libsystem_pthread.dylib       	       0x1842320e8 start_wqthread + 0

Thread 3:
0   libsystem_pthread.dylib       	       0x1842320e8 start_wqthread + 0

Thread 4:
0   libsystem_pthread.dylib       	       0x1842320e8 start_wqthread + 0

Thread 5 Crashed:
0   libsystem_kernel.dylib        	       0x1841fe600 __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x184236f70 pthread_kill + 288
2   libsystem_c.dylib             	       0x184143908 abort + 128
3   libc++abi.dylib               	       0x1841ed44c abort_message + 132
4   libc++abi.dylib               	       0x1841dba24 demangling_terminate_handler() + 320
5   libobjc.A.dylib               	       0x183e813f4 _objc_terminate() + 172
6   libc++abi.dylib               	       0x1841ec710 std::__terminate(void (*)()) + 16
7   libc++abi.dylib               	       0x1841efcdc __cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 88
8   libc++abi.dylib               	       0x1841efc84 __cxa_throw + 92
9   Mixxx                         	       0x103beb31c UdpSocket::Implementation::Bind(IpEndpointName const&) + 208
10  libsystem_pthread.dylib       	       0x1842320fc thread_start + 8


Thread 5 crashed with ARM Thread State (64-bit):
    x0: 0x0000000000000000   x1: 0x0000000000000000   x2: 0x0000000000000000   x3: 0x0000000000000000
    x4: 0x00000001841f1dec   x5: 0x000000016d5fedf0   x6: 0x000000000000000a   x7: 0x0000000000000270
    x8: 0x77f3f5720fd204a8   x9: 0x77f3f573628df4a8  x10: 0x000000000000003d  x11: 0x000000000000001a
   x12: 0x000000000000001a  x13: 0x0000600003deec98  x14: 0x00000000001ff800  x15: 0x00000000000007fb
   x16: 0x0000000000000148  x17: 0x00000001f15a9850  x18: 0x0000000000000000  x19: 0x0000000000000006
   x20: 0x000000000000a00b  x21: 0x000000016d5ff0e0  x22: 0x0000000108f414b0  x23: 0x00006000029c3164
   x24: 0x0000000000000000  x25: 0x0000000000000000  x26: 0x0000000000000000  x27: 0x0000000000000000
   x28: 0x0000000000000000   fp: 0x000000016d5fed60   lr: 0x0000000184236f70
    sp: 0x000000016d5fed40   pc: 0x00000001841fe600 cpsr: 0x40001000
   far: 0x0000000000000000  esr: 0x56000080  Address size fault

Binary Images:
       0x102b44000 -        0x108f0ffff org.mixxx.mixxx (2.6.0) <ec03ac6f-882f-393d-84fe-b26af28a27a6> /Applications/Mixxx.app/Contents/MacOS/Mixxx
       0x10d8b8000 -        0x10d8d7fff com.apple.security.csparser (3.0) <db365164-e7d4-3315-a4bf-a306666f29d7> /System/Library/Frameworks/Security.framework/Versions/A/PlugIns/csparser.bundle/Contents/MacOS/csparser
       0x1177e0000 -        0x117847fff com.apple.AppleMetalOpenGLRenderer (1.0) <cf2a5428-9317-35dd-847f-f1d1970961a0> /System/Library/Extensions/AppleMetalOpenGLRenderer.bundle/Contents/MacOS/AppleMetalOpenGLRenderer
       0x1189fc000 -        0x119097fff com.apple.AGXMetal13-3 (322.10) <25ed3810-fd45-3e81-8e80-5161e3d9d8a9> /System/Library/Extensions/AGXMetal13_3.bundle/Contents/MacOS/AGXMetal13_3
       0x118730000 -        0x11873bfff libobjc-trampolines.dylib (*) <f1242604-dcb7-30a9-a19a-182991e6e645> /usr/lib/libobjc-trampolines.dylib
       0x183eae000 -        0x183f307b3 dyld (*) <6beafde4-b011-3e47-8aae-4d7b6e4bb7e8> /usr/lib/dyld
       0x191cfa000 -        0x191cfaffb com.apple.SoftLinking (1.0) <4289476e-9d27-38fe-8608-69077b6c79bf> /System/Library/PrivateFrameworks/SoftLinking.framework/Versions/A/SoftLinking
       0x187e0d000 -        0x189208fff com.apple.AppKit (6.9) <49d8b1b6-0ea8-36ad-89fd-a41acf00a742> /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit
               0x0 - 0xffffffffffffffff ??? (*) <00000000-0000-0000-0000-000000000000> ???
       0x19739f000 -        0x198f27fff com.apple.GeoServices (1.0) <e672ac74-dff7-3681-95ae-58b57020993e> /System/Library/PrivateFrameworks/GeoServices.framework/Versions/A/GeoServices
       0x184230000 -        0x18423cfff libsystem_pthread.dylib (*) <3b8268be-4e02-3b4a-8b41-baed2bbaacff> /usr/lib/system/libsystem_pthread.dylib
       0x1841f5000 -        0x18422fff7 libsystem_kernel.dylib (*) <9fea25a4-e8ca-3f3d-901c-a53ff2bc7217> /usr/lib/system/libsystem_kernel.dylib
       0x1840ca000 -        0x18414bffb libsystem_c.dylib (*) <96556ba0-9c34-326a-89f4-d3835de617ae> /usr/lib/system/libsystem_c.dylib
       0x1841da000 -        0x1841f4fff libc++abi.dylib (*) <7de440df-bc7d-3ff3-905d-2e17a7629449> /usr/lib/libc++abi.dylib
       0x183e5c000 -        0x183eadca3 libobjc.A.dylib (*) <219c0324-7a4f-338e-a395-3d023b289a7f> /usr/lib/libobjc.A.dylib

External Modification Summary:
  Calls made by other processes targeting this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by this process:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0
  Calls made by all processes on this machine:
    task_for_pid: 0
    thread_create: 0
    thread_set_state: 0

VM Region Summary:
ReadOnly portion of Libraries: Total=1.2G resident=0K(0%) swapped_out_or_unallocated=1.2G(100%)
Writable regions: Total=985.2M written=578K(0%) resident=578K(0%) swapped_out=0K(0%) unallocated=984.6M(100%)

                                VIRTUAL   REGION 
REGION TYPE                        SIZE    COUNT (non-coalesced) 
===========                     =======  ======= 
Activity Tracing                   256K        1 
ColorSync                          496K       25 
CoreGraphics                        16K        1 
Foundation                          16K        1 
Kernel Alloc Once                   32K        1 
MALLOC                           959.4M       43 
MALLOC guard page                  288K       18 
STACK GUARD                       56.1M        6 
Stack                             10.7M        7 
VM_ALLOCATE                        128K        5 
__AUTH                            2290K      351 
__AUTH_CONST                      34.9M      540 
__CTF                               824        1 
__DATA                            24.6M      521 
__DATA_CONST                      18.7M      547 
__DATA_DIRTY                      1249K      163 
__FONT_DATA                        2352        1 
__GLSLBUILTINS                    5174K        1 
__LINKEDIT                       610.1M        6 
__OBJC_RW                         2354K        1 
__TEXT                           625.1M      561 
__TPRO_CONST                       272K        2 
mapped file                      206.8M       25 
owned unmapped memory               48K        1 
page table in kernel               578K        1 
shared memory                      864K       13 
===========                     =======  ======= 
TOTAL                              2.5G     2843 



-----------
Full Report
-----------

{"app_name":"Mixxx","timestamp":"2024-11-05 15:19:40.00 +0000","app_version":"2.6.0","slice_uuid":"ec03ac6f-882f-393d-84fe-b26af28a27a6","build_version":"2.6.0","platform":1,"bundleID":"org.mixxx.mixxx","share_with_app_devs":1,"is_first_party":0,"bug_type":"309","os_version":"macOS 15.1 (24B83)","roots_installed":0,"name":"Mixxx","incident_id":"ECB2D66E-C3F6-4660-9926-EEE3C8343FD9"}
{
  "uptime" : 390000,
  "procRole" : "Foreground",
  "version" : 2,
  "userID" : 501,
  "deployVersion" : 210,
  "modelCode" : "MacBookAir10,1",
  "coalitionID" : 73862,
  "osVersion" : {
    "train" : "macOS 15.1",
    "build" : "24B83",
    "releaseType" : "User"
  },
  "captureTime" : "2024-11-05 15:19:37.3767 +0000",
  "codeSigningMonitor" : 1,
  "incident" : "ECB2D66E-C3F6-4660-9926-EEE3C8343FD9",
  "pid" : 40028,
  "translated" : false,
  "cpuType" : "ARM-64",
  "roots_installed" : 0,
  "bug_type" : "309",
  "procLaunch" : "2024-11-05 15:19:36.8229 +0000",
  "procStartAbsTime" : 9456388843976,
  "procExitAbsTime" : 9456400675349,
  "procName" : "Mixxx",
  "procPath" : "\/Applications\/Mixxx.app\/Contents\/MacOS\/Mixxx",
  "bundleInfo" : {"CFBundleShortVersionString":"2.6.0","CFBundleVersion":"2.6.0","CFBundleIdentifier":"org.mixxx.mixxx"},
  "storeInfo" : {"deviceIdentifierForVendor":"96981D0A-F06A-5C54-A420-2D39164F39F1","thirdParty":true},
  "parentProc" : "launchd",
  "parentPid" : 1,
  "coalitionName" : "org.mixxx.mixxx",
  "crashReporterKey" : "F8168C04-52A7-BAA0-BB7C-E4B896C8C75D",
  "codeSigningID" : "org.mixxx.mixxx",
  "codeSigningTeamID" : "",
  "codeSigningFlags" : 570425857,
  "codeSigningValidationCategory" : 10,
  "codeSigningTrustLevel" : 4294967295,
  "instructionByteStream" : {"beforePC":"fyMD1f17v6n9AwCRcuD\/l78DAJH9e8Go\/w9f1sADX9YQKYDSARAA1A==","atPC":"AwEAVH8jA9X9e7+p\/QMAkWfg\/5e\/AwCR\/XvBqP8PX9bAA1\/WcAqA0g=="},
  "bootSessionUUID" : "4FD08291-BC15-4505-9F3F-5867415EEC8B",
  "wakeTime" : 2082,
  "sleepWakeUUID" : "8BFA3751-3622-49E7-9F66-BCE233E3340B",
  "sip" : "enabled",
  "exception" : {"codes":"0x0000000000000000, 0x0000000000000000","rawCodes":[0,0],"type":"EXC_CRASH","signal":"SIGABRT"},
  "termination" : {"flags":0,"code":6,"namespace":"SIGNAL","indicator":"Abort trap: 6","byProc":"Mixxx","byPid":40028},
  "asi" : {"libsystem_c.dylib":["abort() called"]},
  "extMods" : {"caller":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"system":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"targeted":{"thread_create":0,"thread_set_state":0,"task_for_pid":0},"warnings":0},
  "faultingThread" : 5,
  "threads" : [{"id":7660997,"threadState":{"x":[{"value":6126540304},{"value":8213572608,"symbolLocation":0,"symbol":"google::protobuf::internal::ArenaImpl::thread_cache_"},{"value":8213572616,"symbolLocation":8,"symbol":"google::protobuf::internal::ArenaImpl::thread_cache_"},{"value":0},{"value":0},{"value":0},{"value":7665811997138777455},{"value":0},{"value":6508267028,"symbolLocation":0,"symbol":"invocation function for block in dyld4::RuntimeState::setUpTLVs(dyld3::MachOAnalyzer const*)"},{"value":24},{"value":64913408},{"value":0},{"value":0},{"value":324759552},{"value":28872704},{"value":4706897090},{"value":6508500936,"symbolLocation":0,"symbol":"invocation function for block in dyld3::MachOFile::forEachSegment(void (dyld3::MachOFile::SegmentInfo const&, bool&) block_pointer) const"},{"value":7701436843906798088},{"value":0},{"value":8213572608,"symbolLocation":0,"symbol":"google::protobuf::internal::ArenaImpl::thread_cache_"},{"value":6126540304},{"value":8213572616,"symbolLocation":8,"symbol":"google::protobuf::internal::ArenaImpl::thread_cache_"},{"value":6126540320},{"value":8204797072,"symbolLocation":1088,"symbol":"dyld4::preallocator"},{"value":6832127104},{"value":6832130128},{"value":6126539920},{"value":6832127184},{"value":6126544448}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6508560192},"cpsr":{"value":1610616832},"fp":{"value":6126539504},"sp":{"value":6126539440},"esr":{"value":2449473543,"description":"(Data Abort) byte read Translation fault"},"pc":{"value":6508267072},"far":{"value":8213572616}},"queue":"com.apple.main-thread","frames":[{"imageOffset":91712,"symbol":"invocation function for block in dyld4::RuntimeState::setUpTLVs(dyld3::MachOAnalyzer const*)","symbolLocation":44,"imageIndex":5},{"imageOffset":384832,"symbol":"void dyld3::MachOAnalyzer::forEachThreadLocalVariableInSection<long long>(Diagnostics&, dyld3::MachOFile::SectionInfo const&, void (void* (*)(dyld3::MachOAnalyzer::TLV_Thunk*) __ptrauth<0u, false, 0u>*, unsigned long*) block_pointer) const","symbolLocation":104,"imageIndex":5},{"imageOffset":326712,"symbol":"invocation function for block in dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const","symbolLocation":496,"imageIndex":5},{"imageOffset":8924,"symbol":"dyld3::MachOFile::forEachLoadCommand(Diagnostics&, void (load_command const*, bool&) block_pointer) const","symbolLocation":300,"imageIndex":5},{"imageOffset":322508,"symbol":"dyld3::MachOFile::forEachSection(void (dyld3::MachOFile::SectionInfo const&, bool, bool&) block_pointer) const","symbolLocation":192,"imageIndex":5},{"imageOffset":384416,"symbol":"dyld3::MachOAnalyzer::forEachThreadLocalVariable(Diagnostics&, void (void* (*)(dyld3::MachOAnalyzer::TLV_Thunk*) __ptrauth<0u, false, 0u>*, unsigned long*) block_pointer) const","symbolLocation":208,"imageIndex":5},{"imageOffset":91512,"symbol":"dyld4::RuntimeState::setUpTLVs(dyld3::MachOAnalyzer const*)","symbolLocation":308,"imageIndex":5},{"imageOffset":257320,"symbol":"dyld4::APIs::dlopen_from(char const*, int, void*)::$_0::operator()() const","symbolLocation":1716,"imageIndex":5},{"imageOffset":222048,"symbol":"dyld4::APIs::dlopen_from(char const*, int, void*)","symbolLocation":1092,"imageIndex":5},{"imageOffset":3032,"symbol":"_sl_dlopen","symbolLocation":100,"imageIndex":6},{"imageOffset":8783808,"symbol":"WritingToolsUILibraryCore","symbolLocation":156,"imageIndex":7},{"imageOffset":8741260,"symbol":"+[NSTextView(NSTextView_WritingTools) _supportsWritingTools]","symbolLocation":28,"imageIndex":7},{"imageOffset":193136,"symbol":"-[NSApplication(NSMenuUpdating) _addTextInputMenuItems:]","symbolLocation":124,"imageIndex":7},{"imageOffset":192920,"symbol":"-[NSApplication(NSMenuUpdating) _customizeMainMenu]","symbolLocation":36,"imageIndex":7},{"imageOffset":188036,"symbol":"-[NSApplication finishLaunching]","symbolLocation":588,"imageIndex":7},{"imageOffset":186876,"symbol":"-[NSApplication run]","symbolLocation":252,"imageIndex":7},{"imageOffset":14194820,"symbol":"QCocoaEventDispatcherPrivate::ensureNSAppInitialized()","symbolLocation":300,"imageIndex":0},{"imageOffset":14190716,"symbol":"QCocoaEventDispatcher::processEvents(QFlags<QEventLoop::ProcessEventsFlag>)","symbolLocation":576,"imageIndex":0},{"imageOffset":49208,"symbol":"main","symbolLocation":3124,"imageIndex":0}]},{"id":7661010,"frames":[{"imageOffset":8424,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":10}],"threadState":{"x":[{"value":6127677440},{"value":6147},{"value":6127140864},{"value":0},{"value":409604},{"value":18446744073709551615},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":0},"cpsr":{"value":4096},"fp":{"value":0},"sp":{"value":6127677440},"esr":{"value":1442840704,"description":" Address size fault"},"pc":{"value":6511861992},"far":{"value":0}}},{"id":7661011,"frames":[{"imageOffset":8424,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":10}],"threadState":{"x":[{"value":6128250880},{"value":8195},{"value":6127714304},{"value":0},{"value":409604},{"value":18446744073709551615},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":0},"cpsr":{"value":4096},"fp":{"value":0},"sp":{"value":6128250880},"esr":{"value":1442840704,"description":" Address size fault"},"pc":{"value":6511861992},"far":{"value":0}}},{"id":7661017,"frames":[{"imageOffset":8424,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":10}],"threadState":{"x":[{"value":6128824320},{"value":30467},{"value":6128287744},{"value":0},{"value":409604},{"value":18446744073709551615},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":0},"cpsr":{"value":4096},"fp":{"value":0},"sp":{"value":6128824320},"esr":{"value":1442840704,"description":" Address size fault"},"pc":{"value":6511861992},"far":{"value":0}}},{"id":7661018,"frames":[{"imageOffset":8424,"symbol":"start_wqthread","symbolLocation":0,"imageIndex":10}],"threadState":{"x":[{"value":6129397760},{"value":0},{"value":6128861184},{"value":0},{"value":278532},{"value":18446744073709551615},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":0},"cpsr":{"value":4096},"fp":{"value":0},"sp":{"value":6129397760},"esr":{"value":0,"description":" Address size fault"},"pc":{"value":6511861992},"far":{"value":0}}},{"triggered":true,"id":7661035,"threadState":{"x":[{"value":0},{"value":0},{"value":0},{"value":0},{"value":6511599084},{"value":6129970672},{"value":10},{"value":624},{"value":8643521980094612648},{"value":8643521985777628328},{"value":61},{"value":26},{"value":26},{"value":105553181207704},{"value":2095104},{"value":2043},{"value":328},{"value":8344213584},{"value":0},{"value":6},{"value":40971},{"value":6129971424},{"value":4445181104,"symbolLocation":16,"symbol":"vtable for OscReceivePacketListener"},{"value":105553160057188},{"value":0},{"value":0},{"value":0},{"value":0},{"value":0}],"flavor":"ARM_THREAD_STATE64","lr":{"value":6511882096},"cpsr":{"value":1073745920},"fp":{"value":6129970528},"sp":{"value":6129970496},"esr":{"value":1442840704,"description":" Address size fault"},"pc":{"value":6511650304,"matchesCrashFrame":1},"far":{"value":0}},"frames":[{"imageOffset":38400,"symbol":"__pthread_kill","symbolLocation":8,"imageIndex":11},{"imageOffset":28528,"symbol":"pthread_kill","symbolLocation":288,"imageIndex":10},{"imageOffset":497928,"symbol":"abort","symbolLocation":128,"imageIndex":12},{"imageOffset":78924,"symbol":"abort_message","symbolLocation":132,"imageIndex":13},{"imageOffset":6692,"symbol":"demangling_terminate_handler()","symbolLocation":320,"imageIndex":13},{"imageOffset":152564,"symbol":"_objc_terminate()","symbolLocation":172,"imageIndex":14},{"imageOffset":75536,"symbol":"std::__terminate(void (*)())","symbolLocation":16,"imageIndex":13},{"imageOffset":89308,"symbol":"__cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*)","symbolLocation":88,"imageIndex":13},{"imageOffset":89220,"symbol":"__cxa_throw","symbolLocation":92,"imageIndex":13},{"imageOffset":17462044,"symbol":"UdpSocket::Implementation::Bind(IpEndpointName const&)","symbolLocation":208,"imageIndex":0},{"imageOffset":8444,"symbol":"thread_start","symbolLocation":8,"imageIndex":10}]}],
  "usedImages" : [
  {
    "source" : "P",
    "arch" : "arm64",
    "base" : 4340334592,
    "CFBundleShortVersionString" : "2.6.0",
    "CFBundleIdentifier" : "org.mixxx.mixxx",
    "size" : 104644608,
    "uuid" : "ec03ac6f-882f-393d-84fe-b26af28a27a6",
    "path" : "\/Applications\/Mixxx.app\/Contents\/MacOS\/Mixxx",
    "name" : "Mixxx",
    "CFBundleVersion" : "2.6.0"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 4522213376,
    "CFBundleShortVersionString" : "3.0",
    "CFBundleIdentifier" : "com.apple.security.csparser",
    "size" : 131072,
    "uuid" : "db365164-e7d4-3315-a4bf-a306666f29d7",
    "path" : "\/System\/Library\/Frameworks\/Security.framework\/Versions\/A\/PlugIns\/csparser.bundle\/Contents\/MacOS\/csparser",
    "name" : "csparser",
    "CFBundleVersion" : "61439.41.1.0.1"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 4689100800,
    "CFBundleShortVersionString" : "1.0",
    "CFBundleIdentifier" : "com.apple.AppleMetalOpenGLRenderer",
    "size" : 425984,
    "uuid" : "cf2a5428-9317-35dd-847f-f1d1970961a0",
    "path" : "\/System\/Library\/Extensions\/AppleMetalOpenGLRenderer.bundle\/Contents\/MacOS\/AppleMetalOpenGLRenderer",
    "name" : "AppleMetalOpenGLRenderer",
    "CFBundleVersion" : "1"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 4708089856,
    "CFBundleShortVersionString" : "322.10",
    "CFBundleIdentifier" : "com.apple.AGXMetal13-3",
    "size" : 6930432,
    "uuid" : "25ed3810-fd45-3e81-8e80-5161e3d9d8a9",
    "path" : "\/System\/Library\/Extensions\/AGXMetal13_3.bundle\/Contents\/MacOS\/AGXMetal13_3",
    "name" : "AGXMetal13_3",
    "CFBundleVersion" : "322.10"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 4705157120,
    "size" : 49152,
    "uuid" : "f1242604-dcb7-30a9-a19a-182991e6e645",
    "path" : "\/usr\/lib\/libobjc-trampolines.dylib",
    "name" : "libobjc-trampolines.dylib"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 6508175360,
    "size" : 534452,
    "uuid" : "6beafde4-b011-3e47-8aae-4d7b6e4bb7e8",
    "path" : "\/usr\/lib\/dyld",
    "name" : "dyld"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 6741270528,
    "CFBundleShortVersionString" : "1.0",
    "CFBundleIdentifier" : "com.apple.SoftLinking",
    "size" : 4092,
    "uuid" : "4289476e-9d27-38fe-8608-69077b6c79bf",
    "path" : "\/System\/Library\/PrivateFrameworks\/SoftLinking.framework\/Versions\/A\/SoftLinking",
    "name" : "SoftLinking",
    "CFBundleVersion" : "58"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 6574624768,
    "CFBundleShortVersionString" : "6.9",
    "CFBundleIdentifier" : "com.apple.AppKit",
    "size" : 20955136,
    "uuid" : "49d8b1b6-0ea8-36ad-89fd-a41acf00a742",
    "path" : "\/System\/Library\/Frameworks\/AppKit.framework\/Versions\/C\/AppKit",
    "name" : "AppKit",
    "CFBundleVersion" : "2575.20.21"
  },
  {
    "size" : 0,
    "source" : "A",
    "base" : 0,
    "uuid" : "00000000-0000-0000-0000-000000000000"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 6832123904,
    "CFBundleShortVersionString" : "1.0",
    "CFBundleIdentifier" : "com.apple.GeoServices",
    "size" : 28872704,
    "uuid" : "e672ac74-dff7-3681-95ae-58b57020993e",
    "path" : "\/System\/Library\/PrivateFrameworks\/GeoServices.framework\/Versions\/A\/GeoServices",
    "name" : "GeoServices",
    "CFBundleVersion" : "1986.21.7.31.10"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 6511853568,
    "size" : 53248,
    "uuid" : "3b8268be-4e02-3b4a-8b41-baed2bbaacff",
    "path" : "\/usr\/lib\/system\/libsystem_pthread.dylib",
    "name" : "libsystem_pthread.dylib"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 6511611904,
    "size" : 241656,
    "uuid" : "9fea25a4-e8ca-3f3d-901c-a53ff2bc7217",
    "path" : "\/usr\/lib\/system\/libsystem_kernel.dylib",
    "name" : "libsystem_kernel.dylib"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 6510387200,
    "size" : 532476,
    "uuid" : "96556ba0-9c34-326a-89f4-d3835de617ae",
    "path" : "\/usr\/lib\/system\/libsystem_c.dylib",
    "name" : "libsystem_c.dylib"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 6511501312,
    "size" : 110592,
    "uuid" : "7de440df-bc7d-3ff3-905d-2e17a7629449",
    "path" : "\/usr\/lib\/libc++abi.dylib",
    "name" : "libc++abi.dylib"
  },
  {
    "source" : "P",
    "arch" : "arm64e",
    "base" : 6507839488,
    "size" : 335012,
    "uuid" : "219c0324-7a4f-338e-a395-3d023b289a7f",
    "path" : "\/usr\/lib\/libobjc.A.dylib",
    "name" : "libobjc.A.dylib"
  }
],
  "sharedCache" : {
  "base" : 6507364352,
  "size" : 4753752064,
  "uuid" : "58694c6f-fec3-316e-a11c-b2fa3c2f6559"
},
  "vmSummary" : "ReadOnly portion of Libraries: Total=1.2G resident=0K(0%) swapped_out_or_unallocated=1.2G(100%)\nWritable regions: Total=985.2M written=578K(0%) resident=578K(0%) swapped_out=0K(0%) unallocated=984.6M(100%)\n\n                                VIRTUAL   REGION \nREGION TYPE                        SIZE    COUNT (non-coalesced) \n===========                     =======  ======= \nActivity Tracing                   256K        1 \nColorSync                          496K       25 \nCoreGraphics                        16K        1 \nFoundation                          16K        1 \nKernel Alloc Once                   32K        1 \nMALLOC                           959.4M       43 \nMALLOC guard page                  288K       18 \nSTACK GUARD                       56.1M        6 \nStack                             10.7M        7 \nVM_ALLOCATE                        128K        5 \n__AUTH                            2290K      351 \n__AUTH_CONST                      34.9M      540 \n__CTF                               824        1 \n__DATA                            24.6M      521 \n__DATA_CONST                      18.7M      547 \n__DATA_DIRTY                      1249K      163 \n__FONT_DATA                        2352        1 \n__GLSLBUILTINS                    5174K        1 \n__LINKEDIT                       610.1M        6 \n__OBJC_RW                         2354K        1 \n__TEXT                           625.1M      561 \n__TPRO_CONST                       272K        2 \nmapped file                      206.8M       25 \nowned unmapped memory               48K        1 \npage table in kernel               578K        1 \nshared memory                      864K       13 \n===========                     =======  ======= \nTOTAL                              2.5G     2843 \n",
  "legacyInfo" : {
  "threadTriggered" : {

  }
},
  "logWritingSignature" : "3e56e1b8ebc001b96975d42bb73b59d1ee1a4552",
  "trialInfo" : {
  "rollouts" : [
    {
      "rolloutId" : "652eff3d1bce5442b8d753c9",
      "factorPackIds" : {

      },
      "deploymentId" : 240000009
    },
    {
      "rolloutId" : "64b21a7351cbb02ce3442e4e",
      "factorPackIds" : {
        "REMINDERS_GROCERY" : "6647f0f7b6a75d3dc32993e7"
      },
      "deploymentId" : 240000042
    }
  ],
  "experiments" : [
    {
      "treatmentId" : "45f4e2a5-551b-4bc2-a2dc-19c244dda8f8",
      "experimentId" : "6643969b3099cf28e049862f",
      "deploymentId" : 400000007
    }
  ]
}
}

Model: MacBookAir10,1, BootROM 11881.41.5, proc 8:4:4 processors, 8 GB, SMC 
Graphics: Apple M1, Apple M1, Built-In
Display: Color LCD, 2560 x 1600 Retina, Main, MirrorOff, Online
Memory Module: LPDDR4, Hynix
AirPort: spairport_wireless_card_type_wifi (0x14E4, 0x4378), wl0: Jul 26 2024 20:49:57 version 18.20.458.0.7.8.173 FWID 01-544d6458
IO80211_driverkit-1315.7 "IO80211_driverkit-1315.7" Sep 28 2024 16:04:40
AirPort: 
Bluetooth: Version (null), 0 services, 0 devices, 0 incoming serial ports
Network Service: Wi-Fi, AirPort, en0
USB Device: USB31Bus
USB Device: SanDisk 3.2 Gen1
USB Device: USB31Bus
USB Device: USB3.2 Hub
USB Device: USB3.2 Hub
USB Device: AX88179A
USB Device: NS1081
USB Device: USB2.1 Hub
USB Device: USB2.1 Hub
USB Device: iPhone
USB Device: USB 2.0 Hub
USB Device: USB 2.0 BILLBOARD
Thunderbolt Bus: MacBook Air, Apple Inc.
Thunderbolt Bus: MacBook Air, Apple Inc.

@ArthurVimond
Copy link

ArthurVimond commented Jan 14, 2025

@Eve00000
It's still crashing on macOS arm64 with the following trace:

Thread 6 Crashed:
0   libsystem_kernel.dylib        	       0x18574ea60 __pthread_kill + 8
1   libsystem_pthread.dylib       	       0x185786c20 pthread_kill + 288
2   libsystem_c.dylib             	       0x185693a30 abort + 180
3   libc++abi.dylib               	       0x18573dd08 abort_message + 132
4   libc++abi.dylib               	       0x18572dfa4 demangling_terminate_handler() + 320
5   libobjc.A.dylib               	       0x1853cc1e0 _objc_terminate() + 160
6   libc++abi.dylib               	       0x18573d0cc std::__terminate(void (*)()) + 16
7   libc++abi.dylib               	       0x185740348 __cxxabiv1::failed_throw(__cxxabiv1::__cxa_exception*) + 88
8   libc++abi.dylib               	       0x18574028c __cxa_throw + 308
9   Mixxx                         	       0x1015a85a8 UdpSocket::Implementation::Bind(IpEndpointName const&) + 208
10  libsystem_pthread.dylib       	       0x185781d34 thread_start + 8

@Eve00000
Copy link
Contributor Author

@Eve00000 It's still crashing on macOS arm64 with the following trace:
Thread 6 Crashed:
6 libc++abi.dylib 0x18573d0cc std::__terminate(void (*)()) + 16

I 'm sure thread #9 is from osc but I'm not that sure about #6
To rule out other things: is the official MacOS 13 arm64 download working fine ?

@ArthurVimond
Copy link

Yes, that's why I mentioned the vcpkg config on CI last time. I will try to find some differences between my local build and the one from GitHub Actions.
But for additional information, I also have a Macbook Intel and I tried the GitHub Actions build for macOS Intel on this PR, and it also crashed. Just to say that I'm not 100% sure it's related to architecture (mac Silicon or Intel).

@Eve00000
Copy link
Contributor Author

Eve00000 commented Jan 14, 2025

For a starter, you could check if indeed the same vcpkg is used and compare the build flags of the CI with those of the 'home build'. (sorry, I'm not familiar with vcpkg and building on macOS or Windows)

Yes, YDUC. And I can do better (worse) then you @ronso0 : I am not familiar with vcpkg at all :-(
I did test the intel build in a macOS vm and it worked fine, I also tested the 2.5 version on mac vm before the Xmas launch . I 'll schedule a new test, but it 'll be in a vm as well (as I don't have any mac anymore). And so I'll need to create a fresh one again.
I think @ArthurVimond is very good in vcpkg and mac building (see the app etc), so I think we'll find the solutions by comparing.

@daschuer
Copy link
Member

Regarding vcpkg, this is (still) based on oscpack.
A while a go we have integrated liblo an alternative OSC library to our vcpkg environment.

You put here a oscpack into the lib folder which will be likely ripped of by the distro maintainers anyway. So let's move that also to vcpkg. It is part of Ubuntu already. I will have a look.

Or do we want liblo anyway. Do whe have a view what pros and cons are. Do you?

@daschuer
Copy link
Member

This is what chat-gpt recommends:

Both liblo and oscpack are libraries for implementing the Open Sound Control (OSC) protocol, but they have key differences that might influence your decision on which to use for adding OSC support to Mixxx.

1. General Overview

liblo (Lightweight OSC)

  • Language: C library.

  • Platform: Cross-platform, but primarily focused on Linux and macOS.

  • Features:

    • Implements OSC 1.0 and parts of 1.1.
    • Provides both client and server functionality.
    • Designed to be straightforward and lightweight.
    • Provides type safety and easy handling of OSC messages.
    • Handles low-level network operations for you (UDP, TCP).
  • Pros:

    • Well-documented and stable.
    • Easy to use for both sending and receiving OSC messages.
    • Minimal code required to set up.
    • Active and widely used in the Linux audio community.
  • Cons:

    • Written in C, which may require more care with memory management compared to C++.
    • Less flexible for custom network handling compared to oscpack.

oscpack

  • Language: C++ library.

  • Platform: Cross-platform, works on Linux, macOS, and Windows.

  • Features:

    • Implements core OSC features.
    • Designed to be modular and flexible.
    • Focuses on decoding/encoding OSC messages and lets you handle networking separately.
    • Works well in environments where you want more control over the networking layer.
  • Pros:

    • Written in modern C++, making it easier to integrate into C++ projects like Mixxx.
    • Allows fine-grained control over how OSC messages are sent or received.
    • Lightweight and simple for basic use cases.
  • Cons:

    • Networking is not built-in; you need to implement it yourself (e.g., using BSD sockets or another library like Boost).
    • Slightly less user-friendly for quick prototyping.

2. Comparison for Adding OSC to Mixxx

Ease of Integration

  • liblo: Simpler to set up due to built-in networking support. You can create an OSC server or client in just a few lines of code.
  • oscpack: Requires more effort since you must implement the networking stack, but this could provide greater flexibility if Mixxx needs advanced control over networking.

Language and Compatibility

  • Mixxx is primarily written in C++:
    • oscpack aligns better with C++ projects due to its modern C++ API.
    • liblo is in C, so you might need to write wrappers or deal with C-style integration in your C++ codebase.

Performance

  • liblo: Efficient and optimized for typical OSC use cases, with built-in handling of UDP/TCP.
  • oscpack: Offers similar performance for encoding/decoding but might introduce extra overhead if you implement networking inefficiently.

Networking Requirements

  • If Mixxx's OSC implementation will involve custom protocols or unusual networking setups, oscpack may be a better choice due to its modularity.
  • For standard OSC over UDP/TCP, liblo is faster to implement.

3. Recommendation

For a standard OSC implementation with minimal effort:

  • Use liblo: Its built-in networking and simplicity make it ideal for quick integration.

For more flexibility or if Mixxx requires deep integration with C++ features or custom networking:

  • Use oscpack: Its modular design and C++ orientation might fit better with Mixxx's architecture, though it requires more initial setup.

If you need specific features like multicast, or need deeper examples, I can provide guidance or snippets for both libraries. Let me know!

@Eve00000
Copy link
Contributor Author

Eve00000 commented Jan 14, 2025

Wow, I think @daschuer has a direct connection with chatgpt or maybe shares in OpenAI 😃

As I've written earlier: I have made the choice for OSCPack as I can understand the code in it, I understand the flow and the reason for the different procedures (so you will certainly understand it). I have major problems with liblo.
And as GPT writes: with liblo the convertion of the osc-packages to the CO's in Mixxx would be much harder, with OSCPack I managed to adapt the OSCthings.

You put here a oscpack into the lib folder which will be likely ripped of by the distro maintainers anyway. So let's move that also to vcpkg. It is part of Ubuntu already. I will have a look.
Or do we want liblo anyway. Do whe have a view what pros and cons are. Do you?

As I mentioned before I would take a deeper look at liblo again, but this would be when I have lots of time (and motivation, courage and nothing better to do). On my wish- and workinglist are: smarties/ grouped crates / preparation crates + pannel
Concerning vcpkg, distros and distro maintainers.... I am a real nitwit, I am just stubborn enough to continue searching, reading, observing, studying and analyzing code to find a nice working solution for a problem/question.
__

It's nice to have a comparison, but the comparison is made at the stage there isn't yet one of them both implemented.

So this is what ChatGPT answers on the question 'Can you make a comparison between OSCPACK and liblo to integrate osc in mixxx, with the knowledge that there is already a working implementation of oscpack in mixxx.'

Here’s a comparison of oscpack and liblo for integrating OSC (Open Sound Control) in Mixxx, considering that Mixxx already has a working implementation using oscpack:

  1. Overview
Aspect oscpack liblo
Purpose A lightweight library for handling OSC messages. A full-featured library for OSC messaging.
Language Written in C++. Written in C, with C++ bindings available.
License BSD-style license (permissive). GNU GPL or LGPL (less permissive than oscpack).
Dependencies Minimal dependencies (self-contained). Relies on standard libraries and sockets but adds features like threading.
  1. Features
Aspect oscpack liblo
Protocol Support OSC over UDP. OSC over UDP, TCP, and Unix domain sockets.
Message Parsing Simple and efficient parsing for OSC messages. Advanced parsing with type tags and message introspection.
Address Patterns Supports basic wildcard matching for addresses. Supports advanced OSC address patterns and wildcards.
Client/Server Support Provides both sending and receiving capabilities. Provides robust server and client implementations.
Thread Safety Thread-safety must be implemented externally. Built-in thread-safe features for message handling.
Ease of Use Lightweight and straightforward. Comprehensive but might have a steeper learning curve.
  1. Integration in Mixxx
Aspect oscpack liblo
Existing Code Already integrated into Mixxx. New implementation required, involving significant refactoring.
Compatibility Mixxx’s current use aligns well with oscpack’s features. liblo offers features beyond current needs but might complicate existing implementation.
Performance High-performance due to lightweight nature. Comparable performance; added features may slightly increase overhead.
Extensibility Limited to basic OSC messaging features. Extensible, supporting advanced OSC features like TCP and introspection.
  1. Pros and Cons
    oscpack Pros
  • Already implemented and functioning in Mixxx.
  • Lightweight with minimal overhead.
  • Simple and sufficient for typical OSC needs.
  • Permissive licensing (BSD).
    oscpack Cons
  • Lacks advanced features like TCP support.
  • Requires additional implementation for thread safety.

liblo Pros

  • Comprehensive support for OSC features (TCP, advanced patterns).
  • Thread-safe message handling out of the box.
  • Active in projects requiring complex OSC setups.
    liblo Cons
  • More complex to integrate into the existing codebase.
  • GPL/LGPL licensing may impose restrictions compared to oscpack’s BSD license.
  • Adds features Mixxx might not need, leading to unnecessary complexity.
  1. Recommendation
    Given that Mixxx already has a working implementation with oscpack, it’s advisable to continue with oscpack unless:

    There is a strong need for features only offered by liblo (e.g., OSC over TCP or advanced address pattern matching).
    Future Mixxx development explicitly plans to expand OSC integration significantly, necessitating liblo’s features.

If the current implementation in Mixxx meets functional and performance needs, there’s little advantage in switching to liblo, as the effort required for migration and potential licensing implications could outweigh the benefits.

@ronso0 @daschuer @ArthurVimond
thank you for looking and investing time in this

@daschuer
Copy link
Member

I have prepared a vcpkg for oscpack here:
I have prepared a ports for oscpack here: microsoft/vcpkg#43290
This branch should be redirected to this version or to the distro provided

@Eve00000
Copy link
Contributor Author

I have prepared a vcpkg for oscpack here: I have prepared a ports for oscpack here: microsoft/vcpkg#43290 This branch should be redirected to this version or to the distro provided

Thank you, but honestly I have no idea what this exactly means.
Please note that I made some changes to oscpack as wel (besides the code style / clazy / clangridy), some changes in order to get arm64 working (still needs attention) and to adapt it to the specific needs of Mixxx. That's why I added the oscpack-files under the osc-directory, it's not just using a library.

@daschuer
Copy link
Member

We should contribute the changes upstream.
Also the CMakeList.txt file is incomplete an Debian has also a hand full patches.

@Eve00000
Copy link
Contributor Author

Eve00000 commented Jan 17, 2025

We should contribute the changes upstream. Also the CMakeList.txt file is incomplete an Debian has also a hand full patches.

Sure, but I don't know if the changes match the original idea.
I did create a pr, thank you for minding me.

if (m_pConfig->getValue<bool>(ConfigKey("[OSC]", "OscEnabled"))) {
OscTrackLoadedInGroup(m_pConfig,
getGroup(),
pTrack->getArtist().toLatin1(),
Copy link
Member

@daschuer daschuer Jan 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Latin-1 does not support Ιωάννα "Νάνα" Μούσχουρη for instance.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

too bad for Nana Mouskouri, she'll need new glasses because OSC only supports ASCII characters :-)

Copy link
Member

@daschuer daschuer Jan 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about using OSC-blob for it?

An alternative would be to use base64 or escape special characters Json \uXXXX or
Bas364 zpzOv8+Nz4PPh86/z4XPgc63
URL %CE%9C%CE%BF%CF%8D%CF%83%CF%87%CE%BF%CF%85%CF%81%CE%B7
Html &nbsp;&Mu;&omicron;ύ&sigma;&chi;&omicron;&upsilon;&rho;&eta;

Ti&euml;sto
Ti\u00EBsto
Ti%C3%ABsto

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, I learned a lot by solving this and I gave Nana some new shiny glasses 😃 (see screenshot from MixxxInTouch #50)
-> added a json escape-conversion in the oscfunctions
-> added an unescape routine in the luascripts in MixxxInTouchOSC (new version #50 uploaded here, see screenshot)

getGroup(),
pTrack->getArtist().toLatin1(),
pTrack->getTitle().toLatin1(),
(float)1,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
(float)1,
1f,

we do not used C-Style casts in Mixxx

Copy link
Contributor Author

@Eve00000 Eve00000 Jan 20, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now all of a sudden I'm feeling old :-)

@@ -563,6 +574,18 @@ void EngineBuffer::slotTrackLoaded(TrackPointer pTrack,
m_pTrackSampleRate->set(trackSampleRate.toDouble());
m_pTrackLoaded->forceSet(1);

// EveOSC begin
if (m_pConfig->getValue<bool>(ConfigKey("[OSC]", "OscEnabled"))) {
OscTrackLoadedInGroup(m_pConfig,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Functions shout be named as a imperative. This way you are able to guess form the name what it does and not when it should be called like here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean the functions should be named something like
OscLetsSendInformationToTheClientsBecauseATrackWasLoaded()

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, somhow.

OscFunctionsSendPtrType(m_pConfig,
OscGroup,
"TrackArtist",
DefOscBodyType::STRINGBODY,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be ned to have wapper funtions like OscFunctionsSendStringBody or such.
Using a common prefix for functions like OscFunctions should become a class or namespace.
In this case a class that holds the OSC instance is probably the way to go.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand this remark

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Isn't that just code-makeup?
IIUCWYM than there should be a function called OscFunctionsSendStringBody() that is just accepting the vars and passing them through to the OscFunctionsSendStringBody(), but in this way you can write an 'imperative procedurename' that should explain in it's name what the function needs to do? Makeup for the reader 😄

p << osc::EndBundle;

// Retrieve output port
int CKOscPortOutInt = m_pConfig->getValue(ConfigKey("[OSC]", "OscPortOut")).toInt();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This string lokup is not fast, because of allocating memory. I think it would helpt to cache this in a member variable.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

owkee, can you point me an example?

@daschuer
Copy link
Member

I am arfaid the proposed nameng scheme looks a bit foreign among other solutions. We have:

See: https://opensoundcontrol.stanford.edu/spec-1_0.html

OSC Address Patterns
An OSC Address Pattern is an OSC-string beginning with the character ‘/’ (forward slash).

An OSC Server’s OSC Methods are arranged in a tree strcuture called an OSC Address Space.
The leaves of this tree are the OSC Methods and the branch nodes are called OSC Containers.

An OSC Method’s OSC Address begins with the character ‘/’ (forward slash), followed by the names of all the containers, in order, along the path from the root of the tree to the OSC Method, separated by forward slash characters, followed by the name of the OSC Method. The syntax of OSC Addresses was chosen to match the syntax of URLs

@daschuer
Copy link
Member

Here the Ableton example:
https://github.com/ideoforms/AbletonOSC

It is also interesting that everyone seems to use lower case urls.

I think we ca treat out COs as a huge dictionary of float falues.

I think: QuickEffectRack1_(Channel1Stem2))@super1
May become
/mixxx/qickeffectrack1/channel1stem1/super
you may send it with a value as a setter and without as a getter.

For the parameter value wa may use
/mixxx/qickeffectrack1/channel1stem1/super/parameter

What do you think?

Dies this work with TouchOSC?

@Eve00000
Copy link
Contributor Author

I am arfaid the proposed nameng scheme looks a bit foreign among other solutions. We have:
...
An OSC Method’s OSC Address begins with the character ‘/’ (forward slash), followed by the names of all the containers, in order, along the path from the root of the tree to the OSC Method, separated by forward slash characters, followed by the name of the OSC Method. The syntax of OSC Addresses was chosen to match the syntax of URLs

Indeed the original 1.0 agreement (20 tears ago) was the tree-logic, later there was no more agreement anymore so the 1.1 died. Meanwhile the all software working with OSC made their own syntax (evolution in 20years)

So that was the logic I started with, and as I mentioned I had to make a translation for the CO's that was easy for was easy enough (read: not too complicated) for people who want to create an OSC-interface.
In the beginning I started with:
\Channel1\play
\Master\crossfader
\Library\MoveDown
...
but then came the exceptions like
[EqualizerRack1_[Channel2]Effect1]\parameter1
\QuickEffectRack1
[Channel2Stem1))\super1

And so I choose for a general syntax with the combination of the @-symbol. A kind if Mixxx-interpretation over the OSC-transport-protocol.

I think we ca treat out COs as a huge dictionary of float falues.

I think: QuickEffectRack1_(Channel1Stem2))@super1 -> /mixxx/qickeffectrack1/channel1stem1/super
you may send it with a value as a setter and without as a getter.
For the parameter value -> /mixxx/qickeffectrack1/channel1stem1/super/parameter

Are you very keen on having the original OSC-logic?
It will make it more difficult for users
I propose to make a combination to keep it simple enough for users (the easier the more people will experiment):
only 1 container part in combination with the @ ?

The setter could be the address with a value, but I would like to keep the GetV# / GetP# / GetT#

for TouchOSC it would be OK, fo me ir's a lot of work adapting my complete interface + implementing the whole logic 😃

@daschuer
Copy link
Member

On one hand it is very recommendet to follow established standards, to be future prove. On the other hand we also don't want to complicate things or put extra work on you without a reason. My strong demand here is to look left and right and pick an informed descision. The exact result is secondary.

So let's start.

Tree structure:

I have found this:
https://github.com/Vidvox/OSCQueryProposal

A proposal for self documenting the OSC interface. I think one confirmation is that we can use the ppropsed json format to document our interafce. There are also some other proposals link which all assume OSC is implemnted in a certain way.

The resultin Json responds is a tree like document following the OSC path.

Pattern Matching

The other thing is the wild card capability to do more than one commant at once using ? * and [].

How does your propasl integrate with it?

@daschuer
Copy link
Member

It looks like # is a reserved character and connot be used.

I have not yet found a good description how queries should be implemented in OSC.

I can also imagine to subcribe a certain value. This will than be almost like a mapping. dis you consider this?

@daschuer
Copy link
Member

OscQuerry has it:

{
 	"COMMAND": "LISTEN",
 	"DATA": "/foo"
 }

@Eve00000
Copy link
Contributor Author

In order to make Mixxx ready for the future, in particular when url-instructions get a wider use (e.g. Internet of Things) we 'd like to step up to a /tree/branch/leaf structure. The goal is to also broadcast the complete Mixxx-CO-structure through a query to the environment where the developer is building an interface. In this way the developer does not need to know all CO's, CO's and their characteristics would be 'shared' from within Mixxx. As a base for this logic we will start with converting the OSC-logic.

In PR's #14229 and #14238 will be worked on this evolution, this PR wil remain working and the MixxxInTouchOSC will be maintained until further notice.
The future of OSC in Mixxx will be with a /tree/branch/leaf structure.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants