Skip to content

Commit

Permalink
Remove unnecessary threads
Browse files Browse the repository at this point in the history
  • Loading branch information
khogeland committed Oct 23, 2017
1 parent 12d712b commit 9e08b3d
Show file tree
Hide file tree
Showing 5 changed files with 69 additions and 156 deletions.
29 changes: 2 additions & 27 deletions ui/event.nim
Original file line number Diff line number Diff line change
@@ -1,44 +1,19 @@
import
libmpdclient,
nimbox,
uistate,
../mpd/album

type OmnimStateEventType* = enum
NimboxEvent
SearchResults
StateClose

type OmnimSearchEventType* = enum
UpdateQuery
ExecuteSearch
SearchClose

type OmnimDrawEventType* = enum
UpdateState
Redraw
DrawClose


type OmnimStateEvent* = ref object
case kind*: OmnimStateEventType
of NimboxEvent:
nimboxEvent*: Event
of SearchResults:
songs*: seq[ptr mpd_song]
else: discard
type OmnimSearchResultsEvent* = ref object
songs*: seq[ptr mpd_song]

type OmnimSearchEvent* = ref object
case kind*: OmnimSearchEventType
of UpdateQuery:
query*: string
else: discard

type OmnimDrawEvent* = ref object
case kind*: OmnimDrawEventType
of UpdateState:
searchBoxState*: SearchBoxState
listState*: ListState
else: discard


9 changes: 4 additions & 5 deletions ui/listpane.nim
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import
pane,
uistate,
../mpd/album,
../mpd/mpdeither

Expand Down Expand Up @@ -82,11 +81,11 @@ proc setValues*(this: MpdListPane, values: seq[ptr mpd_song]) =
this.albumValues = albums_for(values)
this.updateView()

proc drawTo*(state: ListState, nb: Nimbox, x, y: int) =
for i, t in state.currentView:
proc drawTo*(this: MpdListPane, nb: Nimbox) =
for i, t in this.currentView:
let style: Style =
if i == state.cursor:
if i == this.cursor:
styReverse
else:
styNone
nb.print(x, y + i, t, clrDefault, clrDefault, style)
nb.print(this.x, this.y + i, t, clrDefault, clrDefault, style)
15 changes: 7 additions & 8 deletions ui/searchbox.nim
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ import
unicode

import
pane,
uistate
pane

import
nimbox
Expand All @@ -28,11 +27,11 @@ proc handleSearchBoxInput*(this: SearchBox, input: Rune) =
proc initSearchBox*(x, y, w, h: int): SearchBox =
return SearchBox(x: x, y: y, width: w, height: h, contents: @[])

proc drawTo*(state: SearchBoxState, nb: Nimbox, x, y: int) =
let line = PREFIX & $state.query
let lineLen = len(state.query) + PREFIX_LEN
proc drawTo*(this: SearchBox, nb: Nimbox) =
let line = PREFIX & $this.contents
let lineLen = len(this.contents) + PREFIX_LEN
var afterCursor = spaces(nb.width-lineLen-1)
nb.print(x, y, line, clrDefault, clrDefault, styUnderline)
nb.print(x + lineLen, y, " ", clrDefault, clrDefault, styReverse)
nb.print(x + lineLen + 1, y, afterCursor, clrDefault, clrDefault, styUnderline)
nb.print(this.x, this.y, line, clrDefault, clrDefault, styUnderline)
nb.print(this.x + lineLen, this.y, " ", clrDefault, clrDefault, styReverse)
nb.print(this.x + lineLen + 1, this.y, afterCursor, clrDefault, clrDefault, styUnderline)

158 changes: 56 additions & 102 deletions ui/ui.nim
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ import

import
event,
uistate,
pane,
listpane,
searchbox
Expand All @@ -28,28 +27,8 @@ import
const MINIMUM_CHARACTERS = 3

var nb: Nimbox
var drawChannel: Channel[OmnimDrawEvent]
var resultsChannel: Channel[OmnimSearchResultsEvent]
var searchChannel: Channel[OmnimSearchEvent]
var stateChannel: Channel[OmnimStateEvent]

proc drawLoop() {.thread.} =
var searchBoxState = initSearchBoxState()
var listState = initListState()
while true:
let event: OmnimDrawEvent = drawChannel.recv()
case event.kind:
of UpdateState:
if event.searchBoxState != nil:
searchBoxState = event.searchBoxState
if event.listState != nil:
listState = event.listState
of Redraw:
nb.clear()
searchBoxState.drawTo(nb, 0, 0)
listState.drawTo(nb, 0, 1)
nb.present()
of DrawClose:
return

proc searchLoop(myCtl: MpdCtl) {.thread.} =
var nextQuery = ""
Expand All @@ -62,103 +41,78 @@ proc searchLoop(myCtl: MpdCtl) {.thread.} =
if len(nextQuery) >= MINIMUM_CHARACTERS:
let query = nextQuery
nextQuery = ""
stateChannel.send(OmnimStateEvent(kind: SearchResults, songs: myCtl.searchSongs(query)))
resultsChannel.send(OmnimSearchResultsEvent(songs: myCtl.searchSongs(query)))
of SearchClose:
return

proc stateLoop(myCtl: MpdCtl, songMode: bool) {.thread.} =
var searchBox = initSearchBox(0, 0, nb.width, 1)
var listPane = initMpdListPane(0, 1, nb.width, nb.height-1, songMode)
while true:
let event: OmnimStateEvent = stateChannel.recv()
var drawThreadUpdate = OmnimDrawEvent(kind: UpdateState)
var searchThreadUpdate = OmnimSearchEvent(kind: UpdateQuery)

proc updateSearchBoxState() =
drawThreadUpdate.searchBoxState = SearchBoxState(query: searchBox.contents)
searchThreadUpdate.query = $searchBox.contents

proc updateListState() =
drawThreadUpdate.listState = ListState(currentView: listPane.currentView, cursor: listPane.cursor)

case event.kind:
of NimboxEvent:
let nbEvent = event.nimboxEvent
case nbEvent.kind:
of EventType.Key:
if (nbEvent.sym == Symbol.Down):
listPane.down()
updateListState()
elif (nbEvent.sym == Symbol.Up):
listPane.up()
updateListState()
elif nbEvent.sym == Symbol.Enter:
listPane.getCurrentValue().map(proc(value: MpdEither) = myCtl.replaceAndPlay(value))
elif nbEvent.ch == Rune('2') and nbEvent.mods.contains(Modifier.Ctrl):
listPane.getCurrentValue().map(proc(value: MpdEither) = myCtl.enqueue(value))
listPane.down()
updateListState()
elif nbEvent.ch == Rune('Z') and nbEvent.mods.contains(Modifier.Ctrl):
listPane.toggleSongMode()
updateListState()
elif nbEvent.sym == Symbol.Character:
searchBox.handleSearchBoxInput(nbEvent.ch)
updateSearchBoxState()
elif nbEvent.sym == Symbol.Space:
searchBox.handleSearchBoxInput(Rune(' '))
updateSearchBoxState()
elif nbEvent.sym == Symbol.Backspace:
searchBox.backspace()
updateSearchBoxState()
of EventType.Resize:
listPane.resizePane(nbEvent.w, nbEvent.h-1)
searchBox.resizePane(nbEvent.w, 1)
updateListState()
updateSearchBoxState()
else:
discard
of SearchResults:
listPane.setValues(event.songs)
updateListState()
of StateClose:
return

if drawThreadUpdate.listState != nil or drawThreadUpdate.searchBoxState != nil:
drawChannel.send(drawThreadUpdate)

if searchThreadUpdate.query != nil:
searchChannel.send(searchThreadUpdate)

proc stopUi*() =
nb.shutdown()
drawChannel.send(OmnimDrawEvent(kind: DrawClose))
searchChannel.send(OmnimSearchEvent(kind: SearchClose))
stateChannel.send(OmnimStateEvent(kind: StateClose))
close drawChannel
close resultsChannel
close searchChannel
close stateChannel

proc startUi*(mpd: MpdCtl, songMode: bool = false) =
nb = newNimbox()
open drawChannel
open resultsChannel
open searchChannel
open stateChannel
spawn drawLoop()
spawn searchLoop(mpd)
spawn stateLoop(mpd, songMode)
defer: stopUi()
var lastTime = 0.0
var searchBox = initSearchBox(0, 0, nb.width, 1)
var listPane = initMpdListPane(0, 1, nb.width, nb.height-1, songMode)
while true:

nb.clear()
listPane.drawTo(nb)
searchBox.drawTo(nb)
nb.present()

let thisTime = epochTime()
drawChannel.send(OmnimDrawEvent(kind: Redraw))
if lastTime + 0.5 < thisTime: # Execute search every half-second
if lastTime + 0.1 < thisTime: # Execute search every 100ms
lastTime = thisTime
searchChannel.send(OmnimSearchEvent(kind: ExecuteSearch))
let event = nb.peekEvent(10)
case event.kind:

var searchThreadUpdate = OmnimSearchEvent(kind: UpdateQuery)

proc updateSearchMessage() = searchThreadUpdate.query = $searchBox.contents

let nbEvent = nb.peekEvent(10)
case nbEvent.kind:
of EventType.Key:
if event.sym == Symbol.Escape:
stopUi()
if nbEvent.sym == Symbol.Escape:
return
else: discard
stateChannel.send(OmnimStateEvent(kind: NimboxEvent, nimboxEvent: event))
if (nbEvent.sym == Symbol.Down):
listPane.down()
elif (nbEvent.sym == Symbol.Up):
listPane.up()
elif nbEvent.sym == Symbol.Enter:
listPane.getCurrentValue().map(proc(value: MpdEither) = mpd.replaceAndPlay(value))
elif nbEvent.ch == Rune('2') and nbEvent.mods.contains(Modifier.Ctrl):
listPane.getCurrentValue().map(proc(value: MpdEither) = mpd.enqueue(value))
listPane.down()
elif nbEvent.ch == Rune('Z') and nbEvent.mods.contains(Modifier.Ctrl):
listPane.toggleSongMode()
elif nbEvent.sym == Symbol.Character:
searchBox.handleSearchBoxInput(nbEvent.ch)
updateSearchMessage()
elif nbEvent.sym == Symbol.Space:
searchBox.handleSearchBoxInput(Rune(' '))
updateSearchMessage()
elif nbEvent.sym == Symbol.Backspace:
searchBox.backspace()
updateSearchMessage()
of EventType.Resize:
listPane.resizePane(nbEvent.w, nbEvent.h-1)
searchBox.resizePane(nbEvent.w, 1)
else:
discard

if len(searchBox.contents) < MINIMUM_CHARACTERS:
listPane.setValues(@[])

if resultsChannel.peek() > 0:
listPane.setValues(resultsChannel.recv().songs)

if searchThreadUpdate.query != nil:
searchChannel.send(searchThreadUpdate)

14 changes: 0 additions & 14 deletions ui/uistate.nim

This file was deleted.

0 comments on commit 9e08b3d

Please sign in to comment.