This forum is for Tips and Tricks. Please do not post any questions in this forum. It is only for information.
78 postsPage 2 of 4
1, 2, 3, 4
I'll look at that part closer if it needs it thanks, but (i'd have to check to remember) The root drop down list has no effect on custom chords at all. Or rather, if it does i forgot to block it. :) It (custom files) was intended to always only give exactly back what you saved so i never set it up to follow a key change after loading one.

Because I'm not a trained musician the way I approached saving and recalling the custom chords (with it all being graphical), it only needed to store and correctly recall the state of the highlighted keys on the piano graphic. The "On/Off" states of the piano keys.

As long as (any bugs aside that I may not be aware of yet), what you see highlighted on the piano graphic visually is what you actually get in the key editor when the notes get placed, it's all good. I left the technicalities of music theory and all that to the musicians. :)

It is after all, just a pretty basic tool. But yes, if i'd intended to scale those up or down after loading, i'd have to code for that.

At any rate, good stuff. If you decide to do anything else related to S1, please share it with the rest of us.
User avatar
by Nelios on Sat Jul 05, 2014 5:59 pm
You're welcome Tshadgett, I hope that'll be useful :)

I'll surely share everything I do for Studio One, if you guys have any ideas/requests, I'll look into it (if it's feasable).
Forgot to mention, if you want to use the tool (Source) you need two specific keybinds:
'Locale Selection End' -> Ctrl + Shift + L
'Locate Selection' -> L (Should be default. Not sure about the name though, I have Studio One in French.)
User avatar
by Lawrence on Sat Jul 05, 2014 6:10 pm
I'm working on something that may (I hope) end up being redundant in the next major update, storing and recalling fader and pans across multiple channels, mini snapshots. If you want we can hash some of that out here, you might have some better ideas about that.

Let me know.

I mean, the original intent was to use VB to get more people hacking because it's easy enough, but since there's not much interest in that, we can turn the page, redirect the thread and go another way, collaborate on some things.

Anywho, here's the early stages, just trying to reliably capture and restore fader and pan, which is working, and then move on to expanding the data array to collect any other possible track data to save and restore per track, and then later trying to turn all that into serial operations for multiple tracks. Along with maybe some useful presets like "Zero All Faders", whatever.

Image

You may have some better ideas about how to approach some of it.
User avatar
by Nelios on Sat Jul 05, 2014 6:38 pm
Sure, that feature would be really useful... I'd love to collaborate on it. Plus posting about that over here would be great, showing progress & things like that. I think that it's the kind of thing (automation programming, macros & programming in general) that most people don't know/are not sure about... But after seeing what can be done, it may inspire someone!

About VB, yeah it's easy, but it's really, REALLY bad if you want to code (even for a beginner). If you don't know where to start, go with C#. Its syntax is easy yet so powerful (it's used in tons of places to make very diverse tools). Coding addons for Studio One, at least as we're doing now, is a good starting point. Easy to do/think about, but still useful -> practical coding is the best way to learn in my opinion.

Anyway, I think collaboration & sharing is the right way to go.

I've got a few ideas for your current project. I'll have to take a look at how you handle things for now though, before saying/doing anything :)
User avatar
by Lawrence on Sat Jul 05, 2014 10:19 pm
About VB, yeah it's easy, but it's really, REALLY bad if you want to code (even for a beginner).

Let's please not do that here, get into one of those "best language" meta discussions. :lol: Nobody tinkering about for fun or hobby purposes really even cares, they just want to create some stuff and keep it moving. :)

Anyway...

I have it working to grab the levels, pans and names from all visible tracks in the short mixet, along with another function to zero out the mixer, Unity/Center. Working well so far.

The approach uses SendMessage to start by directly clicking on the level and pan fields and then using the same method to click back to the first level field from which you can tab into the first name field in the console, which makes it all direct, it's not necessary to enable any fields to start any of the actions. The best approach seems to be working from the short docked mixer, the most tracks showing with all of those fields exposed to grab and restore, but it only works so far for visible tracks (up to 22 here) due to the level and pan fields in the console not being part of a tab group.

If you want I'll share the code tomorrow if you want to run with the general idea in C# but at your skill level you don't need my code.

At any rate, given the lack of general interest (it's kinda just you and me here) I'll probably stay out of this thread for awhile. If you come up with something else cool like the chord app post it.

Thanks. Cool stuff.
User avatar
by mrpicholas on Sat Jul 05, 2014 10:52 pm
Despite there being only two posters here, you should know that others do read and learn from this. Don't assume that there is no interest. If I don't have anything additional to contribute I won't post just to post.

MacBook Pro 2.8 GHz Intel Core i7 with 16GB RAM & OS 11.6.4. Studio One Professional 5, Notion 5, Presonus Quantum 2626, PreSonus Sceptre S6, FaderPort, Melodyne Editor, plugs from Waves, AAS, Arturia, Nomad Factory, IK. Faber-Castell #2 Pencil
User avatar
by whitePhazer on Sun Jul 06, 2014 3:40 am
I am interested in this discussion. When I was in my 20's did a lot of programming using "Delphi", a form of Pascal, even sold one prog, but did it mainly for fun. I am 64 now and haven't programmed for a long time but still find it interesting, so we are interested. What prog language are we using here?

Win 7 64bit
Studio One Professional x64 (always latest update)
Intel i5 3.30GHz overclocked @ 4.20 GHz
Azus deluxe Motherboard
8GB RAM
M-AUDIO - Audiophile 192
M-Audio Oxygen 49
Akai MPD26
American Fender Stratocaster Deluxe
Retired, plenty of spare time
User avatar
by Nelios on Sun Jul 06, 2014 6:17 am
LMike wroteLet's please not do that here, get into one of those "best language" meta discussions. :lol: Nobody tinkering about for fun or hobby purposes really even cares, they just want to create some stuff and keep it moving. :)


That was not my intention :) I never said that C# is the best language ever (it's not, there are no best language, pick the one you're the most comfortable with. If you're a beginner, I'd suggest C# as it combines simplicity with power. Plus what you'll learn will translate to other languages!).

Now, about your project... Clicking is bad (but necessary in this case, unless we find another way) because it's a hardcoded value. What if the user has a different resolution? Different dock size? You don't want to force a certain way/workflow to your user, you want the software to adapt.
So how to fix that? Couple of ideas:
  • Let the user input a few locations (volume, fade).
  • Image searching. The most powerful in my opinion.

There are more possibilities, but those two aren't tied to a resolution for sure.
Why the first should work: link
And the second one (a bit more complicated): link

I've only done image searching (not in C# though, it was an autohotkey macro), so that'll be a learning experience for me... Should be really interesting!
Seeing that there is interest, I'll certainly post my progress once we'll work. How about mini tutorial to follow along? Anyone interested? It won't be a simple "okay, now I'll add this snippet of code" but something more along the line of "okay, now what kind of functionality do I need? How to implement it? Can it be reuseable?". Thinking process & code :).
WhitePhazer, LMike should be using VB & I'm using C#. But YOU are free to use whatever language you want. As long as you're comfortable (you don't want to be lost, don't you? :D).
User avatar
by Lawrence on Sun Jul 06, 2014 8:27 am
Nelios wroteNow, about your project... Clicking is bad (but necessary in this case, unless we find another way) because it's a hardcoded value. What if the user has a different resolution? Different dock size? You don't want to force a certain way/workflow to your user, you want the software to adapt.
So how to fix that?

Those are valid concerns. .

    Those controls are at a predictable Y location from the bottom of the S1 app window. In this case 321 pixels. Of course, that needs verification at different resolutions but that should persist.

    The level and pan fields are also static and predictable if you use actions to set the console short and close all of the left most optional console panel views, but like above, that needs testing at different resolutions to verify that those locations are good at all resolutions.

Here's what I have: Assuming all optional console panels closed and short mixer...

X1 = 71 (first level field)
X2 = 107 (first pan field)
71 px = Static gap from X1 or X2 step to the next
Y = 321 from the bottom of the app window or Screen.WorkingArea.Height - 321 if you force maximize the app window. That (coords) are referenced inside the S1 app window so they can be predicted.

Of course, I'll switch screen resolutions to test that the coordinates will still be good at other resolutions.

So Loop click (X1,Y) copy (or paste on restore), click (X2,Y) copy, X1 & X2 + 71 End Loop will run through all the visible level and pan fields.

Reset X1 to click back on the first level field and TAB * 3 + BackTab will put you into the first name field, then you can run through the track names and capture those. There's no way I see to tab through the names first and then somehow get into the level and pan fields, so capturing the levels and pans first is the current approach.

The user setting I have right now is a field where the user is required to enter how many visible tracks there are so the loop range can be set correctly, how many tracks they can see in the mixer total. txt_MaxTracks

We can test those coordinates and different resolutions and see if they hold up. I think they do. Screen.WorkingArea accounts for the task bar and those controls should always be at a predictable location related to the parent window edges..

P.S. One unrelated nut I could not crack that you maybe can, is double clicking on the S1 app space. My methods didn't work. If you can crack that and get it working and pass along that code bit, that would be great for add-ons in general.
User avatar
by Lawrence on Sun Jul 06, 2014 8:36 am
WhitePhazer, LMike should be using VB & I'm using C#. But YOU are free to use whatever language you want. As long as you're comfortable (you don't want to be lost, don't you?


Sounds good to me. C# and VB (afaik anyway) compile the same in VS / .NET so the end result will be the same. Things like "low level power" don't really contextually play into these kinds of applications but if you're coding a DAW or something, yeah, you wouldn't try that in VB and/or trying to pull that off with the .NET common libraries unless you're nuts. :)

This is or was a bit less critical than all that. ;)

For this purpose I thought VB might be more immediately understandable to the total newbs but if they want to go C#, go for it. I spent some time coding Google Spreadsheet scripts yesterday and I do JavaScript and other similar things and it's certainly true that being familiar with C coding methods do translate better to those things, the language style.

I was actually hoping someone with Xojo would show up so some of this stuff can be enjoyed by Mac users... but if you're (unlike me :)) a pro coder, you can probably do cross platform with yours.
User avatar
by Lawrence on Sun Jul 06, 2014 9:20 am
At any rate, I'll start sharing some of the supporting source bits and you guys can convert it to any language you want, the Windows methods are all the same.

All the following assumes you've already loaded the S1 Window Handle into what is below the variable S1. There are different ways to get it done but I use something like this, which could be shortened but no biggie...

Dim S1 as IntPtr (create a form or module level scoped var for the main window handle)

Note: I initially typed this code block below wrong, I had the exception inside the for / loop which would throw up that message box on every loop. :) Sorry 'bout that, corrected.

    For Each p As Process In Process.GetProcesses
      If InStr(p.MainWindowTitle, "Studio One") > 0 And p.ProcessName = "Studio One" Then
        S1 = p.MainWindowHandle
        Exit Sub ' found the window so exit the code sub or jump over the rest if inline
      End If
    Next
      'Code execution only ever gets here if all processes are parsed with no luck
      'Didn't find the window
      MsgBox("Studio One is not running... yada, yada,...")

SendMessage is an API Declaration that's required for the clicking code. It should be declared at the from or public module level, up at the top of your form code before any subs and after the class name. The underscores there are just a line continuations so if it doesn't format correctly on copy and paste, just remove those and put the declaration on a single line.

Public Declare Function SendMessage Lib "user32.dll" Alias "SendMessageA" _
(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As IntPtr, _
ByVal lParam As IntPtr) As IntPtr

You should also define your mouse constants there the same way (in that same space) to not have to remember those values...

    Public Const MouseDown As IntPtr = &H201
    Public Const MouseUp As IntPtr = &H202

To click on an X,Y coordinate in S1, I use subs and functions like below. The actual code line that clicks somewhere would look like this...

S1_Click(42,55)

... or however you choose to load the X/Y values, with integer vars maybe, which fires this supporting sub below... or alternately function if you prefer using functions for that...

    Public Sub S1_Click(ByVal X As Integer, ByVal Y As Integer)
      Dim ClickPos As IntPtr = SetCoord(X, Y)
      SendMessage(S1, MouseDown, 1, ClickPos) 'left mouse button down
      SendMessage(S1, MouseUp, 1, ClickPos) 'left mouse button up
    End Sub

SetCoord above Is a just simple function that formats the X/Y coordinates ...

    Public Function SetCoord(ByVal Lo As Short, ByVal Hi As Short) As IntPtr
      Return CInt(Hi) << 16 Or Lo
    End Function

Those last two routines above are invisible once you code them, you never have to see them again. The reason for using functions for those types of things is to not have to keep typing the same code over and over, just call the function whenever you need it. So with that coded, just type...

S1_Click(X,Y)

... with X being pixels from the left of the window and Y being pixels down from the top of the window, (140, 200) whatever, to click anywhere on the app window to (I suppose) maybe automate some stuff that doesn't have actions for it yet.

To parse the coordinates inside an app, find the numbers for the x/y locations you want to click on where something is, you can use something like Spy++ or WinInspector or maybe even just measure that with a screen capture.

P.S. As variables go, you should name those concisely. Like if I wanted to load another var with the handle for the detached mix console, another discreet window, it would be named S1_Console or something, the var id for it, so the code would be readable, not confusing, and you or anyone reading it knows what that thing is being used for.

So in the cases above, S1 by itself always = "Main App Window".
User avatar
by Nelios on Sun Jul 06, 2014 9:38 am
Regarding the Double Click, I just tried that and it works. I found the "click" methods on google (link). The negative values are there to test dual screen.
Cool. All of the code and Goggling samples and trying I did was fruitless, which is why I asked.

Oh yeah, how about multiple screens? Hardcode won't work in this case (unless the user places everything on his main screen). How about that: once the user click on the button to apply the saved faders/pans he is asked to click on the FIRST volume value? Once he click you store the cursor value (and maybe check if the pixel color is right or something, else he could click anywhere and it may do something wrong) & loop with that value as a base. Since the gaps are the same everywhere it'll certainly work. What do you think?

By the way, you (not talking to LMike specifically) should be able to compile C# for Mac. I don't own a mac myself so I can't do it, but the sources are there if you want to try...
Last edited by Nelios on Sun Jul 06, 2014 10:00 am, edited 1 time in total.
User avatar
by Lawrence on Sun Jul 06, 2014 9:50 am
^^^^ ACK ^^^^ I inadvertently edited your post when trying to reply. ! Sorry !. Can you add back the part that I couldn't recover? The last paragraph?"


Regarding the Double Click, I just tried that and it works. I found the "click" methods on google (link). The negative values are there to test dual screen.

Cool. All of the code and Goggling samples and trying I did was fruitless, which is why I asked.

Can you post the code bit that works for you to double click with S1 so we can all have it? All the stuff I tried didn't work, partly maybe due to me not coding it correctly. So if you have that bit, just post it. Once we all have the code bit it's a non issue.

Thanks.

Oh yeah, how about multiple screens? Hardcode won't work in this case (unless the user places everything on his main screen). How about that: once the user click on the button to apply the saved faders/pans he is asked to click on the FIRST volume value? Once he click you store the cursor value (and maybe check if the pixel color is right or something, else he could click anywhere and it may do something wrong) & loop with that value as a base. Since the gaps are the same everywhere it'll certainly work. What do you think?

If the console is detached on screen 2 or 3 it will still be valid because the coordinates don't relate to any particular screen or monitor or desktop area, they only relate to the window being addressed. If you're using the detached mixer (and you can test for detachment or not first and grab that Wnd along the way to know if it's detached) it will address the detached mix console window directly wherever it is.

Even if the console is on monitor 3, the X,Y of the data field is still in the same relative place, on the console window. But that needs to be tested /spied on to make sure there's not a small positioning shift with those fields on the detached console, and if so, account for that.

Well, we know the Y value will shift downward on detachment, where it is relative to the bottom of the parent window, so that value has to be noted and included and used with the detached window hWnd condition. I measure those from the bottom (height) of the window up, because that gap never changes, per window, docked (per view anyway) or detached.

...he is asked to click on the FIRST volume value?


No, the coded click does that by itself, if the plotting of X/Y is accurate.

Let's not haggle over it though. :) If you want to take another approach, by all means do that.
User avatar
by Nelios on Sun Jul 06, 2014 9:56 am
Sure, I posted the bit on my post, but I'll post it again: LINK. It's really simple, a single click works, so why not do it twice? (line 27/28). Everything is there, except the hooking bits (there are on Github anyway). I can post it all if that's not enough :)

If the console is detached on screen 2 or 3 it will still be valid because the coordinates don't relate to any particular screen or monitor or desktop area, they only relate to the window being addressed.

I think I understand... Yeah... My method doesn't work like that, it's not tied to a particular application. It clicks anywhere you tell it to (in code). I'll take a look to link it to a certain window though, that'll be better!

No, I already explained that the coded click does that by itself.

I wasn't talking about your code, I was talking about an idea. If you use my method (click anywhere on screen, no link to a particular window) it'll do everything starting from where the user would input the first mouse click.
User avatar
by Lawrence on Sun Jul 06, 2014 10:04 am
Sure, I posted the bit on my post, but I'll post it again: LINK. It's really simple, a single click works, so why not do it twice? (line 27/28). Everything is there, except the hooking bits (there are on Github anyway). I can post it all if that's not enough :)


I have tried those methods, multiple times. It doesn't work here. Neither does the WM double click message, which is why I asked if you have actually tried any of it yourself inside S1 on your system and if so and if you were successful emulating a double click with any of it in the S1 main window space, can you post the code bit that works for you?

Thanks.

I wasn't talking about your code, I was talking about an idea. If you use my method (click anywhere on screen, no link to a particular window) it'll do everything starting from where the user would input the first mouse click.

That's cool. I prefer my method of targeting the window directly but if you want to click on the screen area and not the app window, do that and share how to do that.

Post the code for that method and anyone interested can decide which approach they might want to take.

We're more just trying to see what actually works, not so much trying to see who can do it better. :)
User avatar
by Nelios on Sun Jul 06, 2014 10:10 am
Honestly, I prefer your method too, I'll work on that asap. I'll try to do the double click first :)
And obviously, I wasn't trying to argue or anything, just sharing ideas -> brainstorming and things like that, you know? I'll never say (unless obvious) that a method is better than another one!

That being said, I'm trying to make something that works best, in ANY situation :)
User avatar
by Lawrence on Sun Jul 06, 2014 10:16 am
I hear you, I just didn't want to lose the focus. :)

Anyway, to your earlier point about a detached console window, that needs to be done, test for the detached console first ... try to get it's hWnd before using the main window hWnd var in that code to address the mixer. It you do get a valid return value for the detached console window, you'll know that it's detached and can proceed accordingly.

CCLShawdowWindowClass

The window text "Console" doesn't show up here in Spy, but the other classes, the dialogs and things, have different class names so it should be safe enough to just use that class name to test for the detached mixer until or unless we encounter something with the same class name running concurrently with the detached mixer.

Anyway, I'll take a break but keep reading here as things go along.

Here's what the rough alpha of that code approach looks like capturing and restoring the faders and pans for 20 tracks. It's still a little buggy and it looks (in the YT video) visually slower executing than it really is due to Camtasia recording at 1680 width. And obviously, the UI design is nothing to write home about...

phpBB [video]
User avatar
by Lawrence on Sun Jul 06, 2014 2:06 pm
I might as well post this working Y coordinate code bit along in case someone wants to use it. It uses the GetWindowRect API to get the window dimensions and then parses a valid Y coord by subtracting 321 from the bottom of the window.

' API Declaration
    Public Declare Function GetWindowRect Lib "user32.dll" (ByVal hWnd As IntPtr, ByRef lpRect As RECT) As Boolean
' Rectangle Structure
    Structure RECT
      Public Left As Integer
      Public Top As Integer
      Public Right As Integer
      Public Bottom As Integer
    End Structure
' Test Code
    Dim R As RECT
    GetWindowRect(S1,R) 'Get the Studio One Window Dimensions
    S1_Click(71, R.Bottom - 321)

The original starting X coordinate, 71, is still valid. I tested this with the window restored and sized different ways to make sure that the click still always hits the first level value field and so far it does.

Here's a screen cap of the subroutine that captures those settings. It looks bigger than it really is with all of the commenting and vertical spacing for visual clarity and it can be reduced a good bit later by moving some things into functions.

Here's the same routine decompiled to C#. The red underlines are because the C# project I dropped the code into doesn't have those objects and references in it.
User avatar
by Lawrence on Sun Jul 06, 2014 8:51 pm
Ok, I think the best way for me personally (mmv) to deal with the detached mixer is to just dock it, auto close any open optional panels, write to it or read from it, and detach it again if it's detached when you fire those routines, which will put it back where it was, so that's the general approach I'm taking, along with the Nelios's idea about letting the user set the X/Y start coordinates on the UI, which was a really good idea.

phpBB [video]


I'll let this marinate for a few days before I get back to it and think about what other data might be possible to pull in there.
User avatar
by Lawrence on Mon Jul 07, 2014 8:59 am
I coded an easy way to parse the field coordinate numbers by making a setup mode where when you enter into that mode the app ...

    1. Makes itself a child window in the Studio One app window space.
    2. You move the top left corner of it center of the first field. The numbers are calculated in real time as the form moves.
    3. Exit that mode and test the start fields with those numbers, the first level and pan fields.
    4. Save it and exit setup to bring the app back to the desktop parent as normal.

phpBB [video]

78 postsPage 2 of 4
1, 2, 3, 4

Who is online

Users browsing this forum: No registered users and 84 guests