Add control server.
This commit is contained in:
@@ -6,16 +6,13 @@ author = "luxick"
|
|||||||
description = "Play an image slide show from different sources"
|
description = "Play an image slide show from different sources"
|
||||||
license = "GPL-2.0"
|
license = "GPL-2.0"
|
||||||
srcDir = "src"
|
srcDir = "src"
|
||||||
bin = @["randopix"]
|
bin = @["randopix", "pixctrl"]
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
requires "nim >= 1.0.0", "gintro >= 0.5.5", "argparse >=0.10.1"
|
requires "nim >= 1.0.0", "gintro >= 0.5.5", "argparse >=0.10.1"
|
||||||
|
|
||||||
task debug, "Compile debug version":
|
task debug, "Compile debug version":
|
||||||
exec "nim c -d:debug --debugger:native --out:bin/randopix src/randopix.nim"
|
exec "nim c -d:debug --debugger:native src/randopix.nim"
|
||||||
|
|
||||||
task r, "Compile and run":
|
|
||||||
exec "nim c -r --out:bin/randopix src/randopix.nim"
|
|
||||||
|
|
||||||
task release, "Compile release version":
|
task release, "Compile release version":
|
||||||
exec fmt"nim c -d:release --out:bin/{version}/randopix src/randopix.nim"
|
exec fmt"nim c -d:release --out:randopix-{version} src/randopix.nim"
|
||||||
|
|||||||
15
src/commands.nim
Normal file
15
src/commands.nim
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
const
|
||||||
|
defaultPort* = 5555 ## Default port at which the control server will run
|
||||||
|
|
||||||
|
type
|
||||||
|
Command* {.pure.} = enum
|
||||||
|
Close = "close" ## Closes the control server and exists the applicaiton
|
||||||
|
Refresh = "refresh" ## Force refresh of the image now
|
||||||
|
|
||||||
|
CommandMessage* = object
|
||||||
|
command*: Command ## Command that the application should execute
|
||||||
|
parameter*: string ## Optional parameter for the command
|
||||||
|
|
||||||
|
proc newCommand*(c: Command, p: string = ""): CommandMessage =
|
||||||
|
CommandMessage(command: c, parameter: p)
|
||||||
13
src/pixctrl.nim
Normal file
13
src/pixctrl.nim
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import net
|
||||||
|
import argparse
|
||||||
|
import commands
|
||||||
|
|
||||||
|
var p = newParser("pixctrl"):
|
||||||
|
help("Control utilitiy for randopix")
|
||||||
|
option("-s", "--server", help="Host running the randopix server", default="127.0.0.1")
|
||||||
|
option("-p", "--port", help="Port to connect to the randopix server", default = $defaultPort)
|
||||||
|
|
||||||
|
var socket = newSocket()
|
||||||
|
socket.connect("127.0.0.1", Port(defaultPort))
|
||||||
|
socket.send("Hello, Sockets!\r\L")
|
||||||
|
socket.close()
|
||||||
@@ -1,8 +1,10 @@
|
|||||||
import os, options, strformat
|
import os, options, strformat
|
||||||
import gintro/[gtk, glib, gobject, gio, gdkpixbuf]
|
import gintro/[glib, gobject, gdkpixbuf]
|
||||||
import gintro/gdk except Window
|
import gintro/gdk except Window
|
||||||
|
import gintro/gtk except newSocket, Socket
|
||||||
|
import gintro/gio except Socket
|
||||||
import argparse except run
|
import argparse except run
|
||||||
import providers
|
import providers, server, commands
|
||||||
|
|
||||||
const
|
const
|
||||||
css = slurp("app.css")
|
css = slurp("app.css")
|
||||||
@@ -21,6 +23,8 @@ var
|
|||||||
window: ApplicationWindow
|
window: ApplicationWindow
|
||||||
imageWidget: Image
|
imageWidget: Image
|
||||||
label: Label
|
label: Label
|
||||||
|
# Server vor recieving commands from external tools
|
||||||
|
serverWorker: system.Thread[void]
|
||||||
|
|
||||||
proc enumToStrings(en: typedesc): seq[string] =
|
proc enumToStrings(en: typedesc): seq[string] =
|
||||||
for x in en:
|
for x in en:
|
||||||
@@ -59,7 +63,7 @@ proc newArgs(): Option[Args] =
|
|||||||
fullscreen: not opts.windowed,
|
fullscreen: not opts.windowed,
|
||||||
verbose: opts.verbose,
|
verbose: opts.verbose,
|
||||||
timeout: timeout))
|
timeout: timeout))
|
||||||
except UsageError:
|
except:
|
||||||
echo getCurrentExceptionMsg()
|
echo getCurrentExceptionMsg()
|
||||||
echo p.help
|
echo p.help
|
||||||
|
|
||||||
@@ -106,12 +110,27 @@ proc forceUpdate(action: SimpleAction; parameter: Variant;) =
|
|||||||
|
|
||||||
proc timedUpdate(image: Widget): bool =
|
proc timedUpdate(image: Widget): bool =
|
||||||
let ok = updateImage();
|
let ok = updateImage();
|
||||||
if ok:
|
if not ok:
|
||||||
return true;
|
|
||||||
else:
|
|
||||||
label.notify "Error while refreshing image, retrying..."
|
label.notify "Error while refreshing image, retrying..."
|
||||||
discard timeoutAdd(uint32(args.timeout), timedUpdate, imageWidget)
|
discard timeoutAdd(uint32(args.timeout), timedUpdate, imageWidget)
|
||||||
return false
|
return false
|
||||||
|
|
||||||
|
proc checkServerChannel(parameter: string): bool =
|
||||||
|
## Check the channel from the control server for incomming commands
|
||||||
|
let tried = chan.tryRecv()
|
||||||
|
|
||||||
|
if tried.dataAvailable:
|
||||||
|
let msg: CommandMessage = tried.msg
|
||||||
|
echo "Main app got message: ", msg.command
|
||||||
|
|
||||||
|
case msg.command
|
||||||
|
of Command.Refresh:
|
||||||
|
discard updateImage()
|
||||||
|
else:
|
||||||
|
echo "Command ignored", msg.command
|
||||||
|
|
||||||
|
result = false
|
||||||
|
discard idleAdd(checkServerChannel, parameter)
|
||||||
|
|
||||||
proc toggleFullscreen(action: SimpleAction; parameter: Variant; window: ApplicationWindow) =
|
proc toggleFullscreen(action: SimpleAction; parameter: Variant; window: ApplicationWindow) =
|
||||||
## Fullscreen toggle event
|
## Fullscreen toggle event
|
||||||
@@ -121,12 +140,21 @@ proc toggleFullscreen(action: SimpleAction; parameter: Variant; window: Applicat
|
|||||||
window.fullscreen
|
window.fullscreen
|
||||||
args.fullscreen = not args.fullscreen
|
args.fullscreen = not args.fullscreen
|
||||||
|
|
||||||
|
proc cleanUp(w: ApplicationWindow, app: Application) =
|
||||||
|
## Stop the control server and exit the GTK application
|
||||||
|
echo "Stopping control server..."
|
||||||
|
closeServer()
|
||||||
|
serverWorker.joinThread()
|
||||||
|
chan.close()
|
||||||
|
echo "Server stopped."
|
||||||
|
app.quit()
|
||||||
|
|
||||||
proc quit(action: SimpleAction; parameter: Variant; app: Application) =
|
proc quit(action: SimpleAction; parameter: Variant; app: Application) =
|
||||||
## Application quit event
|
## Application quit event
|
||||||
app.quit()
|
cleanUp(window, app)
|
||||||
|
|
||||||
proc connectSignals(app: Application) =
|
proc connectSignals(app: Application) =
|
||||||
## Connect th GTK signals to the procs
|
## Connect the GTK signals to the procs
|
||||||
let fullscreenAction = newSimpleAction("fullscreen")
|
let fullscreenAction = newSimpleAction("fullscreen")
|
||||||
discard fullscreenAction.connect("activate", toggleFullscreen, window)
|
discard fullscreenAction.connect("activate", toggleFullscreen, window)
|
||||||
app.setAccelsForAction("win.fullscreen", "F")
|
app.setAccelsForAction("win.fullscreen", "F")
|
||||||
@@ -142,6 +170,8 @@ proc connectSignals(app: Application) =
|
|||||||
app.setAccelsForAction("win.update", "U")
|
app.setAccelsForAction("win.update", "U")
|
||||||
window.actionMap.addAction(updateImageAction)
|
window.actionMap.addAction(updateImageAction)
|
||||||
|
|
||||||
|
window.connect("destroy", cleanUp, app)
|
||||||
|
|
||||||
proc appActivate(app: Application) =
|
proc appActivate(app: Application) =
|
||||||
# Parse arguments from the command line
|
# Parse arguments from the command line
|
||||||
let parsed = newArgs()
|
let parsed = newArgs()
|
||||||
@@ -152,7 +182,7 @@ proc appActivate(app: Application) =
|
|||||||
|
|
||||||
window = newApplicationWindow(app)
|
window = newApplicationWindow(app)
|
||||||
window.title = "randopix"
|
window.title = "randopix"
|
||||||
window.setKeepAbove(true)
|
window.setKeepAbove(false)
|
||||||
window.setDefaultSize(800, 600)
|
window.setDefaultSize(800, 600)
|
||||||
|
|
||||||
# Custom styling for e.g. the background color CSS data is in the "style.nim" module
|
# Custom styling for e.g. the background color CSS data is in the "style.nim" module
|
||||||
@@ -177,8 +207,15 @@ proc appActivate(app: Application) =
|
|||||||
app.connectSignals
|
app.connectSignals
|
||||||
window.showAll
|
window.showAll
|
||||||
|
|
||||||
discard updateImage()
|
discard timeoutAdd(500, timedUpdate, imageWidget)
|
||||||
discard timeoutAdd(uint32(args.timeout), timedUpdate, imageWidget)
|
|
||||||
|
## open communication channel from the control server
|
||||||
|
chan.open()
|
||||||
|
|
||||||
|
## Start the server for handling incoming commands
|
||||||
|
createThread(serverWorker, runServer)
|
||||||
|
var tag = ""
|
||||||
|
discard idleAdd(checkServerChannel, tag)
|
||||||
|
|
||||||
when isMainModule:
|
when isMainModule:
|
||||||
let app = newApplication("org.luxick.randopix")
|
let app = newApplication("org.luxick.randopix")
|
||||||
|
|||||||
40
src/server.nim
Normal file
40
src/server.nim
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
import net, json, marshal
|
||||||
|
import commands
|
||||||
|
|
||||||
|
var
|
||||||
|
chan*: Channel[CommandMessage]
|
||||||
|
|
||||||
|
proc closeServer*() =
|
||||||
|
## Sends a "Close" command to the server
|
||||||
|
var socket = newSocket()
|
||||||
|
socket.connect("127.0.0.1", Port(defaultPort))
|
||||||
|
let c = newCommand(Command.Close)
|
||||||
|
socket.send($(%c))
|
||||||
|
socket.close()
|
||||||
|
|
||||||
|
proc runServer*() =
|
||||||
|
var socket = newSocket()
|
||||||
|
socket.bindAddr(Port(defaultPort))
|
||||||
|
socket.listen()
|
||||||
|
echo "Control server is listening"
|
||||||
|
|
||||||
|
while true:
|
||||||
|
# Process client requests
|
||||||
|
var client = newSocket()
|
||||||
|
socket.accept(client)
|
||||||
|
echo("Incomming client")
|
||||||
|
try:
|
||||||
|
var line = client.recvLine()
|
||||||
|
let msg = to[CommandMessage](line)
|
||||||
|
case msg.command
|
||||||
|
of Command.Close:
|
||||||
|
echo "Server recieved termination command. Exiting."
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
# Pass command from client to main applicaiton
|
||||||
|
chan.send(msg)
|
||||||
|
|
||||||
|
except OSError:
|
||||||
|
echo "Server error: ", getCurrentExceptionMsg()
|
||||||
|
except:
|
||||||
|
echo "Invalid command from client"
|
||||||
1
src/server.nim.cfg
Normal file
1
src/server.nim.cfg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
threads:on
|
||||||
Reference in New Issue
Block a user