Skip to content

Commit 274c0fb

Browse files
authored
Merge pull request #32 from cobaltgit/last-reworks
Pre-release polishing
2 parents 6c85404 + 909eb4b commit 274c0fb

17 files changed

Lines changed: 213 additions & 141 deletions

File tree

quark.nimble

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,20 @@ author = "cobaltgit"
55
description = "Quark stock mod for TrimUI Smart"
66
license = "GPL-3.0"
77
srcDir = "src"
8-
bin = @["fbscreenshot/fbscreenshot", "quark_hotkeyd/quark_hotkeyd", "sysjson_monitor/sysjson_monitor", "mainui_game_picker/mainui_game_picker", "bootlogo/bootlogo", "display/display"]
98

109
requires "nim >= 2.0.0"
1110
requires "nimPNG >= 0.3.1"
1211

1312
const Root = getCurrentDir()
1413
const BinDir = Root / "dist" / "System" / "bin"
14+
const Bins = {
15+
"fbscreenshot.nim": "fbscreenshot",
16+
"quark_hotkeyd/main.nim": "quark_hotkeyd",
17+
"sysjson_monitor/main.nim": "sysjson_monitor",
18+
"mainui_game_picker.nim": "mainui_game_picker",
19+
"bootlogo.nim": "bootlogo",
20+
"display.nim": "display",
21+
}.toTable()
1522
const Threads = gorge("nproc")
1623

1724
# Import task files
@@ -20,9 +27,8 @@ include "tasks/dist.nims"
2027
include "tasks/locale.nims"
2128

2229
task buildBins, "Build binaries":
23-
for exe in bin:
24-
let binName = exe.split("/")[^1]
25-
selfExec &"c -o:{BinDir}/{binName} {srcDir}/{exe}.nim"
30+
for src, output in Bins:
31+
selfExec &"c -o:{BinDir}/{output} {srcDir}/{src}"
2632

2733
task cleanup, "Cleanup all":
2834
exec "nimble clean"
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import std/[cmdline, os, posix]
2-
import ../common/[bootlogo, reboot]
3-
import ../display/display
2+
import common/[bootlogo, reboot]
3+
import display
44

55
when isMainModule:
66
var shouldReboot = false

src/common/fb.nim

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,10 @@ const
3232
arr[i] = uint8(i shr 2)
3333
arr
3434

35-
RowOffsets*: array[FbHeight, int] = block:
36-
var arr: array[FbHeight, int]
37-
for y in 0..<FbHeight:
38-
arr[y] = y * FbWidth
39-
arr
40-
41-
RotationXMap*: array[FbHeight, int] = block:
35+
FbXBase*: array[FbHeight, int] = block:
4236
var arr: array[FbHeight, int]
4337
for x in 0..<FbHeight:
44-
arr[x] = 319 - x
38+
arr[x] = (FbHeight - 1 - x) * FbWidth
4539
arr
4640

4741
{.push optimization:speed, checks:off, warnings:off.}
@@ -74,18 +68,19 @@ proc fbscreenshot*(output: string) =
7468

7569
var rotatedPixels = newSeqUninit[uint8](FbPixels * 4)
7670

77-
var srcIdx = 0
78-
for y in 0..<FbHeight:
79-
for x in 0..<FbWidth:
80-
let pixel = uint16(fbData[srcIdx]) or (uint16(fbData[srcIdx + 1]) shl 8)
81-
srcIdx += 2
71+
for x in 0..<FbWidth:
72+
let colBase = x * FbHeight
73+
var srcBase = x * 2
74+
75+
for y in 0..<FbHeight:
76+
let pixel = uint16(fbData[srcBase]) or (uint16(fbData[srcBase + 1]) shl 8)
77+
srcBase += FbWidth * 2
8278

8379
let r = (pixel shr 11) and 0x1F
8480
let g = (pixel shr 5) and 0x3F
8581
let b = pixel and 0x1F
8682

87-
let dstIdx = (x * FbHeight + (FbHeight - 1 - y)) * 4
88-
83+
let dstIdx = (colBase + FbHeight - 1 - y) * 4
8984
rotatedPixels[dstIdx] = FiveToEight[r]
9085
rotatedPixels[dstIdx + 1] = SixToEight[g]
9186
rotatedPixels[dstIdx + 2] = FiveToEight[b]

src/common/ffi/amixer.nim

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
const libasound = "libasound.so.2"
2+
3+
type
4+
SndMixerT* = pointer
5+
SndMixerElemT* = pointer
6+
SndMixerSelemIdT* = pointer
7+
8+
proc snd_mixer_open*(mixer: ptr SndMixerT, mode: cint): cint
9+
{.importc, dynlib: libasound.}
10+
11+
proc snd_mixer_close*(mixer: SndMixerT): cint
12+
{.importc, dynlib: libasound.}
13+
14+
proc snd_mixer_attach*(mixer: SndMixerT, name: cstring): cint
15+
{.importc, dynlib: libasound.}
16+
17+
proc snd_mixer_load*(mixer: SndMixerT): cint
18+
{.importc, dynlib: libasound.}
19+
20+
proc snd_mixer_selem_register*(mixer: SndMixerT,
21+
options: pointer,
22+
classp: pointer): cint
23+
{.importc, dynlib: libasound.}
24+
25+
proc snd_mixer_selem_id_sizeof*(): csize_t
26+
{.importc, dynlib: libasound.}
27+
28+
proc snd_mixer_selem_id_set_name*(obj: SndMixerSelemIdT, val: cstring)
29+
{.importc, dynlib: libasound.}
30+
31+
proc snd_mixer_selem_id_set_index*(obj: SndMixerSelemIdT, val: cuint)
32+
{.importc, dynlib: libasound.}
33+
34+
proc snd_mixer_find_selem*(mixer: SndMixerT,
35+
id: SndMixerSelemIdT): SndMixerElemT
36+
{.importc, dynlib: libasound.}
37+
38+
proc snd_mixer_selem_get_playback_volume_range*(elem: SndMixerElemT,
39+
minVal: ptr clong,
40+
maxVal: ptr clong): cint
41+
{.importc, dynlib: libasound.}
42+
43+
proc snd_mixer_selem_set_playback_volume_all*(elem: SndMixerElemT,
44+
value: clong): cint
45+
{.importc, dynlib: libasound.}

src/common/process.nim

Lines changed: 53 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,58 @@
1-
import std/[os, posix, strformat, strutils, sets]
1+
import std/[os, posix, strformat, strutils, sets, tables]
22

3-
proc killall*(processName: string, signal: cint, excludePid: int = -1): bool =
4-
var killed = false
5-
3+
proc getParentPid(pid: int): int =
4+
try:
5+
let stat = readFile(&"/proc/{pid}/stat")
6+
let afterComm = stat.find(')')
7+
if afterComm < 0:
8+
return -1
9+
let fields = stat[afterComm + 2 .. ^1].splitWhitespace()
10+
if fields.len >= 2:
11+
result = parseInt(fields[1])
12+
else:
13+
result = -1
14+
except CatchableError:
15+
result = -1
16+
17+
proc getProcessMap(): Table[string, seq[int]] =
18+
result = initTable[string, seq[int]]()
619
for kind, path in walkDir("/proc"):
7-
if kind == pcDir:
8-
let name = path.extractFilename()
9-
try:
10-
let pid = parseInt(name)
11-
if pid == excludePid:
12-
continue
13-
14-
let commPath = path / "comm"
15-
if fileExists(commPath):
16-
let comm = readFile(commPath).strip()
17-
18-
if comm == processName:
19-
if kill(cint(pid), signal) == 0:
20-
killed = true
21-
except ValueError:
22-
continue
23-
24-
result = killed
20+
if kind != pcDir:
21+
continue
22+
let name = path.extractFilename()
23+
try:
24+
let pid = parseInt(name)
25+
let commPath = path / "comm"
26+
if fileExists(commPath):
27+
let comm = readFile(commPath).strip()
28+
if comm notin result:
29+
result[comm] = @[]
30+
result[comm].add(pid)
31+
except CatchableError:
32+
continue
33+
34+
proc killall*(processName: string, signal: cint, excludePid: int = -1): bool =
35+
let processMap = getProcessMap()
36+
if processName notin processMap:
37+
return false
38+
39+
for pid in processMap[processName]:
40+
if pid == excludePid:
41+
continue
42+
if kill(cint(pid), signal) == 0:
43+
result = true
2544

2645
proc getProcessChildren*(ppid: int, pids: var HashSet[int]) =
2746
for kind, path in walkDir("/proc"):
28-
if kind == pcDir:
29-
let name = path.extractFilename()
30-
if name.len > 0 and name[0].isDigit:
31-
try:
32-
let pid = parseInt(name)
33-
let statPath = &"/proc/{pid}/stat"
34-
if fileExists(statPath):
35-
let stat = readFile(statPath)
36-
var fields = 0
37-
var parentPid = 0
38-
var inParen = false
39-
var field = ""
40-
41-
for c in stat:
42-
if c == '(':
43-
inParen = true
44-
elif c == ')':
45-
inParen = false
46-
elif c == ' ' and not inParen:
47-
inc fields
48-
if fields == 4:
49-
try:
50-
parentPid = parseInt(field)
51-
except ValueError:
52-
discard
53-
break
54-
field = ""
55-
else:
56-
if not inParen or fields > 0:
57-
field.add(c)
58-
59-
if parentPid == ppid:
60-
pids.incl(pid)
61-
getProcessChildren(pid, pids)
62-
except:
63-
discard
47+
if kind != pcDir:
48+
continue
49+
let name = path.extractFilename()
50+
if name.len == 0 or not name[0].isDigit:
51+
continue
52+
try:
53+
let pid = parseInt(name)
54+
if getParentPid(pid) == ppid:
55+
pids.incl(pid)
56+
getProcessChildren(pid, pids)
57+
except CatchableError:
58+
continue

src/common/reboot.nim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import std/posix
22

33
const
44
SYS_reboot = cast[clong](88)
5-
5+
66
LINUX_REBOOT_MAGIC1 = cast[clong](0xfee1dead'u32)
77
LINUX_REBOOT_MAGIC2 = cast[clong](0x28121969'u32)
88

@@ -12,7 +12,7 @@ const
1212
RB_ENABLE_CAD* = cast[clong](0x89ABCDEF'u32)
1313
RB_DISABLE_CAD* = cast[clong](0x00000000'u32)
1414

15-
proc syscall(number: clong, arg1: clong, arg2: clong, arg3: clong, arg4: clong): clong
15+
proc syscall(number: clong, arg1: clong, arg2: clong, arg3: clong, arg4: clong): clong
1616
{.importc, header: "<unistd.h>", varargs.}
1717

1818
proc reboot*(cmd: clong): clong =
Lines changed: 39 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
import std/[os, posix, strutils]
22
import nimPNG
33

4-
import ../common/[fb, process]
5-
import stb_truetype
4+
import common/[fb, process]
5+
import common/ffi/stb_truetype
66

77
const
88
ScreenWidth = 320
@@ -26,17 +26,6 @@ proc fromRGB565(pixel: uint16, r, g, b: var uint8) {.inline.} =
2626
g = SixToEight[(pixel shr 5) and 0x3F]
2727
b = FiveToEight[pixel and 0x1F]
2828

29-
proc setPixel(fb: ptr UncheckedArray[uint16], x, y: int, color: uint16) {.inline.} =
30-
if x >= 0 and x < ScreenWidth and y >= 0 and y < ScreenHeight:
31-
let fbIdx = RowOffsets[RotationXMap[x]] + y
32-
fb[fbIdx] = color
33-
34-
proc getPixel(fb: ptr UncheckedArray[uint16], x, y: int): uint16 {.inline.} =
35-
if x >= 0 and x < SCREEN_WIDTH and y >= 0 and y < SCREEN_HEIGHT:
36-
let fbIdx = RowOffsets[RotationXMap[x]] + y
37-
return fb[fbIdx]
38-
return 0
39-
4029
proc loadFont(path: string): seq[byte] =
4130
let f = open(path, fmRead)
4231
defer: f.close()
@@ -88,38 +77,50 @@ proc renderTextLine(fb: ptr UncheckedArray[uint16], font: ptr stbtt_fontinfo,
8877
var cr, cg, cb: uint8
8978
fromRGB565(color, cr, cg, cb)
9079

80+
var bitmapBuf = newSeqUninit[byte](64 * 64)
81+
9182
for i, ch in text:
9283
var ix0, iy0, ix1, iy1: cint
9384
stbtt_GetCodepointBitmapBox(font, cint(ch), scale, scale,
9485
addr ix0, addr iy0, addr ix1, addr iy1)
95-
9686
let w = ix1 - ix0
9787
let h = iy1 - iy0
9888

9989
if w > 0 and h > 0:
100-
var bitmap = newSeqUninit[byte](w * h)
101-
stbtt_MakeCodepointBitmap(font, cast[ptr UncheckedArray[byte]](addr bitmap[0]),
102-
w, h, w, scale, scale, cint(ch))
103-
104-
{.push checks:off.}
105-
for by in 0..<h:
106-
for bx in 0..<w:
107-
let alpha = bitmap[by * w + bx]
108-
if alpha > 0:
109-
let px = x + int(ix0) + bx
110-
let py = baseline + int(iy0) + by
111-
112-
if px >= 0 and px < ScreenWidth and py >= 0 and py < ScreenHeight:
113-
let bgPixel = getPixel(fb, px, py)
114-
115-
var bgR, bgG, bgB: uint8
116-
fromRGB565(bgPixel, bgR, bgG, bgB)
117-
118-
let newR = uint8((uint16(cr) * alpha + uint16(bgR) * (255 - alpha)) div 255)
119-
let newG = uint8((uint16(cg) * alpha + uint16(bgG) * (255 - alpha)) div 255)
120-
let newB = uint8((uint16(cb) * alpha + uint16(bgB) * (255 - alpha)) div 255)
121-
122-
setPixel(fb, px, py, toRGB565(newR, newG, newB))
90+
let needed = w * h
91+
if needed > bitmapBuf.len:
92+
bitmapBuf.setLen(needed)
93+
94+
stbtt_MakeCodepointBitmap(font,
95+
cast[ptr UncheckedArray[byte]](addr bitmapBuf[0]),
96+
w, h, w, scale, scale, cint(ch))
97+
98+
let charX = x + int(ix0)
99+
let charY = baseline + int(iy0)
100+
101+
{.push checks: off.}
102+
for bx in 0..<w:
103+
let px = charX + bx
104+
if px < 0 or px >= ScreenWidth: continue
105+
let fbBase = FbXBase[px]
106+
107+
for by in 0..<h:
108+
let alpha = bitmapBuf[by * w + bx]
109+
if alpha == 0: continue
110+
let py = charY + by
111+
if py < 0 or py >= ScreenHeight: continue
112+
113+
if alpha == 255:
114+
fb[fbBase + py] = color
115+
else:
116+
let bgPixel = fb[fbBase + py]
117+
var bgR, bgG, bgB: uint8
118+
fromRGB565(bgPixel, bgR, bgG, bgB)
119+
let inv = 255'u32 - uint32(alpha)
120+
let newR = uint8((uint32(cr) * uint32(alpha) + uint32(bgR) * inv) div 255)
121+
let newG = uint8((uint32(cg) * uint32(alpha) + uint32(bgG) * inv) div 255)
122+
let newB = uint8((uint32(cb) * uint32(alpha) + uint32(bgB) * inv) div 255)
123+
fb[fbBase + py] = toRGB565(newR, newG, newB)
123124
{.pop.}
124125

125126
var advanceWidth, leftSideBearing: cint
@@ -168,7 +169,7 @@ proc display*(text: string,
168169
let g = png.data[srcIdx + 1]
169170
let b = png.data[srcIdx + 2]
170171
srcIdx += 4
171-
fb[RowOffsets[RotationXMap[lx]] + ly] = toRGB565(r.uint8, g.uint8, b.uint8)
172+
fb[FbXBase[lx] + ly] = toRGB565(r.uint8, g.uint8, b.uint8)
172173

173174
if not fileExists(fontPath):
174175
raise newException(IOError, "display: font file not found: " & fontPath)

0 commit comments

Comments
 (0)