// Start initializes the application and runs its main loop. The context
// argument can be used as a means to prematurely cancel the loop. You can
// usually use an empty context here.
Start initializes the application and runs its main loop. The context
argument can be used as a means to prematurely cancel the loop. You can
usually use an empty context here.
// Start initializes the application and runs its main loop . The context // argument can be used as a means to prematurely cancel the loop . You can // usually use an empty context here .
func (app *App) Start(ctx context.Context) (err error) {
	app.msgs = make(chan Msg, 4)
	app.errs = make(chan error)        
	app.polldone = make(chan struct{}) 
	app.effects = make(chan Effect, 4)
	pollMsgNonBlocking := false
	switch app.driver.(type) {
	case DriverPollMsg:
		pollMsgNonBlocking = true
		app.inputs = make(chan Msg, 4)
	}
	defer func() {
		if app.enc != nil {
			nerr := app.enc.gzw.Close()
			if err == nil {
				err = nerr
			} else if app.logger != nil {
				app.logger.Printf("error closing gzip encoder: %v", err)
			}
		}
	}()
	err = app.driver.Init()
	if err != nil {
		return err
	}
	if ctx == nil {
		ctx = context.Background()
	}
	ctx, cancel := context.WithCancel(ctx)
	if app.CatchPanics {
		defer func() {
			if r := recover(); r != nil {
				err = fmt.Errorf("%v", r)
				cancel()
				<-app.polldone
				app.driver.Close()
				log.Printf("Caught panic: %v\nStack Trace:\n", r)
				debug.PrintStack()
			} else {
				<-app.polldone
				app.driver.Close()
			}
		}()
	} else {
		defer func() {
			<-app.polldone
			app.driver.Close()
		}()
	}
	defer cancel()
	app.msgs <- MsgInit{}
	if pollMsgNonBlocking {
		go app.startPollMsgSub(ctx)
	} else {
		go app.startPollMsgs(ctx)
	}
	go app.processEffects(ctx)
	if pollMsgNonBlocking {
		err = app.startWithPollMsg(ctx, cancel)
	} else {
		err = app.start(ctx, cancel)
	}
	return err
}
func ( app * App ) Start ( ctx context . Context ) ( err error ) { app . msgs = make ( chan Msg , 4 ) app . errs = make ( chan error ) app . polldone = make ( chan struct { } ) app . effects = make ( chan Effect , 4 ) pollMsgNonBlocking := false switch app . driver . ( type ) { case DriverPollMsg : pollMsgNonBlocking = true app . inputs = make ( chan Msg , 4 ) } defer func ( ) { if app . enc != nil { nerr := app . enc . gzw . Close ( ) if err == nil { err = nerr } else if app . logger != nil { app . logger . Printf ( " " , err ) } } } ( ) err = app . driver . Init ( ) if err != nil { return err } if ctx == nil { ctx = context . Background ( ) } ctx , cancel := context . WithCancel ( ctx ) if app . CatchPanics { defer func ( ) { if r := recover ( ) ; r != nil { err = fmt . Errorf ( " " , r ) cancel ( ) <- app . polldone app . driver . Close ( ) log . Printf ( " \n \n " , r ) debug . PrintStack ( ) } else { <- app . polldone app . driver . Close ( ) } } ( ) } else { defer func ( ) { <- app . polldone app . driver . Close ( ) } ( ) } defer cancel ( ) app . msgs <- MsgInit { } if pollMsgNonBlocking { go app . startPollMsgSub ( ctx ) } else { go app . startPollMsgs ( ctx ) } go app . processEffects ( ctx ) if pollMsgNonBlocking { err = app . startWithPollMsg ( ctx , cancel ) } else { err = app . start ( ctx , cancel ) } return err }
Start initializes the application and runs its main loop.
Start initializes the application and runs its main loop .
// for driver input errors // PollMsgs subscription finished // frame encoder finalization // driver and context initialization // initialization message (non-blocking, buffered) // input messages queueing // effect processing // start Update on message then Draw main loop