Jump to content


Photo

[Solved] swap note_column. Where to save data to keep them?


  • Please log in to reply
26 replies to this topic

#1 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 30 May 2018 - 19:53

I'm trying to build a function that manages to swap two consecutive note columns (only inside a line, not the entire note column). For the moment, I have built a function that changes the selected note's position, specifically in the right note column.

function pht_msc3_move_note_r()
  local snci = song().selected_note_column_index
  local clm = snci + 1
  if ( clm <= 12 ) and ( song().selected_effect_column == nil ) then
    if not ( song().selected_note_column.is_empty ) then
      if ( song().selected_track.visible_note_columns < clm ) then
        song().selected_track.visible_note_columns = clm
      end
      song().selected_line:note_column( clm ):copy_from( song().selected_note_column )
      song().selected_note_column:clear()
      song().selected_note_column_index = clm
    else
      pht_change_status( "No data to move!" )
    end
  else
    pht_change_status( "Select a valid note column (< 12) to move data!" )
  end
end

But I have already tried to build a function derived from it that allows to invert the values of both note columns. For example, if the original data is these:

F-5 01 72 00 00*  -   C-4 03 56 00 00

 

The result would be this:

C-4 03 56 00 00   -  F-5 01 72 00 00*

(*this selected)

 

To do this I create two tables to store the data, or even copy the entire line in a data buffer. But, if I change one of the columns of value notes, it is also saved in that buffer. How can I generate a data buffer that will not change once the data is stored in it? I could use another line or another "temporal track" to duplicate the data there, but I do not like this solution at all.

 

This is another almost absurd example. The function rotates itself by modifying the data. It is clear that it is badly focused:

function pht_msc3_move_note_r()
  local snci = song().selected_note_column_index
  local clm = snci + 1

  local buffer_pos_1 = song().selected_note_column
  local buffer_pos_2 = song().selected_line:note_column( clm )

  if ( clm <= 12 ) and ( song().selected_effect_column == nil ) then
    if not ( song().selected_note_column.is_empty ) then
      if ( song().selected_track.visible_note_columns < clm ) then
        song().selected_track.visible_note_columns = clm
      end
      song().selected_line:note_column( clm ).note_value = buffer_pos_1.note_value
      song().selected_line:note_column( clm ).instrument_value = buffer_pos_1.instrument_value
      song().selected_line:note_column( clm ).volume_value = buffer_pos_1.volume_value
      song().selected_line:note_column( clm ).panning_value = buffer_pos_1.panning_value
      song().selected_line:note_column( clm ).delay_value = buffer_pos_1.delay_value
      song().selected_line:note_column( clm ).effect_number_value = buffer_pos_1.effect_number_value
      song().selected_line:note_column( clm ).effect_amount_value = buffer_pos_1.effect_amount_value
      ---
      song().selected_note_column.note_value = buffer_pos_2.note_value
      song().selected_note_column.instrument_value = buffer_pos_2.instrument_value
      song().selected_note_column.volume_value = buffer_pos_2.volume_value
      song().selected_note_column.panning_value = buffer_pos_2.panning_value
      song().selected_note_column.delay_value = buffer_pos_2.delay_value
      song().selected_note_column.effect_number_value = buffer_pos_2.effect_number_value
      song().selected_note_column.effect_amount_value = buffer_pos_2.effect_amount_value

      --song().selected_line:note_column( clm ):copy_from( song().selected_note_column )
      --song().selected_note_column:clear()
      --song().selected_note_column_index = clm
    else
      pht_change_status( "No data to move!" )
    end
  else
    pht_change_status( "Select a valid note column (< 12) to move data!" )
  end
end

(It is possible to do the same without breaking down so much data, copying the entire table from note_column). 

 

So, where do I duplicate the data in order to keep them? The fact is that, after modifying any original data in the two columns of notes, keep having the old data stored somewhere. Any ideas?

 
Thanks!
 
Note: do not confuse this issue with renoise.song().tracks[]:swap_note_columns_at(index1, index2), that changes the entire note columns. I just want to interact within a line inside the note_columns.

Edited by Raul (ulneiz), 30 May 2018 - 20:46.

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#2 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 30 May 2018 - 20:45

Ok, I have already found a solution. In LUA  is possible to do this method:

 

local a = {}, --table 1

local b = {}  --table 2

a, b = b, a

 

Since selected_note_column is read-only, it is necessary to swap its properties (note_value, instrument_ value...):

function pht_msc3_move_note_r()
  local snci = song().selected_note_column_index
  local clm = snci + 1
  if ( clm <= 12 ) and ( song().selected_effect_column == nil ) then
    if not ( song().selected_note_column.is_empty ) then
      if ( song().selected_track.visible_note_columns < clm ) then
        song().selected_track.visible_note_columns = clm
      end
      local pos_1 = song().selected_note_column
      local pos_2 = song().selected_line:note_column( clm )
      
      pos_1.note_value, pos_2.note_value = pos_2.note_value, pos_1.note_value
      pos_1.instrument_value, pos_2.instrument_value = pos_2.instrument_value, pos_1.instrument_value
      pos_1.volume_value, pos_2.volume_value = pos_2.volume_value, pos_1.volume_value
      pos_1.panning_value, pos_2.panning_value = pos_2.panning_value, pos_1.panning_value
      pos_1.delay_value, pos_2.delay_value = pos_2.delay_value, pos_1.delay_value
      pos_1.effect_number_value, pos_2.effect_number_value = pos_2.effect_number_value, pos_1.effect_number_value
      pos_1.effect_amount_value, pos_2.effect_amount_value = pos_2.effect_amount_value, pos_1.effect_amount_value

      --song().selected_line:note_column( clm ):copy_from( song().selected_note_column )
      --song().selected_note_column:clear()
      song().selected_note_column_index = clm
    else
      pht_change_status( "No data to move!" )
    end
  else
    pht_change_status( "Select a valid note column (< 12) to move data!" )
  end
end

I usually write by playing many notes at the same time. Then I find it very useful to sort the notes in the note columns as appropriate, where this can be very fast, something you can not do with the mouse (as far as I know)...

 

Solved!


  • ffx likes this

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#3 ffx

ffx

    Composes without Wires burns Directly from Brain to DVD that is already in Store Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPipPip
  • 3390 posts
  • Gender:Not Telling

Posted 30 May 2018 - 21:52

Does this work?:

local indices = {"note", "instrument", "volume", "panning", "delay", "effect_number", "effect_amount"}
local pos_1 = song().selected_note_column
local pos_2 = song().selected_line:note_column( clm )
for i, val in ipairs(indices) do
  pos_1[val .. "_value"], pos_2[val .. "_value"] = pos_2[val .. "_value"], pos_1[val .. "_value"]
end

Edited by ffx, 30 May 2018 - 22:54.

  • Raul (ulneiz) likes this
Test system: macOS 10.13.4, HFS+. Firewire Audio, i7 4770, 8GB Ram, GTX1050 2GB, 48kHz
GUI Automation RecorderNative DSP Context MenuTuned ShortcutsUnified Value Shift And Transpose | Jump To From Send Modified (Docs) | Quick Template | Nisanmol's Groove Tool FixedThemes


#4 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1775 posts
  • Gender:Not Telling

Posted 30 May 2018 - 22:02

Off topic...

 

Don't do this:

local song = renoise.song
local something = song():track(1)

Do this:

local song = renoise.song()
local something = song:track(1)

I'm pretty sure it will save you some time both when typing and when executing :)



#5 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 30 May 2018 - 22:37

Off topic...

 

Don't do this:

local song = renoise.song
local something = song():track(1)

Do this:

local song = renoise.song()
local something = song:track(1)

I'm pretty sure it will save you some time both when typing and when executing :)

 

If I do that, it is necessary to define local song = renoise.song() within all the functions that need it.

 

I use a global: song = renoise.song for the whole tool, and then I use song() within the functions that are needed. Regarding the performance (number of calls) is there a difference?

 

song() used like this is slower or somewhat harmful? I do not mind adding 2 parentheses, if I avoid to save writing the same "local" dozens of times. The context of the tool are dozens of functions that need it.

 

The reason is that it is not possible to write a global or local song = renoise.song(), unless you delay loading the tool after loading the song.


Edited by Raul (ulneiz), 30 May 2018 - 22:38.

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#6 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 00:28

 

Does this work?:

local indices = {"note", "instrument", "volume", "panning", "delay", "effect_number", "effect_amount"}
local pos_1 = song().selected_note_column
local pos_2 = song().selected_line:note_column( clm )
for i, val in ipairs(indices) do
  pos_1[val .. "_value"], pos_2[val .. "_value"] = pos_2[val .. "_value"], pos_1[val .. "_value"]
end

 

Yes! Finally, the function stays that way:

function pht_msc3_move_note_r()
  local snci = song().selected_note_column_index
  local clm = snci + 1
  if ( clm <= 12 ) and ( song().selected_effect_column == nil ) then
    if not ( song().selected_note_column.is_empty ) then
      if ( song().selected_track.visible_note_columns < clm ) then
        song().selected_track.visible_note_columns = clm
      end
      if ( pht_msc3_swap_row_nc == true ) then
        local pos_1 = song().selected_note_column
        local pos_2 = song().selected_line:note_column( clm )
        local id = { "note", "instrument", "volume", "panning", "delay", "effect_number", "effect_amount" }
        for i, val in ipairs( id ) do
          pos_1[val.."_value"], pos_2[val.."_value"] = pos_2[val.."_value"], pos_1[val.."_value"]
        end
      else
        song().selected_line:note_column( clm ):copy_from( song().selected_note_column )
        song().selected_note_column:clear()
      end
      song().selected_note_column_index = clm
    else
      pht_change_status( "No data to move/swap!" )
    end
  else
    pht_change_status( "Select a valid note column (< 12) to move/swap data!" )
  end
end

Saving a few lines is almost always welcome. Thanks! This function works to the right. To the left is very similar. I have added a switch, so you can run two different things, move or swap. Yesterday I composed an orchestral base of 3 minutes, and I yearned a couple of functions like these...


:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#7 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1775 posts
  • Gender:Not Telling

Posted 31 May 2018 - 07:37

If I do that, it is necessary to define local song = renoise.song() within all the functions that need it.


It's more than ten times faster here, so if you access it a lot in a big tool it might make a difference. I just wanted to note it since it's so easy to do it slightly better :)

You can have a global rns = renoise.song() and update it via a new document observable.

#8 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 11:09

It's more than ten times faster here, so if you access it a lot in a big tool it might make a difference. I just wanted to note it since it's so easy to do it slightly better :)

You can have a global rns = renoise.song() and update it via a new document observable.

 

Where and how to put the "new document observable"?

 

This is the typical structure that I'm used to use in my recent tools:

--
-- tool name
--



--main globals
-------------------------------------------------------------------------------------------------
dialog = nil
vb = renoise.ViewBuilder()
vws = vb.views
song = renoise.song() -------------------> where and how to put the "new document observable"?????????????
rnt = renoise.tool()
rna = renoise.app()
rns_version = renoise.RENOISE_VERSION
api_version = renoise.API_VERSION



--other globals
-------------------------------------------------------------------------------------------------




--require
-------------------------------------------------------------------------------------------------
require ("lua/xxx")  -- more song ???????????????????, include many functions and more windows
require ("lua/yyy")  -- more song ???????????????????, include many functions and more windows
require ("lua/zzz")  -- more song ???????????????????, include many functions and more windows



--functions (many functions)
-------------------------------------------------------------------------------------------------
function name_function_01()
  local sti = song.selected_track_index  --song ???????????????????
  local sii = song.selected_instrument_index   --song ???????????????????
  --...
  --...
end
---
function name_function_90()
  rna.window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_PHRASE_EDITOR
  song.selected_instrument.phrase_editor_visible = true  --song ???????????????????
  song.selected_instrument.phrase_playback_mode = renoise.Instrument.PHRASES_PLAY_KEYMAP  --song ???????????????????
  --...
  --...
end



--main content gui
-------------------------------------------------------------------------------------------------
TOOL_GEN_CONTENT = vb:row {
  vb:button {
    text = "Button"
  },
  --...
  --...
}



--show dialog
-------------------------------------------------------------------------------------------------
function show_tool_dialog()
  if ( dialog and dialog.visible ) then dialog:show() return end
  dialog = rna:show_custom_dialog( pht_title, TOOL_GEN_CONTENT, pht_keyhandler )
end



--register menu entry
-------------------------------------------------------------------------------------------------
renoise.tool():add_menu_entry {
  name = "Main Menu:Tools:Name_Tool...",
  invoke = function() show_tool_dialog() end
}
Spoiler

 

In all my previous tools I have used local song = renoise.song() within each function. But I would like to know how to make a global one to song = renoise.song(), and then within each function use song. or song: where necessary.

 

So, where to place and how to place the "new document observable" to avoid the loading error?

 

Note: inside GlobalMidiActions.lua and GlobalOSCActions.lua is used outside the functions a local song = renoise.song, and inside the functions is used song(). or song(): why? Is it 10 times slower?


Edited by Raul (ulneiz), 31 May 2018 - 11:10.

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#9 danoise

danoise

    Probably More God or Borg Than Human Member

  • Renoise Team
  • PipPipPipPipPipPipPipPipPipPipPipPipPipPipPip
  • 6897 posts
  • Gender:Male
  • Location:Berlin
  • Interests:wildlife + urban trekking

Posted 31 May 2018 - 11:33

@Raul: just create the observable anywhere in your main.lua, just like you're adding the "renoise.tool():add_menu_entry" ,etc. 

 

You can have a global rns = renoise.song() and update it via a new document observable.

 

Yes, if you are planning to make an auto-launching tool [1], this is needed as the song is not necessarily available at startup time.

With auto-launching tools, there are two particular scenarios to be aware of (that need testing): 

 

* Starting Renoise with the tool already installed

* Installing the tool for the first time 

 

I've forgotten either one from time to time. Eventually, someone notices and sends me a bug report :D

 

[1] By "auto-launching", I mean a tool that doesn't wait for the user to take some kind of action, but actively "does stuff" on startup.


Tracking with Stuff. API wishlist | Soundcloud


#10 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1775 posts
  • Gender:Not Telling

Posted 31 May 2018 - 11:43

Yeah.. it's a tounge-in-cheek operation indeed. I thought of adding this to the speed optimization thread. Do you think it's correct, or am I missing something in regards to the installation scenario?
 
song = nil

-- Tool code here.

function setup()
  song = renoise.song()
end

renoise.tool().app_new_document_observable:add_notifier(setup)

-- Or tool code here. It doesn't matter.

-- Optional segment below, showing the simplest way to avoid errors with tools
-- that need "auto-launching".

function main()
  -- Do stuff when the tool is loaded.
  -- Set some global bool and check, if you only want main() being executed once.
end

renoise.tool().app_new_document_observable:add_notifier(main)

EDIT: The installation issue might be due to the bad habit of executing main() top-level in the tool? It might be better practice to do that via app_new_document_observable as well (and store a bool if you only want to do it once)

EDIT 2: This should be a safe boiler-plate for any scenario? Note that the order in which notifiers are registered is also reflected in the order by which they are executed, which is nice.

Edited by joule, 31 May 2018 - 15:07.


#11 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 14:53

local song

-- Tool code here.

function setup()
  song = renoise.song()
end

renoise.tool().app_new_document_observable:add_notifier(setup)

As I understand with this code, "song" is a local, that only serves inside the main.lua file. If you have other files through require, this "local song" would not work. I believe (this I would have to prove it).

 

The issue would be to find an easy way to define "song = renoise.song()" and that song is a global one that works for all attachments by require( "lua/file_1" )

 

 

The mother folder of the tool would have these files:

  • main.lua
  • manifest.xml
  • preferences.xml
  • lua (folder):
    • file_1.lua
    • file_2.lua
    • ...
    • file_9.lua

Maybe for a global, should it be like that?:

song = nil

function setup()
  song = renoise.song()
end

renoise.tool().app_new_document_observable:add_notifier(setup)

-- Require files

-- Tool code here

:huh:. This should work for all the required files as well, I suppose. I understand that renoise.tool().app_new_document_observable:add_notifier(setup), only runs once when loading a new song, or when loading renoise (which creates a new song as well).

 

All this is true? I have always thought that in the function setup(), "song" could only be used within this function, not outside (because it must be a local). But I suppose that to declare "song" before, outside as global, will work for all functions inside the entire tool (all the files .lua).

 

All of that is very important. All the functions of the tool depend on it. And so it would be very simple to invoke "song." or "song:" within all the functions of the entire tool, including the .lua files invoked from require().

 

I would like this whole thing to be very clear.

 

 

Additional note: I would like to know why GlobalMidiAction.lua and GlobalOSCactions.lua use song(). or song(): defining the local previously like this: local song = renoise.song.  It is not supposed that local song = renoise.song() is 10 times more faster???


:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#12 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1775 posts
  • Gender:Not Telling

Posted 31 May 2018 - 15:04

Ah sorry. I think you're correct about song = nil being better. Fixed.

The examples you're referring to are probably made that way not to complicate matters too much for new users - trying to stay on point. (You'll also see examples using the pattern iterator, even though there are way faster ways to do things). More importantly, there is the rule about not overdoing optimizations. When only a few calls are made, the speed gain of optimizations are negligible.

But since you're trying to cache renoise.song, I thought I'd share the best way of doing it.

Regarding where variables are accessible. That's what's called its "scope", and is indeed important to understand. A variable will be accessible on the same "level" and all levels below from where it's declared. For example, if you define local j inside a for loop, it is only accessible within that loop. If you define it right before the for loop, it will remain accessible after the loop (set to the last value). I think you're correct that "song = nil" will make song accessible from all files. Fun fact: it's really stored in the _G table as _G.song (G implying global). That's your tools "environment" table, which is a table with its top level listing everything that is "global".

http://lua-users.org...i/ScopeTutorial

Edited by joule, 31 May 2018 - 15:23.


#13 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 16:31

Ah sorry. I think you're correct about song = nil being better. Fixed.

The examples you're referring to are probably made that way not to complicate matters too much for new users - trying to stay on point. (You'll also see examples using the pattern iterator, even though there are way faster ways to do things). More importantly, there is the rule about not overdoing optimizations. When only a few calls are made, the speed gain of optimizations are negligible.

But since you're trying to cache renoise.song, I thought I'd share the best way of doing it.

Regarding where variables are accessible. That's what's called its "scope", and is indeed important to understand. A variable will be accessible on the same "level" and all levels below from where it's declared. For example, if you define local j inside a for loop, it is only accessible within that loop. If you define it right before the for loop, it will remain accessible after the loop (set to the last value). I think you're correct that "song = nil" will make song accessible from all files. Fun fact: it's really stored in the _G table as _G.song (G implying global). That's your tools "environment" table, which is a table with its top level listing everything that is "global".

http://lua-users.org...i/ScopeTutorial

 

Thanks!

 

Ok, I just built a tool template that has just the specific scheme that I would like to use always in my future tools:

 

template tool: Attached File  com.ulneiz.Rodent.xrnx   2.2KB   8 downloads

 

See how all the global ones are ordered, which can be used in all the .lua files of the tool. Finally, the global song is defined as follows:

rnt = renoise.tool()
---
song = nil
function song_obs()
  song = renoise.song()
end
rnt.app_new_document_observable:add_notifier( song_obs )

In this way, it works correctly when loading renoise for the first time, and also when loading any new song afterwards, but return an error after installing the tool, when executing any function ( ...failed in one of its notifiers.     main.lua ?? attempt to index global "song" a nil value )  :blush:  :blush:  :blush:. What is missing here??? If you reload the tools (Tools/Reload all Tools) this error disappears.  :unsure:  :unsure:  :unsure:

 

In summary:
  1. start renoise: ok!
  2. new song: ok!
  3. install tool: fail!!!

 

Thus, within each function, it is possible to use song. or song: without defining a previous location (local song = renoise.song ()).

 

As it is now defined "song" as global, would you get the maximum performance (lower number of calls)?

 

As I understand it, the global "song" is defined only once, and it must be above the code, at the beginning.

 

But, how to fix the tool to avoid any error, maintaining the structure and the global song?


Edited by Raul (ulneiz), 31 May 2018 - 18:27.

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#14 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 16:37

Ok rnt.app_new_document_observable:add_notifier( song_obs ) it only acts when loading a new song, but not when installing a new tool (here it is not loading a new song). Something is missing that says that when you install the tool, update song by reading the function song_obs()

 

Solving this, everything would be solved, I believe.


:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#15 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1775 posts
  • Gender:Not Telling

Posted 31 May 2018 - 16:50

Cool.. forgot one thing it seems. You need to run song_obs() 'manually' ONCE from the first function you call to catch this edge case.

In your case, it would be a good choice to run it someplace in top of the function that shows your GUI.

#16 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 16:55

Cool.. forgot one thing it seems. You need to run song_obs() 'manually' ONCE from the first function you call to catch this edge case.

In your case, it would be a good choice to run it someplace in top of the function that shows your GUI.

 

How? I can not do this:
rnt = renoise.tool()
---
song = nil
function song_obs()
  song = renoise.song()
end

song_obs() -->>>>>>>>>>>>>>>>>>>>> return error!

rnt.app_new_document_observable:add_notifier( song_obs )

I think the GUI has nothing to do, since it does not perform any function where the glogal "song" is required. The problem is executing the function song_obs()

 

Is not there any _observable to run once after installing the tool?


Edited by Raul (ulneiz), 31 May 2018 - 16:55.

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#17 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1775 posts
  • Gender:Not Telling

Posted 31 May 2018 - 16:59

Unfortunately not.

Put it at the top of rdn_main_dialog(). Otherwise you'll try to access song before it's available. The point being you just have to make sure it's being ran once (via what the user does), so it also catches this installation scenario.

Edited by joule, 31 May 2018 - 17:01.


#18 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 17:05

Unfortunately not.

Put it at the top of rdn_main_dialog(). Otherwise you'll try to access song before it's available. The point being you just have to make sure it's being ran once (via what the user does), so it also catches this installation scenario.

 

If I do that, it will be necessary to invoke the song_obs() function within all the functions that are responsible for showing a new window (of the same tool). There must be some way to force the reading of a function immediately after installing a tool.

 

Would this work?

rnt = renoise.tool()
---
song = nil
function song_obs()
  song = renoise.song()
end

if ( song == nil ) and not ( rnt.app_new_document_observable:has_notifier( song_obs ) ) then
  rnt.app_new_document_observable:add_notifier( song_obs )
end

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#19 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 17:11

Perfect!!!! Work!!!!   :)  :)  :)


:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#20 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1775 posts
  • Gender:Not Telling

Posted 31 May 2018 - 17:19

Nah.. I don't think so. Is your GUI+buttons really working even when installing now?

I think this is the practical solution.. put at the top of main.lua.

song = nil

function song_obs()
  song = renoise.song()
end

renoise.tool().app_new_document_observable:add_notifier(song_obs)

if pcall(function() return renoise.song() end) then
  song = renoise.song() -- catching installation scenario
end

Edited by joule, 31 May 2018 - 17:21.


#21 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 17:20

This seems to be the most appropriate order:

-------------------------------------------------------------------------------------------------
--local global variables/tables
main_dialog = nil
local rdn_main_title = " Rodent"
pht_version = "1.1 build 0001"
rns_version = renoise.RENOISE_VERSION
api_version = renoise.API_VERSION
---
vb = renoise.ViewBuilder()
vws = vb.views
rna = renoise.app()
rnt = renoise.tool()
---
song = nil
function song_obs()
  song = renoise.song()
end
if ( song == nil ) and not ( rnt.app_new_document_observable:has_notifier( song_obs ) ) then
  rnt.app_new_document_observable:add_notifier( song_obs )
end



-------------------------------------------------------------------------------------------------
--require
require ( "lua/file_1" )
require ( "lua/file_2" )
--
require ( "lua/keyhandler" )



-------------------------------------------------------------------------------------------------
--main functions

--
--

song = nil    -- the global

 
function song_obs()   -- the function of conversation
  song = renoise.song()
end
 
if ( song == nil ) and not ( rnt.app_new_document_observable:has_notifier( song_obs ) ) then   -- the condition: song == nil ?
  rnt.app_new_document_observable:add_notifier( song_obs )    -- the new document observable
end
 
If this works correctly, it would be most comfortable for a tool that includes several windows. song is only defined once.

Nah.. I don't think so. Is your GUI+buttons really working even when installing now?

 

Yes!


Edited by Raul (ulneiz), 31 May 2018 - 18:37.

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#22 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 17:25

You can try it yourself with this new template: Attached File  com.ulneiz.Rodent.xrnx   2.22KB   9 downloads

 

It seems to work well in all scenarios.


Edited by Raul (ulneiz), 31 May 2018 - 18:26.

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#23 joule

joule

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1775 posts
  • Gender:Not Telling

Posted 31 May 2018 - 17:32

Nope.. not when installing by double-clicking.

Remove the "song_obs()" call from the dialog function. No cheating :)

My solution above seems to work universally.

Edited by joule, 31 May 2018 - 17:35.


#24 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 17:50

Nope.. not when installing by double-clicking.

Remove the "song_obs()" call from the dialog function. No cheating :)

My solution above seems to work universally.

 

^_^ I forgot to delete it  :blink:

-------------------------------------------------------------------------------------------------
--local global variables/tables
main_dialog = nil
local rdn_main_title = " Rodent"
pht_version = "1.1 build 0001"
rns_version = renoise.RENOISE_VERSION
api_version = renoise.API_VERSION
---
vb = renoise.ViewBuilder()
vws = vb.views
rna = renoise.app()
rnt = renoise.tool()
---
song = nil
function song_obs()
  song = renoise.song()
end

-- catching new song / start renoise
rnt.app_new_document_observable:add_notifier( song_obs )

-- catching installation scenario
if pcall ( function() return renoise.song() end ) then
  song = renoise.song()
end



-------------------------------------------------------------------------------------------------
--require
require ( "lua/file_1" )
require ( "lua/file_2" )
--
require ( "lua/keyhandler" )



-------------------------------------------------------------------------------------------------
--main functions
 
Yes now!!!  Thanks!
 
song = nil
 
function song_obs()
  song = renoise.song()
end

-- catching new song / start renoise
rnt.app_new_document_observable:add_notifier( song_obs )

-- catching installation scenario
if pcall ( function() return renoise.song() end ) then
  song = renoise.song()
end
 
Ufff, to have to get here. For me, this "song" issue has always been a nuisance. This should be done in the API in another way so as not to have so many problems with renoise.song (). But hey, this seems to be the best solution so far I've seen.

  • joule likes this

:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler

#25 Raul (ulneiz)

Raul (ulneiz)

    Guruh Motha Fakka is Levitating and Knows Everything About Renoise Member

  • Normal Members
  • PipPipPipPipPipPipPipPipPipPipPipPipPip
  • 1488 posts
  • Gender:Male
  • Location:Spain

Posted 31 May 2018 - 18:26

Then the final tool template looks like this (work fine!): Attached File  com.ulneiz.Rodent.xrnx   2.26KB   9 downloads

 

Look at this!!!... To define some important globals:
  • vb = renoise.ViewBuilder() --ok, easy!
  • vws = vb.views --ok, easy!
  • rna = renoise.app() --ok, easy!
  • rnt = renoise.tool() --ok, easy!
  • song = renoise.song() --no ok, problems for this global!!! In addition, in most tools is the most needed!

It would be nice to detail this whole thing in the thread of renoise tool speed optimization initiativehttp://forum.renoise...ion-initiative/

 

Especially in the type of more complex tools, like this template, you can invoke several internal windows in the same tool, including several files through require("file").


:excl: Development of my tools: KangarooX120SamRenderPhraseTouch  |  GT16-Colors (old)

 

:excl: My API wishlist R3.1 (updated 24 July 2017):

Spoiler

 

:excl: My Renoise 3.1 wishlist (updated 26 September 2017):

Spoiler