diff --git a/Paketti0G01_Loader.lua b/Paketti0G01_Loader.lua index 1b16884..b880e61 100644 --- a/Paketti0G01_Loader.lua +++ b/Paketti0G01_Loader.lua @@ -77,23 +77,6 @@ local function find_sample_rate_index(rate) return 1 -- default to 22050 if not found end -local function pakettiGetXRNIDefaultPresetFiles() - local presetsFolder = "Presets/" - local files = {} - local handle = io.popen('ls "' .. presetsFolder .. '"') - if handle then - for file in handle:lines() do - if file:match("%.xrni$") then - table.insert(files, file) - end - end - handle:close() - end - return files -end - -local presetFiles = pakettiGetXRNIDefaultPresetFiles() - local os_name=os.platform() local default_executable if os_name=="WINDOWS"then @@ -185,8 +168,8 @@ preferences = renoise.Document.create("ScriptingToolPreferences") { }, -- changes made - -- Paketti ReSpeak Segment - pakettiReSpeak = { + -- Paketti eSpeak Segment + pakettieSpeak = { word_gap=3, capitals=5, pitch=35, @@ -280,14 +263,17 @@ preferences = renoise.Document.create("ScriptingToolPreferences") { Length = 64, SetName = false, Name = "" - } + }, + pakettiDynamicViews = { + bla ="ble" + } } -- Assigning Preferences to renoise.tool renoise.tool().preferences = preferences -- Accessing Segments -ReSpeak = renoise.tool().preferences.pakettiReSpeak +eSpeak = renoise.tool().preferences.pakettieSpeak pakettiThemeSelector = renoise.tool().preferences.pakettiThemeSelector WipeSlices = renoise.tool().preferences.WipeSlices AppSelection = renoise.tool().preferences.AppSelection @@ -307,27 +293,25 @@ end -- Call the initialization function once initialize_filter_index() - - - --- Function to load preset files local function pakettiGetXRNIDefaultPresetFiles() local presetsFolder = "Presets/" - local files = {} - local handle = io.popen('ls "' .. presetsFolder .. '"') - if handle then - for file in handle:lines() do - if file:match("%.xrni$") then - table.insert(files, file) - end - end - handle:close() + local files = os.filenames(presetsFolder, "*.xrni") + + -- Check if any presets were found + if not files or #files == 0 then + renoise.app():show_status("No .xrni preset files found in: " .. presetsFolder) + return { "" } end + + -- Sort the files alphabetically for better user experience + table.sort(files, function(a, b) return a:lower() < b:lower() end) + + -- Insert a default option at the beginning + table.insert(files, 1, "") + return files end -local presetFiles = pakettiGetXRNIDefaultPresetFiles() - -- Function to create horizontal rule function horizontal_rule() return vb:horizontal_aligner{mode="justify", width="100%", vb:space{width=2}, vb:row{height=2, width="30%", style="panel"}, vb:space{width=2}} @@ -395,6 +379,8 @@ function show_paketti_preferences() return end + local presetFiles = pakettiGetXRNIDefaultPresetFiles() + -- Get the initial value (index) for the popup local pakettiDefaultXRNIDisplayId = "pakettiDefaultXRNIDisplay_" .. tostring(math.random(2,30000)) local pakettiDefaultDrumkitXRNIDisplayId = "pakettiDefaultDrumkitXRNIDisplay_" .. tostring(math.random(2,30000)) diff --git a/PakettiAudioProcessing.lua b/PakettiAudioProcessing.lua index 8ae037c..6407a77 100644 --- a/PakettiAudioProcessing.lua +++ b/PakettiAudioProcessing.lua @@ -824,6 +824,41 @@ renoise.tool():add_keybinding {name = "Sample Editor:Paketti:Invert Right, Sum M renoise.tool():add_keybinding {name = "Sample Editor:Paketti:Audio Diff", invoke = function() create_audio_diff_sample() end} renoise.tool():add_keybinding {name = "Global:Paketti:Paketti Audio Processing Tools Dialog...", invoke = function() PakettiAudioProcessingToolsDialogShow() end} +function update_sample_details(details_text, sample_name_text) + -- If UI elements are not properly initialized, exit early + -- if not details_text or not sample_name_text then + -- print("UI elements are not initialized yet.") + -- return + -- end + + local song = renoise.song() + if song then + local instrument = song.selected_instrument + if instrument then + local sample_index = song.selected_sample_index + + if sample_index > 0 and sample_index <= #instrument.samples then + local sample = instrument:sample(sample_index) + if sample then + local buffer = sample.sample_buffer + if buffer and buffer.has_sample_data then + -- Update the UI elements with valid sample data + details_text.text = string.format("Details: %dHz, %dbit, %d frames", + buffer.sample_rate, buffer.bit_depth, buffer.number_of_frames) + sample_name_text.text = "Name: " .. sample.name + + renoise.app():show_status("Sample details and name updated.") + return -- Exit after successful update + end + end + end + end + end + + -- Fallback if no valid sample is available + details_text.text = "Details: No valid sample selected" + sample_name_text.text = "Name: No valid sample selected" +end function PakettiStripSilence() local song = renoise.song() @@ -934,7 +969,6 @@ function PakettiStripSilence() renoise.app():show_status("Removed Silence from beginning + end of sample at threshold " .. (threshold * 100) .. "%") end - function PakettiMoveSilence() local song = renoise.song() local sample_index = song.selected_sample_index @@ -1117,42 +1151,6 @@ end renoise.tool():add_keybinding { name="Sample Editor:Paketti:Max Amp DC Offset Kick Generator", invoke=function() pakettiMaxAmplitudeDCOffsetKickCreator() end } renoise.tool():add_menu_entry { name="Sample Editor:Paketti..:Max Amp DC Offset Kick Generator", invoke=function() pakettiMaxAmplitudeDCOffsetKickCreator() end } -function update_sample_details(details_text, sample_name_text) - -- If UI elements are not properly initialized, exit early - -- if not details_text or not sample_name_text then - -- print("UI elements are not initialized yet.") - -- return - -- end - - local song = renoise.song() - if song then - local instrument = song.selected_instrument - if instrument then - local sample_index = song.selected_sample_index - - if sample_index > 0 and sample_index <= #instrument.samples then - local sample = instrument:sample(sample_index) - if sample then - local buffer = sample.sample_buffer - if buffer and buffer.has_sample_data then - -- Update the UI elements with valid sample data - details_text.text = string.format("Details: %dHz, %dbit, %d frames", - buffer.sample_rate, buffer.bit_depth, buffer.number_of_frames) - sample_name_text.text = "Name: " .. sample.name - - renoise.app():show_status("Sample details and name updated.") - return -- Exit after successful update - end - end - end - end - end - - -- Fallback if no valid sample is available - details_text.text = "Details: No valid sample selected" - sample_name_text.text = "Name: No valid sample selected" -end - -- Function to apply the recursive DC offset correction algorithm function remove_dc_offset_recursive() local sample_buffer = renoise.song().selected_sample.sample_buffer diff --git a/PakettiEightOneTwenty.lua b/PakettiEightOneTwenty.lua index e510a0b..c82466c 100644 --- a/PakettiEightOneTwenty.lua +++ b/PakettiEightOneTwenty.lua @@ -1,54 +1,43 @@ --- Initialize ViewBuilder local vb = renoise.ViewBuilder() +local dialog, rows = nil, {} +local track_names, track_indices, instrument_names +local play_checkbox, follow_checkbox, bpm_display, groove_enabled_checkbox, random_gate_button, fill_empty_label, fill_empty_slider, global_step_buttons, global_controls --- Declare global variables -local dialog = nil -local rows = {} -local track_names = {} -local track_indices = {} -local instrument_names = {} -local play_checkbox = nil -local follow_checkbox = nil -local bpm_display = nil -local groove_enabled_checkbox = nil -local random_gate_button = nil -local fill_empty_label = nil -local fill_empty_slider = nil -local global_step_buttons = nil -local global_controls = nil - --- Function to set global steps across all rows local function set_global_steps(steps) for _, row_elements in ipairs(rows) do - row_elements.updating_steps = true -- Prevent notifier from triggering + row_elements.updating_steps = true row_elements.valuebox.value = steps row_elements.updating_steps = false row_elements.print_to_pattern() end renoise.app():show_status("All step counts set to " .. tostring(steps) .. ".") + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end --- Function to implement Random Gate local function random_gate() - -- For each checkbox position (1 to 16) + for _, row_elements in ipairs(rows) do + row_elements.updating_checkboxes = true + end for i = 1, 16 do - -- Randomly select one of the 8 rows local selected_row = math.random(1, #rows) - -- Set the selected checkbox to true, others to false for row_index, row_elements in ipairs(rows) do row_elements.checkboxes[i].value = (row_index == selected_row) end end - -- Update all patterns for _, row_elements in ipairs(rows) do row_elements.print_to_pattern() + row_elements.valuebox.value = 16 + end + for _, row_elements in ipairs(rows) do + row_elements.updating_checkboxes = false end - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 as per your requirement + renoise.app():show_status("Stepcount reset to 16, all rows filled with one checkbox per each rowstep.") + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end --- Function to fill empty steps randomly local function fill_empty_steps(probability) for _, row_elements in ipairs(rows) do + row_elements.updating_checkboxes = true local checkboxes = row_elements.checkboxes for i = 1, 16 do if not checkboxes[i].value then @@ -57,12 +46,12 @@ local function fill_empty_steps(probability) end end end + row_elements.updating_checkboxes = false row_elements.print_to_pattern() end - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 as per your requirement + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end --- Key Handler for Dialog local function PakettiEightSlotsByOneTwentyKeyHandler(dialog, key) local closer = preferences.pakettiDialogClose.value if key.modifiers == "" and key.name == closer then @@ -75,40 +64,157 @@ local function PakettiEightSlotsByOneTwentyKeyHandler(dialog, key) end end --- Function to update instrument list and popups local function update_instrument_list_and_popups() instrument_names = {} for i, instr in ipairs(renoise.song().instruments) do table.insert(instrument_names, instr.name ~= "" and instr.name or "Instrument " .. i) end - for i, row_elements in ipairs(rows) do local instrument_popup = row_elements.instrument_popup local previous_value = instrument_popup.value - instrument_popup.items = instrument_names - if previous_value <= #instrument_names then instrument_popup.value = previous_value else instrument_popup.value = 1 end + row_elements.update_sample_name_label() + end +end + +local function debug_instruments_and_samples() + print("----- Debug: Instruments and Samples (Velocity 00-7F) -----") + for row_index, row_elements in ipairs(rows) do + local instrument_index = row_elements.instrument_popup.value + local instrument = renoise.song().instruments[instrument_index] + local instrument_name = instrument and (instrument.name ~= "" and instrument.name or "Instrument " .. instrument_index) or "Unknown Instrument" + if instrument then + local sample_count = #instrument.samples + if sample_count > 0 then + for sample_index, sample in ipairs(instrument.samples) do + local velocity_min = sample.sample_mapping and sample.sample_mapping.velocity_range and sample.sample_mapping.velocity_range[1] or nil + local velocity_max = sample.sample_mapping and sample.sample_mapping.velocity_range and sample.sample_mapping.velocity_range[2] or nil + if velocity_min == 0x00 and velocity_max == 0x7F then + local sample_name = sample.name ~= "" and sample.name or "Sample " .. sample_index + print(string.format("Row %d: Instrument [%d] '%s', Sample [%d] '%s' has Velocity Range: %02X-%02X", row_index, instrument_index, instrument_name, sample_index, sample_name, velocity_min, velocity_max)) + end + end + end + end + end + print("----- End of Debug -----") +end + +local function reverse_sample(row_elements) + local instrument_index = row_elements.instrument_popup.value + local instrument = renoise.song().instruments[instrument_index] + if not instrument then + renoise.app():show_message("Instrument not found for this row.") + return + end + local sample_to_reverse = nil + for _, sample in ipairs(instrument.samples) do + local velocity_min = sample.sample_mapping and sample.sample_mapping.velocity_range and sample.sample_mapping.velocity_range[1] + local velocity_max = sample.sample_mapping and sample.sample_mapping.velocity_range and sample.sample_mapping.velocity_range[2] + if velocity_min == 0x00 and velocity_max == 0x7F then + sample_to_reverse = sample + break + end + end + if not sample_to_reverse or not sample_to_reverse.sample_buffer then + renoise.app():show_message("Sample with velocity range 00-7F not found or has no audio data for this row.") + return + end + local sample_buffer = sample_to_reverse.sample_buffer + local num_channels = sample_buffer.number_of_channels + local num_frames = sample_buffer.number_of_frames + if num_channels == 0 or num_frames == 0 then + renoise.app():show_message("Selected sample has no channels or frames for this row.") + return + end + sample_buffer:prepare_sample_data_changes() + for channel = 1, num_channels do + local channel_data = {} + for frame = 1, num_frames do + channel_data[frame] = sample_buffer:sample_data(channel, frame) + end + for i = 1, math.floor(num_frames / 2) do + channel_data[i], channel_data[num_frames - i + 1] = channel_data[num_frames - i + 1], channel_data[i] + end + for frame = 1, num_frames do + sample_buffer:set_sample_data(channel, frame, channel_data[frame]) + end + end + sample_buffer:finalize_sample_data_changes() + local sample_name = sample_to_reverse.name ~= "" and sample_to_reverse.name or "Sample " .. sample_to_reverse.index + local instrument_name = instrument.name ~= "" and instrument.name or "Instrument " .. instrument_index + renoise.app():show_status(string.format("Reversed Sample '%s' of Instrument '%s' for Row.", sample_name, instrument_name)) +end + +local function reverse_all() + local reversed_samples = {} + for row_index, row_elements in ipairs(rows) do + local instrument_index = row_elements.instrument_popup.value + local instrument = renoise.song().instruments[instrument_index] + if not instrument then + table.insert(reversed_samples, string.format("Row %d: Instrument not found.", row_index)) + else + local sample_to_reverse = nil + for _, sample in ipairs(instrument.samples) do + local velocity_min = sample.sample_mapping and sample.sample_mapping.velocity_range and sample.sample_mapping.velocity_range[1] + local velocity_max = sample.sample_mapping and sample.sample_mapping.velocity_range and sample.sample_mapping.velocity_range[2] + if velocity_min == 0x00 and velocity_max == 0x7F then + sample_to_reverse = sample + break + end + end + if not sample_to_reverse or not sample_to_reverse.sample_buffer then + table.insert(reversed_samples, string.format("Row %d: Sample not found or no audio data.", row_index)) + else + local sample_buffer = sample_to_reverse.sample_buffer + local num_channels = sample_buffer.number_of_channels + local num_frames = sample_buffer.number_of_frames + if num_channels == 0 or num_frames == 0 then + table.insert(reversed_samples, string.format("Row %d: Selected sample has no channels or frames.", row_index)) + else + sample_buffer:prepare_sample_data_changes() + for channel = 1, num_channels do + local channel_data = {} + for frame = 1, num_frames do + channel_data[frame] = sample_buffer:sample_data(channel, frame) + end + for i = 1, math.floor(num_frames / 2) do + channel_data[i], channel_data[num_frames - i + 1] = channel_data[num_frames - i + 1], channel_data[i] + end + for frame = 1, num_frames do + sample_buffer:set_sample_data(channel, frame, channel_data[frame]) + end + end + sample_buffer:finalize_sample_data_changes() + local sample_name = sample_to_reverse.name ~= "" and sample_to_reverse.name or "Sample " .. sample_to_reverse.index + local instrument_name = instrument.name ~= "" and instrument.name or "Instrument " .. instrument_index + table.insert(reversed_samples, string.format("Row %d: Reversed Sample '%s' of Instrument '%s'.", row_index, sample_name, instrument_name)) + end + end + end + end + if #reversed_samples > 0 then + local status_message = table.concat(reversed_samples, "\n") + renoise.app():show_status(status_message) + else + renoise.app():show_status("No samples were reversed.") end end --- Function to create a single row local function PakettiEightSlotsByOneTwentyCreateRow(row_index) local row_elements = {} - preferences.PakettiEightSlotsByOneTwenty = preferences.PakettiEightSlotsByOneTwenty or {} local row_prefs = preferences.PakettiEightSlotsByOneTwenty[row_index] or {} preferences.PakettiEightSlotsByOneTwenty[row_index] = row_prefs - - -- Colors for buttons - local normal_color = nil - local highlight_color = { 0x22 / 255, 0xaa / 255, 0xff / 255 } -- Custom highlight color for specific buttons - - -- Numbered Buttons (for display) + + local normal_color, highlight_color = nil, {0x22 / 255, 0xaa / 255, 0xff / 255} + + -- Create Number Buttons (1-16) local number_buttons = {} for i = 1, 16 do local is_highlight = (i == 1 or i == 5 or i == 9 or i == 13) @@ -116,119 +222,112 @@ local function PakettiEightSlotsByOneTwentyCreateRow(row_index) text = string.format("%02d", i), width = 30, color = is_highlight and highlight_color or normal_color, - notifier = function() end, -- No action needed - active = false, -- Make buttons non-clickable + notifier = function() end, + active = false } end - - -- Create Checkboxes + + -- Create Checkboxes (1-16) local checkboxes = {} for i = 1, 16 do checkboxes[i] = vb:checkbox { value = false, width = 30, notifier = function() - row_elements.print_to_pattern() - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame + if not row_elements.updating_checkboxes then + row_elements.print_to_pattern() + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR + end end } end - - -- Create Popups and Controls + + -- Track Popup local track_popup = vb:popup { items = track_names, - value = row_prefs.track_value or row_index, -- Load from preferences or default to row_index + value = row_prefs.track_value or row_index, notifier = function(value) row_prefs.track_value = value row_elements.initialize_row() end } - - -- Mute/Unmute Checkbox with minimized text width + + -- Mute Checkbox local mute_checkbox = vb:checkbox { - value = false, -- Will be set in initialize_row() + value = false, notifier = function(value) - -- Save to preferences row_prefs.mute_value = value - - -- Mute or unmute the track immediately local track_index = track_indices[track_popup.value] local track = renoise.song().tracks[track_index] track.mute_state = value and renoise.Track.MUTE_STATE_MUTED or renoise.Track.MUTE_STATE_ACTIVE - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end } - - -- Valuebox for Steps without "Steps:" label + + -- Valuebox for Steps local valuebox = vb:valuebox { min = 1, max = 16, value = 16, - width = 50, -- Adjusted width to 50 + width = 50, notifier = function(value) if not row_elements.updating_steps then row_elements.print_to_pattern() - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end end } - + -- Slider for Sample Selection local slider = vb:slider { min = 1, max = 120, value = 1, - width = 100, + width = 130, notifier = function(value) - -- Select the instrument defined in instrument_popup local instrument_index = row_elements.instrument_popup.value renoise.song().selected_instrument_index = instrument_index - -- Assuming midi_sample_velocity_switcharoo is defined elsewhere if type(midi_sample_velocity_switcharoo) == "function" then midi_sample_velocity_switcharoo(value) end row_elements.update_sample_name_label() - renoise.app().window.active_middle_frame = 5 -- Focus Sample Editor + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR end } - + -- Sample Name Label - local sample_name_label = vb:text { text = "Sample Name", font = "bold", style = "strong" } - - -- Instrument Popup with increased width + local sample_name_label = vb:text { + text = "Sample Name", + font = "bold", + style = "strong" + } + + -- Instrument Popup local instrument_popup = vb:popup { items = instrument_names, - value = row_prefs.instrument_value or row_index, -- Load from preferences or default to row_index - width = 150, -- Increased width + value = row_prefs.instrument_value or row_index, + width = 150, notifier = function(value) row_prefs.instrument_value = value row_elements.print_to_pattern() row_elements.update_sample_name_label() - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR end } - - -- Function to print to pattern for this row + + -- Function to Print to Pattern local function print_to_pattern() - -- Efficiently write notes to the pattern - - -- Get the pattern and its length local song = renoise.song() local pattern = song.selected_pattern local pattern_length = pattern.number_of_lines - local steps = valuebox.value local track_index = track_indices[track_popup.value] local instrument_index = instrument_popup.value - - -- Write note data to the first 'steps' lines based on the checkboxes local track_in_pattern = pattern.tracks[track_index] - - -- Write notes based on checkboxes + for line = 1, steps do local checkbox_value = checkboxes[line].value local note_line = track_in_pattern:line(line).note_columns[1] - if checkbox_value then note_line.note_string = "C-4" note_line.instrument_value = instrument_index - 1 @@ -236,58 +335,55 @@ local function PakettiEightSlotsByOneTwentyCreateRow(row_index) note_line:clear() end end - - -- Replicate the initial 'steps' lines throughout the rest of the pattern + for line = steps + 1, pattern_length do local source_line_index = ((line - 1) % steps) + 1 local source_note_line = track_in_pattern:line(source_line_index).note_columns[1] local dest_note_line = track_in_pattern:line(line).note_columns[1] - dest_note_line:copy_from(source_note_line) end end - - -- Function to update sample name label + + -- Function to Update Sample Name Label local function update_sample_name_label() local instrument = renoise.song().instruments[instrument_popup.value] - local sample_index = math.floor(slider.value) - if instrument.samples[sample_index] then - local sample = instrument.samples[sample_index] - if sample.name ~= "" then - sample_name_label.text = sample.name - else - sample_name_label.text = "Sample " .. sample_index + local sample_name = "No valid sample selected" + if instrument and #instrument.samples > 0 then + for _, sample in ipairs(instrument.samples) do + local velocity_min = sample.sample_mapping and sample.sample_mapping.velocity_range and sample.sample_mapping.velocity_range[1] + local velocity_max = sample.sample_mapping and sample.sample_mapping.velocity_range and sample.sample_mapping.velocity_range[2] + if velocity_min == 0x00 and velocity_max == 0x7F then + sample_name = sample.name ~= "" and sample.name or "Sample " .. sample.index + break + end end - else - sample_name_label.text = "No sample" end + sample_name_label.text = sample_name end - - -- Function to initialize the row (populate checkboxes and set mute state) + + -- Function to Initialize Row local function initialize_row() - -- Populate checkboxes local track_index = track_indices[track_popup.value] local track = renoise.song().tracks[track_index] local pattern = renoise.song().selected_pattern local line_count = pattern.number_of_lines - - -- Temporarily disable checkboxes during initialization + row_elements.updating_checkboxes = true + for i = 1, 16 do checkboxes[i].active = false checkboxes[i].value = false end - + for line = 1, math.min(line_count, 16) do local note_line = pattern.tracks[track_index].lines[line].note_columns[1] if note_line and note_line.note_string == "C-4" then checkboxes[line].value = true end end - + local mute = track.mute_state == renoise.Track.MUTE_STATE_MUTED mute_checkbox.value = mute - - -- Determine the instrument used and set instrument_popup.value + local instrument_used = nil for line = 1, math.min(line_count, 16) do local note_line = pattern.tracks[track_index].lines[line].note_columns[1] @@ -296,61 +392,98 @@ local function PakettiEightSlotsByOneTwentyCreateRow(row_index) break end end - - if instrument_used then instrument_popup.value = instrument_used + 1 end + + if instrument_used and instrument_used + 1 <= #instrument_names then + instrument_popup.value = instrument_used + 1 + else + instrument_popup.value = 1 + end + update_sample_name_label() - - -- Re-enable checkboxes after initialization + row_elements.updating_checkboxes = false + for i = 1, 16 do checkboxes[i].active = true end end - - -- Browse Function + + -- Function to Browse Instrument local function browse_instrument() - renoise.song().selected_track_index = 1 -- Set selected_track_index to 1 - renoise.song().selected_instrument_index = instrument_popup.value - -- Assuming pitchBendDrumkitLoader is defined elsewhere + local track_popup_value = track_popup.value + local instrument_popup_value = instrument_popup.value + local track_index = track_indices[track_popup_value] + local instrument_index = instrument_popup_value + renoise.song().selected_track_index = track_index + renoise.song().selected_instrument_index = instrument_index + if type(pitchBendDrumkitLoader) == "function" then pitchBendDrumkitLoader() + else + renoise.app():show_warning("pitchBendDrumkitLoader function is not defined.") + end + + local instrument = renoise.song().instruments[instrument_index] + if not instrument then + renoise.app():show_warning("Selected instrument does not exist.") + return end - --local instrument = renoise.song().instruments[instrument_popup.value] - local instrument=renoise.song().selected_instrument + for _, sample in ipairs(instrument.samples) do - sample.sample_mapping.base_note = 48 -- C-4 - sample.sample_mapping.note_range = { 0, 119 } + sample.sample_mapping.base_note = 48 + sample.sample_mapping.note_range = {0, 119} end + renoise.app():show_status("Base notes set to C-4 and key mapping adjusted for all samples.") - update_instrument_list_and_popups() -- Refresh instruments - slider.value = 1 -- Set slider to minimum (first sample gets 00-7F) + + if renoise.song().tracks[track_index] then + renoise.song().tracks[track_index].name = instrument.name ~= "" and instrument.name or "Instrument " .. instrument_index + renoise.app():show_status("Track " .. track_index .. " renamed to '" .. (instrument.name ~= "" and instrument.name or "Instrument " .. instrument_index) .. "'.") + else + renoise.app():show_warning("Selected track does not exist.") + end + + local selected_device = renoise.song().selected_device + if selected_device and instrument and #instrument.samples > 0 then + selected_device.display_name = "8120_row" .. row_index + renoise.app():show_status("Selected device renamed to '8120_row" .. row_index .. "'.") + else + renoise.app():show_status("No valid device loaded; device not renamed.") + end + + update_instrument_list_and_popups() + slider.value = 1 + + if type(pakettiSampleVelocityRangeChoke) == "function" then + pakettiSampleVelocityRangeChoke(1) + end + update_sample_name_label() - renoise.app().window.active_middle_frame = 5 -- Focus Sample Editor + row_elements.random_button_pressed = random_button_pressed + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR end - - -- Refresh Instruments Function + + -- Function to Refresh Instruments local function refresh_instruments() update_instrument_list_and_popups() - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR end - - -- Select Button Functionality + + -- Function to Select Instrument local function select_instrument() - renoise.song().selected_instrument_index = instrument_popup.value - renoise.app().window.active_middle_frame = 5 -- Focus Sample Editor + renoise.song().selected_instrument_index = instrument_popup.value + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR end - - -- Random Button Functionality + + -- Function for Random Button Pressed local function random_button_pressed() - -- Select the instrument defined in instrument_popup - local instrument_index = instrument_popup.value + row_elements.updating_checkboxes = true + local instrument_index = row_elements.instrument_popup.value renoise.song().selected_instrument_index = instrument_index - - -- Assuming sample_random is defined elsewhere + if type(sample_random) == "function" then sample_random() end - - -- Find the sample that has key range 0-127 and set slider to that sample index + local instrument = renoise.song().instruments[instrument_index] for sample_index, sample in ipairs(instrument.samples) do if sample.sample_mapping.note_range[1] == 0 and sample.sample_mapping.note_range[2] == 127 then @@ -358,18 +491,52 @@ local function PakettiEightSlotsByOneTwentyCreateRow(row_index) break end end - - -- Update sample name label + update_sample_name_label() - - -- Select the first track renoise.song().selected_track_index = 1 - - -- Focus frame 1 as per your requirement - renoise.app().window.active_middle_frame = 5 + row_elements.updating_checkboxes = false + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR end - - -- Assemble the row with control buttons, including row-specific < and > buttons + + -- Function to Randomize Steps + local function randomize() + row_elements.updating_checkboxes = true + for i = 1, 16 do + checkboxes[i].value = math.random() >= 0.5 + end + row_elements.print_to_pattern() + row_elements.updating_checkboxes = false + end + + -- Function to Show Automation + local function show_automation() + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_MIXER + renoise.app().window.lower_frame_is_visible = true + renoise.app().window.active_lower_frame = renoise.ApplicationWindow.LOWER_FRAME_TRACK_AUTOMATION + renoise.song().selected_track_index = row_index + renoise.song().selected_device_index = 2 + renoise.app():show_status("Showing Automation for Row " .. row_index) + end + + -- Define select_instrument function + local function select_instrument() + renoise.song().selected_instrument_index = instrument_popup.value + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR + end + + -- Assign select_instrument to row_elements + row_elements.select_instrument = select_instrument + + -- Define the Reverse Button with Corrected Notifier + local reverse_button = vb:button { + text = "Reverse", + notifier = function() + row_elements.select_instrument(); + reverse_sample(row_elements) + end + } + + -- Define the Row Column Layout local row = vb:column { vb:row(number_buttons), vb:row { @@ -377,183 +544,176 @@ local function PakettiEightSlotsByOneTwentyCreateRow(row_index) checkboxes[5], checkboxes[6], checkboxes[7], checkboxes[8], checkboxes[9], checkboxes[10], checkboxes[11], checkboxes[12], checkboxes[13], checkboxes[14], checkboxes[15], checkboxes[16], - valuebox, - sample_name_label + valuebox, sample_name_label }, vb:row { - vb:button { text = "<", notifier = function() - -- Shift checkboxes left in this specific row - local first_value = checkboxes[1].value - for i = 1, 15 do - checkboxes[i].value = checkboxes[i + 1].value + vb:button { + text = "<", + notifier = function() + row_elements.updating_checkboxes = true + local first_value = checkboxes[1].value + for i = 1, 15 do + checkboxes[i].value = checkboxes[i + 1].value + end + checkboxes[16].value = first_value + row_elements.print_to_pattern() + row_elements.updating_checkboxes = false + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end - checkboxes[16].value = first_value - print_to_pattern() - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 - end }, - vb:button { text = ">", notifier = function() - -- Shift checkboxes right in this specific row - local last_value = checkboxes[16].value - for i = 16, 2, -1 do - checkboxes[i].value = checkboxes[i - 1].value + }, + vb:button { + text = ">", + notifier = function() + row_elements.updating_checkboxes = true + local last_value = checkboxes[16].value + for i = 16, 2, -1 do + checkboxes[i].value = checkboxes[i - 1].value + end + checkboxes[1].value = last_value + row_elements.print_to_pattern() + row_elements.updating_checkboxes = false + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end - checkboxes[1].value = last_value - print_to_pattern() - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 - end }, - vb:button { text = "Clear", notifier = function() - for i = 1, 16 do - checkboxes[i].value = false + }, + vb:button { + text = "Clear", + notifier = function() + row_elements.updating_checkboxes = true + for i = 1, 16 do + checkboxes[i].value = false + end + row_elements.print_to_pattern() + row_elements.updating_checkboxes = false + renoise.app():show_status("Wiped all steps of row " .. row_index .. ".") + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end - row_elements.print_to_pattern() - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 - end }, - vb:button { text = "Randomize", notifier = function() - for i = 1, 16 do - checkboxes[i].value = math.random() >= 0.5 + }, + vb:button { + text = "Randomize", + notifier = function() + row_elements.updating_checkboxes = true + for i = 1, 16 do + checkboxes[i].value = math.random() >= 0.5 + end + row_elements.print_to_pattern() + row_elements.updating_checkboxes = false + renoise.app():show_status("Randomized steps of row " .. row_index .. ".") + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end - row_elements.print_to_pattern() - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 - end }, + }, track_popup, - vb:row { -- Group Mute Checkbox and Label closely + vb:row { mute_checkbox, - vb:text { text = "Mute", font = "bold", style = "strong", width = 30 }, + vb:text {text = "Mute", font = "bold", style = "strong", width = 30} }, instrument_popup, - vb:button { text = "Browse", notifier = browse_instrument }, - vb:button { text = "Refresh", notifier = refresh_instruments }, - vb:button { text = "Select", notifier = select_instrument }, + vb:button {text = "Browse", notifier = browse_instrument}, + vb:button {text = "Refresh", notifier = refresh_instruments}, + vb:button {text = "Show", notifier = select_instrument}, slider, - vb:button { text = "Random", notifier = random_button_pressed }, - }, + vb:button {text = "Random", notifier = random_button_pressed}, + vb:button {text = "Show Automation", notifier = show_automation}, + reverse_button -- Add the Reverse button here + } } - - -- Store elements for later use + + -- Assign Elements to row_elements Table row_elements.checkboxes = checkboxes row_elements.valuebox = valuebox row_elements.slider = slider row_elements.track_popup = track_popup row_elements.instrument_popup = instrument_popup row_elements.mute_checkbox = mute_checkbox - row_elements.initialize_row = initialize_row -- Store initialize_row function - row_elements.print_to_pattern = print_to_pattern -- Store print_to_pattern function - row_elements.update_sample_name_label = update_sample_name_label -- Store update_sample_name_label function - - -- Initialize the row (populate checkboxes and set mute state) - initialize_row() - + + -- Assign Functions to row_elements Table + row_elements.initialize_row = initialize_row + row_elements.print_to_pattern = print_to_pattern + row_elements.update_sample_name_label = update_sample_name_label + row_elements.randomize = randomize + row_elements.random_button_pressed = random_button_pressed + + -- Initialize the Row + row_elements.initialize_row() + return row, row_elements end --- Function to create global controls at the top -local function create_global_controls() - -- Groove Enabled Checkbox - play_checkbox = vb:checkbox { - value = renoise.song().transport.playing, - notifier = function(value) - if value then - renoise.song().transport:start(renoise.Transport.PLAYMODE_RESTART_PATTERN) - else - renoise.song().transport:stop() - end - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame - end - } - follow_checkbox = vb:checkbox { - value = renoise.song().transport.follow_player, - notifier = function(value) - renoise.song().transport.follow_player = value - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame - end - } - - - groove_enabled_checkbox = vb:checkbox { - value = renoise.song().transport.groove_enabled, - notifier = function(value) - renoise.song().transport.groove_enabled = value - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame - end - } - - -- Play Checkbox - play_checkbox = vb:checkbox { - value = renoise.song().transport.playing, - notifier = function(value) - if value then - renoise.song().transport:start(renoise.Transport.PLAYMODE_RESTART_PATTERN) - else - renoise.song().transport:stop() - end - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame - end - } +local function update_bpm() + local random_bpm = math.random(20, 300) + renoise.song().transport.bpm = random_bpm + bpm_display.text = "BPM: " .. tostring(random_bpm) + renoise.app():show_status("BPM set to " .. random_bpm) +end - -- Follow Checkbox - follow_checkbox = vb:checkbox { - value = renoise.song().transport.follow_player, - notifier = function(value) - renoise.song().transport.follow_player = value - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame +function create_global_controls() + play_checkbox = vb:checkbox {value = renoise.song().transport.playing, midi_mapping = "Paketti:Paketti Groovebox 8120:Play Control", notifier = function(value) + if value then + renoise.song().transport:start(renoise.Transport.PLAYMODE_RESTART_PATTERN) + else + renoise.song().transport:stop() end - } - - -- BPM Display - bpm_display = vb:text { - text = "BPM: " .. tostring(renoise.song().transport.bpm), - font = "bold", - style = "strong", - width = 20, - } - - -- Function to increase BPM + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR + end} + follow_checkbox = vb:checkbox {value = renoise.song().transport.follow_player, notifier = function(value) + renoise.song().transport.follow_player = value + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR + end} + groove_enabled_checkbox = vb:checkbox {value = renoise.song().transport.groove_enabled, notifier = function(value) + renoise.song().transport.groove_enabled = value + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR + renoise.app().window.active_lower_frame = renoise.ApplicationWindow.LOWER_FRAME_TRACK_DSPS + end} + bpm_display=vb:button{text="BPM: " .. tostring(renoise.song().transport.bpm),width=60,notifier=update_bpm} + local function increase_bpm() - renoise.song().transport.bpm = renoise.song().transport.bpm + 1 + local new_bpm = renoise.song().transport.bpm + 1 + if new_bpm > 999 then new_bpm = 999 end + renoise.song().transport.bpm = new_bpm bpm_display.text = "BPM: " .. tostring(renoise.song().transport.bpm) - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end - - -- Function to decrease BPM + local function decrease_bpm() - renoise.song().transport.bpm = renoise.song().transport.bpm - 1 + local new_bpm = renoise.song().transport.bpm - 1 + if new_bpm < 20 then new_bpm = 20 end + renoise.song().transport.bpm = new_bpm bpm_display.text = "BPM: " .. tostring(renoise.song().transport.bpm) - renoise.app().window.active_middle_frame = renoise.app().window.active_middle_frame + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end - - -- Groove Sliders and Labels - local local_groove_sliders = {} - local local_groove_labels = {} - local groove_controls = vb:row {} - + + local function divide_bpm() + local new_bpm = math.floor(renoise.song().transport.bpm / 2) + if new_bpm < 20 then new_bpm = 20 end + renoise.song().transport.bpm = new_bpm + bpm_display.text = "BPM: " .. tostring(renoise.song().transport.bpm) + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR + end + + local function multiply_bpm() + local new_bpm = renoise.song().transport.bpm * 2 + if new_bpm > 999 then new_bpm = 999 end + renoise.song().transport.bpm = new_bpm + bpm_display.text = "BPM: " .. tostring(renoise.song().transport.bpm) + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR + end + + local local_groove_sliders, local_groove_labels, groove_controls = {}, {}, vb:row {} for i = 1, 4 do local groove_value = renoise.song().transport.groove_amounts[i] or 0 - local_groove_labels[i] = vb:text { - text = string.format("%d%%", groove_value * 100), - width = 30, - } - local_groove_sliders[i] = vb:slider { - min = 0.0, - max = 1.0, - value = groove_value, - width = 100, - notifier = function(value) - local_groove_labels[i].text = string.format("%d%%", value * 100) - -- Collect all groove values - local groove_values = {} - for j = 1, 4 do - groove_values[j] = local_groove_sliders[j].value - end - -- Set groove_amounts to the array of groove_values - renoise.song().transport.groove_amounts = groove_values - renoise.song().selected_track_index = renoise.song().sequencer_track_count+1 - renoise.app().window.active_middle_frame = 2 + local_groove_labels[i] = vb:text {text = string.format("%d%%", groove_value * 100), width = 30} + local_groove_sliders[i] = vb:slider {min = 0.0, max = 1.0, value = groove_value, width = 100, notifier = function(value) + local_groove_labels[i].text = string.format("%d%%", value * 100) + local groove_values = {} + for j = 1, 4 do + groove_values[j] = local_groove_sliders[j].value end - } - groove_controls:add_child(vb:row { local_groove_sliders[i], local_groove_labels[i] }) + renoise.song().transport.groove_amounts = groove_values + renoise.song().selected_track_index = renoise.song().sequencer_track_count + 1 + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_MIXER + end} + groove_controls:add_child(vb:row {local_groove_sliders[i], local_groove_labels[i]}) end - - -- Random Groove Function + local function randomize_groove() local groove_values = {} for i = 1, 4 do @@ -564,135 +724,85 @@ local function create_global_controls() end renoise.song().transport.groove_amounts = groove_values renoise.song().transport.groove_enabled = true - renoise.song().selected_track_index = renoise.song().sequencer_track_count+1 - renoise.app().window.active_middle_frame = 2 + renoise.song().selected_track_index = renoise.song().sequencer_track_count + 1 + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_MIXER + renoise.app().window.active_lower_frame = renoise.ApplicationWindow.LOWER_FRAME_TRACK_DSPS end - - -- Random Groove Button - local random_groove_button = vb:button{text="Random Groove",notifier=randomize_groove} - - -- Create Global Steps with << and >> - global_step_buttons = vb:row { - vb:text { text = "Global Steps:", font = "bold", style = "strong", width = 100 }, - vb:button { text = "1", notifier = function() set_global_steps(1) end }, - vb:button { text = "2", notifier = function() set_global_steps(2) end }, - vb:button { text = "4", notifier = function() set_global_steps(4) end }, - vb:button { text = "6", notifier = function() set_global_steps(6) end }, - vb:button { text = "8", notifier = function() set_global_steps(8) end }, - vb:button { text = "12", notifier = function() set_global_steps(12) end }, - vb:button { text = "16", notifier = function() set_global_steps(16) end }, - vb:button { text = "<<", notifier = function() - -- Shift all checkboxes left across all rows - for _, row_elements in ipairs(rows) do - local first_value = row_elements.checkboxes[1].value - for i = 1, 15 do - row_elements.checkboxes[i].value = row_elements.checkboxes[i + 1].value - end - row_elements.checkboxes[16].value = first_value - row_elements.print_to_pattern() - end - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 - end }, - vb:button { text = ">>", notifier = function() - -- Shift all checkboxes right across all rows + + random_gate_button = vb:button{ text="Random Gate", midi_mapping="Paketti:Paketti Groovebox 8120:Random Gate", notifier=function() + random_gate() + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR + end} + + fill_empty_label = vb:text{ text="Fill Empty Steps: 0%", width=90 } + fill_empty_slider = vb:slider {min = 0, max = 100, value = 0, width = 150, notifier = function(value) + fill_empty_label.text = "Fill Empty Steps: " .. tostring(math.floor(value)) .. "%" + if value == 0 then for _, row_elements in ipairs(rows) do - local last_value = row_elements.checkboxes[16].value - for i = 16, 2, -1 do - row_elements.checkboxes[i].value = row_elements.checkboxes[i - 1].value + row_elements.updating_checkboxes = true + for i = 1, 16 do + row_elements.checkboxes[i].value = false end - row_elements.checkboxes[1].value = last_value + row_elements.updating_checkboxes = false row_elements.print_to_pattern() end - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 - end }, - } - - -- Random Gate Button - random_gate_button = vb:button { - text = "Random Gate", - notifier = function() - random_gate() - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 as per your requirement - end - } - - -- Fill Empty Steps Randomly Slider - fill_empty_label=vb:text{text="Fill Empty Steps: 0%",width=90} - - fill_empty_slider = vb:slider { - min = 0, - max = 100, - value = 0, - width = 150, - notifier = function(value) - fill_empty_label.text = "Fill Empty Steps: " .. tostring(math.floor(value)) .. "%" - if value == 0 then - -- Run Clear All script - for _, row_elements in ipairs(rows) do - for i = 1, 16 do - row_elements.checkboxes[i].value = false - end - row_elements.print_to_pattern() - end - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 - else - fill_empty_steps(value / 100) -- Call the fill_empty_steps function - renoise.app().window.active_middle_frame = 1 -- Keep focus on frame 1 - end + renoise.app():show_status("Wiped all steps of each row.") + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR + else + fill_empty_steps(value / 100) + renoise.app():show_status("Filled empty steps with " .. tostring(math.floor(value)) .. "% probability.") + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end - } - - -- Clear All Button Functionality + end} + local function clear_all() for _, row_elements in ipairs(rows) do + row_elements.updating_checkboxes = true local checkboxes = row_elements.checkboxes for i = 1, 16 do checkboxes[i].value = false end + row_elements.updating_checkboxes = false row_elements.print_to_pattern() end - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 + renoise.app():show_status("Wiped all steps of each row.") + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end - - -- Random Fill Button Functionality + local function random_fill() for _, row_elements in ipairs(rows) do - -- Set the steps to a random number between 1 and 16 + row_elements.updating_checkboxes = true local random_steps = math.random(1, 16) - row_elements.updating_steps = true -- Prevent notifier from triggering + row_elements.updating_steps = true row_elements.valuebox.value = random_steps row_elements.updating_steps = false - -- Clear checkboxes local checkboxes = row_elements.checkboxes for i = 1, 16 do checkboxes[i].value = false end - -- Fill random checkboxes up to random_steps for i = 1, random_steps do local rand_index = math.random(1, 16) checkboxes[rand_index].value = true end + row_elements.updating_checkboxes = false row_elements.print_to_pattern() end - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 + renoise.app():show_status("Randomly filled each row, and set step values for each instrument.") + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end - - -- Fetch Button Functionality + local function fetch_pattern() - -- Disable all checkboxes to prevent interaction during fetching for _, row_elements in ipairs(rows) do for _, checkbox in ipairs(row_elements.checkboxes) do checkbox.active = false end end - - -- Iterate through each row and fetch the pattern content for i, row_elements in ipairs(rows) do local track_index = track_indices[row_elements.track_popup.value] local pattern = renoise.song().selected_pattern local line_count = pattern.number_of_lines local instrument_used = nil - + row_elements.updating_checkboxes = true for line = 1, math.min(line_count, 16) do local note_line = pattern.tracks[track_index].lines[line].note_columns[1] if note_line and note_line.note_string == "C-4" then @@ -704,129 +814,288 @@ local function create_global_controls() row_elements.checkboxes[line].value = false end end - if instrument_used then row_elements.instrument_popup.value = instrument_used + 1 renoise.song().selected_instrument_index = row_elements.instrument_popup.value end row_elements.print_to_pattern() + row_elements.updating_checkboxes = false end - - -- Re-enable all checkboxes after fetching for _, row_elements in ipairs(rows) do for _, checkbox in ipairs(row_elements.checkboxes) do checkbox.active = true end end - renoise.app():show_status("Pattern fetched successfully.") - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 as per your requirement + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end - - -- Create Global Controls Layout + + local function random_all() + for _, row_elements in ipairs(rows) do + if row_elements.random_button_pressed then + row_elements.random_button_pressed() + else + renoise.app():show_status("Error: random_button_pressed not found for a row.") + end + end + renoise.app():show_status("Each Instrument Bank now has a Random Selected Sample.") + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR + end + + local function randomize_all() + for _, row_elements in ipairs(rows) do + row_elements.randomize() + end + renoise.app():show_status("Each Instrument Row step content has now been randomized.") + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR + end + + local reverse_all_button = vb:button {text = "Reverse All", notifier = reverse_all} + local global_controls = vb:column { vb:row { - play_checkbox, - vb:text { text = "Play", font = "bold", style = "strong", width = 20 }, - follow_checkbox, - vb:text { text = "Follow", font = "bold", style = "strong", width = 30 }, - - vb:button { text = "-", notifier = decrease_bpm }, + play_checkbox, vb:text {text = "Play", font = "bold", style = "strong", width = 30}, + follow_checkbox, vb:text {text = "Follow", font = "bold", style = "strong", width = 50}, + vb:button {text = "/2", notifier = divide_bpm}, + vb:button {text = "-", notifier = decrease_bpm}, bpm_display, - vb:button { text = "+", notifier = increase_bpm }, - vb:button { text = "Clear All", notifier = clear_all }, - vb:button { text = "Random Fill", notifier = random_fill }, + vb:button {text = "+", notifier = increase_bpm}, + vb:button {text = "*2", notifier = multiply_bpm}, + vb:button {text = "Clear All", notifier = clear_all}, + vb:button {text = "Random Fill", midi_mapping="Paketti:Paketti Groovebox 8120:Random Fill", notifier = random_fill}, random_gate_button, - vb:button { text = "Fetch", notifier = fetch_pattern }, + vb:button {text = "Fetch", notifier = fetch_pattern}, fill_empty_label, - fill_empty_slider - }, + fill_empty_slider, + vb:button {text = "Random All", notifier = random_all}, + vb:button {text = "Randomize All", notifier = randomize_all}, + reverse_all_button + } } - - -- Create Global Groove Controls + local global_groove_controls = vb:row { - groove_enabled_checkbox, - vb:text { text = "Global Groove", font = "bold", style = "strong", width = 100 }, - groove_controls, - random_groove_button + groove_enabled_checkbox, vb:text {text = "Global Groove", font = "bold", style = "strong", width = 100}, + groove_controls, vb:button {text = "Random Groove", midi_mapping="Paketti:Paketti Groovebox 8120:Random Groove", notifier = randomize_groove} } - + return global_controls, global_groove_controls, global_step_buttons end --- Function to create and show the dialog local function PakettiEightSlotsByOneTwentyDialog() - -- Ensure dialog is not already open if dialog and dialog.visible then dialog:show() return end - - -- Populate track and instrument names - track_names = {} - track_indices = {} + track_names, track_indices, instrument_names = {}, {}, {} for i, track in ipairs(renoise.song().tracks) do if track.type == renoise.Track.TRACK_TYPE_SEQUENCER then table.insert(track_names, track.name) table.insert(track_indices, i) end end - - instrument_names = {} for i, instr in ipairs(renoise.song().instruments) do table.insert(instrument_names, instr.name ~= "" and instr.name or "Instrument " .. i) end - - -- Create global controls and groove controls fresh each time local global_controls, global_groove_controls, global_step_buttons = create_global_controls() - - -- Create a fresh dialog content column - local dc = vb:column { - global_controls, - global_groove_controls, - global_step_buttons - } - - -- Create 8 rows + local dc = vb:column {global_controls, global_groove_controls, global_step_buttons} for i = 1, 8 do local row, elements = PakettiEightSlotsByOneTwentyCreateRow(i) dc:add_child(row) - rows[i] = elements -- Store the row elements for updating later + rows[i] = elements end + dc:add_child(vb:button {text = "Run Debug", notifier = function() + debug_instruments_and_samples() + renoise.app():show_status("Debug information printed to console.") + end}) + dc:add_child(vb:button {text = "Print to Pattern", notifier = function() + for i, elements in ipairs(rows) do + elements.print_to_pattern() + end + renoise.app():show_status("Pattern updated successfully.") + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR + end}) + for _, row_elements in ipairs(rows) do + row_elements.update_sample_name_label() + end + debug_instruments_and_samples() + dialog = renoise.app():show_custom_dialog("Paketti Groovebox 8120", dc, PakettiEightSlotsByOneTwentyKeyHandler) +end - -- Add "Print to Pattern" button - dc:add_child( - vb:button { - text = "Print to Pattern", - notifier = function() - for i, elements in ipairs(rows) do - elements.print_to_pattern() +local function assign_midi_mappings() + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Increase BPM", invoke = function(message) + if message:is_trigger() then increase_bpm() end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Decrease BPM", invoke = function(message) + if message:is_trigger() then decrease_bpm() end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Divide BPM by 2", invoke = function(message) + if message:is_trigger() then divide_bpm() end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Multiply BPM by 2", invoke = function(message) + if message:is_trigger() then multiply_bpm() end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Play Toggle", invoke = function(message) + if message:is_trigger() then play_checkbox.value = not play_checkbox.value end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Follow Toggle", invoke = function(message) + if message:is_trigger() then follow_checkbox.value = not follow_checkbox.value end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Clear All", invoke = function(message) + if message:is_trigger() then clear_all() end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Random Fill", invoke = function(message) + if message:is_trigger() then random_fill() end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Random Gate", invoke = function(message) + if message:is_trigger() then random_gate() end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Fetch Pattern", invoke = function(message) + if message:is_trigger() then fetch_pattern() end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Fill Empty Steps Slider", invoke = function(message) + if message:is_trigger() then + local new_value = fill_empty_slider.value + 10 + if new_value > 100 then new_value = 100 end + fill_empty_slider.value = new_value + end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Random All", invoke = function(message) + if message:is_trigger() then random_all() end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Randomize All", invoke = function(message) + if message:is_trigger() then randomize_all() end + end} + local step_button_names = {"1", "2", "4", "6", "8", "12", "16", "<<", ">>"} + for _, step in ipairs(step_button_names) do + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Global Step " .. step, invoke = function(message) + if message:is_trigger() then + if step == "<<" then + for _, row_elements in ipairs(rows) do + row_elements.updating_checkboxes = true + local first_value = row_elements.checkboxes[1].value + for i = 1, 15 do + row_elements.checkboxes[i].value = row_elements.checkboxes[i + 1].value + end + row_elements.checkboxes[16].value = first_value + row_elements.print_to_pattern() + end + renoise.app():show_status("All steps shifted to the left.") + elseif step == ">>" then + for _, row_elements in ipairs(rows) do + row_elements.updating_checkboxes = true + local last_value = row_elements.checkboxes[16].value + for i = 16, 2, -1 do + row_elements.checkboxes[i].value = row_elements.checkboxes[i - 1].value + end + row_elements.checkboxes[1].value = last_value + row_elements.print_to_pattern() + end + renoise.app():show_status("All steps shifted to the right.") + else + set_global_steps(tonumber(step)) end - renoise.app():show_status("Pattern updated successfully.") - renoise.app().window.active_middle_frame = 1 -- Focus frame 1 as per your requirement + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_PATTERN_EDITOR end - } - ) - - -- Show the dialog - dialog = renoise.app():show_custom_dialog( - "Eight Slots by 120 Samples", - dc, - PakettiEightSlotsByOneTwentyKeyHandler - ) + end} + end + for row = 1, 8 do + for step = 1, 16 do + renoise.tool():add_midi_mapping {name = string.format("Paketti:Paketti Groovebox 8120:Row%d Step%d", row, step), invoke = function(message) + if message:is_trigger() then + local row_elements = rows[row] + if row_elements and row_elements.checkboxes[step] then + row_elements.checkboxes[step].value = not row_elements.checkboxes[step].value + end + end + end} + end + local buttons = {"<", ">", "Clear", "Randomize", "Browse", "Show", "Random", "Show Automation", "Reverse"} + for _, btn in ipairs(buttons) do + renoise.tool():add_midi_mapping {name = string.format("Paketti:Paketti Groovebox 8120:Row%d %s", row, btn), invoke = function(message) + if message:is_trigger() then + local row_elements = rows[row] + if row_elements then + if btn == "<" then + row_elements.updating_checkboxes = true + local first_value = row_elements.checkboxes[1].value + for i = 1, 15 do + row_elements.checkboxes[i].value = row_elements.checkboxes[i + 1].value + end + row_elements.checkboxes[16].value = first_value + row_elements.print_to_pattern() + row_elements.updating_checkboxes = false + renoise.app():show_status(string.format("Row %d: Steps shifted left.", row)) + elseif btn == ">" then + row_elements.updating_checkboxes = true + local last_value = row_elements.checkboxes[16].value + for i = 16, 2, -1 do + row_elements.checkboxes[i].value = row_elements.checkboxes[i - 1].value + end + row_elements.checkboxes[1].value = last_value + row_elements.print_to_pattern() + row_elements.updating_checkboxes = false + renoise.app():show_status(string.format("Row %d: Steps shifted right.", row)) + elseif btn == "Clear" then + row_elements.updating_checkboxes = true + for i = 1, 16 do + row_elements.checkboxes[i].value = false + end + row_elements.updating_checkboxes = false + row_elements.print_to_pattern() + renoise.app():show_status(string.format("Row %d: All steps cleared.", row)) + elseif btn == "Randomize" then + row_elements.updating_checkboxes = true + for i = 1, 16 do + row_elements.checkboxes[i].value = math.random() >= 0.5 + end + row_elements.updating_checkboxes = false + row_elements.print_to_pattern() + renoise.app():show_status(string.format("Row %d: Steps randomized.", row)) + elseif btn == "Browse" then + row_elements.browse_instrument() + elseif btn == "Show" then + row_elements.select_instrument() + elseif btn == "Random" then + row_elements.random_button_pressed() + elseif btn == "Show Automation" then + row_elements.show_automation() + elseif btn == "Reverse" then + reverse_sample(row_elements) + end + end + end + end} + end + end + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Random Groove", invoke = function(message) + if message:is_trigger() then randomize_groove() end + end} + renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120:Reverse All", invoke = function(message) + if message:is_trigger() then reverse_all() end + end} end --- Add Keybinding to toggle the dialog -renoise.tool():add_keybinding { - name = "Global:Paketti:Eight Slots by 120 Samples", - invoke = function() +assign_midi_mappings() + +renoise.tool():add_keybinding {name = "Global:Paketti:Paketti Groovebox 8120", invoke = function() + if dialog and dialog.visible then + dialog:close() + dialog = nil + rows = {} + else PakettiEightSlotsByOneTwentyDialog() end end} + +renoise.tool():add_menu_entry {name = "Main Menu:Tools:Paketti..:Paketti Groovebox 8120", invoke = function() + if dialog and dialog.visible then + dialog:close() + dialog = nil + rows = {} + else PakettiEightSlotsByOneTwentyDialog() end end} + +renoise.tool():add_midi_mapping {name = "Paketti:Paketti Groovebox 8120", invoke = function(message) + if message:is_trigger() then if dialog and dialog.visible then dialog:close() dialog = nil rows = {} - else - PakettiEightSlotsByOneTwentyDialog() - end - end -} + else PakettiEightSlotsByOneTwentyDialog() end end end} diff --git a/PakettiExperimental_Verify.lua b/PakettiExperimental_Verify.lua index e797c64..8e1ce31 100644 --- a/PakettiExperimental_Verify.lua +++ b/PakettiExperimental_Verify.lua @@ -1,39 +1,3 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -- TODO: make this use loadnative("name",XML) okay? function PakettiInvertDeviceTrackDSP() loadnative("Audio/Effects/Native/Gainer") @@ -45,11 +9,16 @@ function PakettiInvertDeviceTrackDSP() renoise.app():show_status("Preset loading failed.") return end - - local device = renoise.song().selected_device or renoise.song().selected_sample_device + local device + if renoise.app().window.active_middle_frame == 7 or renoise.app().window.active_middle_frame == 6 then + device = renoise.song().selected_sample_device + else + device = renoise.song().selected_device + end if device then device.active_preset_data = preset_xml + device.display_name = "Inverter" renoise.app():show_status("Preset successfully loaded from: Presets/PakettiGainerInverter.xml") else renoise.app():show_status("No device found to apply the preset.") @@ -96,6 +65,7 @@ renoise.tool():add_midi_mapping{name="Paketti:Insert Inverter Device to TrackDSP + local function flood_fill_column() @@ -2707,10 +2677,7 @@ end -- --end --renoise.tool():add_keybinding{name="Global:Paketti:Stair", invoke=function() stairs() end} -renoise.tool():add_menu_entry{name="--Pattern Editor:Paketti..:Devices..:Bypass All Devices on Channel", invoke=function() effectbypass() end} -renoise.tool():add_menu_entry{name="Pattern Editor:Paketti..:Devices..:Enable All Devices on Channel", invoke=function() effectenable() end} ---------------------------- - -- has-line-input + add-line-input function has_line_input() -- Write some code to find the line input in the correct place @@ -3318,13 +3285,6 @@ renoise.tool():add_menu_entry{name="Sample Editor:Paketti..:Unison Generator",in renoise.tool():add_menu_entry{name="Sample Mappings:Paketti..:Unison Generator",invoke=PakettiCreateUnisonSamples} renoise.tool():add_menu_entry{name="Instrument Box:Paketti..:Unison Generator",invoke=PakettiCreateUnisonSamples} - - - - - - - --------- -- Helper function to check if in a valid note column local function is_in_note_column() diff --git a/PakettiImpulseTracker.lua b/PakettiImpulseTracker.lua index c3e861c..867a6bc 100644 --- a/PakettiImpulseTracker.lua +++ b/PakettiImpulseTracker.lua @@ -455,6 +455,113 @@ function DoubleSelect() end renoise.tool():add_keybinding{name="Pattern Editor:Paketti:Impulse Tracker ALT-D Double Select", invoke=function() DoubleSelect() end} + +----------- +-- Function to select the pattern range in automation +function selectPatternRangeInAutomation() + local song = renoise.song() + + -- Check if the automation lower frame is displayed + if not (renoise.app().window.active_lower_frame == renoise.ApplicationWindow.LOWER_FRAME_TRACK_AUTOMATION) then + renoise.app():show_status("Automation lower frame is not displayed.") + return + end + + local selected_pattern_index = song.selected_pattern_index + local selected_track_index = song.selected_track_index + + -- Check if an automatable parameter is selected + local automation_parameter = song.selected_automation_parameter + if not automation_parameter or not automation_parameter.is_automatable then + renoise.app():show_status("Please select an automatable parameter.") + return + end + + -- Get the selection in the pattern editor + local pattern_selection = song.selection_in_pattern + if pattern_selection == nil then + renoise.app():show_status("No selection in pattern editor.") + return + end + + local start_line = pattern_selection.start_line + local end_line = pattern_selection.end_line + + -- Access the track's automation for the selected parameter + local track_automation = song:pattern(selected_pattern_index):track(selected_track_index) + local envelope = track_automation:find_automation(automation_parameter) + + -- If no automation envelope exists, create one + if not envelope then + envelope = track_automation:create_automation(automation_parameter) + end + + -- Calculate automation selection range based on pattern selection + local pattern_lines = song:pattern(selected_pattern_index).number_of_lines + local automation_start = math.floor((start_line / pattern_lines) * envelope.length) + local automation_end = math.floor(((end_line + 1) / pattern_lines) * envelope.length) + + -- Set the selection range in the automation envelope + envelope.selection_range = { automation_start, automation_end } + + -- Notify the user + renoise.app():show_status("Automation selection set from line " .. start_line .. " to line " .. end_line) +end + +-- IT: ALT-D (whole track) Double-select +function DoubleSelectAutomation() + local s = renoise.song() + local lpb = s.transport.lpb + local sip = s.selection_in_pattern + local last_column = s.selected_track.visible_effect_columns + s.selected_track.visible_note_columns + local protectrow = lpb + s.selected_line_index - 1 + if protectrow > s.selected_pattern.number_of_lines then + protectrow = s.selected_pattern.number_of_lines + end + + if sip == nil or sip.start_track ~= s.selected_track_index or s.selected_line_index ~= s.selection_in_pattern.start_line then + s.selection_in_pattern = { + start_line = s.selected_line_index, + end_line = protectrow, + start_track = s.selected_track_index, + end_track = s.selected_track_index, + start_column = 1, + end_column = last_column + } + else + local endline = sip.end_line + local startline = sip.start_line + local new_endline = (endline - startline) * 2 + (startline + 1) + + if new_endline > s.selected_pattern.number_of_lines then + new_endline = s.selected_pattern.number_of_lines + end + + s.selection_in_pattern = { + start_line = startline, + end_line = new_endline, + start_track = s.selected_track_index, + end_track = s.selected_track_index, + start_column = 1, + end_column = last_column + } + end + + -- After updating the pattern selection, update the automation selection + selectPatternRangeInAutomation() +end + +renoise.tool():add_keybinding{ + name = "Pattern Editor:Paketti:Impulse Tracker ALT-D Double Select W/ Automation", + invoke = function() DoubleSelectAutomation() end +} + + + + + + + -------------------------------------------------------------------------------------------------------------------------------- -- Protman's set octave -- Protman: Thanks to suva for the function per octave declaration loop :) @@ -1297,7 +1404,30 @@ renoise.tool():add_keybinding{name="Global:Paketti:Impulse Tracker CTRL-N New So ----------------------------------------------------- ----ALT-U -function Deselect_All() renoise.song().selection_in_pattern=nil end +function Deselect_All() + local song = renoise.song() + + -- Deselect the selection in the pattern editor + song.selection_in_pattern = nil + + -- If the automation lower frame is showing, clear the automation selection + if renoise.app().window.active_lower_frame == renoise.ApplicationWindow.LOWER_FRAME_TRACK_AUTOMATION then + local selected_track_index = song.selected_track_index + local selected_pattern_index = song.selected_pattern_index + local automation_parameter = song.selected_automation_parameter + + -- Check if an automatable parameter is selected + if automation_parameter then + local track_automation = song:pattern(selected_pattern_index):track(selected_track_index) + local envelope = track_automation:find_automation(automation_parameter) + + -- If there is an automation envelope, clear its selection + if envelope then + envelope.selection_range = {1,1} + end + end + end +end function Deselect_Phr() renoise.song().selection_in_phrase =nil end renoise.tool():add_keybinding{name="Pattern Editor:Selection:Impulse Tracker ALT-U Unmark Selection",invoke=function() Deselect_All() end} diff --git a/PakettiLoadDevices.lua b/PakettiLoadDevices.lua index f607be1..b25c3fe 100644 --- a/PakettiLoadDevices.lua +++ b/PakettiLoadDevices.lua @@ -1,4 +1,4 @@ -local vb -- ViewBuilder will be initialized within the function scope +local vb local checkboxes = {} local deviceReadableNames = {} local addedKeyBindings = {} @@ -8,13 +8,10 @@ local device_types = {"Native", "VST", "VST3", "AudioUnit", "LADSPA", "DSSI"} local custom_dialog local dialog_content_view local device_list_view -local current_device_list_content = nil -- Variable to keep track of current content +local current_device_list_content = nil --- Variable to control the number of devices per column -local DEVICES_PER_COLUMN = 39 -- Adjusted as per your request - --- Variable for random selection percentage -local random_select_percentage = 0 -- Initialized to 0% +local DEVICES_PER_COLUMN = 39 +local random_select_percentage = 0 -- Initialize Preferences File function initializePreferencesFile() @@ -67,7 +64,6 @@ function saveToPreferencesFile(keyBindingName, midiMappingName, path) file:close() end --- Check if any devices are selected function isAnyDeviceSelected() for _, cb_info in ipairs(checkboxes) do if cb_info.checkbox.value then @@ -77,11 +73,10 @@ function isAnyDeviceSelected() return false end --- Load Selected Devices function loadSelectedDevices() if not isAnyDeviceSelected() then renoise.app():show_status("Nothing was selected, doing nothing.") - return false -- Indicate that no devices were loaded + return false end local track_index = renoise.song().selected_track_index @@ -96,10 +91,9 @@ function loadSelectedDevices() end end end - return true -- Indicate that devices were loaded + return true end --- Add as Shortcut function addAsShortcut() if not isAnyDeviceSelected() then renoise.app():show_status("Nothing was selected, doing nothing.") @@ -153,21 +147,19 @@ function addAsShortcut() renoise.app():show_status("Devices added. Open Settings -> Keys, search for 'Load Device' or Midi Mappings and search for 'Load Device'") end --- Reset Selection function resetSelection() for _, cb_info in ipairs(checkboxes) do cb_info.checkbox.value = false end end --- Update Random Selection based on Slider function updateRandomSelection() if #checkboxes == 0 then renoise.app():show_status("Nothing to randomize from.") return end - resetSelection() -- Clear previous selections + resetSelection() local numDevices = #checkboxes local percentage = random_select_percentage @@ -193,26 +185,20 @@ function updateRandomSelection() indices[i] = i end - -- Shuffle indices for i = numDevices, 2, -1 do local j = math.random(1, i) indices[i], indices[j] = indices[j], indices[i] end - -- Select the first numSelections devices for i = 1, numSelections do local idx = indices[i] checkboxes[idx].checkbox.value = true end end --- Create Device List function createDeviceList(plugins, title) if #plugins == 0 then - return vb:column{ - -- vb:text{text=title, font="bold", height=20}, - vb:text{text="No Devices found for this type.", font="italic", height=20} - } + return vb:column{vb:text{text="No Devices found for this type.", font="italic", height=20}} end -- Determine number of columns based on DEVICES_PER_COLUMN @@ -235,11 +221,7 @@ function createDeviceList(plugins, title) local checkbox_id = "checkbox_" .. title .. "_" .. tostring(device_index) .. "_" .. tostring(math.random(1000000)) local checkbox = vb:checkbox{value=false, id=checkbox_id} checkboxes[#checkboxes + 1] = {checkbox=checkbox, path=plugin.path, name=plugin.name} - local plugin_row = vb:row{ - spacing=4, - checkbox, - vb:text{text=plugin.name} - } + local plugin_row = vb:row{spacing=4,checkbox,vb:text{text=plugin.name}} columns[col]:add_child(plugin_row) device_index = device_index + 1 end @@ -251,17 +233,11 @@ function createDeviceList(plugins, title) end return vb:column{ - -- vb:text{text=title, font="bold", height=20}, - vb:horizontal_aligner{ - mode = "center", - column_container - } - } + vb:horizontal_aligner{mode="center",column_container}} end --- Update Device List function updateDeviceList() - checkboxes = {} -- Clear previous checkboxes + checkboxes = {} deviceReadableNames = {} local track_index = renoise.song().selected_track_index local available_devices = renoise.song().tracks[track_index].available_devices @@ -292,8 +268,7 @@ function updateDeviceList() {name = "(Hidden) RingMod", path = "Audio/Effects/Native/RingMod"}, {name = "(Hidden) Scream Filter", path = "Audio/Effects/Native/Scream Filter"}, {name = "(Hidden) Shaper", path = "Audio/Effects/Native/Shaper"}, - {name = "(Hidden) Stutter", path = "Audio/Effects/Native/Stutter"} - } + {name = "(Hidden) Stutter", path = "Audio/Effects/Native/Stutter"}} for i, device_path in ipairs(available_devices) do if device_path:find("Native/") then @@ -302,12 +277,10 @@ function updateDeviceList() end end - -- Sort the native devices by name (including devices starting with special characters) table.sort(native_devices, function(a, b) return a.name:lower() < b.name:lower() end) - -- Append hidden devices at the end for _, hidden_device in ipairs(hidden_devices) do table.insert(native_devices, hidden_device) end @@ -333,7 +306,6 @@ function updateDeviceList() end end - -- Sort the VST3 devices alphabetically table.sort(vst3_devices, function(a, b) return a.name:lower() < b.name:lower() end) @@ -349,7 +321,6 @@ function updateDeviceList() end end - -- Sort the AudioUnit devices alphabetically table.sort(au_devices, function(a, b) return a.name:lower() < b.name:lower() end) @@ -390,7 +361,6 @@ elseif current_device_type == "LADSPA" then end end - -- Sort the DSSI devices by name table.sort(dssi_devices, function(a, b) return a.name:lower() < b.name:lower() end) @@ -398,7 +368,6 @@ elseif current_device_type == "LADSPA" then device_list_content = createDeviceList(dssi_devices, "DSSI Devices") end - -- Update the device_list_view if current_device_list_content then device_list_view:remove_child(current_device_list_content) end @@ -407,7 +376,6 @@ elseif current_device_type == "LADSPA" then current_device_list_content = device_list_content end --- Show Device List Dialog function showDeviceListDialog() current_device_list_content = nil @@ -415,19 +383,15 @@ current_device_list_content = nil checkboxes = {} local track_index = renoise.song().selected_track_index - -- Dropdown Menu local dropdown = vb:popup{ items = device_types, value = 1, notifier = function(index) current_device_type = device_types[index] updateDeviceList() - end - } + end} - -- Random Selection Slider local random_selection_controls = vb:row{ - -- spacing = 10, vb:text{text = "Random Select:", width = 80, style="strong",font="bold"}, vb:slider{ id = "random_select_slider", @@ -438,118 +402,55 @@ current_device_list_content = nil notifier = function(value) random_select_percentage = value updateRandomSelection() - end - }, - vb:text{ - id = "random_percentage_text", - text = "None", - width = 40, - align = "center" - }, - vb:button{ - text = "All", - -- height = button_height, - width = 20, + end}, + vb:text{id="random_percentage_text",text="None",width=40, + align="center"}, + vb:button{text="All",width=20, notifier = function() for _, cb_info in ipairs(checkboxes) do cb_info.checkbox.value = true end vb.views["random_select_slider"].value = 100 vb.views["random_percentage_text"].text = "All" - end - }, - vb:button{ - text = "None", - -- height = button_height, - width = 20, + end}, + vb:button{text="None",width=20, notifier = function() resetSelection() vb.views["random_select_slider"].value = 0 vb.views["random_percentage_text"].text = "None" - end - } + end}} - } - - -- Action Buttons local button_height = renoise.ViewBuilder.DEFAULT_DIALOG_BUTTON_HEIGHT local action_buttons = vb:column{ - -- uniform = true, - -- width = "100%", - vb:horizontal_aligner{ - width = "100%", - vb:button{ - text = "Load Device(s)", - width = 60, - -- height = button_height, + vb:horizontal_aligner{width="100%", + vb:button{text="Load Device(s)",width=60, notifier = function() if loadSelectedDevices() then renoise.app():show_status("Devices loaded.") end end }, - vb:button{ - text = "Add Device(s) as Shortcut(s) & MidiMappings", - -- height = button_height, - width = 140, - notifier = addAsShortcut - }, - - vb:button{ - text = "Cancel", - -- height = button_height, - width = 30, - notifier = function() - custom_dialog:close() - end - } - - - --[[ vb:button{ - text = "Load Device(s) & Close", - width = "33%", - height = button_height, - notifier = function() - if loadSelectedDevices() then - custom_dialog:close() - end - end - },]]-- - } - } - - -- Placeholder for Device List + vb:button{text="Add Device(s) as Shortcut(s) & MidiMappings",width=140, + notifier = addAsShortcut}, + vb:button{text="Cancel",width=30, + notifier = function() custom_dialog:close() end}}} device_list_view = vb:column{} - - -- Main Dialog Content - dialog_content_view = vb:column{ - margin = 10, - spacing = 5, - device_list_view, --- action_buttons - } + dialog_content_view = vb:column{margin = 10,spacing = 5,device_list_view,} -- Wrap in a column to include the dropdown local dialog_content = vb:column{ vb:horizontal_aligner{ vb:text{text = "Device Type: ", font="bold",style="strong"}, - dropdown,action_buttons,random_selection_controls}, --- vb:horizontal_aligner{ - -- random_selection_controls},--random_selection_controls - - dialog_content_view - } + dropdown,action_buttons,random_selection_controls},dialog_content_view} custom_dialog = renoise.app():show_custom_dialog("Load Device(s)", dialog_content, my_Devicekeyhandler_func) - -- Initial Update updateDeviceList() end function my_Devicekeyhandler_func(custom_dialog, key) local closer = preferences.pakettiDialogClose.value if key.modifiers == "" and key.name == closer then - custom_dialog:close() custom_dialog = nil return nil diff --git a/PakettiLoaders.lua b/PakettiLoaders.lua index 9f9cd64..7501376 100644 --- a/PakettiLoaders.lua +++ b/PakettiLoaders.lua @@ -1306,17 +1306,7 @@ renoise.tool():add_menu_entry{name="Mixer:Paketti..:Expose/Hide Selected Track A renoise.tool():add_keybinding{name="Global:Paketti:Expose/Hide Selected Track ALL Device Parameters", invoke=function() exposeHideParametersInMixer() end} - - - - - - - - - - - +--[[ function launchApp(appName) os.execute(appName) end @@ -1326,35 +1316,61 @@ function terminalApp(scriptPath) os.execute(command) end ---renoise.tool():add_menu_entry{name="Disk Browser Files:Paketti..:Run Experimental Script",invoke=function() terminalApp("/Users/esaruoho/torretemp.sh") end} - ---renoise.tool():add_menu_entry{name="Disk Browser Files:Paketti..:Run Experimental Script",invoke=function() terminalApp("/Users/esaruoho/macOS_EnableScriptingTools.sh") end} +renoise.tool():add_menu_entry{name="Disk Browser Files:Paketti..:Run Experimental Script",invoke=function() terminalApp("/Users/esaruoho/macOS_EnableScriptingTools.sh") end} renoise.tool():add_menu_entry{name="Disk Browser Files:Paketti..:Open macOS Terminal",invoke=function() launchApp("open -a Terminal.app") end} - - - - ----- +]]-- function effectbypass() local number = (table.count(renoise.song().selected_track.devices)) - for i=2,number do - renoise.song().selected_track.devices[i].is_active=false +for i=2,number do renoise.song().selected_track.devices[i].is_active=false end - renoise.app():show_status("Disabled all Track DSP Devices on Selected Channel") + renoise.app():show_status("Disabled all Track DSP Devices on Selected Track") end function effectenable() local number = (table.count(renoise.song().selected_track.devices)) -for i=2,number do -renoise.song().selected_track.devices[i].is_active=true +for i=2,number do renoise.song().selected_track.devices[i].is_active=true end -renoise.app():show_status("Enabled all Track DSP Devices on Selected Channel") +renoise.app():show_status("Enabled all Track DSP Devices on Selected Track") end -renoise.tool():add_menu_entry{name="--Mixer:Paketti..:Bypass All Devices on Channel", invoke=function() effectbypass() end} -renoise.tool():add_menu_entry{name="Mixer:Paketti..:Enable All Devices on Channel", invoke=function() effectenable() end} +renoise.tool():add_keybinding{name="Global:Paketti:Bypass All Devices on Track", invoke=function() effectbypass() end} +renoise.tool():add_keybinding{name="Global:Paketti:Enable All Devices on Track", invoke=function() effectenable() end} +renoise.tool():add_menu_entry{name="--Mixer:Paketti..:Bypass All Devices on Track", invoke=function() effectbypass() end} +renoise.tool():add_menu_entry{name="Mixer:Paketti..:Enable All Devices on Track", invoke=function() effectenable() end} +renoise.tool():add_menu_entry {name="Mixer:Paketti..:Bypass All Devices on All Tracks",invoke=function() PakettiAllDevices(false) end} +renoise.tool():add_menu_entry {name="Mixer:Paketti..:Enable All Devices on All Tracks",invoke=function() PakettiAllDevices(true) end} +renoise.tool():add_menu_entry{name="Mixer:Paketti..:Bypass/Enable All Other Track DSP Devices (Toggle)",invoke=function() toggle_bypass_selected_device() end} +renoise.tool():add_menu_entry{name="--Pattern Editor:Paketti..:Devices..:Bypass All Devices on Track", invoke=function() effectbypass() end} +renoise.tool():add_menu_entry{name="Pattern Editor:Paketti..:Devices..:Enable All Devices on Track", invoke=function() effectenable() end} + + +function PakettiAllDevices(state) + local song = renoise.song() + local total_tracks = song.sequencer_track_count + 1 + song.send_track_count + + for i = 1, total_tracks do + local track = song.tracks[i] + if #track.devices > 1 then + for j = 2, #track.devices do + track.devices[j].is_active = state + end + end + end + + local status_message = state and "Enabled" or "Bypassed" + renoise.app():show_status("All devices " .. status_message .. " from device[2] onward for all tracks") +end + +renoise.tool():add_keybinding {name="Global:Paketti:Bypass All Devices on All Tracks",invoke=function() PakettiAllDevices(false) end} +renoise.tool():add_keybinding {name="Global:Paketti:Enable All Devices on All Tracks",invoke=function() PakettiAllDevices(true) end} + +renoise.tool():add_midi_mapping {name="Paketti:Bypass All Devices on All Tracks",invoke=function(message) if message:is_trigger() then PakettiAllDevices(false) end end} +renoise.tool():add_midi_mapping {name="Paketti:Enable All Devices on All Tracks",invoke=function(message) if message:is_trigger() then PakettiAllDevices(true) end end} + +renoise.tool():add_menu_entry {name="Pattern Editor:Paketti..:Bypass All Devices on All Tracks",invoke=function() PakettiAllDevices(false) end} +renoise.tool():add_menu_entry {name="Pattern Editor:Paketti..:Enable All Devices on All Tracks",invoke=function() PakettiAllDevices(true) end} -- Utility function to print a formatted list from the provided items @@ -1409,9 +1425,6 @@ function listDevicesByType(typeFilter) printItems(deviceItems) end - - - function insertMonoToEnd() local track = renoise.song().selected_track local mono_device_index = nil @@ -1916,7 +1929,7 @@ end} -- Adding menu entries and keybinding for the combined randomizer dialog renoise.tool():add_menu_entry{name="--Main Menu:Tools:Paketti..:Plugins/Devices:Randomize Devices and Plugins Dialog",invoke=function() openCombinedRandomizerDialog() end} renoise.tool():add_menu_entry{name="DSP Device:Paketti..:Randomize Devices and Plugins Dialog",invoke=function() openCombinedRandomizerDialog() end} -renoise.tool():add_menu_entry{name="Mixer:Paketti..:Randomize Devices and Plugins Dialog",invoke=function() openCombinedRandomizerDialog() end} +renoise.tool():add_menu_entry{name="--Mixer:Paketti..:Randomize Devices and Plugins Dialog",invoke=function() openCombinedRandomizerDialog() end} renoise.tool():add_keybinding{name="Global:Paketti:Randomize Devices and Plugins Dialog",invoke=function() openCombinedRandomizerDialog() end} -- Adding keybindings for user preferences for the selected device diff --git a/PakettiMidi.lua b/PakettiMidi.lua index ad573eb..688a7f3 100644 --- a/PakettiMidi.lua +++ b/PakettiMidi.lua @@ -1576,7 +1576,7 @@ local function clamp_value(value) return math.max(0.0, math.min(1.0, value)) end -local function record_midi_value(value) +function record_midi_value(value) local song = renoise.song() local automation_parameter = song.selected_automation_parameter @@ -1651,7 +1651,6 @@ local function record_midi_value(value) print("Automation recorded at playhead: " .. playhead_line .. " with value: " .. tostring(clamped_value)) end --- MIDI mapping function renoise.tool():add_midi_mapping{ name = "Paketti:Record Automation to Selected Parameter", invoke = function(midi_msg) @@ -1660,7 +1659,6 @@ renoise.tool():add_midi_mapping{ local normalized_value = midi_msg.int_value / 127 print("Received MIDI value: " .. tostring(midi_msg.int_value) .. " (normalized: " .. tostring(normalized_value) .. ")") - -- Call the function to record the value record_midi_value(normalized_value) end } diff --git a/PakettiRequests.lua b/PakettiRequests.lua index 7e91a43..958f969 100644 --- a/PakettiRequests.lua +++ b/PakettiRequests.lua @@ -2791,7 +2791,6 @@ function toggle_bypass_selected_device() end renoise.tool():add_menu_entry{name="DSP Device:Paketti..:Bypass/Enable All Other Track DSP Devices (Toggle)",invoke=function() toggle_bypass_selected_device() end} -renoise.tool():add_menu_entry{name="Mixer:Paketti..:Bypass/Enable All Other Track DSP Devices (Toggle)",invoke=function() toggle_bypass_selected_device() end} renoise.tool():add_keybinding{name="Global:Paketti:Bypass All Other Track DSP Devices (Toggle)",invoke=function() toggle_bypass_selected_device() end} renoise.tool():add_midi_mapping{name="Paketti:Bypass All Other Track DSP Devices (Toggle)",invoke=function() toggle_bypass_selected_device() end} diff --git a/PakettiSamples.lua b/PakettiSamples.lua index 47f27bb..649c625 100644 --- a/PakettiSamples.lua +++ b/PakettiSamples.lua @@ -1453,9 +1453,10 @@ end renoise.tool():add_menu_entry{name="--Main Menu:Tools:Paketti..:Clean Render Selected Track/Group", invoke = function() pakettiCleanRenderSelection() end} renoise.tool():add_menu_entry{name="--Pattern Editor:Paketti..:Clean Render Selected Track/Group", invoke = function() pakettiCleanRenderSelection() end} -renoise.tool():add_menu_entry{name="Mixer:Paketti..:Clean Render Selected Track/Group", invoke = function() pakettiCleanRenderSelection() end} renoise.tool():add_menu_entry{name="--Instrument Box:Paketti..:Clean Render Selected Track/Group", invoke = function() pakettiCleanRenderSelection() end} renoise.tool():add_keybinding{name="Pattern Editor:Paketti:Clean Render Selected Track/Group", invoke = function() pakettiCleanRenderSelection() end} +renoise.tool():add_menu_entry{name="--Mixer:Paketti..:Clean Render Selected Track/Group", invoke = function() pakettiCleanRenderSelection() end} + renoise.tool():add_keybinding{name="Mixer:Paketti:Clean Render Selected Track/Group", invoke = function() pakettiCleanRenderSelection() end} ------ -- Define render state (initialized when starting to render) @@ -1661,7 +1662,13 @@ end renoise.tool():add_menu_entry{name="Main Menu:Tools:Paketti..:Clean Render Selected Track/Group LPB*2", invoke = function() pakettiCleanRenderSelectionLPB() end} renoise.tool():add_menu_entry{name="Pattern Editor:Paketti..:Clean Render Selected Track/Group LPB*2", invoke = function() pakettiCleanRenderSelectionLPB() end} +renoise.tool():add_menu_entry{name="Pattern Editor:Paketti..:Clean Render Seamless Selected Track/Group", invoke = function() PakettiSeamlessCleanRenderSelection() end} + + renoise.tool():add_menu_entry{name="Mixer:Paketti..:Clean Render Selected Track/Group LPB*2", invoke = function() pakettiCleanRenderSelectionLPB() end} +renoise.tool():add_menu_entry{name="Mixer:Paketti..:Clean Render Seamless Selected Track/Group", invoke = function() PakettiSeamlessCleanRenderSelection() end} + + renoise.tool():add_menu_entry{name="Instrument Box:Paketti..:Clean Render Selected Track/Group LPB*2", invoke = function() pakettiCleanRenderSelectionLPB() end} renoise.tool():add_keybinding{name="Pattern Editor:Paketti:Clean Render Selected Track/Group LPB*2", invoke = function() pakettiCleanRenderSelectionLPB() end} renoise.tool():add_keybinding{name="Mixer:Paketti:Clean Render Selected Track/Group LPB*2", invoke = function() pakettiCleanRenderSelectionLPB() end} @@ -2711,6 +2718,13 @@ renoise.tool():add_menu_entry{name="--Main Menu:Tools:Paketti..:Clean Render and renoise.tool():add_menu_entry{name="Main Menu:Tools:Paketti..:Clean Render and Save Selected Track/Group as .FLAC", invoke=function() CleanRenderAndSaveSelection("FLAC") end} renoise.tool():add_menu_entry{name="Pattern Editor:Paketti..:Clean Render and Save Selected Track/Group as .WAV", invoke=function() CleanRenderAndSaveSelection("WAV") end} renoise.tool():add_menu_entry{name="Pattern Editor:Paketti..:Clean Render and Save Selected Track/Group as .FLAC", invoke=function() CleanRenderAndSaveSelection("FLAC") end} + +renoise.tool():add_menu_entry{name="Mixer:Paketti..:Clean Render and Save Selected Track/Group as .WAV", invoke=function() CleanRenderAndSaveSelection("WAV") end} +renoise.tool():add_menu_entry{name="Mixer:Paketti..:Clean Render and Save Selected Track/Group as .FLAC", invoke=function() CleanRenderAndSaveSelection("FLAC") end} + + + + renoise.tool():add_keybinding{name="Global:Paketti:Clean Render&Save Selected Track/Group (.WAV)", invoke=function() CleanRenderAndSaveSelection("WAV") end} renoise.tool():add_keybinding{name="Global:Paketti:Clean Render&Save Selected Track/Group (.FLAC)", invoke=function() CleanRenderAndSaveSelection("FLAC") end} renoise.tool():add_menu_entry{name="--Pattern Editor:Paketti..:Duplicate and Reverse Instrument", invoke=PakettiDuplicateAndReverseInstrument} @@ -3016,8 +3030,6 @@ end -- Menu and keybinding for rendering renoise.tool():add_menu_entry{name="--Main Menu:Tools:Paketti..:Clean Render Seamless Selected Track/Group", invoke = function() PakettiSeamlessCleanRenderSelection() end} -renoise.tool():add_menu_entry{name="--Pattern Editor:Paketti..:Clean Render Seamless Selected Track/Group", invoke = function() PakettiSeamlessCleanRenderSelection() end} -renoise.tool():add_menu_entry{name="Mixer:Paketti..:Clean Render Seamles Selected Track/Group", invoke = function() PakettiSeamlessCleanRenderSelection() end} renoise.tool():add_menu_entry{name="--Instrument Box:Paketti..:Clean Render Seamless Selected Track/Group", invoke = function() PakettiSeamlessCleanRenderSelection() end} renoise.tool():add_keybinding{name="Pattern Editor:Paketti:Clean Render Seamless Selected Track/Group", invoke = function() PakettiSeamlessCleanRenderSelection() end} renoise.tool():add_keybinding{name="Mixer:Paketti:Clean Render Seamless Selected Track/Group", invoke = function() PakettiSeamlessCleanRenderSelection() end} diff --git a/PakettieSpeak.lua b/PakettieSpeak.lua index 58165a4..bcdf5eb 100644 --- a/PakettieSpeak.lua +++ b/PakettieSpeak.lua @@ -65,7 +65,7 @@ function PakettieSpeakLoadTextfile(refresh) vb.views.PakettieSpeak_text_field.text = content vb.views.PakettieSpeak_load_textfile_button.text = selected_textfile:match("[^/\\]+$") print("Loaded textfile:", content) - ReSpeak.text.value = content + eSpeak.text.value = content PakettieSpeakCreateSample() PakettieSpeakUpdateLineCount() -- Update line count after loading textfile else @@ -114,7 +114,7 @@ local randomize_everything = vb:row{ result = result .. characters:sub(random_index, random_index) end vb.views.PakettieSpeak_text_field.text = result - ReSpeak.text.value = result + eSpeak.text.value = result PakettieSpeakCreateSample() PakettieSpeakUpdateLineCount() end @@ -134,7 +134,7 @@ local randomize_everything = vb:row{ result = result .. consonants:sub(random_index, random_index) end vb.views.PakettieSpeak_text_field.text = result - ReSpeak.text.value = result + eSpeak.text.value = result PakettieSpeakCreateSample() PakettieSpeakUpdateLineCount() end @@ -153,7 +153,7 @@ local randomize_vowels = vb:button{id = "PakettieSpeak_randomize_vowels", result = result .. vowels:sub(random_index, random_index) end vb.views.PakettieSpeak_text_field.text = result - ReSpeak.text.value = result + eSpeak.text.value = result PakettieSpeakCreateSample() PakettieSpeakUpdateLineCount() end @@ -163,14 +163,14 @@ local randomize_vowels = vb:button{id = "PakettieSpeak_randomize_vowels", local exe_button = vb:button{id="PakettieSpeak_exe_button", width = control_width, height = 24, - text = PakettieSpeakRevertPath(ReSpeak.executable), + text = PakettieSpeakRevertPath(eSpeak.executable), notifier = function() local filename = renoise.app():prompt_for_filename_to_read({"*.*"}, "Select Executable") if filename ~= "" then - ReSpeak.executable = PakettieSpeakConvertPath(filename) - renoise.tool().preferences.pakettiReSpeak.executable = ReSpeak.executable - vb.views.PakettieSpeak_exe_button.text = PakettieSpeakRevertPath(ReSpeak.executable) + eSpeak.executable = PakettieSpeakConvertPath(filename) + renoise.tool().preferences.pakettieSpeak.executable = eSpeak.executable + vb.views.PakettieSpeak_exe_button.text = PakettieSpeakRevertPath(eSpeak.executable) vb.views.PakettieSpeak_exe_button.width = math.min(#vb.views.PakettieSpeak_exe_button.text * 8, control_width) end end} @@ -193,7 +193,7 @@ local loadtext_refresh= vb:row{ notifier = function() PakettieSpeakLoadTextfile(true) print("Refresh: loaded textfile and updated textfield") - ReSpeak.text.value = vb.views.PakettieSpeak_text_field.text + eSpeak.text.value = vb.views.PakettieSpeak_text_field.text PakettieSpeakUpdateLineCount() end } @@ -209,7 +209,7 @@ local eSpeak_textfield= vb:column{ width = 373, height = 100, style = "border", - text = tostring(ReSpeak.text.value), + text = tostring(eSpeak.text.value), notifier = function() PakettieSpeakUpdateLineCount() end @@ -227,13 +227,13 @@ local which_row= vb:row{ local text = vb.views.PakettieSpeak_text_field.text local lines = PakettieSpeakGetLines(text) if value == 0 then - ReSpeak.text.value = text -- Render all text + eSpeak.text.value = text -- Render all text else local selected_line = lines[value] or "" - ReSpeak.text.value = selected_line + eSpeak.text.value = selected_line end - if ReSpeak.render_on_change.value then - PakettieSpeakCreateSample(ReSpeak.text.value) + if eSpeak.render_on_change.value then + PakettieSpeakCreateSample(eSpeak.text.value) end end } @@ -288,7 +288,7 @@ local start_pos= vb:row{ if vb.views.PakettieSpeak_length_pos.value > 0 then vb.views.PakettieSpeak_length_pos.value = vb.views.PakettieSpeak_length_pos.value - 1 PakettieSpeakUpdateSelection() - if ReSpeak.render_on_change.value then + if eSpeak.render_on_change.value then PakettieSpeakCreateSample(vb.views.PakettieSpeak_selection_display.text) end end @@ -301,7 +301,7 @@ local start_pos= vb:row{ if vb.views.PakettieSpeak_length_pos.value < 500 then vb.views.PakettieSpeak_length_pos.value = vb.views.PakettieSpeak_length_pos.value + 1 PakettieSpeakUpdateSelection() - if ReSpeak.render_on_change.value then + if eSpeak.render_on_change.value then PakettieSpeakCreateSample(vb.views.PakettieSpeak_selection_display.text) end end @@ -333,7 +333,7 @@ local eSpeakselection= vb:row{ local selected_text = text:sub(start, end_pos) print("Selected text:", selected_text) renoise.app():show_status("Selected text: " .. selected_text) - ReSpeak.text.value = selected_text + eSpeak.text.value = selected_text PakettieSpeakCreateSample() else renoise.app():show_status("Invalid selection range") @@ -348,11 +348,11 @@ local settingsControls= vb:row{ id = "PakettieSpeak_language", width = 250, items = LANGUAGE_NAMES, - value = ReSpeak.language.value, + value = eSpeak.language.value, notifier = function(idx) if not button_press_active then - ReSpeak.language.value = idx - if ReSpeak.render_on_change.value then PakettieSpeakCreateSample(ReSpeak.text.value) end + eSpeak.language.value = idx + if eSpeak.render_on_change.value then PakettieSpeakCreateSample(eSpeak.text.value) end end end }, @@ -363,8 +363,8 @@ local settingsControls= vb:row{ if vb.views.PakettieSpeak_language.value > 1 then button_press_active = true vb.views.PakettieSpeak_language.value = vb.views.PakettieSpeak_language.value - 1 - ReSpeak.language.value = vb.views.PakettieSpeak_language.value - if ReSpeak.render_on_change.value then PakettieSpeakCreateSample(ReSpeak.text.value) end + eSpeak.language.value = vb.views.PakettieSpeak_language.value + if eSpeak.render_on_change.value then PakettieSpeakCreateSample(eSpeak.text.value) end button_press_active = false else renoise.app():show_status("You are at the beginning of the list.") @@ -378,8 +378,8 @@ local settingsControls= vb:row{ if vb.views.PakettieSpeak_language.value < #LANGUAGE_NAMES then button_press_active = true vb.views.PakettieSpeak_language.value = vb.views.PakettieSpeak_language.value + 1 - ReSpeak.language.value = vb.views.PakettieSpeak_language.value - if ReSpeak.render_on_change.value then PakettieSpeakCreateSample(ReSpeak.text.value) end + eSpeak.language.value = vb.views.PakettieSpeak_language.value + if eSpeak.render_on_change.value then PakettieSpeakCreateSample(eSpeak.text.value) end button_press_active = false else renoise.app():show_status("You are at the bottom of the list.") @@ -393,11 +393,11 @@ local eSpeakvoice= vb:row{ id = "PakettieSpeak_voice", width = 250, items = VOICES, - value = ReSpeak.voice.value, + value = eSpeak.voice.value, notifier = function(idx) if not button_press_active then - ReSpeak.voice.value = idx - if ReSpeak.render_on_change.value then PakettieSpeakCreateSample(ReSpeak.text.value) end + eSpeak.voice.value = idx + if eSpeak.render_on_change.value then PakettieSpeakCreateSample(eSpeak.text.value) end end end }, @@ -408,8 +408,8 @@ local eSpeakvoice= vb:row{ if vb.views.PakettieSpeak_voice.value > 2 then button_press_active = true vb.views.PakettieSpeak_voice.value = vb.views.PakettieSpeak_voice.value - 1 - ReSpeak.voice.value = vb.views.PakettieSpeak_voice.value - if ReSpeak.render_on_change.value then PakettieSpeakCreateSample(ReSpeak.text.value) end + eSpeak.voice.value = vb.views.PakettieSpeak_voice.value + if eSpeak.render_on_change.value then PakettieSpeakCreateSample(eSpeak.text.value) end button_press_active = false else renoise.app():show_status("You are at the beginning of the list") @@ -423,8 +423,8 @@ local eSpeakvoice= vb:row{ if vb.views.PakettieSpeak_voice.value < #VOICES then button_press_active = true vb.views.PakettieSpeak_voice.value = vb.views.PakettieSpeak_voice.value + 1 - ReSpeak.voice.value = vb.views.PakettieSpeak_voice.value - if ReSpeak.render_on_change.value then PakettieSpeakCreateSample(ReSpeak.text.value) end + eSpeak.voice.value = vb.views.PakettieSpeak_voice.value + if eSpeak.render_on_change.value then PakettieSpeakCreateSample(eSpeak.text.value) end button_press_active = false else renoise.app():show_status("You are at the bottom of the list") @@ -439,10 +439,10 @@ local eSpeakgapbox= vb:row{ width = valuebox_width, min = 1, max = 10000, - value = ReSpeak.word_gap.value, + value = eSpeak.word_gap.value, steps = {1, 10, 100}, notifier = function(gap) - ReSpeak.word_gap.value = gap + eSpeak.word_gap.value = gap print("Word Gap set to:", gap) end } @@ -455,10 +455,10 @@ local eSpeakpitchcap= vb:row{ width = valuebox_width, min = 1, max = 100, - value = ReSpeak.capitals.value, + value = eSpeak.capitals.value, steps = {1, 5}, notifier = function(capitals) - ReSpeak.capitals.value = capitals + eSpeak.capitals.value = capitals print("Pitch Capitals set to:", capitals) end } @@ -471,10 +471,10 @@ local eSpeakpitchbox= vb:row{ width = valuebox_width, min = 0, max = 99, - value = ReSpeak.pitch.value, + value = eSpeak.pitch.value, steps = {1, 5}, notifier = function(pitch) - ReSpeak.pitch.value = pitch + eSpeak.pitch.value = pitch print("Pitch set to:", pitch) end } @@ -487,10 +487,10 @@ local eSpeakamplitude= vb:row{ width = valuebox_width, min = 0, max = 200, - value = ReSpeak.amplitude.value, + value = eSpeak.amplitude.value, steps = {1, 5}, notifier = function(amplitude) - ReSpeak.amplitude.value = amplitude + eSpeak.amplitude.value = amplitude print("Amplitude set to:", amplitude) end } @@ -503,10 +503,10 @@ local eSpeakamplitude= vb:row{ width = valuebox_width, min = 1, max = 500, - value = ReSpeak.speed.value, + value = eSpeak.speed.value, steps = {1, 5}, notifier = function(speed) - ReSpeak.speed.value = speed + eSpeak.speed.value = speed print("Speed set to:", speed) end } @@ -530,9 +530,9 @@ local settingsColumn= vb:column{ id = "PakettieSpeak_clear_all_samples", width = 18, height = 18, - value = ReSpeak.clear_all_samples.value == true, + value = eSpeak.clear_all_samples.value == true, notifier = function(bool) - ReSpeak.clear_all_samples.value = bool + eSpeak.clear_all_samples.value = bool print("Clear All Samples set to:", bool) end }, @@ -543,9 +543,9 @@ local settingsColumn= vb:column{ id = "PakettieSpeak_add_render_to_current_instrument", width = 18, height = 18, - value = ReSpeak.add_render_to_current_instrument.value == true, + value = eSpeak.add_render_to_current_instrument.value == true, notifier = function(bool) - ReSpeak.add_render_to_current_instrument.value = bool + eSpeak.add_render_to_current_instrument.value = bool vb.views.PakettieSpeak_clear_all_samples.value = false print("Add Render to Current Instrument set to:", bool) end @@ -557,9 +557,9 @@ local settingsColumn= vb:column{ id = "PakettieSpeak_render_on_change", width = 18, height = 18, - value = ReSpeak.render_on_change.value == true, + value = eSpeak.render_on_change.value == true, notifier = function(bool) - ReSpeak.render_on_change.value = bool + eSpeak.render_on_change.value = bool print("Render on Change set to:", bool) end }, @@ -575,25 +575,25 @@ local eSpeakloadsave= vb:horizontal_aligner{ notifier = function() local filename = renoise.app():prompt_for_filename_to_read({"*.rts"}, "Load Settings") if filename ~= "" then - local result = ReSpeak:load_from(filename) + local result = eSpeak:load_from(filename) if result == nil then renoise.app():show_error("Unable to Load Settings.") else print("Loaded Settings:", result) - vb.views.PakettieSpeak_text_field.text = tostring(ReSpeak.text.value) - vb.views.PakettieSpeak_language.value = ReSpeak.language.value - vb.views.PakettieSpeak_voice.value = ReSpeak.voice.value - vb.views.PakettieSpeak_gap_box.value = ReSpeak.word_gap.value - vb.views.PakettieSpeak_capitals_box.value = ReSpeak.capitals.value - vb.views.PakettieSpeak_pitch_box.value = ReSpeak.pitch.value - vb.views.PakettieSpeak_amplitude_box.value = ReSpeak.amplitude.value - vb.views.PakettieSpeak_speed_box.value = ReSpeak.speed.value - local espeak_executable = PakettieSpeakRevertPath(ReSpeak.executable) + vb.views.PakettieSpeak_text_field.text = tostring(eSpeak.text.value) + vb.views.PakettieSpeak_language.value = eSpeak.language.value + vb.views.PakettieSpeak_voice.value = eSpeak.voice.value + vb.views.PakettieSpeak_gap_box.value = eSpeak.word_gap.value + vb.views.PakettieSpeak_capitals_box.value = eSpeak.capitals.value + vb.views.PakettieSpeak_pitch_box.value = eSpeak.pitch.value + vb.views.PakettieSpeak_amplitude_box.value = eSpeak.amplitude.value + vb.views.PakettieSpeak_speed_box.value = eSpeak.speed.value + local espeak_executable = PakettieSpeakRevertPath(eSpeak.executable) vb.views.PakettieSpeak_exe_button.text = espeak_executable vb.views.PakettieSpeak_exe_button.width = math.min(#vb.views.PakettieSpeak_exe_button.text * 8, control_width) - renoise.tool().preferences.pakettiReSpeak.executable = espeak_executable - vb.views.PakettieSpeak_clear_all_samples.value = ReSpeak.clear_all_samples.value == true - vb.views.PakettieSpeak_render_on_change.value = ReSpeak.render_on_change.value == true + renoise.tool().preferences.pakettieSpeak.executable = espeak_executable + vb.views.PakettieSpeak_clear_all_samples.value = eSpeak.clear_all_samples.value == true + vb.views.PakettieSpeak_render_on_change.value = eSpeak.render_on_change.value == true PakettieSpeakUpdateLineCount() end end @@ -608,8 +608,8 @@ local eSpeakloadsave= vb:horizontal_aligner{ notifier = function() local filename = renoise.app():prompt_for_filename_to_write(".rts", "Save Settings") if filename ~= "" then - ReSpeak.text.value = vb.views.PakettieSpeak_text_field.text - local result = ReSpeak:save_as(filename) + eSpeak.text.value = vb.views.PakettieSpeak_text_field.text + local result = eSpeak:save_as(filename) if result == nil then renoise.app():show_error("Unable to Save Settings.") else @@ -627,7 +627,7 @@ local lastbuttons= vb:horizontal_aligner{ width = button_width, height = 24, notifier = function() - ReSpeak.text.value = vb.views.PakettieSpeak_text_field.text + eSpeak.text.value = vb.views.PakettieSpeak_text_field.text PakettieSpeakCreateSample() normalize_selected_sample() renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR @@ -639,24 +639,28 @@ local lastbuttons= vb:horizontal_aligner{ height = 24, notifier = function() vb.views.PakettieSpeak_language.value = math.random(1, #LANGUAGE_NAMES) - ReSpeak.language.value = vb.views.PakettieSpeak_language.value + eSpeak.language.value = vb.views.PakettieSpeak_language.value vb.views.PakettieSpeak_voice.value = math.random(1, #VOICES) - ReSpeak.voice.value = vb.views.PakettieSpeak_voice.value + eSpeak.voice.value = vb.views.PakettieSpeak_voice.value local random_gap = math.random(1, 100) vb.views.PakettieSpeak_gap_box.value = random_gap - ReSpeak.word_gap.value = random_gap + eSpeak.word_gap.value = random_gap local random_capitals = math.random(1, 100) vb.views.PakettieSpeak_capitals_box.value = random_capitals - ReSpeak.capitals.value = random_capitals + eSpeak.capitals.value = random_capitals local random_pitch = math.random(0, 99) vb.views.PakettieSpeak_pitch_box.value = random_pitch - ReSpeak.pitch.value = random_pitch + eSpeak.pitch.value = random_pitch local random_speed = math.random(1, 500) vb.views.PakettieSpeak_speed_box.value = random_speed - ReSpeak.speed.value = random_speed - if ReSpeak.render_on_change.value then - PakettieSpeakCreateSample(ReSpeak.text.value) + eSpeak.speed.value = random_speed + if eSpeak.render_on_change.value then + PakettieSpeakCreateSample(eSpeak.text.value) end + eSpeak.text.value = vb.views.PakettieSpeak_text_field.text + PakettieSpeakCreateSample() + normalize_selected_sample() + renoise.app().window.active_middle_frame = renoise.ApplicationWindow.MIDDLE_FRAME_INSTRUMENT_SAMPLE_EDITOR end } } @@ -692,25 +696,25 @@ end function PakettieSpeakPrepare() print("Starting dialog with settings:") - print("Text:", ReSpeak.text.value) - print("Loaded Language:",ReSpeak.language.value) - print("Loaded Voice:",ReSpeak.voice.value) - print("Loaded Word Gap:",ReSpeak.word_gap.value) - print("Loaded Pitch Capitals:",ReSpeak.capitals.value) - print("Loaded Pitch:",ReSpeak.pitch.value) - print("Loaded Amplitude:",ReSpeak.amplitude.value) - print("Loaded Speed:",ReSpeak.speed.value) - print("Loaded Executable:",ReSpeak.executable.value) - print("Loaded Clear All Samples:",ReSpeak.clear_all_samples.value) + print("Text:",eSpeak.text.value) + print("Loaded Language:",eSpeak.language.value) + print("Loaded Voice:",eSpeak.voice.value) + print("Loaded Word Gap:",eSpeak.word_gap.value) + print("Loaded Pitch Capitals:",eSpeak.capitals.value) + print("Loaded Pitch:",eSpeak.pitch.value) + print("Loaded Amplitude:",eSpeak.amplitude.value) + print("Loaded Speed:",eSpeak.speed.value) + print("Loaded Executable:",eSpeak.executable.value) + print("Loaded Clear All Samples:",eSpeak.clear_all_samples.value) if dialog and dialog.visible then dialog:show() return end - local espeak_location = renoise.tool().preferences.pakettiReSpeak.executable + local espeak_location = renoise.tool().preferences.pakettieSpeak.executable if espeak_location ~= "" then - ReSpeak.executable = PakettieSpeakConvertPath(espeak_location) + eSpeak.executable = PakettieSpeakConvertPath(espeak_location) else renoise.app():show_alert("Please set the eSpeak path before running.") return @@ -724,12 +728,12 @@ function PakettieSpeakKeyHandlerFunc(dialog, key) if key.modifiers == "control" and key.name == "r" then PakettieSpeakLoadTextfile(true) print("Refresh: loaded textfile and updated textfield") - ReSpeak.text.value = vb.views.PakettieSpeak_text_field.text + eSpeak.text.value = vb.views.PakettieSpeak_text_field.text PakettieSpeakUpdateLineCount() end if key.modifiers == "control" and key.name == "return" then - ReSpeak.text.value = vb.views.PakettieSpeak_text_field.text + eSpeak.text.value = vb.views.PakettieSpeak_text_field.text PakettieSpeakCreateSample() normalize_selected_sample() end @@ -743,7 +747,7 @@ if key.modifiers == "alt" and key.name == "return" then local selected_text = text:sub(start, end_pos) print("Selected text:", selected_text) renoise.app():show_status("Selected text: " .. selected_text) - ReSpeak.text.value = selected_text + eSpeak.text.value = selected_text PakettieSpeakCreateSample() else renoise.app():show_status("Invalid selection range") @@ -765,7 +769,7 @@ end function PakettieSpeakToggleDialog() if dialog and dialog.visible then - ReSpeak.text.value = vb.views.PakettieSpeak_text_field.text + eSpeak.text.value = vb.views.PakettieSpeak_text_field.text PakettieSpeakCreateSample() else PakettieSpeakPrepare() @@ -773,24 +777,24 @@ function PakettieSpeakToggleDialog() end function PakettieSpeakCreateSample(custom_text) - local text_to_render = custom_text or ReSpeak.text.value + local text_to_render = custom_text or eSpeak.text.value print(text_to_render) - local executable = PakettieSpeakRevertPath(ReSpeak.executable) + local executable = PakettieSpeakRevertPath(eSpeak.executable) local path = os.tmpname() .. ".wav" local cmd = executable - cmd=cmd .. " -a " .. ReSpeak.amplitude.value - cmd=cmd .. " -v " .. LANGUAGE_SHORTS[ReSpeak.language.value] + cmd=cmd .. " -a " .. eSpeak.amplitude.value + cmd=cmd .. " -v " .. LANGUAGE_SHORTS[eSpeak.language.value] - if ReSpeak.voice.value ~= 1 then - cmd = cmd .. "+" .. VOICES[ReSpeak.voice.value] + if eSpeak.voice.value ~= 1 then + cmd = cmd .. "+" .. VOICES[eSpeak.voice.value] end cmd=cmd .. " -b 1 -m " - cmd=cmd .. " -p " .. ReSpeak.pitch.value - cmd=cmd .. " -s " .. ReSpeak.speed.value - cmd=cmd .. " -g " .. ReSpeak.word_gap.value - cmd=cmd .. " -k " .. ReSpeak.capitals.value + cmd=cmd .. " -p " .. eSpeak.pitch.value + cmd=cmd .. " -s " .. eSpeak.speed.value + cmd=cmd .. " -g " .. eSpeak.word_gap.value + cmd=cmd .. " -k " .. eSpeak.capitals.value cmd=cmd .. " -w " .. path cmd=cmd .. ' "' .. text_to_render .. '"' @@ -802,7 +806,7 @@ function PakettieSpeakCreateSample(custom_text) local instrument -- **Check if "Add Render to Current Instrument" is Enabled** - if ReSpeak.add_render_to_current_instrument.value then + if eSpeak.add_render_to_current_instrument.value then -- **If No Instruments Exist, Load the Pitchbend Instrument** if #song.instruments == 0 then pakettiPreferencesDefaultInstrumentLoader() @@ -819,10 +823,10 @@ function PakettieSpeakCreateSample(custom_text) local new_sample_index = #instrument.samples + 1 local sample = instrument:insert_sample_at(new_sample_index) song.selected_sample_index = new_sample_index - sample.name = "eSpeak (" .. LANGUAGE_NAMES[ReSpeak.language.value] .. ", " .. VOICES_NAMES[ReSpeak.voice.value] .. ")" + sample.name = "eSpeak (" .. LANGUAGE_NAMES[eSpeak.language.value] .. ", " .. VOICES_NAMES[eSpeak.voice.value] .. ")" print("Added new sample slot to current instrument:", sample.name) - elseif ReSpeak.clear_all_samples.value then + elseif eSpeak.clear_all_samples.value then -- **Existing Behavior: Clear All Samples and Add One** instrument = song.selected_instrument pakettiPreferencesDefaultInstrumentLoader() @@ -831,7 +835,7 @@ function PakettieSpeakCreateSample(custom_text) end local sample = instrument:insert_sample_at(1) song.selected_sample_index = 1 - sample.name = "eSpeak (" .. LANGUAGE_NAMES[ReSpeak.language.value] .. ", " .. VOICES_NAMES[ReSpeak.voice.value] .. ")" + sample.name = "eSpeak (" .. LANGUAGE_NAMES[eSpeak.language.value] .. ", " .. VOICES_NAMES[eSpeak.voice.value] .. ")" print("Cleared all samples and added new sample:", sample.name) else @@ -840,9 +844,9 @@ function PakettieSpeakCreateSample(custom_text) song.selected_instrument_index = song.selected_instrument_index + 1 pakettiPreferencesDefaultInstrumentLoader() instrument = song.selected_instrument - instrument.name = "eSpeak (" .. LANGUAGE_NAMES[ReSpeak.language.value] .. ", " .. VOICES_NAMES[ReSpeak.voice.value] .. ")" + instrument.name = "eSpeak (" .. LANGUAGE_NAMES[eSpeak.language.value] .. ", " .. VOICES_NAMES[eSpeak.voice.value] .. ")" local sample = instrument:insert_sample_at(1) - sample.name = "eSpeak (" .. LANGUAGE_NAMES[ReSpeak.language.value] .. ", " .. VOICES_NAMES[ReSpeak.voice.value] .. ")" + sample.name = "eSpeak (" .. LANGUAGE_NAMES[eSpeak.language.value] .. ", " .. VOICES_NAMES[eSpeak.voice.value] .. ")" song.selected_sample_index = 1 print("Inserted new instrument and added sample:", sample.name) end @@ -879,7 +883,7 @@ renoise.tool():add_menu_entry{name="Sample Editor:Paketti..:Paketti eSpeak Text- renoise.tool():add_keybinding{name="Global:Paketti:Paketti eSpeak Text-to-Speech",invoke=function() PakettieSpeakToggleDialog() end} renoise.tool():add_keybinding{name="Global:Paketti:Paketti eSpeak Generate Sample",invoke=function() if dialog and dialog.visible then - ReSpeak.text.value = vb.views.PakettieSpeak_text_field.text + eSpeak.text.value = vb.views.PakettieSpeak_text_field.text PakettieSpeakCreateSample() normalize_selected_sample() else PakettieSpeakPrepare() end end } @@ -894,7 +898,7 @@ renoise.tool():add_keybinding{name="Global:Paketti:Paketti eSpeak Generate Selec local selected_text = text:sub(start, end_pos) print("Selected text:", selected_text) renoise.app():show_status("Selected text: " .. selected_text) - ReSpeak.text.value = selected_text + eSpeak.text.value = selected_text PakettieSpeakCreateSample() else renoise.app():show_status("Invalid selection range") @@ -909,16 +913,16 @@ for value = 0, 31 do local selected_line = (value == 0) and text or (lines[value] or "") -- Protection: do nothing if selected line is empty if selected_line == "" then return end - ReSpeak.text.value = selected_line - if ReSpeak.render_on_change.value then - PakettieSpeakCreateSample(ReSpeak.text.value) end end} + eSpeak.text.value = selected_line + if eSpeak.render_on_change.value then + PakettieSpeakCreateSample(eSpeak.text.value) end end} end renoise.tool():add_keybinding{name="Global:Paketti:Paketti eSpeak Refresh",invoke=function() if dialog and dialog.visible then PakettieSpeakLoadTextfile(true) print("Refresh: loaded textfile and updated textfield") - ReSpeak.text.value = vb.views.PakettieSpeak_text_field.text + eSpeak.text.value = vb.views.PakettieSpeak_text_field.text PakettieSpeakUpdateLineCount() else PakettieSpeakPrepare() end end} diff --git a/preferences.xml b/preferences.xml index 4e30214..9f25e77 100644 --- a/preferences.xml +++ b/preferences.xml @@ -2,21 +2,8 @@ 2 4 - 2 + 1.0 false - - 69 - 58 - leglegl - 68 - /opt/homebrew/bin/espeak-ng - true - 3 - 4 - false - 52 - 201 - 4 12st_Pitchbend.xrni false @@ -55,6 +42,7 @@ false 1.0 false + false 1.0 2 false @@ -62,17 +50,18 @@ 1.0 - 147.11538461538461 - 91.835664335664333 + 51.713286713286706 + 10.6993006993007 false true - true + false true - 58 + 81 - 88200 - LP Clean + esc + LP Moog true + DeviceChains/ Audio/Effects/AU/aufx:dLay:oDin Audio/Effects/Native/Distortion 2 @@ -88,8 +77,9 @@ true 0.0 - false - true + + ble + 1.0 4 @@ -105,6 +95,7 @@ false false + false true /Users/esaruoho/Music/samples/colugatest/ColugaSampleSave/ @@ -116,20 +107,41 @@ /opt/homebrew/Cellar/yt-dlp/2024.8.6/libexec/bin/yt-dlp true + true - Slot 10: Empty - false + --- .. .. 40 .. ....|| + false + true + 29.333333333333332 false - Slot 09: Empty - C-3 08 7F 20 30 ....||0B00|0D00 + ||0B32 + C-6 08 7F 20 30 ....||0B00|0D00 --- .. .. .. 55 ....|| OFF .. .. .. .. .... | --- .. .. .. .. .... | --- .. .. .. .. .... | --- .. .. .. .. ....|| --- .. .. .. AA .... | --- .. .. .. 55 .... | --- .. .. .. AA .... | --- .. .. .. AA ....|| --- .. .. .. .. 0B00||0D30 - C-4 00 30 50 30 0AF0 | F-4 00 .. .. .. ....||0B00|0S00|0E00|0F00 + C-1 00 30 50 30 0AF0 | F-4 00 .. .. .. ....||0B00|0S00|0E00|0F00 OFF .. .. .. .. .... | --- .. .. .. .. .... | --- .. .. .. .. .... | --- .. .. .. .. ....|| - C-4 00 .. .. .. .... | D-4 00 .. .. .. .... | F-4 00 .. .. .. .... | G-4 00 .. .. .. ....||0B05|0C04|0D03|0E01 + C-2 01 .. .. .. .... | --- .. .. .. .. ....|| + + 67 + 69 + false + Hello, I am Macintosh. It sure is great to get out of that bag! + +Unaccustomed as I am to public speaking, I'd like to share with you a maxim I thought of the first time I met an IBM mainframe: Never trust a computer that you can't lift! + +Obviously, I can talk, but right now I'd like to sit back and listen. So it is with considerable pride that I introduce a man who has been like a father to me... Steve Jobs! + 81 + /opt/homebrew/bin/espeak-ng + false + 5 + 1.0 + true + 31 + 22 + <No Theme Selected> @@ -137,7 +149,6 @@ Little Phatty Theme ulneiz_graycream phase_plant - small_hours_r Default Pico-8 Dusty Chocolate Academic @@ -147,7 +158,6 @@ Space Latte Metal redark Osi-Cyberpunk1 - purple poison arrow frog Graphite RC1 sQeetz_Emerald Osi-BladeRunner @@ -155,26 +165,25 @@ Osi-TrackerHacker mango-theme Textured - BW Zero-G-Inverted - Basic Light Theme Breed - Xan-Neon sea dragon Brown #12 Willingly (Jr‚tion) Black and Pink Sononoise-Dark Orange biology + Mineral-Hills-Mod-of-dracula-redux-theme-1.0-LightBlueButtons true false Darkness A - 2 + 32 12st_Pitchbend_Drumkit_C0.xrni - false + 2 false + false true false false @@ -190,7 +199,7 @@ /Applications/Ableton Live 12 Suite.app true - 32 + 88200 <_0G01_Loader>false 0.021075268817204128 diff --git a/preferencesDynamicView.xml b/preferencesDynamicView.xml index 47b7f4e..8d86847 100644 --- a/preferencesDynamicView.xml +++ b/preferencesDynamicView.xml @@ -16,12 +16,12 @@ false false true - 2 - 6 - 2 - true - true - true + 1.0 + 1.0 + 1.0 + false + false + false false false 1.0