TouchOSC template with scrolling songs list

Hi Guys
I created my first beta version of template with advanced features by the scripts.

Some indication:

  • All the controllers have the show/hidden function. So if the controller is not present in the rackspace it’s not visible in touchOSC.
  • Tapping on the song and part labels you can to moving up and down the songs parts
  • On the sliders1 and sliders1 labels you can see 2 examples of two different mode to visualize the values. Slider1 visualizes a parameter value and Slider2 visualizes a midi Value

Note: If you want add some controllers is very important the “Tag”. All labels are grouped with the controllers by the “Tag”.

  • The Page of SongList is a rivisited copy of template by “rank13”… Thank you man for your great Job.
    The grid list is scrollable and the max number of songs visibles in the grid is determinate by the number of row and column of the grid. If you need to calibrate the scroller, after the modify of the grid, you can see the instructions in the scripts.

Issues encountered:

  • If I change songs parts from TouchOSC everything work perfectly, but if I change songs parts from my midi controller or PC, the controllers in TouchOSC are shown or hidden randomly.
    UDP ports in the router are opened and the speed of the Wifi is 866Mbps…I tried different router, Ethernet, wifi but the issue persist.
    If I use my phone with touchOSC inside in hotspot mode connected to the Pc everything work well…
    Same issue by the way with the Lemur template, so I don’t know…
    Do you have some advice on this?
    -I apologize for my poor knowledge of the English language. I hope you can understand me anyway. :sweat_smile:

I’m not a programmer, so if you have some advice to improve the scripts or the template in general you are welcome…All together we can create a perfect template. :joy:
As soon as I have the permissions I’ll post the images and the material to download so you can try it and let me know

Here the code in the root:

---- controllers grouped by Tag

local Faders={}
local Knobs={}

-----grid songs label
local songlist=root:findByName("sng",true)
-----Songs pager position
local songs= self.children.pager.children.SongsPage
local N_faders=4
local N_knob=4

function init()
sendOSC('/SetList/GetSongList')
sendOSC('/SelectSongByIndex', 0)

for i=1, N_faders do
  Faders[i]=root:findAllByProperty("tag","F"..i,true)
  Knobs[i]=root:findAllByProperty("tag","K"..i,true)
end

--[] <-- Deleting one of previous character (e.g. "["), the following command lines will be activate, renaming all the labels from song 1 to song"x"

 --click on start and test the scrolling. If you need to calibrate it click on the fader used to scrolling the list and follow the instructions

 --After that remember to reinsert the charater deleted before
     
  for i = 1, #songlist.children do
   songlist.children[i].values.text = "song "..i
  end --]]

end


function onReceiveOSC(message,connections)
local path = message[1]
local arguments = message[2]

songlist: notify("list", {path, arguments})
  
 ------hide/show objects
  for i=1 , #Faders do -- number of faders
   for j=1, #Faders[i] do -- objects grouped to faders by tag name (labelName, labelValue, fader)
   
   if path=='/ClearAll' 
   then
   Faders[i][j].visible=false
   Knobs[i][j].visible=false
   end
   
   if path=='/Slider'..i..'Name' 
   --or
--path=='/F_Val'..i..'Name' 
   then
   Faders[i][j].visible=true
   end
   
   if path=='/Knob'..i..'Name' 
   -- or
--path=='/K_Val'..i..'Name' 
   then
   Knobs[i][j].visible=true
   end
  end
 end
----------------------------
 
   
  -- If the setlist changes in GP, request the new song list
   if path == '/SetListChanged' then
    sendOSC('/SetList/GetSongList')
  
   end
  
  -- Use LUA string functions to extract the song number
  -- from the GP SongName message e.g. /SongName9
  -- The last message received will provide the total song count
  if string.find(path, '/SongName') then
    local songCount = tonumber(string.match(path, '%d+')) + 1
    
    -- Store the song count in a label
  songs.children['SongCount'].values.text = tostring(songCount)  
  end
  
  -- Get the currently selected song number and store in a label
  if path == '/CurrentSongIndex' then
    local song =  arguments[1].value + 1
    
    -- Rather than set the label directly, you can also trigger
    -- a callback for the label and pass it the song count.
    -- There is a small script in the CurrentSong label to handle this.
    self.notify(songs.children['CurrentSong'], tostring(song))
    songlist: notify("songID", tostring(song))  
  end
  
  -- Once the last song name has been received (and total count 
  -- is calculated), hide any song labels that aren't required.
  if path == '/SongListEnd'
     
  then
    local songCount = tonumber(songs.children['SongCount'].values.text)
    
    -- Iterate through all the song labels in the 'songs' group
    -- and set the visibility property. Adding similar controls
    -- to a 'Group' gives them an index, which is useful for processing.
    songlist: notify("hide", songCount)
    
  end
  
  -- Similar to the song count, use LUA string functions to extract
  -- the song part number and store in a hidden label.
  if string.find(path, '/SongPart%d+') then
    local partCount = tonumber(string.match(path, '%d+')) + 1
    songs.children['SongPartCount'].values.text = tostring(partCount)
  end
  
  -- Once the last song part message is received (and total song part
  -- is calculated), hide any song part labels that aren't required.
  if path == '/SongPartsEnd' then
    local partCount = tonumber(songs.children['SongPartCount'].values.text)
    
    -- Iterate through all the song part labels in the 'SongParts' group
    -- and set the visibility property.
    for i = 1, #songs.children['SongParts'].children do
      songs.children['SongParts'].children[i].visible = (i <= partCount)
    end
  end
end
3 Likes

Hi @NanoMalefico,

welcome to the family :wink:

1 Like

I saw now that there is an error in the code…
the correct code is --[[ but i can’t amend it now :pensive:

Ok now we can do it :grinning:
Some images:



script song list grid:

function onValueChanged(key)
 if (key=="touch" and self.values.touch==true)
  and (self.name~="sng")
 then
 sendOSC('/SelectSongByIndex', self.index-1) 
  end
end

function onReceiveNotify(key, value)
 -- Songs to labels
 if key=="list" then
 local path=value[1]
 local arg=value[2]
  for i=1, #self.children do
   if path == '/SongName'..i-1 then
     self.children[i].values.text=i.."   "..arg[1].value
   end
  end
end
 -- hide label 
if key=="hide" then
 for i = 1, #self.children do     
     self.children[i].visible = (i <= value)
 end
end
 
 -- Color label
 if key=="songID" then
 for i=1, 40 do
  if value==self.children[i].name
   then
   self.children[i].color=Color(0.8,0.8,0.8)
    else
   self.children[i].color=Color(0.4,0.4,0.4)
    end
  end
 end 
end

script scrolling song list in the fader:

local scroll=800  -- edit this number to calibrate the scroll

local mygrid=self.parent.children.sng

 function onValueChanged(key)
  if key=="x" then
   mygrid.frame.y=self.values.x*-scroll

  end
end

GP_BETA.zip (10.7 KB)
touchosc_TEST.gig (686.6 KB)

1 Like

Great job @NanoMalefico, I will check this out.
It’s good to see you were able to use some of the prior scripts and template I did a while back :wink:

2 Likes

Thanks @rank13 but you are my teacher. Everything I learned I did by reading your posts and some examples on the net. I don’t know programming languages ​​like python, lua, C etc but reading your posts I learned a lot. This forum is a gold mine for anyone who wants to learn. :heart_eyes:

5 Likes

Wonderful, thanks for this contribution! @rank13 Sir scripts are always a good starting point. :wink:

3 Likes

First update 1.0
Now you don’t need to calibrate the scrolling.
You can add or remove rows in the grid of songs list, resize it end nothing else :wink:

Here the code changed in the fader :

local rows = 20 --max rows avaiable in the grid
local group_h = self.parent.frame.h
local mygrid = self.parent.children.sng
local init_y = 0 --mygrid.frame.y start position
local fullheight = 0 -- height of the grid
local h_cell = 0 -- height cell grid
local visible = 0  -- number of rows visible in the page
local offset = 4

function init()
fullheight = mygrid.frame.h
h_cell = fullheight/rows
visible = group_h/h_cell
end

function onValueChanged(key)
if key == "x" then
mygrid.frame.y = self.values.x * (init_y - (rows-visible) * (h_cell + offset))
end
end

GP_BETA_1_0.zip (11.3 KB)

1 Like


The first official version is ready.
Now you can add and remove sliders, buttons, knobs, labels etc wherever you want, as you like without limits of number.
When the template starts, everything will be recognized automatically, so you won’t need to modify the script.
I recommend, when add a new controller with its name and value labels to insert the “tag” for each one.

New code here:

---Template for GigPerformer 1.0----
--Credits: rank13 from GigPerformer community----

---- controllers grouped by Tag
local Faders={}
local Knobs={}
local Buttons={}
-----Number of controllers
local N_faders = #root:findAllByType(ControlType.FADER, true)
local N_knobs = #root:findAllByType(ControlType.RADIAL, true)
local N_buttons =#root:findAllByType(ControlType.BUTTON, true)
-----grid songs label
local songlist=root:findByName("sng",true)
-----Songs pager position
local songs= self.children.pager.children.SongsPage
local mixer= self.children.pager.children.Main

----function init controllers
 function init_ctrls(num,tag_control)
  local control={}
   for i=1, num do
    control[i]=root:findAllByProperty("tag",""..tag_control..i,true)
   end
  return control
 end
 
 function init()
 sendOSC('/SetList/GetSongList')
 sendOSC('/SelectSongByIndex', 0)
 Faders = init_ctrls(N_faders,"F")
 Knobs = init_ctrls(N_knobs,"K")
 Buttons = init_ctrls(N_buttons, "B")

  --[[ --Use it for Test grid songs list--  
  for i = 1, #songlist.children do
   songlist.children[i].values.text = "song "..i
  end --]]
  
end
--Function Clear All-- 
function clear (obj)
  for i=1 , #obj do 
   for j=1, #obj[i] do 
   obj[i][j].visible=false
   end
  end
end
--Function Show controllers
function show (obj,id)
 for i=1, #obj  do 
   for j=1, #obj[i] do 
    if i==id then 
    obj[i][j].visible=true
    end
   end
 end
end

---callback OSC message
function onReceiveOSC(message,connections)
 local path = message[1]
 local arguments = message[2]
 
 ---send songs list to the songs list grid
 songlist: notify("list", {path, arguments})
  
 ------hide/show objects 
   if path=='/ClearAll' then  
    clear(Faders)
    clear(Knobs) 
    clear(Buttons)
   end
   --show sliders
   if string.find(path, '/Slider%d+Name') then
    local f_id = tonumber(string.match(path,'%d+'))
    show(Faders,f_id)
   end
   --show knobs
   if string.find (path, '/Knob%d+Name' )  then
    local k_id = tonumber(string.match(path,'%d+'))
    show(Knobs,k_id)
   end
   --show buttons
  if string.find (path, '/Button%d+Name' ) then
    local b_id = tonumber(string.match(path,'%d+'))
    show(Buttons,b_id)
   end

        -------Song List by rank13 ----------------
        
  -- If the setlist changes in GP, request the new song list
   if path == '/SetListChanged' then
    sendOSC('/SetList/GetSongList')
   end
  
  -- The last message received will provide the total song count
  if string.find(path, '/SongName') then
    local songCount = tonumber(string.match(path, '%d+')) + 1
    
    -- Store the song count in a label
  songs.children['SongCount'].values.text = tostring(songCount)  
  end
  
  -- Get the currently selected song number and store in a label
  if path == '/CurrentSongIndex' then
    local song =  arguments[1].value + 1
    self.notify(songs.children['CurrentSong'], tostring(song))
    
  --the current song will change its label color
    songlist: notify("songID", tostring(song))  
  end
  
  -- Once the last song name has been received (and total count 
  -- is calculated), hide any song labels that aren't required.
  if path == '/SongListEnd'
     
  then
    local songCount = tonumber(songs.children['SongCount'].values.text)
    
    -- Iterate through all the song labels in the 'songs' group
    -- and set the visibility property. Adding similar controls
    -- to a 'Group' gives them an index, which is useful for processing.
    songlist: notify("hide", songCount)
    
  end
  
  -- Similar to the song count, use LUA string functions to extract
  -- the song part number and store in a hidden label.
  if string.find(path, '/SongPart%d+') then
    local partCount = tonumber(string.match(path, '%d+')) + 1
    songs.children['SongPartCount'].values.text = tostring(partCount)
  end
  
  -- Once the last song part message is received (and total song part
  -- is calculated), hide any song part labels that aren't required.
  if path == '/SongPartsEnd' then
    local partCount = tonumber(songs.children['SongPartCount'].values.text)
    
    -- Iterate through all the song part labels in the 'SongParts' group
    -- and set the visibility property.
    for i = 1, #songs.children['SongParts'].children do
      songs.children['SongParts'].children[i].visible = (i <= partCount)
      mixer.children.parts.children[i].visible = (i <= partCount)
    end
  end
end

GP_Official_1_0.zip (13.0 KB)

GIG preset for test:
touchosc_TEST.gig (1.2 MB)

5 Likes