// main program loop.
func main() {
	var host config.Host
	// Connect to Kodi, this is required.
	kodiTimeout := time.Duration(0)
	if cfg.Kodi != nil {
		if cfg.Kodi.Timeout != nil {
			kodiTimeout = time.Duration(*cfg.Kodi.Timeout)
		}
		host = *cfg.Kodi
	} else if cfg.XBMC != nil {
		if cfg.XBMC.Timeout != nil {
			kodiTimeout = time.Duration(*cfg.XBMC.Timeout)
		}
		host = *cfg.XBMC
	} else {
		log.Fatal(`You must provide Kodi/XBMC connection details in your configuration`)
	}
	k, err := kodi_jsonrpc.New(
		fmt.Sprintf(`%s:%d`, host.Address, host.Port),
		kodiTimeout,
	)

	defer k.Close()
	if err != nil {
		log.WithField(`error`, err).Fatal(`Failed to obtain Kodi connection`)
	}

	// If the configuration specifies a Hyperion connection, use it.
	if cfg.Hyperion != nil {
		hyperion.Connect(&cfg)
		defer hyperion.Close()
	}

	// If the configuration specifies a LIFX connection, use it.
	if cfg.LIFX != nil {
		lifx.Connect(&cfg)
		defer lifx.Close()
	}

	// If the configuration specifies a boblight connection, use it.
	if cfg.Boblight != nil {
		boblight.Connect(&cfg)
		defer boblight.Close()
	}

	// Get callbacks from configuration.
	callbacks := cfg.Callbacks.(map[string]interface{})

	// Execute callbacks for the special `Startup` notification.
	if callbacks[`Startup`] != nil {
		// LIFX groups take some time to populate, so we add an arbitrary delay
		// here to try and compensate
		if cfg.LIFX != nil {
			time.Sleep(LIFXDELAY)
		}
		execute(callbacks[`Startup`].([]interface{}))
	}

	// Loop while reading from Kodi.
	for {
		// Read from Kodi.
		notification := <-k.Notifications

		// Match Kodi notification to our configured callbacks.
		if callbacks[notification.Method] != nil {
			cbs := callbacks[notification.Method].([]interface{})
			switch notification.Method {
			case `Player.OnPlay`, `Player.OnPause`, `Player.OnStop`:
				cbs = callbacksByType(notification.Params.Data.Item.Type, cbs)
			}
			execute(cbs)
		}
	}
}
// main program loop.
func main() {
	var host config.Host
	// Connect to Kodi, this is required.
	kodiTimeout := time.Duration(0)
	if cfg.Kodi != nil {
		if cfg.Kodi.Timeout != nil {
			kodiTimeout = time.Duration(*cfg.Kodi.Timeout)
		}
		host = *cfg.Kodi
	} else if cfg.XBMC != nil {
		if cfg.XBMC.Timeout != nil {
			kodiTimeout = time.Duration(*cfg.XBMC.Timeout)
		}
		host = *cfg.XBMC
	} else {
		log.Fatal(`You must provide Kodi/XBMC connection details in your configuration`)
	}
	k, err := kodi_jsonrpc.New(
		fmt.Sprintf(`%s:%d`, host.Address, host.Port),
		kodiTimeout,
	)

	defer k.Close()
	if err != nil {
		log.WithField(`error`, err).Fatal(`Failed to obtain Kodi connection`)
	}

	// If the configuration specifies a Hyperion connection, use it.
	if cfg.Hyperion != nil {
		hyperion.Connect(fmt.Sprintf(`%s:%d`, cfg.Hyperion.Address, cfg.Hyperion.Port))
		defer hyperion.Close()
	}

	// If the configuration specifies a LIFX connection, use it.
	if cfg.LIFX != nil {
		lifx.Connect(cfg)
		defer lifx.Close()
	}

	// Get callbacks from configuration.
	callbacks := cfg.Callbacks.(map[string]interface{})

	// Execute callbacks for the special `Startup` notification.
	if callbacks[`Startup`] != nil {
		execute(callbacks[`Startup`].([]interface{}))
	}

	// Loop while reading from Kodi.
	for {
		// Read from Kodi.
		notification := <-k.Notifications

		// Match Kodi notification to our configured callbacks.
		if callbacks[notification.Method] != nil {
			cbs := callbacks[notification.Method].([]interface{})
			// The Player.OnPlay notification supports an filtering by item type.
			if notification.Method == `Player.OnPlay` {
				cbs = callbacksByType(notification.Params.Data.Item.Type, cbs)
			}
			execute(cbs)
		}
	}
}