├── examples ├── sqlitetst.dir │ ├── go.mod │ └── sqlitetst.go └── devinfo │ └── main.go ├── docker-compose.yaml ├── patches ├── dns-pb.patch └── go-pb.patch ├── goinkview.c ├── certs.go ├── app.go ├── LICENSE ├── Dockerfile ├── events.go ├── keyboard.go ├── log.go ├── graphics.go ├── inkview.go ├── network.go ├── screen.go ├── text.go ├── const.go ├── utils.go ├── README.md ├── cli.go ├── ui.go └── inkview.h /examples/sqlitetst.dir/go.mod: -------------------------------------------------------------------------------- 1 | module sqlitetst 2 | 3 | go 1.15 4 | 5 | require github.com/mattn/go-sqlite3 v1.14.6 6 | -------------------------------------------------------------------------------- /docker-compose.yaml: -------------------------------------------------------------------------------- 1 | version: "3.8" 2 | 3 | services: 4 | pb-go: 5 | image: 5keeve/pocketbook-go-sdk:6.3.0-b288-v1 6 | build: 7 | context: . 8 | entrypoint: 9 | - /go/bin/go 10 | command: 11 | - build 12 | volumes: 13 | - type: bind 14 | source: ./examples 15 | target: /app -------------------------------------------------------------------------------- /patches/dns-pb.patch: -------------------------------------------------------------------------------- 1 | --- dnsconfig_unix.go 2018-02-11 00:03:52.513314071 +0200 2 | +++ dnsconfig_unix.go 2018-02-11 00:04:09.653412723 +0200 3 | @@ -15,7 +15,7 @@ 4 | ) 5 | 6 | var ( 7 | - defaultNS = []string{"127.0.0.1:53", "[::1]:53"} 8 | + defaultNS = []string{"127.0.0.1:53"} 9 | getHostname = os.Hostname // variable for testing 10 | ) 11 | 12 | -------------------------------------------------------------------------------- /patches/go-pb.patch: -------------------------------------------------------------------------------- 1 | --- exec.go 2020-12-03 18:32:44.000000000 +0100 2 | +++ exec.go 2021-01-08 23:58:50.000000000 +0100 3 | @@ -3073,7 +3073,7 @@ 4 | func (b *Builder) disableBuildID(ldflags []string) []string { 5 | switch cfg.Goos { 6 | case "android", "dragonfly", "linux", "netbsd": 7 | - ldflags = append(ldflags, "-Wl,--build-id=none") 8 | + // ldflags = append(ldflags, "-Wl,--build-id=none") 9 | } 10 | return ldflags 11 | } 12 | -------------------------------------------------------------------------------- /goinkview.c: -------------------------------------------------------------------------------- 1 | #include "_cgo_export.h" 2 | 3 | int main_handler(int t, int p1, int p2) { 4 | return goMainHandler(t, p1, p2); 5 | } 6 | 7 | void c_keyboard_handler(char* text) { 8 | goKeyboardHandler(text); 9 | } 10 | 11 | void c_rotate_handler(int direction){ 12 | goRotateHandler(direction); 13 | } 14 | 15 | void c_dialog_handler(int button){ 16 | goDialogHandler(button); 17 | } 18 | 19 | void c_timeedit_handler(long newtime){ 20 | goTimeEditHandler(newtime); 21 | } -------------------------------------------------------------------------------- /examples/devinfo/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | 8 | "github.com/dennwc/inkview" 9 | ) 10 | 11 | func main() { 12 | ink.RunCLI(func(ctx context.Context, w io.Writer) error { 13 | fmt.Fprintln(w, "Device:") 14 | fmt.Fprintln(w, ink.DeviceModel()) 15 | fmt.Fprintln(w, ink.SoftwareVersion()) 16 | fmt.Fprintln(w, ink.HwAddress()) 17 | fmt.Fprintln(w) 18 | 19 | for _, name := range ink.Connections() { 20 | fmt.Fprintf(w, "conn: %q", name) 21 | } 22 | return nil 23 | }, nil) 24 | } 25 | -------------------------------------------------------------------------------- /certs.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | import ( 4 | "crypto/x509" 5 | "encoding/asn1" 6 | ) 7 | 8 | // InitCerts will read system certificates pool. 9 | // 10 | // This pool is usually populated by the first call to tls.Dial or similar, 11 | // but this operation might take up to 30 sec on some devices, leading to handshake timeout. 12 | // 13 | // Calling this function before dialing will fix the problem. 14 | func InitCerts() error { 15 | // hand-crafted fake cert that will force system pool to be populated 16 | // but will fail with an error directly after this 17 | cert := x509.Certificate{ 18 | Raw: []byte{0}, 19 | UnhandledCriticalExtensions: []asn1.ObjectIdentifier{nil}, 20 | } 21 | _, err := cert.Verify(x509.VerifyOptions{}) 22 | if _, ok := err.(x509.SystemRootsError); ok { 23 | return err 24 | } 25 | return nil 26 | } 27 | -------------------------------------------------------------------------------- /app.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | type App interface { 4 | // Init is called when application is started. 5 | Init() error 6 | // Close is called before exiting an application. 7 | Close() error 8 | 9 | // Draw is called each time an application view should be updated. 10 | // Can be queued by Repaint. 11 | Draw() 12 | 13 | //// Show is called when application becomes active. 14 | //// Delivered on application start and when switching from another app. 15 | //Show() bool 16 | //// Hide is called when application becomes inactive (switching to another app). 17 | //Hide() bool 18 | 19 | // Key is called on each key-related event. 20 | Key(e KeyEvent) bool 21 | // Pointer is called on each pointer-related event. 22 | Pointer(e PointerEvent) bool 23 | // Touch is called on each touch-related event. 24 | Touch(e TouchEvent) bool 25 | // Orientation is called each time an orientation of device changes. 26 | Orientation(o Orientation) bool 27 | } 28 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Denys Smirnov 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | FROM 5keeve/pocketbook-sdk:6.3.0-b288-v1 2 | 3 | LABEL maintainer="https://github.com/Skeeve" 4 | 5 | ARG GOLANG_VERSION=17.2 6 | 7 | RUN apt-get update && \ 8 | apt-get install -y xz-utils git curl && \ 9 | apt-get clean 10 | 11 | # download Pocketbook SDK 12 | ADD ./patches/* /tmp/ 13 | 14 | # download specified Go binary release that will act as a bootstrap compiler for Go toolchain 15 | # download sources for that release and apply the patch 16 | # build a new toolchain and remove an old one 17 | RUN mkdir /gosrc \ 18 | && curl https://dl.google.com/go/go1.17.2.linux-amd64.tar.gz | tar xzf - --directory=/ \ 19 | && curl https://dl.google.com/go/go1.17.2.src.tar.gz | tar xzf - --directory=/gosrc \ 20 | && patch /gosrc/go/src/cmd/go/internal/work/exec.go < /tmp/go-pb.patch \ 21 | && patch /gosrc/go/src/net/dnsconfig_unix.go < /tmp/dns-pb.patch \ 22 | && cd /gosrc/go/src && GOROOT_BOOTSTRAP=/go ./make.bash \ 23 | && rm -r /go && mv /gosrc/go /go && rm -r /gosrc \ 24 | ; 25 | WORKDIR /app 26 | VOLUME /app 27 | 28 | ENTRYPOINT ["/go/bin/go"] 29 | CMD ["build"] 30 | 31 | ADD ./*.go ./*.c ./*.h /gopath/src/github.com/dennwc/inkview/ 32 | 33 | ARG CC=${SDK_BASE}/usr/bin/arm-obreey-linux-gnueabi-clang 34 | ARG GOOS=linux 35 | ARG GOARCH=arm 36 | ARG GOARM=7 37 | ARG CGO_ENABLED=1 38 | 39 | ENV GOROOT=/go GOPATH=/gopath PATH="/go/bin:${SDK_BASE}/usr/bin:$PATH" CC=${CC} GOOS=${GOOS} GOARCH=${GOARCH} GOARM=${GOARM} CGO_ENABLED=${CGO_ENABLED} 40 | 41 | RUN go get github.com/mattn/go-sqlite3 42 | -------------------------------------------------------------------------------- /events.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | /* 4 | #include "inkview.h" 5 | 6 | #cgo CFLAGS: -pthread 7 | #cgo LDFLAGS: -pthread -lpthread -linkview 8 | */ 9 | import "C" 10 | import "image" 11 | 12 | type KeyEvent struct { 13 | Key Key 14 | State KeyState 15 | } 16 | 17 | type PointerEvent struct { 18 | image.Point 19 | State PointerState 20 | } 21 | 22 | type TouchEvent struct { 23 | image.Point 24 | State TouchState 25 | } 26 | 27 | type KeyState int 28 | 29 | const ( 30 | KeyStateDown = KeyState(C.EVT_KEYDOWN) 31 | KeyStatePress = KeyState(C.EVT_KEYPRESS) 32 | KeyStateUp = KeyState(C.EVT_KEYUP) 33 | KeyStateRelease = KeyState(C.EVT_KEYRELEASE) 34 | KeyStateRepeat = KeyState(C.EVT_KEYREPEAT) 35 | ) 36 | 37 | type PointerState int 38 | 39 | const ( 40 | PointerUp = PointerState(C.EVT_POINTERUP) 41 | PointerDown = PointerState(C.EVT_POINTERDOWN) 42 | PointerMove = PointerState(C.EVT_POINTERMOVE) 43 | PointerLong = PointerState(C.EVT_POINTERLONG) 44 | PointerHold = PointerState(C.EVT_POINTERHOLD) 45 | ) 46 | 47 | type TouchState int 48 | 49 | const ( 50 | TouchUp = TouchState(C.EVT_TOUCHUP) 51 | TouchDown = TouchState(C.EVT_TOUCHDOWN) 52 | TouchMove = TouchState(C.EVT_TOUCHMOVE) 53 | ) 54 | 55 | // Key is a key code for buttons. 56 | type Key int 57 | 58 | const ( 59 | KeyBack = Key(C.KEY_BACK) 60 | KeyDelete = Key(C.KEY_DELETE) 61 | KeyOk = Key(C.KEY_OK) 62 | KeyUp = Key(C.KEY_UP) 63 | KeyDown = Key(C.KEY_DOWN) 64 | KeyLeft = Key(C.KEY_LEFT) 65 | KeyRight = Key(C.KEY_RIGHT) 66 | KeyMinus = Key(C.KEY_MINUS) 67 | KeyPlus = Key(C.KEY_PLUS) 68 | KeyMenu = Key(C.KEY_MENU) 69 | KeyMusic = Key(C.KEY_MUSIC) 70 | KeyPower = Key(C.KEY_POWER) 71 | KeyPrev = Key(C.KEY_PREV) 72 | KeyNext = Key(C.KEY_NEXT) 73 | KeyPrev2 = Key(C.KEY_PREV2) 74 | KeyNext2 = Key(C.KEY_NEXT2) 75 | ) 76 | 77 | type Orientation int 78 | 79 | const ( 80 | Orientation0 = Orientation(C.ROTATE0) 81 | Orientation90 = Orientation(C.ROTATE90) 82 | Orientation180 = Orientation(C.ROTATE180) 83 | Orientation270 = Orientation(C.ROTATE270) 84 | ) 85 | -------------------------------------------------------------------------------- /keyboard.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | /* 4 | #include "inkview.h" 5 | 6 | #cgo CFLAGS: -pthread 7 | #cgo LDFLAGS: -pthread -lpthread -linkview 8 | 9 | extern void c_keyboard_handler(char *); 10 | */ 11 | import "C" 12 | import ( 13 | "unsafe" 14 | ) 15 | 16 | //export goKeyboardHandler 17 | func goKeyboardHandler(text *C.char) { 18 | 19 | userKeyboardHandler(C.GoString(text)) 20 | keyboardBuffer = []byte{} 21 | } 22 | 23 | var keyboardBuffer []byte 24 | 25 | type KeyboardHandler func(string) 26 | 27 | var userKeyboardHandler KeyboardHandler 28 | 29 | func SetKeyboardHandler(kh KeyboardHandler) { 30 | userKeyboardHandler = kh 31 | } 32 | 33 | // Open default keyboard 34 | func OpenKeyboard(placeholder string, buflen int) { 35 | 36 | if buflen <= 0 { 37 | buflen = 1024 38 | } 39 | 40 | keyboardBuffer = make([]byte, buflen) 41 | 42 | ctitle, free := cString(placeholder) 43 | defer free() 44 | 45 | cbuffer := (*C.char)(unsafe.Pointer(&keyboardBuffer[0])) 46 | 47 | var chandler C.iv_keyboardhandler 48 | chandler = (C.iv_keyboardhandler)(C.c_keyboard_handler) 49 | 50 | C.OpenKeyboard(ctitle, cbuffer, C.int(buflen), C.int(0), chandler) 51 | } 52 | 53 | // Open keyboard from .kbd file 54 | func OpenCustomKeyboard(keyboardFileName, placeholder string, buflen int) { 55 | 56 | if buflen <= 0 { 57 | buflen = 1024 58 | } 59 | 60 | keyboardBuffer = make([]byte, buflen) 61 | 62 | ctitle, free := cString(placeholder) 63 | defer free() 64 | 65 | cbuffer := (*C.char)(unsafe.Pointer(&keyboardBuffer[0])) 66 | 67 | var chandler C.iv_keyboardhandler 68 | chandler = (C.iv_keyboardhandler)(C.c_keyboard_handler) 69 | 70 | cfileName, free2 := cString(keyboardFileName) 71 | defer free2() 72 | 73 | C.OpenCustomKeyboard(cfileName, ctitle, cbuffer, C.int(buflen), C.int(0), chandler) 74 | } 75 | 76 | // Probably changes the keybaord language 77 | func LoadKeyboard() { 78 | keyboardLang, free := cString(defaultKeyboardLang) 79 | defer free() 80 | C.LoadKeyboard(keyboardLang) 81 | } 82 | 83 | // Close keyboard layout 84 | func CloseKeyboard() { 85 | C.CloseKeyboard() 86 | } 87 | -------------------------------------------------------------------------------- /log.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | import ( 4 | "bytes" 5 | "fmt" 6 | "image" 7 | ) 8 | 9 | func NewLog(r image.Rectangle, sz int) *Log { 10 | f := OpenFont(DefaultFontMono, sz, true) 11 | return &Log{ 12 | clip: r, font: f, h: sz, 13 | } 14 | } 15 | 16 | type Log struct { 17 | clip image.Rectangle 18 | font *Font 19 | lines []string // lines buffer 20 | w int // font width (since we use monospaced font) 21 | h int // font height 22 | Spacing int // line spacing 23 | } 24 | 25 | func (l *Log) Close() { 26 | l.font.Close() 27 | l.lines = nil 28 | } 29 | func (l *Log) appendLine(line string) { 30 | h := l.clip.Size().Y 31 | lh := l.h + l.Spacing 32 | n := h / lh 33 | if h%lh != 0 { 34 | n++ 35 | } 36 | if dn := len(l.lines) + 1 - n; dn > 0 { 37 | // remove exceeding lines 38 | copy(l.lines, l.lines[dn:]) 39 | l.lines = l.lines[:len(l.lines)-dn] 40 | } 41 | l.lines = append(l.lines, line) 42 | } 43 | func (l *Log) Write(p []byte) (int, error) { 44 | lines := bytes.Split(p, []byte{'\n'}) 45 | if len(lines) != 0 && len(l.lines) != 0 { 46 | // append string to the last line 47 | li := len(l.lines) - 1 48 | last := l.lines[li] 49 | l.lines = l.lines[:li] 50 | l.appendLine(last + string(lines[0])) 51 | lines = lines[1:] 52 | } 53 | // add new lines 54 | for _, line := range lines { 55 | l.appendLine(string(line)) 56 | } 57 | return len(p), nil 58 | } 59 | func (l *Log) Draw() { 60 | l.font.SetActive(Black) 61 | if l.w == 0 { 62 | l.w = CharWidth('a') 63 | } 64 | FillArea(l.clip, White) 65 | h := l.clip.Size().Y 66 | if h < l.h { 67 | DrawString(l.clip.Min, "window size is too small") 68 | return 69 | } 70 | for i := len(l.lines) - 1; i >= 0; i-- { 71 | s := l.lines[i] 72 | h -= l.h + l.Spacing 73 | if h < 0 { 74 | break 75 | } 76 | if s == "" { 77 | continue 78 | } 79 | p := image.Pt(0, h) 80 | DrawString(p.Add(l.clip.Min), s) 81 | } 82 | } 83 | 84 | func (l *Log) WriteString(s string) error { 85 | _, err := l.Write([]byte(s)) 86 | return err 87 | } 88 | 89 | func (l *Log) Println(args ...interface{}) error { 90 | return l.WriteString(fmt.Sprint(args...)) 91 | } 92 | 93 | func (l *Log) Printf(format string, args ...interface{}) error { 94 | return l.WriteString(fmt.Sprintf(format, args...)) 95 | } 96 | -------------------------------------------------------------------------------- /graphics.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | /* 4 | #include "inkview.h" 5 | 6 | #cgo CFLAGS: -pthread 7 | #cgo LDFLAGS: -pthread -lpthread -linkview 8 | */ 9 | import "C" 10 | 11 | import ( 12 | "image" 13 | "image/color" 14 | ) 15 | 16 | func Pad(r image.Rectangle, n int) image.Rectangle { 17 | dp := image.Pt(n, n) 18 | r.Min = r.Min.Add(dp) 19 | r.Max = r.Max.Sub(dp) 20 | return r 21 | } 22 | 23 | var ( 24 | Black = color.Black 25 | White = color.White 26 | DarkGray = color.Gray{0x55} 27 | LightGray = color.Gray{0xaa} 28 | ) 29 | 30 | func colorToInt(cl color.Color) int { 31 | r, g, b, _ := cl.RGBA() 32 | // 0x00RRGGBB 33 | return (int(b>>8) & 0xff) + int((g>>8)&0xff)<<8 + int((r>>8)&0xff)<<16 34 | } 35 | 36 | // ClearScreen fills current canvas with white color. 37 | func ClearScreen() { 38 | C.ClearScreen() 39 | } 40 | 41 | func SetClip(r image.Rectangle) { 42 | sz := r.Size() 43 | C.SetClip(C.int(r.Min.X), C.int(r.Min.Y), C.int(sz.X), C.int(sz.Y)) 44 | } 45 | 46 | func DrawPixel(p image.Point, cl color.Color) { 47 | C.DrawPixel(C.int(p.X), C.int(p.Y), C.int(colorToInt(cl))) 48 | } 49 | 50 | func DrawLine(p1, p2 image.Point, cl color.Color) { 51 | C.DrawLine(C.int(p1.X), C.int(p1.Y), C.int(p2.X), C.int(p2.Y), C.int(colorToInt(cl))) 52 | } 53 | 54 | func DrawRect(r image.Rectangle, cl color.Color) { 55 | sz := r.Size() 56 | C.DrawRect(C.int(r.Min.X), C.int(r.Min.Y), C.int(sz.X), C.int(sz.Y), C.int(colorToInt(cl))) 57 | } 58 | 59 | func FillArea(r image.Rectangle, cl color.Color) { 60 | sz := r.Size() 61 | C.FillArea(C.int(r.Min.X), C.int(r.Min.Y), C.int(sz.X), C.int(sz.Y), C.int(colorToInt(cl))) 62 | } 63 | 64 | func InvertArea(r image.Rectangle) { 65 | sz := r.Size() 66 | C.InvertArea(C.int(r.Min.X), C.int(r.Min.Y), C.int(sz.X), C.int(sz.Y)) 67 | } 68 | 69 | func InvertAreaBW(r image.Rectangle) { 70 | sz := r.Size() 71 | C.InvertAreaBW(C.int(r.Min.X), C.int(r.Min.Y), C.int(sz.X), C.int(sz.Y)) 72 | } 73 | 74 | func DimArea(r image.Rectangle, cl color.Color) { 75 | sz := r.Size() 76 | C.DimArea(C.int(r.Min.X), C.int(r.Min.Y), C.int(sz.X), C.int(sz.Y), C.int(colorToInt(cl))) 77 | } 78 | 79 | func DrawSelection(r image.Rectangle, cl color.Color) { 80 | sz := r.Size() 81 | C.DrawSelection(C.int(r.Min.X), C.int(r.Min.Y), C.int(sz.X), C.int(sz.Y), C.int(colorToInt(cl))) 82 | } 83 | 84 | // https://en.wikipedia.org/wiki/Dither 85 | func DitherArea(r image.Rectangle, levels int, method int) { 86 | C.DitherArea(C.int(r.Min.X), C.int(r.Min.Y), C.int(r.Max.X), C.int(r.Max.Y), C.int(levels), C.int(method)) 87 | } 88 | -------------------------------------------------------------------------------- /inkview.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | /* 4 | #include "inkview.h" 5 | 6 | extern int main_handler(int t, int p1, int p2); 7 | 8 | #cgo CFLAGS: -pthread 9 | #cgo LDFLAGS: -pthread -lpthread -linkview 10 | */ 11 | import "C" 12 | import ( 13 | "image" 14 | "sync" 15 | ) 16 | 17 | var ( 18 | mainMu sync.Mutex 19 | mainApp App 20 | 21 | errMu sync.Mutex 22 | mainErr error 23 | ) 24 | 25 | func SetErr(err error) { 26 | errMu.Lock() 27 | mainErr = err 28 | errMu.Unlock() 29 | } 30 | 31 | // Run starts main event loop. It should be called before calling any other function. 32 | func Run(app App) error { 33 | if app == nil { 34 | panic("no app") 35 | } 36 | mainMu.Lock() 37 | defer mainMu.Unlock() 38 | SetErr(nil) 39 | 40 | mainApp = app 41 | C.InkViewMain(C.iv_handler(C.main_handler)) 42 | 43 | errMu.Lock() 44 | err := mainErr 45 | errMu.Unlock() 46 | return err 47 | } 48 | 49 | func handleEvent(typ int, p1, p2 int) bool { 50 | switch typ { 51 | case C.EVT_INIT: 52 | if err := mainApp.Init(); err != nil { 53 | mainErr = err 54 | Exit() 55 | } 56 | return true 57 | case C.EVT_EXIT: 58 | if err := mainApp.Close(); err != nil { 59 | mainErr = err 60 | } 61 | return true 62 | case C.EVT_SHOW: 63 | mainApp.Draw() 64 | return true 65 | //case C.EVT_HIDE: 66 | //case C.EVT_FOREGROUND: 67 | // return mainApp.Show() 68 | //case C.EVT_BACKGROUND: 69 | // return mainApp.Hide() 70 | case C.EVT_ORIENTATION: 71 | return mainApp.Orientation(Orientation(p1)) 72 | default: 73 | switch { 74 | case typ >= C.EVT_KEYDOWN && typ <= C.EVT_KEYREPEAT: 75 | return mainApp.Key(KeyEvent{ 76 | Key: Key(p1), 77 | State: KeyState(typ), 78 | }) 79 | case typ >= C.EVT_POINTERUP && typ <= C.EVT_POINTERHOLD: 80 | return mainApp.Pointer(PointerEvent{ 81 | Point: image.Pt(p1, p2), 82 | State: PointerState(typ), 83 | }) 84 | case typ >= C.EVT_TOUCHUP && typ <= C.EVT_TOUCHMOVE: 85 | return mainApp.Touch(TouchEvent{ 86 | Point: image.Pt(p1, p2), 87 | State: TouchState(typ), 88 | }) 89 | } 90 | } 91 | return false 92 | } 93 | 94 | //export goMainHandler 95 | func goMainHandler(typ int, p1, p2 int) int { 96 | if handleEvent(typ, p1, p2) { 97 | return 1 98 | } 99 | return 0 100 | } 101 | 102 | //func OpenScreen() { 103 | // C.OpenScreen() 104 | //} 105 | 106 | //func OpenScreenExt() { 107 | // C.OpenScreenExt() 108 | //} 109 | 110 | // Exit can be called to exit an application event loop. 111 | func Exit() { 112 | C.CloseApp() 113 | } 114 | -------------------------------------------------------------------------------- /network.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | /* 4 | #include "inkview.h" 5 | 6 | #cgo CFLAGS: -pthread 7 | #cgo LDFLAGS: -pthread -lpthread -linkview 8 | */ 9 | import "C" 10 | 11 | import ( 12 | "errors" 13 | "fmt" 14 | "sync" 15 | ) 16 | 17 | var queryNetworkOnce sync.Once 18 | 19 | // HwAddress returns device MAC address. 20 | func HwAddress() string { 21 | return C.GoString(C.GetHwAddress()) 22 | } 23 | 24 | // Connections returns all available network connections. 25 | // Name can be used as an argument to Connect. 26 | func Connections() []string { 27 | list := C.EnumConnections() 28 | return strArr(list) 29 | } 30 | 31 | func WirelessNetworks() []string { 32 | list := C.EnumWirelessNetworks() 33 | return strArr(list) 34 | } 35 | 36 | type NetError struct { 37 | Code int 38 | Text string 39 | } 40 | 41 | func (e NetError) Error() string { 42 | if e.Text != "" { 43 | return e.Text 44 | } 45 | return fmt.Sprintf("unknown net error: %d", e.Code) 46 | } 47 | 48 | func netError(e C.int) error { 49 | if e == 0 { 50 | return nil 51 | } 52 | str := C.GoString(C.NetError(e)) 53 | return NetError{Code: int(e), Text: str} 54 | } 55 | 56 | func Connect(name string) error { 57 | cname, free := cString(name) 58 | defer free() 59 | e := C.NetConnect(cname) 60 | return netError(e) 61 | } 62 | 63 | func Disconnect() error { 64 | e := C.NetDisconnect() 65 | return netError(e) 66 | } 67 | 68 | func OpenNetworkInfo() { 69 | C.OpenNetworkInfo() 70 | } 71 | 72 | var ( 73 | ErrNoConnections = errors.New("no connections available") 74 | ) 75 | 76 | // KeepNetwork will connect a default network interface on the device and will keep it enabled. 77 | // Returned function can be called to disconnect an interface. 78 | func KeepNetwork() (func(), error) { 79 | conns := Connections() 80 | if len(conns) == 0 { 81 | return nil, ErrNoConnections 82 | } 83 | var last error 84 | for _, c := range conns { 85 | last = Connect(c) 86 | if last == nil { 87 | return func() { 88 | _ = Disconnect() 89 | }, nil 90 | } 91 | } 92 | return nil, last 93 | } 94 | 95 | // Obtained through reverse engineering, automatically connecting to the network and maintaining an active connection 96 | // requires passing null instead of the network name. 97 | // If not connected display network select or warning message, return error if connection failed 98 | func ConnectDefault() error { 99 | 100 | queryNetworkOnce.Do(func() { 101 | QueryNetwork() 102 | }) 103 | 104 | if int(C.NetConnect(nil)) != 0 { 105 | return errors.New("Can't connect network") 106 | } 107 | 108 | return nil 109 | } 110 | 111 | func QueryNetwork() { 112 | C.QueryNetwork() 113 | } 114 | -------------------------------------------------------------------------------- /screen.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | /* 4 | #include "inkview.h" 5 | 6 | #cgo CFLAGS: -pthread 7 | #cgo LDFLAGS: -pthread -lpthread -linkview 8 | */ 9 | import "C" 10 | 11 | import ( 12 | "image" 13 | ) 14 | 15 | func ScreenSize() image.Point { 16 | return image.Point{ 17 | X: int(C.ScreenWidth()), 18 | Y: int(C.ScreenHeight()), 19 | } 20 | } 21 | 22 | func Screen() image.Rectangle { 23 | return image.Rectangle{ 24 | Max: ScreenSize(), 25 | } 26 | } 27 | 28 | // Repaint puts Draw event into app's events queue. Eventually Draw method will be called on app object. 29 | // 30 | // Usage: Call Repaint to make app (eventually) redraw itself on the screen. 31 | func Repaint() { 32 | C.Repaint() 33 | } 34 | 35 | // FullUpdate sends content of the whole screen buffer to display driver. Display depth is set to 2 bpp (usually) or 4 36 | // bpp if necessary. Function isn't synchronous i.e. it returns faster, than display is redrawn. 37 | // Update is performed for active app (task) only, if display isn't locked and NO_DISPLAY flag in 38 | // ivstate.uiflags isn't set. 39 | // 40 | // Usage: Tradeoff between quality and speed. Recommended for text and common UI elements. Not 41 | // recommended if quality of picture (image) is required, in such case use FullUpdateHQ(). 42 | func FullUpdate() { 43 | C.FullUpdate() 44 | } 45 | 46 | // SoftUpdate is an alternative to FullUpdate. It's effect is (almost) PartialUpdate for the whole screen. 47 | func SoftUpdate() { 48 | C.SoftUpdate() 49 | } 50 | 51 | // PartialUpdate sends content of the given rectangle in screen buffer to display driver. Function is smart and tries to 52 | // perform the most suitable update possible: black and white update is performed if all pixels in given rectangle 53 | // are black and white. Otherwise grayscale update is performed. If whole screen is specified, then grayscale update is performed. 54 | func PartialUpdate(r image.Rectangle) { 55 | sz := r.Size() 56 | C.PartialUpdate(C.int(r.Min.X), C.int(r.Min.Y), C.int(sz.X), C.int(sz.Y)) 57 | } 58 | 59 | func PartialUpdateBW(r image.Rectangle) { 60 | sz := r.Size() 61 | C.PartialUpdateBW(C.int(r.Min.X), C.int(r.Min.Y), C.int(sz.X), C.int(sz.Y)) 62 | } 63 | 64 | func SetOrientation(orientation Orientation) { 65 | C.SetOrientation(C.int(orientation)) 66 | } 67 | 68 | // Original pb apps prefer to use setDefaultOrientation on init action (It's an undocumented function, found by reverse engineering) 69 | func SetDefaultOrientation(orientation Orientation) { 70 | C.SetOrientation(C.int(orientation)) 71 | } 72 | 73 | func GetOrientation() Orientation { 74 | return Orientation(C.GetOrientation()) 75 | } 76 | 77 | func SetGlobalOrientation(orientation Orientation) { 78 | C.SetGlobalOrientation(C.int(orientation)) 79 | } 80 | 81 | func GetGlobalOrientation() Orientation { 82 | return Orientation(C.GetOrientation()) 83 | } 84 | -------------------------------------------------------------------------------- /text.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | /* 4 | #include "inkview.h" 5 | 6 | #cgo CFLAGS: -pthread 7 | #cgo LDFLAGS: -pthread -lpthread -linkview 8 | */ 9 | import "C" 10 | 11 | import ( 12 | "fmt" 13 | "image" 14 | "image/color" 15 | "unsafe" 16 | ) 17 | 18 | const ( 19 | DefaultFont = string(C.DEFAULTFONT) 20 | DefaultFontBold = string(C.DEFAULTFONTB) 21 | DefaultFontItalic = string(C.DEFAULTFONTI) 22 | DefaultFontBoldItalic = string(C.DEFAULTFONTBI) 23 | DefaultFontMono = string(C.DEFAULTFONTM) 24 | ) 25 | 26 | func OpenFont(name string, size int, aa bool) *Font { 27 | cname, free := cString(name) 28 | defer free() 29 | p := C.OpenFont(cname, C.int(size), cbool(aa)) 30 | if p == nil { 31 | return nil 32 | } 33 | return &Font{p: p} 34 | } 35 | 36 | type Font struct { 37 | p *C.ifont 38 | } 39 | 40 | func (f *Font) SetActive(cl color.Color) { 41 | if f != nil && f.p != nil { 42 | C.SetFont(f.p, C.int(colorToInt(cl))) 43 | } 44 | } 45 | func (f *Font) Close() { 46 | if f == nil || f.p == nil { 47 | return 48 | } 49 | C.CloseFont(f.p) 50 | f.p = nil 51 | } 52 | 53 | func DrawString(p image.Point, s string) { 54 | cs, free := cString(s) 55 | defer free() 56 | C.DrawString(C.int(p.X), C.int(p.Y), cs) 57 | } 58 | 59 | func DrawStringR(p image.Point, s string) { 60 | cs, free := cString(s) 61 | defer free() 62 | C.DrawStringR(C.int(p.X), C.int(p.Y), cs) 63 | } 64 | 65 | func CharWidth(c rune) int { 66 | return int(C.CharWidth(C.ushort(c))) 67 | } 68 | 69 | func StringWidth(s string) int { 70 | cs, free := cString(s) 71 | defer free() 72 | return int(C.StringWidth(cs)) 73 | } 74 | 75 | func SetTextStrength(n int) { 76 | C.SetTextStrength(C.int(n)) 77 | } 78 | 79 | func GetCurrentLang() string { 80 | configs, err := GetConfig() 81 | if err == nil { 82 | lang, ok := configs["language"] 83 | if ok { 84 | return fmt.Sprintf("%v", lang) 85 | } 86 | } 87 | return "en" 88 | } 89 | 90 | // Probably changes the language the app should run in, translations depend on it 91 | func LoadLanguage(lang string) { 92 | cLang, free := cString(lang) 93 | defer free() 94 | C.LoadLanguage(cLang) 95 | } 96 | 97 | // Add translation text that will later be used in getLangText 98 | func AddTranslation(label, trans string) { 99 | cLabel, free := cString(label) 100 | defer free() 101 | cTrans, free2 := cString(trans) 102 | defer free2() 103 | C.AddTranslation(cLabel, cTrans) 104 | } 105 | 106 | // Get text with translation, translation variables can be found only in original pocketbook apps 107 | func GetLangText(s string) string { 108 | cS, free := cString(s) 109 | defer free() 110 | cText := C.GetLangText(cS) 111 | defer C.free(unsafe.Pointer(cText)) 112 | return C.GoString(cText) 113 | } 114 | -------------------------------------------------------------------------------- /examples/sqlitetst.dir/sqlitetst.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "database/sql" 5 | "log" 6 | "os" 7 | "path/filepath" 8 | 9 | _ "github.com/mattn/go-sqlite3" // Import go-sqlite3 library 10 | ) 11 | 12 | func main() { 13 | os.Chdir(filepath.Dir("/mnt/ext1")) 14 | os.Remove("/mnt/ext1/sqlite-database.db") // I delete the file to avoid duplicated records. SQLite is a file based database. 15 | 16 | log.Println("Creating sqlite-database.db...") 17 | file, err := os.Create("/mnt/ext1/sqlite-database.db") // Create SQLite file 18 | if err != nil { 19 | log.Fatal(err.Error()) 20 | } 21 | file.Close() 22 | log.Println("/mnt/ext1/sqlite-database.db created") 23 | 24 | sqliteDatabase, _ := sql.Open("sqlite3", "/mnt/ext1/sqlite-database.db") // Open the created SQLite File 25 | defer sqliteDatabase.Close() // Defer Closing the database 26 | createTable(sqliteDatabase) // Create Database Tables 27 | 28 | // INSERT RECORDS 29 | insertStudent(sqliteDatabase, "0001", "Liana Kim", "Bachelor") 30 | insertStudent(sqliteDatabase, "0002", "Glen Rangel", "Bachelor") 31 | insertStudent(sqliteDatabase, "0003", "Martin Martins", "Master") 32 | insertStudent(sqliteDatabase, "0004", "Alayna Armitage", "PHD") 33 | insertStudent(sqliteDatabase, "0005", "Marni Benson", "Bachelor") 34 | insertStudent(sqliteDatabase, "0006", "Derrick Griffiths", "Master") 35 | insertStudent(sqliteDatabase, "0007", "Leigh Daly", "Bachelor") 36 | insertStudent(sqliteDatabase, "0008", "Marni Benson", "PHD") 37 | insertStudent(sqliteDatabase, "0009", "Klay Correa", "Bachelor") 38 | 39 | // DISPLAY INSERTED RECORDS 40 | displayStudents(sqliteDatabase) 41 | } 42 | 43 | func createTable(db *sql.DB) { 44 | createStudentTableSQL := `CREATE TABLE student ( 45 | "idStudent" integer NOT NULL PRIMARY KEY AUTOINCREMENT, 46 | "code" TEXT, 47 | "name" TEXT, 48 | "program" TEXT 49 | );` // SQL Statement for Create Table 50 | 51 | log.Println("Create student table...") 52 | statement, err := db.Prepare(createStudentTableSQL) // Prepare SQL Statement 53 | if err != nil { 54 | log.Fatal(err.Error()) 55 | } 56 | statement.Exec() // Execute SQL Statements 57 | log.Println("student table created") 58 | } 59 | 60 | // We are passing db reference connection from main to our method with other parameters 61 | func insertStudent(db *sql.DB, code string, name string, program string) { 62 | log.Println("Inserting student record ...") 63 | insertStudentSQL := `INSERT INTO student(code, name, program) VALUES (?, ?, ?)` 64 | statement, err := db.Prepare(insertStudentSQL) // Prepare statement. This is good to avoid SQL injections 65 | if err != nil { 66 | log.Fatalln(err.Error()) 67 | } 68 | _, err = statement.Exec(code, name, program) 69 | if err != nil { 70 | log.Fatalln(err.Error()) 71 | } 72 | } 73 | 74 | func displayStudents(db *sql.DB) { 75 | row, err := db.Query("SELECT * FROM student ORDER BY name") 76 | if err != nil { 77 | log.Fatal(err) 78 | } 79 | defer row.Close() 80 | for row.Next() { // Iterate and fetch the records from result cursor 81 | var id int 82 | var code string 83 | var name string 84 | var program string 85 | row.Scan(&id, &code, &name, &program) 86 | log.Println("Student: ", code, " ", name, " ", program) 87 | } 88 | } 89 | -------------------------------------------------------------------------------- /const.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | const ( 4 | FlashDir = "/mnt/ext1" 5 | SdCardDir = "/mnt/ext2" 6 | UsbDir = "/mnt/ext3" 7 | SystemData = "/ebrmain" 8 | UserData = "/mnt/ext1/system" 9 | UserData2 = "/mnt/ext2/system" 10 | TempDir = "/tmp" 11 | SystemFontDir = "/ebrmain/fonts" 12 | UserFontDir = "/mnt/ext1/system/fonts" 13 | TempFontPath = "/tmp/fonts" 14 | PhotoTempDir = "/tmp/photo" 15 | UserProfiles = "/mnt/ext1/system/profiles" 16 | UserProfiles2 = "/mnt/ext2/system/profiles" 17 | CurrentProfile = "/mnt/ext1/system/profiles/.current" 18 | LastProfile = "/mnt/ext1/system/profiles/.last" 19 | SalvageProfiles = "/mnt/ext1/system/profiles/.salvage" 20 | ConfigPath = "/mnt/ext1/system/config" 21 | StatePath = "/mnt/ext1/system/state" 22 | SystemThemesPath = "/ebrmain/themes" 23 | UserThemesPath = "/mnt/ext1/system/themes" 24 | GlobalConfigFile = "/mnt/ext1/system/config/global.cfg" 25 | NetworkConfigFile = "/mnt/ext1/system/config/network.cfg" 26 | TsCalData = "/mnt/ext1/system/config/tsc.dat" 27 | TsCalData2 = "/tmp/tsc.dat" 28 | SystemLangPath = "/ebrmain/language" 29 | UserLangPath = "/mnt/ext1/system/language" 30 | SystemKbdPath = "/ebrmain/language/keyboard" 31 | UserKbdPath = "/mnt/ext1/system/language/keyboard" 32 | SystemDictPath = "/ebrmain/dictionaries" 33 | UserDictPath1 = "/mnt/ext1/system/dictionaries" 34 | UserDictPath2 = "/mnt/ext2/system/dictionaries" 35 | SystemLogoPath = "/ebrmain/logo" 36 | UserLogoPath = "/mnt/ext1/system/logo" 37 | NotesPath = "/mnt/ext1/notes" 38 | GamePath = "/mnt/ext1/applications" 39 | UserAppDir = "/mnt/ext1/system/bin" 40 | CachePath = "/mnt/ext1/system/cache" 41 | BackupDir = "/mnt/ext2/backup" 42 | UserBookshelf = "/mnt/ext1/system/bin/bookshelf.app" 43 | SystemBookshelf = "/ebrmain/bin/bookshelf.app" 44 | UserMpd = "/mnt/ext1/system/bin/mpd.app" 45 | SystemMpd = "/ebrmain/bin/mpd.app" 46 | StateCleaner = "/ebrmain/bin/cleanstate.sh" 47 | BackupScript = "/ebrmain/bin/backup.sh" 48 | RestoreScript = "/ebrmain/bin/restore.sh" 49 | NetAgent = "/ebrmain/bin/netagent" 50 | BooklandApp = "/ebrmain/bin/bookland.app" 51 | UserMplayer = "/mnt/ext1/system/bin/mplayer.so" 52 | UserBookinfo = "/mnt/ext1/system/bin/bookinfo.so" 53 | PocketbookSig = "/mnt/ext1/system/.pocketbook" 54 | LastOpenBooks = "/mnt/ext1/system/state/lastopen.txt" 55 | Favorites = "/mnt/ext1/system/favorite" 56 | CurrentBook = "/tmp/.current" 57 | BookshelfState = "/tmp/.bsstate" 58 | BookshelfStateNv = "/mnt/ext1/system/state/.bsstate" 59 | HistoryFile = "/tmp/history.txt" 60 | DicKeyboard = "/tmp/dictionary.kbd" 61 | PlaylistFile = "/tmp/playlist.pls" 62 | NetAgentLog = "/tmp/netagent.log" 63 | AdobePath = "/mnt/ext1/.adobe-digital-editions" 64 | AdobePath2 = "/mnt/ext2/.adobe-digital-editions" 65 | HandlersPath = "/mnt/ext1/system/config/handlers.cfg" 66 | UrlHistory = "/mnt/ext1/system/cache/urlhistory.txt" 67 | WebCache = "/tmp/webcache" 68 | WebCacheIndex = "/tmp/webcache/index" 69 | WidgetsConfig = "/mnt/ext1/system/config/widgets" 70 | WidgetsOpen = "/mnt/ext1/system/config/widgets/open.cfg" 71 | ) 72 | -------------------------------------------------------------------------------- /utils.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | /* 4 | #include "inkview.h" 5 | 6 | #cgo CFLAGS: -pthread 7 | #cgo LDFLAGS: -pthread -lpthread -linkview 8 | */ 9 | import "C" 10 | 11 | import ( 12 | "bufio" 13 | "os" 14 | "strings" 15 | "time" 16 | "unsafe" 17 | ) 18 | 19 | var defaultKeyboardLang = "en" 20 | 21 | func cbool(v bool) C.int { 22 | if v { 23 | return 1 24 | } 25 | return 0 26 | } 27 | 28 | func incPtr(ptr unsafe.Pointer) unsafe.Pointer { 29 | return unsafe.Pointer(uintptr(unsafe.Pointer(ptr)) + unsafe.Sizeof(C.size_t(0))) 30 | } 31 | 32 | func strArr(list **C.char) (out []string) { 33 | if list == nil { 34 | return 35 | } 36 | for list != nil { 37 | s := C.GoString(*list) 38 | if len(s) == 0 { 39 | break 40 | } 41 | out = append(out, s) 42 | list = (**C.char)(incPtr(unsafe.Pointer(list))) 43 | } 44 | return 45 | } 46 | 47 | func SetSleepMode(on bool) { 48 | C.iv_sleepmode(cbool(on)) 49 | } 50 | 51 | func SleepMode() bool { 52 | return C.GetSleepmode() != 0 53 | } 54 | 55 | func BatteryPower() int { 56 | return int(C.GetBatteryPower()) 57 | } 58 | 59 | func Temperature() int { 60 | return int(C.GetTemperature()) 61 | } 62 | 63 | func IsPressed(key Key) bool { 64 | return C.IsKeyPressed(C.int(key)) != 0 65 | } 66 | 67 | func IsCharging() bool { 68 | return C.IsCharging() != 0 69 | } 70 | 71 | func IsUSBconnected() bool { 72 | return C.IsUSBconnected() != 0 73 | } 74 | 75 | func IsSDinserted() bool { 76 | return C.IsSDinserted() != 0 77 | } 78 | 79 | func DeviceModel() string { 80 | return C.GoString(C.GetDeviceModel()) 81 | } 82 | 83 | func HardwareType() string { 84 | return C.GoString(C.GetHardwareType()) 85 | } 86 | 87 | func SoftwareVersion() string { 88 | return C.GoString(C.GetSoftwareVersion()) 89 | } 90 | 91 | func SerialNumber() string { 92 | return C.GoString(C.GetSerialNumber()) 93 | } 94 | 95 | func DeviceKey() string { 96 | return C.GoString(C.GetDeviceKey()) 97 | } 98 | 99 | func Sleep(dt time.Duration, deep bool) { 100 | ms := int(dt / time.Millisecond) 101 | if ms == 0 { 102 | ms = 1 103 | } 104 | _ = C.GoSleep(C.int(ms), cbool(deep)) 105 | } 106 | 107 | func SetAutoPowerOff(on bool) { 108 | C.SetAutoPowerOff(cbool(on)) 109 | } 110 | 111 | func PowerOff() { 112 | C.PowerOff() 113 | } 114 | 115 | func OpenMainMenu() { 116 | C.OpenMainMenu() 117 | } 118 | 119 | func GetConfig() (map[string]string, error) { 120 | file, err := os.Open(C.GLOBALCONFIGFILE) 121 | if err != nil { 122 | return nil, err 123 | } 124 | defer file.Close() 125 | 126 | configs := make(map[string]string) 127 | scanner := bufio.NewScanner(file) 128 | for scanner.Scan() { 129 | line := scanner.Text() 130 | if parts := strings.SplitN(line, "=", 2); len(parts) == 2 { 131 | configs[parts[0]] = parts[1] 132 | } 133 | } 134 | 135 | if err := scanner.Err(); err != nil { 136 | return nil, err 137 | } 138 | 139 | return configs, nil 140 | } 141 | 142 | // open the book in the default reader. If the .app file, then run the application 143 | func OpenBook(path string) { 144 | cPath, free := cString(path) 145 | defer free() 146 | C.OpenBook(cPath, (*C.char)(nil), C.int(0)) 147 | } 148 | 149 | func PageSnapshot() { 150 | C.PageSnapshot() 151 | } 152 | 153 | func cString(str string) (*C.char, func()) { 154 | cstr := C.CString(str) 155 | return cstr, func() { 156 | C.free(unsafe.Pointer(cstr)) 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Go SDK for Pocketbook 2 | 3 | Unofficial Go SDK for Pocketbook based on libinkview. 4 | 5 | Supports graphical user interfaces and CLI apps. 6 | 7 | ## Build a CLI app 8 | 9 | Standard Go compiler should be able to cross-compile the binary 10 | for the device (no need for SDK): 11 | 12 | ``` 13 | GOOS=linux GOARCH=arm GOARM=5 go build main.go 14 | ``` 15 | 16 | Note that some additional workarounds are necessary if you want to access 17 | a network from your app. In this case you may still need SDK. 18 | 19 | Although this binary will run on the device, you will need a third-party 20 | application to actually see an output of you program (like 21 | [pbterm](http://users.physik.fu-berlin.de/~jtt/PB/)). 22 | 23 | The second option is to wrap the program into `RunCLI` - it will 24 | emulate terminal output and write it to device display. 25 | 26 | ## Preparation - Build or pull the Docker Image 27 | 28 | You can pull a docker images from dockerhub: 29 | 30 | ```bash 31 | docker pull 5keeve/pocketbook-go-sdk:6.3.0-b288-v1 32 | ``` 33 | 34 | To build this image on your own, feel free to use `docker-compose.yaml`. 35 | 36 | ```bash 37 | docker-compose build 38 | ``` 39 | 40 | This will create a `pb-go` service which can be used to compile a go program. 41 | 42 | Adjust the `source` path in `docker-compose.yaml` to your needs. 43 | 44 | With the current settings you can compile the test programs. 45 | 46 | E.g.: 47 | 48 | ```bash 49 | docker-compose run --rm pb-go build ./sqlitetst.dir/sqlitetst.go 50 | ``` 51 | 52 | **Note** In order to see some output for this, you need to run in using something like pbterm. 53 | If you just start it without pbterm you can verify successful execution by attaching your 54 | device to your computer and check for the presence of the file `sqlite-database.db`. 55 | 56 | ```bash 57 | docker-compose run --rm pb-go build ./devinfo/main.go 58 | ``` 59 | 60 | 61 | Alternatively, after building the image, `docker` can be used to compile without adjusting the file. 62 | 63 | ``` 64 | docker run --rm -v $(PATH_TO_PROJECT):/app 5keeve/pocketbook-go-sdk:6.3.0-b288-v1 build -o $(APP_NAME).app 65 | ``` 66 | 67 | Or there is an alternative image with newer versions of Goland: `sunsung/pocketbook-go-sdk:latest` 68 | 69 | ``` 70 | docker run --rm -v $(PATH_TO_PROJECT):/app sunsung/pocketbook-go-sdk:latest build -o $(APP_NAME).app . 71 | ``` 72 | 73 | 74 | ## Build an app with UI 75 | 76 | To build your app or any example, run (requires Docker): 77 | 78 | ```bash 79 | cd ./examples/sqlitetst.dir/ 80 | docker run --rm -v $PWD:/app dennwc/pocketbook-go-sdk build -o sqlitetst.app 81 | ``` 82 | 83 | ```bash 84 | cd ./examples/devinfo/ 85 | docker run --rm -v $PWD:/app dennwc/pocketbook-go-sdk 86 | mv app devinfo.app 87 | ``` 88 | 89 | You may also need to mount GOPATH to container to build your app: 90 | 91 | ``` 92 | docker run --rm -v $PWD:/app -v $GOPATH:/gopath dennwc/pocketbook-go-sdk 93 | ``` 94 | 95 | To run an binary, copy it into `applications/app-name.app` folder 96 | on the device and it should appear in the applications list. 97 | 98 | ## Notes on networking 99 | 100 | By default, device will try to shutdown network interface to save battery, 101 | thus you will need to call SDK functions to keep device online (see `KeepNetwork`). 102 | 103 | Also note that establishing TLS will require Go to read system 104 | certificate pool that might take up to 30 sec on some devices and will 105 | lead to TLS handshake timeouts. You will need to call `InitCerts` first 106 | to fix the problem. 107 | 108 | IPv6 is not enabled on some devices, thus a patch to Go DNS lib is required 109 | to skip lookup on IPv6 address (SDK already includes the patch). 110 | Similar problems may arise when trying to dial IPv6 directly. 111 | 112 | ## Notes on workdir 113 | 114 | Application will have a working directory set to FS root, and not to 115 | a parent directory. 116 | To use relative paths properly change local dir to a binary's parent 117 | directory: `os.Chdir(filepath.Dir(os.Args[0]))`. 118 | -------------------------------------------------------------------------------- /cli.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | import ( 4 | "context" 5 | "fmt" 6 | "io" 7 | "sync" 8 | "sync/atomic" 9 | "time" 10 | ) 11 | 12 | var DefaultFontHeight = 14 13 | 14 | type RunFunc func(ctx context.Context, w io.Writer) error 15 | 16 | func newLogWriter(log *Log, update func()) *logWriter { 17 | return &logWriter{log: log, update: update} 18 | } 19 | 20 | type logWriter struct { 21 | log *Log 22 | update func() 23 | } 24 | 25 | func (w *logWriter) Write(p []byte) (int, error) { 26 | defer w.update() 27 | return w.log.Write(p) 28 | } 29 | func (w *logWriter) draw() { 30 | w.log.Draw() 31 | } 32 | func (w *logWriter) close() { 33 | w.log.Close() 34 | } 35 | 36 | func newCliApp(fnc RunFunc, c RunConfig) *cliApp { 37 | return &cliApp{cli: fnc, conf: c} 38 | } 39 | 40 | type cliApp struct { 41 | redraws int32 // atomic 42 | 43 | conf RunConfig 44 | cli RunFunc 45 | 46 | wg sync.WaitGroup 47 | err error 48 | stop func() 49 | 50 | log *logWriter 51 | 52 | stopNet func() 53 | 54 | rmu sync.Mutex 55 | running bool 56 | } 57 | 58 | func (app *cliApp) setRunning(v bool) { 59 | app.rmu.Lock() 60 | app.running = v 61 | app.rmu.Unlock() 62 | } 63 | 64 | func (app *cliApp) isRunning() bool { 65 | app.rmu.Lock() 66 | v := app.running 67 | app.rmu.Unlock() 68 | return v 69 | } 70 | 71 | func (app *cliApp) redraw() { 72 | // allow only one repaint in queue 73 | if atomic.CompareAndSwapInt32(&app.redraws, 0, 1) { 74 | Repaint() 75 | } 76 | } 77 | func (app *cliApp) draw() { 78 | ClearScreen() 79 | app.log.draw() 80 | FullUpdate() 81 | atomic.StoreInt32(&app.redraws, 0) 82 | } 83 | 84 | func (app *cliApp) println(args ...interface{}) { 85 | fmt.Fprintln(app.log, args...) 86 | } 87 | 88 | func (app *cliApp) Init() error { 89 | ClearScreen() 90 | l := NewLog(Pad(Screen(), 10), DefaultFontHeight) 91 | app.log = newLogWriter(l, app.redraw) 92 | 93 | if app.conf.Certs { 94 | now := time.Now() 95 | app.println("reading certs...") 96 | app.draw() 97 | if err := InitCerts(); err != nil { 98 | app.println("error reading certs:", err) 99 | } else { 100 | app.println("loaded certs in", time.Since(now)) 101 | } 102 | app.draw() 103 | } 104 | 105 | if app.conf.Network { 106 | var err error 107 | app.stopNet, err = KeepNetwork() 108 | if err != nil { 109 | app.println("cannot connect to the network:", err) 110 | } else { 111 | app.println("network connected") 112 | } 113 | app.draw() 114 | } 115 | 116 | app.setRunning(true) 117 | 118 | ctx, cancel := context.WithCancel(context.Background()) 119 | app.stop = cancel 120 | app.wg.Add(1) 121 | go func() { 122 | defer app.wg.Done() 123 | err := app.cli(ctx, app.log) 124 | if app.stopNet != nil { 125 | app.stopNet() 126 | } 127 | app.err = err 128 | if err != nil { 129 | app.println("error:", err) 130 | } 131 | app.println("") 132 | app.redraw() 133 | }() 134 | return nil 135 | } 136 | 137 | func (app *cliApp) stopCli() error { 138 | if !app.isRunning() { 139 | return app.err 140 | } 141 | app.stop() 142 | app.wg.Wait() 143 | app.setRunning(false) 144 | return app.err 145 | } 146 | 147 | func (app *cliApp) Close() error { 148 | err := app.stopCli() 149 | app.log.close() 150 | if app.stopNet != nil { 151 | app.stopNet() 152 | } 153 | return err 154 | } 155 | 156 | func (app *cliApp) Draw() { 157 | app.draw() 158 | } 159 | 160 | func (*cliApp) Show() bool { 161 | return false 162 | } 163 | 164 | func (*cliApp) Hide() bool { 165 | return false 166 | } 167 | 168 | func (app *cliApp) Key(e KeyEvent) bool { 169 | if app.isRunning() || (e.Key == KeyPrev && e.State == KeyStateDown) { 170 | Exit() 171 | return true 172 | } 173 | return false 174 | } 175 | 176 | func (app *cliApp) Pointer(e PointerEvent) bool { 177 | if app.isRunning() { 178 | Exit() 179 | return true 180 | } 181 | if e.State == PointerDown { 182 | app.redraw() 183 | } 184 | return true 185 | } 186 | 187 | func (*cliApp) Touch(e TouchEvent) bool { 188 | return false 189 | } 190 | 191 | func (*cliApp) Orientation(o Orientation) bool { 192 | return false 193 | } 194 | 195 | type RunConfig struct { 196 | Certs bool // initialize certificate pool 197 | Network bool // keep networking enabled while app is running 198 | } 199 | 200 | // RunCLI starts a command-line application that can write to device display. 201 | // Context will be cancelled when application is closed. 202 | // Provided callback can use any SDK functions. 203 | func RunCLI(fnc RunFunc, c *RunConfig) error { 204 | if c == nil { 205 | c = &RunConfig{} 206 | } 207 | return Run(newCliApp(fnc, *c)) 208 | } 209 | -------------------------------------------------------------------------------- /ui.go: -------------------------------------------------------------------------------- 1 | package ink 2 | 3 | /* 4 | #include "inkview.h" 5 | 6 | #cgo CFLAGS: -pthread 7 | #cgo LDFLAGS: -pthread -lpthread -linkview 8 | 9 | extern void c_rotate_handler(int direction); 10 | extern void c_dialog_handler(int button); 11 | extern void c_timeedit_handler(long time); 12 | 13 | */ 14 | import "C" 15 | 16 | import ( 17 | "fmt" 18 | "image" 19 | "time" 20 | ) 21 | 22 | var DefaultDelay = time.Second 23 | 24 | type RotateBoxHandler func(Orientation) 25 | 26 | var userRotateBoxHandler RotateBoxHandler 27 | 28 | // return 1 for left button, 2 for right button. 1 for progressbar cancel button 29 | type DialogHandler func(button int) 30 | 31 | var userDialogHandler DialogHandler 32 | 33 | type TimeEditHandler func(time time.Time) 34 | 35 | var userTimeEditHandler TimeEditHandler 36 | 37 | type Icon int 38 | 39 | const ( 40 | Info = Icon(C.ICON_INFORMATION) 41 | Question = Icon(C.ICON_QUESTION) 42 | Warning = Icon(C.ICON_WARNING) 43 | Error = Icon(C.ICON_ERROR) 44 | ) 45 | 46 | func SetMessageDelay(time time.Duration) { 47 | DefaultDelay = time 48 | } 49 | 50 | func Message(icon Icon, title, text string, dt time.Duration) { 51 | if dt == 0 { 52 | dt = DefaultDelay 53 | } 54 | ctitle, free := cString(title) 55 | defer free() 56 | ctxt, free2 := cString(text) 57 | defer free2() 58 | C.Message(C.int(icon), ctitle, ctxt, C.int(dt/time.Millisecond)) 59 | } 60 | 61 | func messagef(icon Icon, title, def, format string, args ...interface{}) { 62 | if title == "" { 63 | title = def 64 | } 65 | Message(icon, title, fmt.Sprintf(format, args...), 0) 66 | } 67 | 68 | func Infof(title, format string, args ...interface{}) { 69 | messagef(Info, title, "Info", format, args...) 70 | } 71 | 72 | func Questionf(title, format string, args ...interface{}) { 73 | messagef(Question, title, "Question", format, args...) 74 | } 75 | 76 | func Warningf(title, format string, args ...interface{}) { 77 | messagef(Warning, title, "Warning", format, args...) 78 | } 79 | 80 | func Errorf(title, format string, args ...interface{}) { 81 | messagef(Error, title, "Error", format, args...) 82 | } 83 | 84 | func ShowHourglass() { 85 | C.ShowHourglass() 86 | } 87 | 88 | func ShowHourglassAt(p image.Point) { 89 | C.ShowHourglassAt(C.int(p.X), C.int(p.Y)) 90 | } 91 | 92 | func HideHourglass() { 93 | C.HideHourglass() 94 | } 95 | 96 | func DisableExitHourglass() { 97 | C.DisableExitHourglass() 98 | } 99 | 100 | func DrawTopPanel() { 101 | emptyStr, free := cString("") 102 | defer free() 103 | C.DrawPanel(nil, emptyStr, emptyStr, -1) 104 | } 105 | 106 | func OpenRotateBox() { 107 | var rotateHandler C.iv_rotatehandler 108 | rotateHandler = (C.iv_rotatehandler)(C.c_rotate_handler) 109 | C.OpenRotateBox(rotateHandler) 110 | } 111 | 112 | func SetRotateBoxHandler(handler RotateBoxHandler) { 113 | userRotateBoxHandler = handler 114 | } 115 | 116 | //export goRotateHandler 117 | func goRotateHandler(d C.int) { 118 | userRotateBoxHandler(Orientation(d)) 119 | } 120 | 121 | func Dialog(icon Icon, title, text, button1, button2 string) { 122 | ctitle, free1 := cString(title) 123 | defer free1() 124 | ctext, free2 := cString(text) 125 | defer free2() 126 | cbutton1, free3 := cString(button1) 127 | defer free3() 128 | cbutton2, free4 := cString(button2) 129 | defer free4() 130 | 131 | var dialogHandler C.iv_dialoghandler 132 | dialogHandler = (C.iv_dialoghandler)(C.c_dialog_handler) 133 | 134 | C.Dialog(C.int(icon), ctitle, ctext, cbutton1, cbutton2, dialogHandler) 135 | } 136 | 137 | func SetDialogHandler(handler DialogHandler) { 138 | userDialogHandler = handler 139 | } 140 | 141 | //export goDialogHandler 142 | func goDialogHandler(button C.int) { 143 | userDialogHandler(int(button)) 144 | } 145 | 146 | // Use dialog handler for callback 147 | func OpenProgressbar(icon Icon, title, text string, percent int) { 148 | ctitle, free := cString(title) 149 | defer free() 150 | ctext, free2 := cString(text) 151 | defer free2() 152 | var dialogHandler C.iv_dialoghandler 153 | dialogHandler = (C.iv_dialoghandler)(C.c_dialog_handler) 154 | C.OpenProgressbar(C.int(icon), ctitle, ctext, C.int(percent), dialogHandler) 155 | } 156 | 157 | func UpdateProgressbar(text string, percent int) { 158 | ctext, free := cString(text) 159 | defer free() 160 | C.UpdateProgressbar(ctext, C.int(percent)) 161 | } 162 | 163 | func CloseProgressbar() { 164 | C.CloseProgressbar() 165 | } 166 | 167 | func SetTimeEditHandler(handler TimeEditHandler) { 168 | userTimeEditHandler = handler 169 | } 170 | 171 | //export goTimeEditHandler 172 | func goTimeEditHandler(t C.long) { 173 | userTimeEditHandler(time.Unix(int64(t), 0)) 174 | } 175 | 176 | func OpenTimeEdit(title string, p image.Point, initime time.Time) { 177 | ctitle, free := cString(title) 178 | defer free() 179 | var timeEditHandler C.iv_timeedithandler 180 | timeEditHandler = (C.iv_timeedithandler)(C.c_timeedit_handler) 181 | C.OpenTimeEdit(ctitle, C.int(p.X), C.int(p.Y), C.long(initime.Unix()), timeEditHandler) 182 | } 183 | -------------------------------------------------------------------------------- /inkview.h: -------------------------------------------------------------------------------- 1 | #ifndef INKVIEW_H 2 | #define INKVIEW_H 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | /* 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #include FT_FREETYPE_H 28 | #include FT_GLYPH_H 29 | #include FT_IMAGE_H 30 | #include FT_OUTLINE_H 31 | */ 32 | 33 | #ifdef __cplusplus 34 | extern "C" 35 | { 36 | #endif 37 | 38 | #define APP_UID 101 39 | #define APP_GID 101 40 | 41 | #ifndef IVSAPP 42 | #if !defined(__CYGWIN__) && defined(__i386__) 43 | # define DIRPREFIX "/usr/local/pocketbook" 44 | #else 45 | # define DIRPREFIX "" 46 | #endif 47 | #define FLASHDIR DIRPREFIX "/mnt/ext1" 48 | #define SDCARDDIR DIRPREFIX "/mnt/ext2" 49 | #define USBDIR DIRPREFIX "/mnt/ext3" 50 | #define SYSTEMDATA DIRPREFIX "/ebrmain" 51 | #define USERDATA FLASHDIR "/system" 52 | #define USERDATA2 SDCARDDIR "/system" 53 | #define TEMPDIR DIRPREFIX "/tmp" 54 | #else 55 | #define FLASHDIR "./system/mnt/ext1" 56 | #define SDCARDDIR "./system/mnt/ext2" 57 | #define USBDIR "./system/mnt/ext3" 58 | #define SYSTEMDATA "./system" 59 | #define USERDATA SYSTEMDATA 60 | #define USERDATA2 SDCARDDIR "/system" 61 | #define TEMPDIR "./system/tmp" 62 | #endif 63 | 64 | #define SYSTEMFONTDIR SYSTEMDATA "/fonts" 65 | #define USERFONTDIR USERDATA "/fonts" 66 | #define TEMPFONTPATH TEMPDIR "/fonts" 67 | #define PHOTOTEMPDIR TEMPDIR "/photo" 68 | #define USERPROFILES USERDATA "/profiles" 69 | #define USERPROFILES2 USERDATA2 "/profiles" 70 | #define CURRENTPROFILE USERPROFILES "/.current" 71 | #define LASTPROFILE USERPROFILES "/.last" 72 | #define SALVAGEPROFILES USERPROFILES "/.salvage" 73 | #define CONFIGPATH USERDATA "/config" 74 | #define STATEPATH USERDATA "/state" 75 | #define SYSTEMTHEMESPATH SYSTEMDATA "/themes" 76 | #define USERTHEMESPATH USERDATA "/themes" 77 | #define GLOBALCONFIGFILE CONFIGPATH "/global.cfg" 78 | #define NETWORKCONFIGFILE CONFIGPATH "/network.cfg" 79 | #define TSCALDATA CONFIGPATH "/tsc.dat" 80 | #define TSCALDATA2 TEMPDIR "/tsc.dat" 81 | #define SYSTEMLANGPATH SYSTEMDATA "/language" 82 | #define USERLANGPATH USERDATA "/language" 83 | #define SYSTEMKBDPATH SYSTEMDATA "/language/keyboard" 84 | #define USERKBDPATH USERDATA "/language/keyboard" 85 | #define SYSTEMDICTPATH SYSTEMDATA "/dictionaries" 86 | #define USERDICTPATH1 USERDATA "/dictionaries" 87 | #define USERDICTPATH2 USERDATA2 "/dictionaries" 88 | #define SYSTEMLOGOPATH SYSTEMDATA "/logo" 89 | #define USERLOGOPATH USERDATA "/logo" 90 | #define NOTESPATH FLASHDIR "/notes" 91 | #define GAMEPATH FLASHDIR "/applications" 92 | #define USERAPPDIR USERDATA "/bin" 93 | #define CACHEPATH USERDATA "/cache" 94 | #define BACKUPDIR SDCARDDIR "/backup" 95 | #define USERBOOKSHELF USERDATA "/bin/bookshelf.app" 96 | #define SYSTEMBOOKSHELF SYSTEMDATA "/bin/bookshelf.app" 97 | #define USERMPD USERDATA "/bin/mpd.app" 98 | #define SYSTEMMPD SYSTEMDATA "/bin/mpd.app" 99 | #define STATECLEANER SYSTEMDATA "/bin/cleanstate.sh" 100 | #define BACKUPSCRIPT SYSTEMDATA "/bin/backup.sh" 101 | #define RESTORESCRIPT SYSTEMDATA "/bin/restore.sh" 102 | #define NETAGENT SYSTEMDATA "/bin/netagent" 103 | #define BOOKLANDAPP SYSTEMDATA "/bin/bookland.app" 104 | #define USERMPLAYER USERDATA "/bin/mplayer.so" 105 | #define USERBOOKINFO USERDATA "/bin/bookinfo.so" 106 | #define POCKETBOOKSIG USERDATA "/.pocketbook" 107 | #define LASTOPENBOOKS STATEPATH "/lastopen.txt" 108 | #define FAVORITES USERDATA "/favorite" 109 | #define CURRENTBOOK TEMPDIR "/.current" 110 | #define BOOKSHELFSTATE TEMPDIR"/.bsstate" 111 | #define BOOKSHELFSTATE_NV STATEPATH "/.bsstate" 112 | #define HISTORYFILE TEMPDIR "/history.txt" 113 | #define DICKEYBOARD TEMPDIR "/dictionary.kbd" 114 | #define PLAYLISTFILE TEMPDIR "/playlist.pls" 115 | #define NETAGENTLOG TEMPDIR "/netagent.log" 116 | #define ADOBEPATH FLASHDIR "/.adobe-digital-editions" 117 | #define ADOBEPATH2 SDCARDDIR "/.adobe-digital-editions" 118 | #define HANDLERSPATH CONFIGPATH "/handlers.cfg" 119 | #define URLHISTORY CACHEPATH "/urlhistory.txt" 120 | #define WEBCACHE "/tmp/webcache" 121 | #define WEBCACHEINDEX WEBCACHE "/index" 122 | #define WIDGETSCONFIG CONFIGPATH "/widgets" 123 | #define WIDGETSOPEN WIDGETSCONFIG "/open.cfg" 124 | 125 | #define DEFAULTFONT "LiberationSans" 126 | #define DEFAULTFONTB "LiberationSans-Bold" 127 | #define DEFAULTFONTI "LiberationSans-Italic" 128 | #define DEFAULTFONTBI "LiberationSans-BoldItalic" 129 | #define DEFAULTFONTM "LiberationMono" 130 | 131 | #define PF_LOCAL 0x01 132 | #define PF_SDCARD 0x02 133 | 134 | #define SYSTEMDEPTH 8 135 | 136 | #define MSG_REQUEST 0x7fffffff 137 | #define MSG_OK 1 138 | #define MSG_ERROR 0 139 | 140 | #define MSG_FORMAT 0x101 141 | #define MSG_SETTIME 0x102 142 | #define MSG_SETPROFILE 0x103 143 | #define MSG_PWENCRYPT 0x104 144 | #define MSG_PWDECRYPT 0x105 145 | #define MSG_RESTART 0x106 146 | #define MSG_REMOUNTFS 0x107 147 | #define MSG_REG_CHECK 0x10d 148 | #define MSG_REG_WRITE 0x10e 149 | #define MSG_DEVICEKEY 0xad0be01 150 | 151 | #define EVT_INIT 21 152 | #define EVT_EXIT 22 153 | #define EVT_SHOW 23 154 | #define EVT_REPAINT 23 155 | #define EVT_HIDE 24 156 | #define EVT_KEYDOWN 25 157 | #define EVT_KEYPRESS 25 158 | #define EVT_KEYUP 26 159 | #define EVT_KEYRELEASE 26 160 | #define EVT_KEYREPEAT 28 161 | #define EVT_POINTERUP 29 162 | #define EVT_POINTERDOWN 30 163 | #define EVT_POINTERMOVE 31 164 | #define EVT_POINTERLONG 34 165 | #define EVT_POINTERHOLD 35 166 | #define EVT_ORIENTATION 32 167 | 168 | #define EVT_TOUCHUP 40 169 | #define EVT_TOUCHDOWN 41 170 | #define EVT_TOUCHMOVE 42 171 | 172 | #define EVT_SNAPSHOT 71 173 | #define EVT_FSCHANGED 72 174 | 175 | #define EVT_MP_STATECHANGED 81 176 | #define EVT_MP_TRACKCHANGED 82 177 | 178 | #define EVT_PREVPAGE 91 179 | #define EVT_NEXTPAGE 92 180 | #define EVT_OPENDIC 93 181 | 182 | #define EVT_TAB 119 183 | #define EVT_PANEL 120 184 | #define EVT_PANEL_ICON 121 185 | #define EVT_PANEL_TEXT 122 186 | #define EVT_PANEL_PROGRESS 123 187 | #define EVT_PANEL_MPLAYER 124 188 | #define EVT_PANEL_USBDRIVE 125 189 | #define EVT_PANEL_NETWORK 126 190 | #define EVT_PANEL_CLOCK 127 191 | #define EVT_PANEL_BLUETOOTH 128 192 | 193 | #define EVT_BT_RXCOMPLETE 171 194 | #define EVT_BT_TXCOMPLETE 172 195 | 196 | #define EVT_SYNTH_ENDED 200 197 | #define EVT_DIC_CLOSED 201 198 | 199 | #define ISKEYEVENT(x) ((x)>=25 && (x)<=28) 200 | #define ISPOINTEREVENT(x) (((x)>=29 && (x)<=31) || ((x)>=34 && (x)<=35)) 201 | #define ISPANELEVENT(x) ((x)>=119 && (x) <= 132) 202 | 203 | #undef KEY_UP 204 | #undef KEY_DOWN 205 | #undef KEY_LEFT 206 | #undef KEY_RIGHT 207 | #undef KEY_OK 208 | #undef KEY_BACK 209 | #undef KEY_MENU 210 | #undef KEY_DELETE 211 | #undef KEY_MUSIC 212 | #undef KEY_POWER 213 | #undef KEY_PREV 214 | #undef KEY_NEXT 215 | #undef KEY_MINUS 216 | #undef KEY_PLUS 217 | #undef KEY_0 218 | #undef KEY_1 219 | #undef KEY_2 220 | #undef KEY_3 221 | #undef KEY_4 222 | #undef KEY_5 223 | #undef KEY_6 224 | #undef KEY_7 225 | #undef KEY_8 226 | #undef KEY_9 227 | 228 | #define KEY_BACK 0x1b 229 | #define KEY_DELETE 0x08 230 | #define KEY_OK 0x0a 231 | #define KEY_UP 0x11 232 | #define KEY_DOWN 0x12 233 | #define KEY_LEFT 0x13 234 | #define KEY_RIGHT 0x14 235 | #define KEY_MINUS 0x15 236 | #define KEY_PLUS 0x16 237 | #define KEY_MENU 0x17 238 | #define KEY_MUSIC 0x1e 239 | #define KEY_POWER 0x01 240 | #define KEY_PREV 0x18 241 | #define KEY_NEXT 0x19 242 | #define KEY_PREV2 0x1c 243 | #define KEY_NEXT2 0x1d 244 | 245 | #define KEY_0 0x30 246 | #define KEY_1 0x31 247 | #define KEY_2 0x32 248 | #define KEY_3 0x33 249 | #define KEY_4 0x34 250 | #define KEY_5 0x35 251 | #define KEY_6 0x36 252 | #define KEY_7 0x37 253 | #define KEY_8 0x38 254 | #define KEY_9 0x39 255 | 256 | #define BLACK 0x000000 257 | #define DGRAY 0x555555 258 | #define LGRAY 0xaaaaaa 259 | #define WHITE 0xffffff 260 | 261 | #define ITEM_HEADER 1 262 | #define ITEM_ACTIVE 2 263 | #define ITEM_INACTIVE 3 264 | #define ITEM_SUBMENU 5 265 | #define ITEM_SEPARATOR 6 266 | #define ITEM_BULLET 7 267 | #define ITEM_HIDDEN 128 268 | 269 | #define KBD_NORMAL 0 270 | #define KBD_ENTEXT 1 271 | #define KBD_PHONE 2 272 | #define KBD_NUMERIC 4 273 | #define KBD_IPADDR 5 274 | #define KBD_FILENAME 6 275 | #define KBD_URL 7 276 | #define KBD_DATE 8 277 | #define KBD_TIME 9 278 | #define KBD_DATETIME 10 279 | #define KBD_HEX 11 280 | 281 | #define KBD_UPPER 0x10 282 | #define KBD_LOWER 0x20 283 | #define KBD_FIRSTUPPER 0x30 284 | 285 | #define KBD_PASSWORD 0x100 286 | #define KBD_NOSELECT 0x200 287 | #define KBD_SCREENTOP 0x400 288 | 289 | #define KBD_PASSEVENTS 0x8000 290 | 291 | #define ICON_INFORMATION 1 292 | #define ICON_QUESTION 2 293 | #define ICON_WARNING 3 294 | #define ICON_ERROR 4 295 | 296 | #define DEF_BUTTON1 0 297 | #define DEF_BUTTON2 0x1000 298 | 299 | #define PANELICON_BOOK ((const ibitmap *) -11) 300 | #define PANELICON_LOAD ((const ibitmap *) -12) 301 | 302 | #define LIST_BEGINPAINT 1 303 | #define LIST_PAINT 2 304 | #define LIST_ENDPAINT 3 305 | #define LIST_OPEN 4 306 | #define LIST_MENU 5 307 | #define LIST_DELETE 6 308 | #define LIST_EXIT 7 309 | #define LIST_ORIENTATION 8 310 | #define LIST_POINTER 9 311 | #define LIST_INFO 11 312 | #define LIST_SCROLL 12 313 | 314 | #define LISTFLAG_SCROLL 0x40000000 315 | 316 | #define BMK_CLOSED -1 317 | #define BMK_SELECTED 1 318 | #define BMK_ADDED 2 319 | #define BMK_REMOVED 3 320 | #define BMK_PAINT 4 321 | 322 | #define CFG_TEXT 1 323 | #define CFG_CHOICE 2 324 | #define CFG_INDEX 3 325 | #define CFG_TIME 4 326 | #define CFG_FONT 5 327 | #define CFG_FONTFACE 6 328 | #define CFG_INFO 7 329 | #define CFG_NUMBER 8 330 | #define CFG_ENTEXT 9 331 | #define CFG_PASSWORD 10 332 | #define CFG_IPADDR 11 333 | #define CFG_URL 12 334 | #define CFG_PHONE 13 335 | #define CFG_ACTIONS 14 336 | #define CFG_CUSTOM 30 337 | #define CFG_SUBMENU 31 338 | 339 | #define CFG_HIDDEN 128 340 | 341 | #define ALIGN_LEFT 1 342 | #define ALIGN_CENTER 2 343 | #define ALIGN_RIGHT 4 344 | #define ALIGN_FIT 8 345 | #define VALIGN_TOP 16 346 | #define VALIGN_MIDDLE 32 347 | #define VALIGN_BOTTOM 64 348 | #define ROTATE 128 349 | #define HYPHENS 256 350 | #define DOTS 512 351 | #define RTLAUTO 1024 352 | #define UNDERLINE 2048 353 | #define STRETCH 4096 354 | #define TILE 8192 355 | 356 | #define ARROW_LEFT 1 357 | #define ARROW_RIGHT 2 358 | #define ARROW_UP 3 359 | #define ARROW_DOWN 4 360 | #define SYMBOL_OK 5 361 | #define SYMBOL_PAUSE 6 362 | #define SYMBOL_BULLET 7 363 | #define ARROW_UPDOWN 8 364 | 365 | #define IMAGE_BW 1 366 | #define IMAGE_GRAY2 2 367 | #define IMAGE_GRAY4 4 368 | #define IMAGE_GRAY8 8 369 | #define IMAGE_RGB 24 370 | 371 | #define ROTATE0 0 372 | #define ROTATE90 1 373 | #define ROTATE270 2 374 | #define ROTATE180 3 375 | 376 | #define XMIRROR 4 377 | #define YMIRROR 8 378 | 379 | #define DITHER_THRESHOLD 0 380 | #define DITHER_PATTERN 1 381 | #define DITHER_DIFFUSION 2 382 | 383 | #define MP_STOPPED 0 384 | #define MP_REQUEST_FOR_PLAY 1 385 | #define MP_PLAYING 2 386 | #define MP_PAUSED 3 387 | #define MP_PREVTRACK 4 388 | #define MP_NEXTTRACK 5 389 | 390 | #define MP_ONCE 0 391 | #define MP_CONTINUOUS 1 392 | #define MP_RANDOM 2 393 | 394 | #define FTYPE_UNKNOWN 0 395 | #define FTYPE_BOOK 1 396 | #define FTYPE_PICTURE 2 397 | #define FTYPE_MUSIC 3 398 | #define FTYPE_APPLICATION 4 399 | #define FTYPE_WEBLINK 5 400 | #define FTYPE_FOLDER 255 401 | 402 | #define OB_ADDTOLAST 0x01 403 | #define OB_WITHRETURN 0x02 404 | #define OB_SOFTUPDATE 0x10 405 | 406 | #define NET_BLUETOOTH 0x0001 407 | #define NET_WIFI 0x0002 408 | #define NET_BTREADY 0x0100 409 | #define NET_WIFIREADY 0x0200 410 | #define NET_CONNECTED 0x0f00 411 | 412 | #define CONN_GPRS 1 413 | #define CONN_WIFI 2 414 | 415 | #define BLUETOOTH_OFF 0 416 | #define BLUETOOTH_HIDDEN 1 417 | #define BLUETOOTH_VISIBLE 2 418 | 419 | #define NET_OK 0 420 | #define NET_CONNECT 1 421 | #define NET_TRANSFER 2 422 | 423 | #define NET_FAIL -11 424 | #define NET_ABORTED -12 425 | #define NET_EINIT -13 426 | #define NET_EWRONGID -14 427 | #define NET_ENETWORK -15 428 | #define NET_EFILE -16 429 | #define NET_EPIPE -17 430 | #define NET_ETHREAD -18 431 | #define NET_EPROTO -19 432 | #define NET_EURL -20 433 | #define NET_ERESOLVE -21 434 | #define NET_ECONNECT -22 435 | #define NET_EACCESS -23 436 | #define NET_ENOTFOUND -24 437 | #define NET_EPARTIAL -25 438 | #define NET_EBROKEN -26 439 | #define NET_ETIMEOUT -27 440 | #define NET_ESERVER -28 441 | #define NET_EHTTP -29 442 | #define NET_EHARDWARE -30 443 | #define NET_ENOTCONF -31 444 | #define NET_EBADCONF -32 445 | #define NET_ENODEVICE -33 446 | #define NET_EPPP -34 447 | #define NET_EDISABLED -35 448 | 449 | #define GSENSOR_OFF 0 450 | #define GSENSOR_ON 1 451 | #define GSENSOR_INTR 2 452 | 453 | #define VN_NOPATH 0x01 454 | #define VN_NOESCAPE 0x02 455 | #define VN_ABSOLUTE 0x04 456 | #define VN_RELATIVE 0x08 457 | 458 | typedef struct irect_s { 459 | 460 | short x; 461 | short y; 462 | short w; 463 | short h; 464 | int flags; 465 | 466 | } irect; 467 | 468 | typedef struct ibitmap_s { 469 | 470 | unsigned short width; 471 | unsigned short height; 472 | unsigned short depth; 473 | unsigned short scanline; 474 | unsigned char data[]; 475 | 476 | } ibitmap; 477 | 478 | typedef int (*iv_handler)(int type, int par1, int par2); 479 | typedef void (*iv_timerproc)(); 480 | 481 | typedef void (*iv_menuhandler)(int index); 482 | typedef void (*iv_keyboardhandler)(char *text); 483 | typedef void (*iv_dialoghandler)(int button); 484 | typedef void (*iv_timeedithandler)(long newtime); 485 | typedef void (*iv_fontselecthandler)(char *fontr, char *fontb, char *fonti, char *fontbi); 486 | typedef void (*iv_dirselecthandler)(char *path); 487 | typedef void (*iv_confighandler)(); 488 | typedef void (*iv_itemchangehandler)(char *name); 489 | typedef void (*iv_pageselecthandler)(int page); 490 | typedef void (*iv_bmkhandler)(int action, int page, long long position); 491 | typedef void (*iv_tochandler)(long long position); 492 | typedef void (*iv_itempaint)(int x, int y, int index, int selected); 493 | typedef int (*iv_listhandler)(int action, int x, int y, int idx, int state); 494 | typedef void (*iv_rotatehandler)(int direction); 495 | typedef int (*iv_turnproc)(int direction); 496 | typedef int (*iv_recurser)(char *path, int type, void *data); 497 | 498 | typedef int (*iv_hashenumproc)(char *name, void *value, void *userdata); 499 | typedef int (*iv_hashcmpproc)(char *name1, void *value1, char *name2, void *value2); 500 | typedef void * (*iv_hashaddproc)(void *data); 501 | typedef void (*iv_hashdelproc)(void *data); 502 | 503 | typedef struct ihash_item_s { 504 | 505 | char *name; 506 | void *value; 507 | struct ihash_item_s *next; 508 | 509 | } ihash_item; 510 | 511 | typedef struct ihash_s { 512 | 513 | int prime; 514 | int count; 515 | iv_hashaddproc addproc; 516 | iv_hashdelproc delproc; 517 | struct ihash_item_s **items; 518 | 519 | } ihash; 520 | 521 | typedef struct imenu_s { 522 | 523 | short type; 524 | short index; 525 | char *text; 526 | struct imenu_s *submenu; 527 | 528 | } imenu; 529 | 530 | typedef struct icanvas_s { 531 | 532 | int width; 533 | int height; 534 | int scanline; 535 | int depth; 536 | int clipx1, clipx2; 537 | int clipy1, clipy2; 538 | unsigned char *addr; 539 | 540 | } icanvas; 541 | 542 | typedef struct ifont_s { 543 | 544 | char *name; 545 | char *family; 546 | int size; 547 | unsigned char aa; 548 | unsigned char isbold; 549 | unsigned char isitalic; 550 | unsigned char _r1; 551 | unsigned short charset; 552 | unsigned short _r2; 553 | int color; 554 | int height; 555 | int linespacing; 556 | int baseline; 557 | void *fdata; 558 | 559 | } ifont; 560 | 561 | typedef struct ievent_s { 562 | 563 | iv_handler hproc; 564 | unsigned short type; 565 | unsigned short _reserved; 566 | unsigned short par1; 567 | unsigned short par2; 568 | 569 | } ievent; 570 | 571 | typedef struct iconfig_s { 572 | 573 | char *filename; 574 | ihash *hash; 575 | ihash *vhash; 576 | int changed; 577 | 578 | } iconfig; 579 | 580 | typedef struct iconfigedit_s { 581 | 582 | int type; 583 | const ibitmap *icon; 584 | char *text; 585 | char *hint; 586 | char *name; 587 | char *deflt; 588 | char **variants; 589 | struct iconfigedit_s *submenu; 590 | 591 | } iconfigedit; 592 | 593 | typedef struct oldconfigedit_s { 594 | 595 | char *text; 596 | char *name; 597 | int type; 598 | char *deflt; 599 | char **variants; 600 | 601 | } oldconfigedit; 602 | 603 | typedef struct tocentry_s { 604 | 605 | int level; 606 | int page; 607 | long long position; 608 | char *text; 609 | 610 | } tocentry; 611 | 612 | typedef struct itimer_s { 613 | 614 | iv_timerproc tp; 615 | int weak; 616 | long long extime; 617 | char name[16]; 618 | 619 | } itimer; 620 | 621 | typedef struct bookinfo_s { 622 | 623 | int type; 624 | char *typedesc; 625 | char *path; 626 | char *filename; 627 | char *title; 628 | char *author; 629 | char *series; 630 | char *genre[10]; 631 | ibitmap *icon; 632 | int year; 633 | long size; 634 | time_t ctime; 635 | 636 | } bookinfo; 637 | 638 | typedef struct iv_filetype_s { 639 | 640 | char *extension; 641 | char *description; 642 | int type; 643 | char *program; 644 | ibitmap *icon; 645 | 646 | } iv_filetype; 647 | 648 | typedef struct iv_template_s { 649 | 650 | int width; 651 | int height; 652 | ibitmap *background; 653 | ibitmap *bg_folder; 654 | ibitmap *bg_folder_a; 655 | ibitmap *bg_file; 656 | ibitmap *bg_file_a; 657 | irect iconpos; 658 | irect mediaiconpos; 659 | irect line1pos; 660 | irect line2pos; 661 | irect line3pos; 662 | ifont *line1font; 663 | ifont *line2font; 664 | ifont *line3font; 665 | 666 | } iv_template; 667 | 668 | typedef struct iv_wlist_s { 669 | 670 | char *word; 671 | short x1; 672 | short y1; 673 | short x2; 674 | short y2; 675 | 676 | } iv_wlist; 677 | 678 | 679 | typedef struct iv_netinfo_s { 680 | 681 | int connected; 682 | char name[64]; 683 | char device[64]; 684 | char security[64]; 685 | char prefix[64]; 686 | int index; 687 | int atime; 688 | int speed; 689 | int reserved_0e; 690 | unsigned long bytes_in; 691 | unsigned long bytes_out; 692 | unsigned long packets_in; 693 | unsigned long packets_out; 694 | 695 | } iv_netinfo; 696 | 697 | typedef struct iv_sessioninfo_s { 698 | 699 | char *url; 700 | char *ctype; 701 | long response; 702 | int length; 703 | int progress; 704 | 705 | } iv_sessioninfo; 706 | 707 | typedef iv_wlist* (*pointer_to_word_hand_t)(int x, int y, int forward); 708 | 709 | void OpenScreen(); 710 | void OpenScreenExt(); 711 | void InkViewMain(iv_handler h); 712 | void CloseApp(); 713 | 714 | // Screen information 715 | 716 | int ScreenWidth(); 717 | int ScreenHeight(); 718 | 719 | // Orientation and g-sensor 720 | // Set screen orientation: 0=portrait, 1=landscape 90, 2=landscape 270, 3=portrait 180 721 | // For global settings: -1=auto (g-sensor) 722 | 723 | void SetOrientation(int n); 724 | void SetDefaultOrientation(int n); // Original pb apps prefer to use setDefaultOrientation (It's an undocumented function, found by reverse engineering) 725 | int GetOrientation(); 726 | void SetGlobalOrientation(int n); 727 | int GetGlobalOrientation(); 728 | int QueryGSensor(); 729 | void SetGSensor(int mode); 730 | int ReadGSensor(int *x, int *y, int *z); 731 | void CalibrateGSensor(); 732 | 733 | // Graphic functions. Color=0x00RRGGBB 734 | 735 | void ClearScreen(); 736 | void SetClip(int x, int y, int w, int h); 737 | void DrawPixel(int x, int y, int color); 738 | void DrawLine(int x1, int y1, int x2, int y2,int color); 739 | void DrawRect(int x, int y, int w, int h, int color); 740 | void FillArea(int x, int y, int w, int h, int color); 741 | void InvertArea(int x, int y, int w, int h); 742 | void InvertAreaBW(int x, int y, int w, int h); 743 | void DimArea(int x, int y, int w, int h, int color); 744 | void DrawSelection(int x, int y, int w, int h, int color); 745 | void DitherArea(int x, int y, int w, int h, int levels, int method); 746 | void Stretch(const unsigned char *src, int format, int sw, int sh, int scanline, int dx, int dy, int dw, int dh, int rotate); 747 | void SetCanvas(icanvas *c); 748 | icanvas *GetCanvas(); 749 | void Repaint(); 750 | 751 | // Bitmap functions 752 | 753 | ibitmap *LoadBitmap(const char *filename); 754 | int SaveBitmap(const char *filename, ibitmap *bm); 755 | ibitmap *BitmapFromScreen(int x, int y, int w, int h); 756 | ibitmap *BitmapFromScreenR(int x, int y, int w, int h, int rotate); 757 | ibitmap *NewBitmap(int w, int h); 758 | ibitmap *LoadJPEG(const char *path, int w, int h, int br, int co, int proportional); 759 | void DrawBitmap(int x, int y, const ibitmap *b); 760 | void DrawBitmapArea(int x, int y, const ibitmap *b, int bx, int by, int bw, int bh); 761 | void DrawBitmapRect(int x, int y, int w, int h, ibitmap *b, int flags); 762 | void DrawBitmapRect2(irect *rect, ibitmap *b); 763 | void StretchBitmap(int x, int y, int w, int h, const ibitmap *src, int flags); 764 | void TileBitmap(int x, int y, int w, int h, const ibitmap *src); 765 | ibitmap *CopyBitmap(const ibitmap *bm); 766 | void MirrorBitmap(ibitmap *bm, int m); 767 | 768 | // Text functions 769 | 770 | char **EnumFonts(); 771 | ifont *OpenFont(const char *name, int size, int aa); 772 | void CloseFont(ifont *f); 773 | void SetFont(ifont *font, int color); 774 | void DrawString(int x, int y, const char *s); 775 | void DrawStringR(int x, int y, const char *s); 776 | int TextRectHeight(int width, const char *s, int flags); 777 | char *DrawTextRect(int x, int y, int w, int h, const char *s, int flags); 778 | char *DrawTextRect2(irect *rect, const char *s); 779 | int CharWidth(unsigned short c); 780 | int StringWidth(const char *s); 781 | int DrawSymbol(int x, int y, int symbol); 782 | void RegisterFontList(ifont **fontlist, int count); 783 | void SetTextStrength(int n); 784 | 785 | // Screen update functions 786 | 787 | void FullUpdate(); 788 | void SoftUpdate(); 789 | void PartialUpdate(int x, int y, int w, int h); 790 | void PartialUpdateBW(int x, int y, int w, int h); 791 | void DynamicUpdateBW(int x, int y, int w, int h); 792 | void FineUpdate(); 793 | void DynamicUpdate(); 794 | int FineUpdateSupported(); 795 | 796 | // Event handling functions 797 | 798 | iv_handler SetEventHandler(iv_handler hproc); 799 | iv_handler SetEventHandlerEx(iv_handler hproc); 800 | iv_handler GetEventHandler(); 801 | void SendEvent(iv_handler hproc, int type, int par1, int par2); 802 | void FlushEvents(); 803 | 804 | // Timer functions 805 | 806 | void SetHardTimer(const char *name, iv_timerproc tproc, int ms); 807 | void SetWeakTimer(const char *name, iv_timerproc tproc, int ms); 808 | long long QueryTimer(iv_timerproc tp); 809 | void ClearTimer(iv_timerproc tproc); 810 | 811 | // UI functions 812 | 813 | void OpenMenu(imenu *menu, int pos, int x, int y, iv_menuhandler hproc); 814 | void OpenMenu3x3(const ibitmap *mbitmap, const char *strings[9], iv_menuhandler hproc); 815 | void OpenList(const char *title, const ibitmap *background, int itemw, int itemh, int itemcount, int cpos, iv_listhandler hproc); 816 | void OpenDummyList(const char *title, const ibitmap *background, char *text, iv_listhandler hproc); 817 | char **EnumKeyboards(); 818 | void LoadKeyboard(const char *kbdlang); 819 | void OpenKeyboard(const char *title, char *buffer, int maxlen, int flags, iv_keyboardhandler hproc); 820 | void OpenCustomKeyboard(const char *filename, const char *title, char *buffer, int maxlen, int flags, iv_keyboardhandler hproc); 821 | void CloseKeyboard(); 822 | void OpenPageSelector(iv_pageselecthandler hproc); 823 | void OpenTimeEdit(const char *title, int x, int y, long intime, iv_timeedithandler hproc); 824 | void OpenDirectorySelector(const char *title, char *buf, int len, iv_dirselecthandler hproc); 825 | void OpenFontSelector(const char *title, const char *font, int with_size, iv_fontselecthandler hproc); 826 | void OpenBookmarks(int page, long long position, int *bmklist, long long *poslist, 827 | int *bmkcount, int maxbmks, iv_bmkhandler hproc); 828 | void SwitchBookmark(int page, long long position, int *bmklist, long long *poslist, 829 | int *bmkcount, int maxbmks, iv_bmkhandler hproc); 830 | void OpenContents(tocentry *toc, int count, long long position, iv_tochandler hproc); 831 | void OpenRotateBox(iv_rotatehandler hproc); 832 | void Message(int icon, const char *title, const char *text, int timeout); 833 | void Dialog(int icon, const char *title, const char *text, const char *button1, const char *button2, iv_dialoghandler hproc); 834 | void CloseDialog(); 835 | void OpenProgressbar(int icon, const char *title, const char *text, int percent, iv_dialoghandler hproc); 836 | int UpdateProgressbar(const char *text, int percent); 837 | void CloseProgressbar(); 838 | void ShowHourglass(); 839 | void ShowHourglassAt(int x, int y); 840 | void HideHourglass(); 841 | void DisableExitHourglass(); 842 | void SetPanelType(int type); 843 | int DrawPanel(const ibitmap *icon, const char *text, const char *title, int percent); 844 | int DrawTabs(const ibitmap *icon, int current, int total); 845 | int PanelHeight(); 846 | void SetKeyboardRate(int t1, int t2); 847 | 848 | // Configuration functions 849 | 850 | iconfig * GetGlobalConfig(); 851 | iconfig * OpenConfig(const char *path, iconfigedit *ce); 852 | int SaveConfig(iconfig *cfg); 853 | void CloseConfig(iconfig *cfg); 854 | int ReadInt(iconfig *cfg, const char *name, int deflt); 855 | char *ReadString(iconfig *cfg, const char *name, const char *deflt); 856 | char *ReadSecret(iconfig *cfg, const char *name, const char *deflt); 857 | void WriteInt(iconfig *cfg, const char *name, int value); 858 | void WriteString(iconfig *cfg, const char *name, const char *value); 859 | void WriteSecret(iconfig *cfg, const char *name, const char *value); 860 | void WriteIntVolatile(iconfig *cfg, const char *name, int value); 861 | void WriteStringVolatile(iconfig *cfg, const char *name, const char *value); 862 | void DeleteInt(iconfig *cfg, const char *name); 863 | void DeleteString(iconfig *cfg, const char *name); 864 | void OpenConfigEditor(const char *header, iconfig *cfg, iconfigedit *ce, iv_confighandler hproc, iv_itemchangehandler cproc); 865 | void OpenConfigSubmenuExt(const char *title, iconfigedit *ice, int pos); 866 | void OpenConfigSubmenu(const char *title, iconfigedit *ice); 867 | void UpdateCurrentConfigPage(); 868 | void UpdateConfigPage(const char *title, iconfigedit *ice); 869 | void CloseConfigLevel(); 870 | void GetKeyMapping(char *act0[], char *act1[]); 871 | unsigned long QueryDeviceButtons(); 872 | 873 | // String hash functions 874 | 875 | ihash * hash_new(int prime); 876 | void hash_add(ihash *h, const char *name, const char *value); 877 | void hash_delete(ihash *h, const char *name); 878 | char *hash_find(ihash *h, const char *name); 879 | 880 | // Object hash functions 881 | 882 | ihash * vhash_new(int prime, iv_hashaddproc addproc, iv_hashdelproc delproc); 883 | void vhash_add(ihash *h, const char *name, const void *value); 884 | void vhash_delete(ihash *h, const char *name); 885 | void *vhash_find(ihash *h, const char *name); 886 | 887 | // Common hash functions 888 | 889 | void hash_clear(ihash *h); 890 | void hash_destroy(ihash *h); 891 | int hash_count(ihash *h); 892 | void hash_enumerate(ihash *h, iv_hashcmpproc cmpproc, iv_hashenumproc enumproc, void *userdata); 893 | 894 | // filesystem functions 895 | 896 | int iv_stat(const char *name, struct stat *st); 897 | int iv_access(const char *pathname, int mode); 898 | FILE *iv_fopen(const char *name, const char *mode); 899 | int iv_fread(void *buffer, int size, int count, FILE *f); 900 | int iv_fwrite(const void *buffer, int size, int count, FILE *f); 901 | int iv_fseek(FILE *f, long offset, int whence); 902 | long iv_ftell(FILE *f); 903 | int iv_fclose(FILE *f); 904 | int iv_fgetc(FILE *f); 905 | char *iv_fgets(char *string, int n, FILE *f); 906 | int iv_mkdir(const char *pathname, mode_t mode); 907 | void iv_buildpath(const char *filename); 908 | DIR *iv_opendir(const char *dirname); 909 | struct dirent *iv_readdir(DIR *dir); 910 | int iv_closedir(DIR *dir); 911 | int iv_unlink(const char *name); 912 | int iv_rmdir(const char *name); 913 | int iv_truncate(const char *name, int length); 914 | int iv_rename(const char *oldname, const char *newname); 915 | void iv_preload(const char *name, int count); 916 | void iv_sync(); 917 | int iv_validate_name(const char *s, int flags); 918 | 919 | // ipc functions 920 | 921 | long iv_ipc_request(long type, long attr, unsigned char *data, int inlen, int outlen); 922 | long iv_ipc_cmd(long type, long param); 923 | 924 | // Language functions 925 | 926 | char ** EnumLanguages(); 927 | void LoadLanguage(const char *lang); 928 | void AddTranslation(const char *label, const char *trans); 929 | char *GetLangText(const char *s); 930 | char *GetLangTextF(const char *s, ...); 931 | void SetRTLBook(int rtl); 932 | int IsRTL(); // depends only on the system language 933 | int IsBookRTL(); // can be overwritten by application 934 | 935 | #define T(x) GetLangText(#x) 936 | #define TF(x...) GetLangTextF(x) 937 | 938 | // User profile functions 939 | 940 | char **EnumProfiles(); 941 | int GetProfileType(const char *name); 942 | int CreateProfile(const char *name, int type); 943 | int RenameProfile(const char *oldname, const char *newname); 944 | int DeleteProfile(const char *name); 945 | char *GetCurrentProfile(); 946 | void SetCurrentProfile(const char *name, int flags); 947 | void OpenProfileSelector(); 948 | 949 | // Theme functions 950 | 951 | char ** EnumThemes(); 952 | void OpenTheme(const char *path); 953 | ibitmap *GetResource(const char *name, const ibitmap *deflt); 954 | int GetThemeInt(const char *name, int deflt); 955 | char *GetThemeString(const char *name, const char *deflt); 956 | ifont *GetThemeFont(const char *name, const char *deflt); 957 | void GetThemeRect(const char *name, irect *rect, int x, int y, int w, int h, int flags); 958 | 959 | // Book functions 960 | 961 | iv_filetype *GetSupportedFileTypes(); 962 | bookinfo *GetBookInfo(const char *name); 963 | ibitmap *GetBookCover(const char *name, int width, int height); 964 | char *GetAssociatedFile(const char *name, int index); 965 | char *CheckAssociatedFile(const char *name, int index); 966 | void SetReadMarker(const char *name, int isread); 967 | iv_filetype *FileType(const char *path); 968 | void SetFileHandler(const char *path, const char *handler); 969 | char *GetFileHandler(const char *path); 970 | void OpenBook(const char *path, const char *position, int flags); 971 | void BookReady(const char *path); 972 | char **GetLastOpen(); 973 | void AddLastOpen(const char *path); 974 | void OpenLastBooks(); 975 | 976 | // Media functions 977 | 978 | void OpenPlayer(); 979 | void PlayFile(const char *filename); 980 | void LoadPlaylist(char **pl); 981 | char **GetPlaylist(); 982 | void PlayTrack(int n); 983 | void PreviousTrack(); 984 | void NextTrack(); 985 | int GetCurrentTrack(); 986 | int GetTrackSize(); 987 | void SetTrackPosition(int pos); 988 | int GetTrackPosition(); 989 | void SetPlayerState(int state); 990 | int GetPlayerState(); 991 | void SetPlayerMode(int mode); 992 | int GetPlayerMode(); 993 | void TogglePlaying(); 994 | void SetVolume(int n); 995 | int GetVolume(); 996 | void SetEqualizer(int *eq); 997 | void GetEqualizer(int *eq); 998 | 999 | // Notepad functions 1000 | 1001 | char **EnumNotepads(); 1002 | void OpenNotepad(const char *name); 1003 | void CreateNote(const char *filename, const char *title, long long position); 1004 | void CreateNoteFromImages(const char *filename, const char *title, long long position, ibitmap *img1, ibitmap *img2); 1005 | void CreateNoteFromPage(const char *filename, const char *title, long long position); 1006 | void CreateEmptyNote(const char *text); 1007 | void OpenNotesMenu(const char *filename, const char *title, long long position); 1008 | 1009 | // Dictionary functions 1010 | 1011 | char **EnumDictionaries(); 1012 | int OpenDictionary(const char *name); 1013 | void CloseDictionary(); 1014 | int LookupWord(const char *what, char **word, char **trans); 1015 | int LookupWordExact(const char *what, char **word, char **trans); 1016 | int LookupPrevious(char **word, char **trans); 1017 | int LookupNext(char **word, char **trans); 1018 | void OpenDictionaryView(iv_wlist *wordlist, const char *dicname); 1019 | void OpenControlledDictionaryView(pointer_to_word_hand_t pointer_handler, iv_wlist *wordlist, const char *dicname); 1020 | 1021 | // Text reflow API 1022 | 1023 | void iv_reflow_start(int x, int y, int w, int h, int scale); 1024 | void iv_reflow_bt(); 1025 | void iv_reflow_et(); 1026 | void iv_reflow_div(); 1027 | void iv_reflow_addchar(int code, int x, int y, int w, int h); 1028 | void iv_reflow_addimage(int x, int y, int w, int h, int flags); 1029 | int iv_reflow_subpages(); 1030 | void iv_reflow_render(int spnum); 1031 | int iv_reflow_getchar(int *x, int *y); 1032 | int iv_reflow_getimage(int *x, int *y, int *scale); 1033 | int iv_reflow_words(); 1034 | char *iv_reflow_getword(int n, int *spnum, int *x, int *y, int *w, int *h); 1035 | void iv_reflow_clear(); 1036 | 1037 | // Additional functions 1038 | void iv_sleepmode(int on); 1039 | int GetSleepmode(); 1040 | int GetBatteryPower(); 1041 | int GetTemperature(); 1042 | int IsCharging(); 1043 | int IsUSBconnected(); 1044 | int IsSDinserted(); 1045 | int IsPlayingMP3(); 1046 | int IsKeyPressed(int key); 1047 | char *GetDeviceModel(); 1048 | char *GetHardwareType(); 1049 | char *GetSoftwareVersion(); 1050 | int GetHardwareDepth(); 1051 | char *GetSerialNumber(); 1052 | char *GetWaveformFilename(); 1053 | char *GetDeviceKey(); 1054 | unsigned char *GetDeviceFingerprint(); 1055 | char *CurrentDateStr(); 1056 | char *DateStr(time_t t); 1057 | int GoSleep(int ms, int deep); 1058 | void SetAutoPowerOff(int en); 1059 | void PowerOff(); 1060 | int SafeMode(); 1061 | void OpenMainMenu(); 1062 | int WriteStartupLogo(const ibitmap *bm); 1063 | int PageSnapshot(); 1064 | int RestoreStartupLogo(); 1065 | int QueryTouchpanel(); 1066 | void CalibrateTouchpanel(); 1067 | void OpenCalendar(); 1068 | 1069 | int QueryNetwork(); 1070 | char *GetHwAddress(); 1071 | int GetBluetoothMode(); 1072 | int SetBluetoothMode(int mode, int flags); 1073 | char **EnumBTdevices(); 1074 | void OpenBTdevicesMenu(char *title, int x, int y, iv_itemchangehandler hproc); 1075 | int BtSendFiles(char *mac, char **files); 1076 | char **EnumWirelessNetworks(); 1077 | char **EnumConnections(); 1078 | int GetBTservice(const char *mac, const char *service); 1079 | int NetConnect(const char *name); 1080 | int NetDisconnect(); 1081 | void OpenNetworkInfo(); 1082 | void *QuickDownload(const char *url, int *retsize, int timeout); 1083 | int NewSession(); 1084 | void CloseSession(int id); 1085 | void SetUserAgent(int id, const char *ua); 1086 | void SetProxy(int id, const char *host, int port, const char *user, const char *pass); 1087 | int Download(int id, const char *url, const char *postdata, FILE **fp, int timeout); 1088 | int DownloadTo(int id, const char *url, const char *postdata, const char *filename, int timeout); 1089 | int GetSessionStatus(int id); 1090 | char * GetHeader(int id, const char *name); 1091 | iv_sessioninfo *GetSessionInfo(int id); 1092 | void PauseTransfer(int id); 1093 | void ResumeTransfer(int id); 1094 | void AbortTransfer(int id); 1095 | char *NetError(int e); 1096 | void NetErrorMessage(int e); 1097 | 1098 | 1099 | int iv_strcmp(const char *s1, const char *s2); 1100 | int iv_strncmp(const char *s1, const char *s2, size_t n); 1101 | int iv_strcasecmp(const char *s1, const char *s2); 1102 | int iv_strncasecmp(const char *s1, const char *s2, size_t n); 1103 | int escape(const char *val, char *buf, int size); 1104 | int unescape(const char *val, char *buf, int size); 1105 | void trim_right(char *s); 1106 | unsigned short *get_encoding_table(const char *enc); 1107 | int convert_to_utf(const char *src, char *dest, int destsize, const char *enc); 1108 | int utf2ucs(const char *s, unsigned short *us, int maxlen); 1109 | int utf2ucs4(const char *s, unsigned int *us, int maxlen); 1110 | int ucs2utf(const unsigned short *us, char *s, int maxlen); 1111 | int utfcasecmp(const char *sa, const char *sb); 1112 | int utfncasecmp(const char *sa, const char *sb, int n); 1113 | char *utfcasestr(const char *sa, const char *sb); 1114 | void utf_toupper(char *s); 1115 | void utf_tolower(char *s); 1116 | void md5sum(const unsigned char *data, int len, unsigned char *digest); 1117 | int base64_encode(const unsigned char *in, int len, char *out); 1118 | int base64_decode(const char *in, unsigned char *out, int len); 1119 | int copy_file(const char *src, const char *dst); 1120 | int move_file(const char *src, const char *dst); 1121 | int copy_file_with_af(const char *src, const char *dst); 1122 | int move_file_with_af(const char *src, const char *dst); 1123 | int unlink_file_with_af(const char *name); 1124 | int recurse_action(const char *path, iv_recurser proc, void *data, int creative, int this_too); 1125 | 1126 | // dialog show on the screen 1127 | int GetDialogShow(); // 1 - dialog showing, 0 - dialog hidden. 1128 | 1129 | #ifdef __cplusplus 1130 | } 1131 | #endif 1132 | 1133 | #endif 1134 | 1135 | --------------------------------------------------------------------------------