func main() { config := engine.DefaultConfig() battery := plugin.NewBattery() ping := plugin.NewPing() go (func() { for { select { case event := <-ping.Incoming: log.Println("New ping from device:", event.Device.Name) case event := <-battery.Incoming: log.Println("Battery:", event.Device.Name, event.BatteryBody) } } })() hdlr := plugin.NewHandler() hdlr.Register(battery) hdlr.Register(ping) e := engine.New(hdlr, config) go (func() { for { select { case device := <-e.RequestsPairing: e.PairDevice(device) } } })() e.Listen() }
func main() { err := utils.CreateLockFile() if err != nil { utils.NotifyLockingPid() log.Fatal("Cannot create lock file:", err) } config := engine.DefaultConfig() priv, err := utils.LoadPrivateKey() if priv == nil { log.Fatal("Could not get private key:", err) } if err != nil { log.Println("Warning: error while loading private key:", err) } config.PrivateKey = priv knownDevices, err := utils.LoadKnownDevices() if err != nil { log.Println("Warning: error while loading known devices:", err) } config.KnownDevices = knownDevices battery := plugin.NewBattery() ping := plugin.NewPing() notification := plugin.NewNotification() mprisPlugin := plugin.NewMpris() telephony := plugin.NewTelephony() sftp := plugin.NewSftp() conn, err := dbus.SessionBus() if err != nil { panic(err) } notifier, err := notify.New(conn) if err != nil { panic(err) } go (func() { notificationsMap := map[string]int{} var callNotification int var batteryNotification int for { select { case event := <-ping.Incoming: log.Println("Ping:", event.Device.Name) n := newNotification() n.AppIcon = utils.GetDeviceIcon(event.Device) n.Summary = "Ping from " + event.Device.Name notifier.SendNotification(n) case event := <-battery.Incoming: log.Println("Battery:", event.Device.Name, event.BatteryBody) if event.ThresholdEvent == plugin.BatteryThresholdEventLow { n := newNotification() n.AppIcon = "battery-caution" n.Summary = event.Device.Name + " has low battery" id, _ := notifier.SendNotification(n) batteryNotification = int(id) } if event.IsCharging { if batteryNotification != 0 { notifier.CloseNotification(batteryNotification) batteryNotification = 0 } } case event := <-notification.Incoming: log.Println("Notification:", event.Device.Name, event.NotificationBody) id, exists := notificationsMap[event.NotificationBody.Id] if event.IsCancel { if exists { notifier.CloseNotification(id) } break } n := newNotification() n.AppIcon = utils.GetDeviceIcon(event.Device) n.Summary = "Notification from " + event.AppName + " on " + event.Device.Name n.Body = event.Ticker if exists { n.ReplacesID = uint32(id) } newId, _ := notifier.SendNotification(n) notificationsMap[event.NotificationBody.Id] = int(newId) // TODO: wait for notification dismiss and send message to remote case event := <-mprisPlugin.Incoming: log.Println("Mpris:", event.Device.Name, event.MprisBody) if event.RequestPlayerList { names, err := mpris.List(conn) if err != nil { log.Println("Warning: cannot list available MPRIS players", err) break } mprisPlugin.SendPlayerList(event.Device, names) } if event.Player != "" { player := mpris.New(conn, event.Player) event.RequestNowPlaying = true switch event.Action { case "Next": player.Next() case "Previous": player.Previous() case "Pause": player.Pause() case "PlayPause": player.PlayPause() case "Stop": player.Stop() case "Play": player.Play() default: event.RequestNowPlaying = false } if event.SetVolume != 0 { player.SetVolume(float64(event.SetVolume) / 100) event.RequestVolume = true } if event.RequestNowPlaying || event.RequestVolume { reply := &plugin.MprisBody{} if event.RequestNowPlaying { metadata := player.GetMetadata() reply.NowPlaying = metadata["xesam:title"].String() reply.IsPlaying = (player.GetPlaybackStatus() == "Playing") reply.Length = float64(metadata["mpris:length"].Value().(int64)) / 1000 reply.Pos = float64(player.GetPosition()) / 1000 } if event.RequestVolume { reply.Volume = int(player.GetVolume() * 100) } event.Device.Send(plugin.MprisType, reply) } } case event := <-telephony.Incoming: log.Println("Telephony:", event.Device.Name, event.TelephonyBody) contactName := event.PhoneNumber if contactName == "" { contactName = event.PhoneNumber } if event.TelephonyBody.Event == plugin.TelephonySms { n := newNotification() n.AppIcon = utils.GetDeviceIcon(event.Device) n.Hints["category"] = dbus.MakeVariant("im.received") n.Summary = "SMS from " + contactName + " on " + event.Device.Name n.Body = event.MessageBody notifier.SendNotification(n) break } if event.IsCancel { if callNotification != 0 { notifier.CloseNotification(callNotification) callNotification = 0 } break } n := newNotification() n.Hints["category"] = dbus.MakeVariant("im") if callNotification != 0 { n.ReplacesID = uint32(callNotification) } switch event.TelephonyBody.Event { case plugin.TelephonyRinging: n.AppIcon = "call-start" n.Summary = "Call from " + contactName + " on " + event.Device.Name case plugin.TelephonyTalking: n.AppIcon = "call-start" n.Summary = "Calling " + contactName + " on " + event.Device.Name case plugin.TelephonyMissedCall: n.AppIcon = "call-stop" n.Summary = "Missed call from " + contactName + " on " + event.Device.Name } id, _ := notifier.SendNotification(n) callNotification = int(id) case event := <-sftp.Incoming: log.Println("Sftp:", event.Device.Name, event.SftpBody) utils.MountSftp(event.Ip, event.Port, event.User, event.Password) } } })() hdlr := plugin.NewHandler() hdlr.Register(battery) hdlr.Register(ping) hdlr.Register(notification) hdlr.Register(mprisPlugin) hdlr.Register(telephony) hdlr.Register(sftp) e := engine.New(hdlr, config) var i *ui.Ui go (func() { devices := map[string]*network.Device{} notifications := map[string]int{} closed := notifier.NotificationClosed() actions := notifier.ActionInvoked() sigs := make(chan os.Signal, 1) signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGUSR1) startUi := func() { if i == nil { plugins := &ui.PluginCollection{ Sftp: sftp, } i = ui.New(e, plugins) for _, d := range devices { if d.Paired { i.Connected <- d } else { i.Available <- d } } go (func() { <-i.Quit i = nil })() } else { i.Raise() } } getDeviceFromNotification := func(notificationId int) *network.Device { for deviceId, id := range notifications { if id == notificationId { if device, ok := devices[deviceId]; ok { return device } else { return nil } } } return nil } deviceAvailable := func(device *network.Device) { n := newNotification() n.AppIcon = utils.GetDeviceIcon(device) n.Summary = device.Name n.Body = "New device available" n.Hints["category"] = dbus.MakeVariant("device") n.Actions = []string{"pair", "Pair device"} id, _ := notifier.SendNotification(n) notifications[device.Id] = int(id) if i != nil { i.Available <- device } } deviceRequestsPairing := func(device *network.Device) { n := newNotification() n.AppIcon = utils.GetDeviceIcon(device) n.Summary = device.Name n.Body = "New pair request" n.Hints["category"] = dbus.MakeVariant("device") n.Actions = []string{"pair", "Accept", "unpair", "Reject"} id, _ := notifier.SendNotification(n) notifications[device.Id] = int(id) } deviceConnected := func(device *network.Device) { n := newNotification() n.AppIcon = utils.GetDeviceIcon(device) n.Summary = device.Name n.Body = "Device connected" n.Hints["resident"] = dbus.MakeVariant(true) n.Hints["category"] = dbus.MakeVariant("device.added") n.Actions = []string{"default", "Open"} id, _ := notifier.SendNotification(n) notifications[device.Id] = int(id) if i != nil { i.Connected <- device } } cleanup := func() { // Close all notifications for _, id := range notifications { notifier.CloseNotification(id) } } for { select { case device := <-e.Joins: if device.Id == "" { continue } devices[device.Id] = device if device.Paired { deviceConnected(device) } else { deviceAvailable(device) } case device := <-e.RequestsPairing: if id, ok := notifications[device.Id]; ok { notifier.CloseNotification(id) } deviceRequestsPairing(device) case device := <-e.Paired: if id, ok := notifications[device.Id]; ok { notifier.CloseNotification(id) } err := utils.SaveKnownDevices(config.KnownDevices) if err != nil { log.Println("Cannot save known devices:", err) } deviceConnected(device) case device := <-e.Unpaired: if id, ok := notifications[device.Id]; ok { notifier.CloseNotification(id) } if i != nil { i.Disconnected <- device } case device := <-e.Leaves: if id, ok := notifications[device.Id]; ok { notifier.CloseNotification(id) } if _, ok := devices[device.Id]; ok { delete(devices, device.Id) } if i != nil { i.Unavailable <- device } case signal := <-actions: device := getDeviceFromNotification(int(signal.Id)) if device == nil { continue } log.Println(device.Name, signal.ActionKey) switch signal.ActionKey { case "pair": err := e.PairDevice(device) if err != nil { log.Println("Cannot pair device:", err) } case "unpair": err := e.UnpairDevice(device) if err != nil { log.Println("Cannot unpair device:", err) } case "default": startUi() i.SelectDevice(device) } case signal := <-closed: device := getDeviceFromNotification(int(signal.Id)) if device != nil { log.Println(device.Name, signal.Reason) delete(notifications, device.Id) if signal.Reason == notify.ReasonDismissedByUser { //device.Close() } } case signal := <-sigs: if signal == syscall.SIGUSR1 { // Restore device notifications for _, device := range devices { if !device.Paired { continue } if _, ok := notifications[device.Id]; !ok { deviceConnected(device) } } startUi() } else { // Interrupt signal received cleanup() os.Exit(0) } } } })() e.Listen() }