#!/usr/bin/env ruby
#SCvim pipe
#this is a script to pass things from scvim to sclang
#
#Copyright 2007 Alex Norman
#
#This file is part of SCVIM.
#
#SCVIM is free software: you can redistribute it and/or modify
#it under the terms of the GNU General Public License as published by
#the Free Software Foundation, either version 3 of the License, or
#(at your option) any later version.
#
#SCVIM is distributed in the hope that it will be useful,
#but WITHOUT ANY WARRANTY; without even the implied warranty of
#MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#GNU General Public License for more details.
#
#You should have received a copy of the GNU General Public License
#along with SCVIM.  If not, see <http://www.gnu.org/licenses/>.

require 'fileutils'
require 'open3'
require 'optparse'

pipe_loc = "/tmp/sclang-pipe" unless (pipe_loc = ENV["SCVIM_PIPE_LOC"])
rundir = "/tmp/"
if ENV["SCLANG_RUNDIR"]
  rundir = ENV["SCLANG_RUNDIR"]
elsif RUBY_PLATFORM =~ /darwin/
  rundir = "/Applications/SuperCollider/"
end

pid_loc = "/tmp/sclangpipe_app-pid" unless (pid_loc = ENV["SCVIM_PIPE_PID_LOC"])

app = nil
[
  `which sclang`.chomp,
  '/Applications/SuperCollider/SuperCollider.app/Contents/Resources/sclang',
  '/Applications/SuperCollider/sclang',
].each do |l|
  if File.exists?(l)
    app = l
    break
  end
end

unless app
  puts "cannot find sclang executable, is it in your path?"
  exit -1
end

sclangargs = "-i scvim"  # this arg must always be passed, so that sclang knows to load classes from folders named "scide_scvim"

opts = OptionParser.new do |opts|
  opts.on("-h", "--help", "Display this help") do
    puts opts
    exit
  end
  opts.on("-d <path>", "Set runtime directory") do |d|
    rundir = d
  end

  opts.on("-g <memory-growth>[km]", "Set heap growth (default 256k)") do |g|
    sclangargs = sclangargs + " -g #{g}"
  end

  opts.on("-l <path>", "Set library configuration file") do |l|
    sclangargs = sclangargs + " -l #{l}"
  end

  opts.on("-m <memory-space>[km]", "Set initial heap size (default 2m)") do |m|
    sclangargs = sclangargs + " -m #{m}"
  end

  opts.on("-u <network-port-number>", "Set UDP listening port (default 57120)") do |p|
    sclangargs = sclangargs + " -u #{p}"
  end

  opts.on("-r", "Call Main.run on startup") do
    sclangargs = sclangargs + " -r"
  end

  opts.on("-s", "Call Main.stop on shutdown") do
    sclangargs = sclangargs + " -s"
  end

end

opts.parse!(ARGV)

File.open(pid_loc, "w"){ |f| f.puts Process.pid }

#remove the pipe if it exists
FileUtils.rm(pipe_loc) if File.exists?(pipe_loc)
#make a new pipe
system("mkfifo", pipe_loc)

pipeproc = Proc.new {
  trap("INT") do
    Process.exit
  end
  IO.popen("#{app} -d #{rundir.chomp} #{sclangargs}", "w") do |sclang|
    loop {
      x = `cat #{pipe_loc}`
      sclang.print x if x
    }
  end
}

$p = Process.fork { pipeproc.call }

#if we get a hup then we kill the pipe process and
#restart it
trap("HUP") do
  Process.kill("INT", $p)
  $p = Process.fork { pipeproc.call }
end

#clean up after us
trap("INT") do
  FileUtils.rm(pipe_loc)
  FileUtils.rm(pid_loc)
  exit
end

#we sleep until a signal comes
sleep(1) until false
