# Universal Sonic Pi Song Queue System - Proper Loop Stopping
# Works with ANY Sonic Pi code - no modifications needed!

# Global state
set :current_song_id, 0
set :master_volume, 1.0
set :is_transitioning, false

# Main OSC listener
live_loop :song_queue do
  use_real_time
  
  song_data = sync "/osc*/run-code"
  new_song_code = song_data[0].to_s
  
  # Simple debounce
  if get[:is_transitioning]
    puts "Busy - skipping new song"
    next
  end
  
  set :is_transitioning, true
  old_song_id = get[:current_song_id]
  new_song_id = old_song_id + 1
  set :current_song_id, new_song_id
  
  puts "Starting song #{new_song_id}"
  
  in_thread do
    # Fade out current song if exists
    if old_song_id > 0
      puts "Fading out song #{old_song_id}"
      20.times do |i|
        vol = 1.0 - (i / 19.0)
        set :master_volume, vol
        sleep 0.1
      end
      
      # Signal old song to stop
      cue "stop_song_#{old_song_id}"
      sleep 1.0  # Give time for loops to stop cleanly
    end
    
    # Set volume to 0 for new song
    set :master_volume, 0.0
    
    # Start new song
    begin
      # Modify the code to add song-specific loop names and stop conditions
      modified_code = new_song_code.gsub(/live_loop\s+:(\w+)\s+do/) do |match|
        loop_name = $1
        "live_loop :song_#{new_song_id}_#{loop_name} do
  stop if get[:current_song_id] != #{new_song_id}"
      end
      
      # Replace amp parameters to use master volume
      volume_controlled_code = modified_code.gsub(/amp:\s*([0-9.]+)/) do |match|
        original_amp = $1
        "amp: #{original_amp} * get[:master_volume]"
      end
      
      # Replace sync calls to use the new song-specific loop names
      sync_fixed_code = volume_controlled_code.gsub(/sync\s+:(\w+)/) do |match|
        original_loop_name = $1
        "sync :song_#{new_song_id}_#{original_loop_name}"
      end
      
      eval(sync_fixed_code)
      
      puts "Song #{new_song_id} started"
      
      # Fade in new song
      sleep 0.3
      20.times do |i|
        vol = i / 19.0
        set :master_volume, vol
        sleep 0.1
      end
      
      puts "Song #{new_song_id} active"
      
    rescue Exception => e
      puts "Song error: #{e.message}"
      puts e.backtrace[0..2].join("\n")
    end
    
    set :is_transitioning, false
  end
end

# Status monitor
live_loop :status do
  puts "Queue: Song #{get[:current_song_id]} | Volume: #{get[:master_volume].round(2)} | Busy: #{get[:is_transitioning]}"
  sleep 8
end

puts "🎵 Improved Queue Ready - Send code to /run-code"
  