func (r *SDLRenderer) destroyCliRenderer() {
	if r.cliSurface_orNil != nil {
		cliSurface := r.cliSurface_orNil
		r.cliSurface_orNil = nil
		cli.SetRenderer(nil)
		<-composer.RemoveInputSurface(cliSurface.GetSurface())
		done := make(chan bool)
		cliSurface.EventCh() <- clingon.Cmd_Terminate{done}
		<-done
		cliSurface.GetSurface().Free()
		cliSurface.Font.Close()
	}
}
Synchronously destroy the CLI renderer
package sdl_output
import (
	"bytes"
	"errors"
	"flag"
	"fmt"
	"github.com/scottferg/Go-SDL/sdl"
	"github.com/scottferg/Go-SDL/ttf"
	"github.com/remogatto/clingon"
	"github.com/remogatto/gospeccy/src/env"
	"github.com/remogatto/gospeccy/src/interpreter"
	"github.com/remogatto/gospeccy/src/spectrum"
	"reflect"
	"sync"
)
const DEFAULT_JOYSTICK_ID = 0
var (
	shutdown sync.WaitGroup
	cli *clingon.Console
	r *SDLRenderer
	joystick *sdl.Joystick
	composer *SDLSurfaceComposer
)
type SDLSurfaceAccessor interface {
	UpdatedRectsCh() <-chan []sdl.Rect
	GetSurface() *sdl.Surface
}
type cmd_newSurface struct {
	surface SDLSurfaceAccessor
	done    chan bool
}
type cmd_newCliSurface struct {
	surface_orNil *clingon.SDLRenderer
	done          chan bool
}
const (
	HIDE = iota
	SHOW
)
type cmd_newSlider struct {
	anim        *clingon.Animation
	targetState int  
}
type SDLRenderer struct {
	app                           *spectrum.Application
	speccy                        *spectrum.Spectrum48k
	scale2x, fullscreen           bool
	consoleY                      int16
	width, height                 int
	appSurface, speccySurface     SDLSurfaceAccessor
	cliSurface_orNil              *clingon.SDLRenderer
	toggling                      bool
	appSurfaceCh, speccySurfaceCh chan cmd_newSurface
	cliSurfaceCh                  chan cmd_newCliSurface
	sliderCh chan cmd_newSlider
	audio     bool
	audioFreq uint
	hqAudio   bool
}
type wrapSurface struct {
	surface *sdl.Surface
}
func (s *wrapSurface) GetSurface() *sdl.Surface {
	return s.surface
}
func (s *wrapSurface) UpdatedRectsCh() <-chan []sdl.Rect {
	return nil
}
func width(scale2x, fullscreen bool) int {
	if fullscreen {
		scale2x = true
	}
	if scale2x {
		return spectrum.TotalScreenWidth * 2
	}
	return spectrum.TotalScreenWidth
}
func height(scale2x, fullscreen bool) int {
	if fullscreen {
		scale2x = true
	}
	if scale2x {
		return spectrum.TotalScreenHeight * 2
	}
	return spectrum.TotalScreenHeight
}
func newAppSurface(app *spectrum.Application, scale2x, fullscreen bool) SDLSurfaceAccessor {
	var sdlMode int64
	if fullscreen {
		scale2x = true
		sdlMode |= sdl.FULLSCREEN
		sdl.ShowCursor(sdl.DISABLE)
	} else {
		sdl.ShowCursor(sdl.ENABLE)
		sdlMode |= sdl.SWSURFACE
	}
	<-composer.ReplaceOutputSurface(nil)
	surface := sdl.SetVideoMode(int(width(scale2x, fullscreen)), int(height(scale2x, fullscreen)), 32, uint32(sdlMode))
	if app.Verbose {
		app.PrintfMsg("video surface resolution: %dx%d", surface.W, surface.H)
	}
	<-composer.ReplaceOutputSurface(surface)
	return &wrapSurface{surface}
}
func newSpeccySurface(app *spectrum.Application, speccy *spectrum.Spectrum48k, scale2x, fullscreen bool) SDLSurfaceAccessor {
	var speccySurface SDLSurfaceAccessor
	if fullscreen {
		scale2x = true
	}
	if scale2x {
		sdlScreen := NewSDLScreen2x(app)
		speccy.CommandChannel <- spectrum.Cmd_AddDisplay{sdlScreen}
		speccySurface = sdlScreen
	} else {
		sdlScreen := NewSDLScreen(app)
		speccy.CommandChannel <- spectrum.Cmd_AddDisplay{sdlScreen}
		speccySurface = sdlScreen
	}
	return speccySurface
}
func newCLISurface(scale2x, fullscreen bool) *clingon.SDLRenderer {
	cliSurface := clingon.NewSDLRenderer(
		sdl.CreateRGBSurface(
			sdl.SRCALPHA,
			width(scale2x, fullscreen),
			height(scale2x, fullscreen)/2, 32, 0, 0, 0, 0),
		newFont(scale2x, fullscreen),
	)
	cliSurface.GetSurface().SetAlpha(sdl.SRCALPHA, 0xdd)
	return cliSurface
}
func newFont(scale2x, fullscreen bool) *ttf.Font {
	if fullscreen {
		scale2x = true
	}
	var font *ttf.Font
	{
		path, err := spectrum.FontPath("VeraMono.ttf")
		if err != nil {
			panic(err.Error())
		}
		if scale2x {
			font = ttf.OpenFont(path, 12)
		} else {
			font = ttf.OpenFont(path, 10)
		}
		if font == nil {
			panic(sdl.GetError())
		}
	}
	return font
}
func NewSDLRenderer(app *spectrum.Application, speccy *spectrum.Spectrum48k, scale2x, fullscreen bool, audio, hqAudio bool, audioFreq uint) *SDLRenderer {
	width := width(scale2x, fullscreen)
	height := height(scale2x, fullscreen)
	r := &SDLRenderer{
		app:              app,
		speccy:           speccy,
		scale2x:          scale2x,
		fullscreen:       fullscreen,
		appSurfaceCh:     make(chan cmd_newSurface),
		speccySurfaceCh:  make(chan cmd_newSurface),
		cliSurfaceCh:     make(chan cmd_newCliSurface),
		appSurface:       newAppSurface(app, scale2x, fullscreen),
		speccySurface:    newSpeccySurface(app, speccy, scale2x, fullscreen),
		cliSurface_orNil: nil,
		width:            width,
		height:           height,
		consoleY:         int16(height),
		sliderCh:         make(chan cmd_newSlider),
		audio:            audio,
		audioFreq:        audioFreq,
		hqAudio:          hqAudio,
	}
	composer.AddInputSurface(r.speccySurface.GetSurface(), 0, 0, r.speccySurface.UpdatedRectsCh())
	go r.loop()
	return r
}
func (r *SDLRenderer) Terminated() bool {
	return r.app.TerminationInProgress() || r.app.Terminated()
}
func (r *SDLRenderer) ResizeVideo(scale2x, fullscreen bool) {
	finished := make(chan byte)
	r.speccy.CommandChannel <- spectrum.Cmd_CloseAllDisplays{finished}
	<-finished
	if r.scale2x != scale2x {
		if scale2x {
			y := int16(r.height) - r.consoleY
			r.consoleY = int16(2*r.height) - 2*y
		} else {
			y := int16(r.height) - r.consoleY
			r.consoleY = int16(r.height/2) - y/2
		}
	}
	r.width = width(scale2x, fullscreen)
	r.height = height(scale2x, fullscreen)
	r.scale2x = scale2x
	r.fullscreen = fullscreen
	done := make(chan bool)
	r.appSurfaceCh <- cmd_newSurface{newAppSurface(r.app, scale2x, fullscreen), done}
	<-done
	r.speccySurfaceCh <- cmd_newSurface{newSpeccySurface(r.app, r.speccy, scale2x, fullscreen), done}
	<-done
	if r.cliSurface_orNil != nil {
		r.cliSurfaceCh <- cmd_newCliSurface{newCLISurface(scale2x, fullscreen), done}
		<-done
	}
}
func (r *SDLRenderer) ShowPaintedRegions(enable bool) {
	composer.ShowPaintedRegions(enable)
}
func (r *SDLRenderer) setAudioParameters(enable, hqAudio bool, freq uint) {
	r.audio = enable
	r.hqAudio = hqAudio
	r.audioFreq = freq
	finished := make(chan byte)
	r.speccy.CommandChannel <- spectrum.Cmd_CloseAllAudioReceivers{finished}
	<-finished
	if enable {
		audio, err := NewSDLAudio(r.app, freq, hqAudio)
		if err == nil {
			finished := make(chan byte)
			r.speccy.CommandChannel <- spectrum.Cmd_CloseAllAudioReceivers{finished}
			<-finished
			r.speccy.CommandChannel <- spectrum.Cmd_AddAudioReceiver{audio}
		} else {
			r.app.PrintfMsg("%s", err)
			return
		}
	}
}
func (r *SDLRenderer) EnableAudio(enable bool) {
	r.setAudioParameters(enable, r.hqAudio, r.audioFreq)
}
func (r *SDLRenderer) SetAudioFreq(freq uint) {
	if r.audioFreq != freq {
		r.setAudioParameters(r.audio, r.hqAudio, freq)
	}
}
func (r *SDLRenderer) SetAudioQuality(hqAudio bool) {
	if r.hqAudio != hqAudio {
		r.setAudioParameters(r.audio, hqAudio, r.audioFreq)
	}
}