fixes for libnice and editDistance
This commit is contained in:
parent
42392bb90f
commit
dd51386030
7 changed files with 169 additions and 139 deletions
|
|
@ -31,7 +31,12 @@ Array types. In the past we used that names to indicate array parameters, it was
|
|||
it was ugly using names to indicates data types. So we fixed that. And we have added some better support for
|
||||
GList parameter. GLists are now converted to Nim seqs and vice versa. Not everywhere still, and this conversion
|
||||
is still untested, as GList parameters are used most of the time in exotic functions only. Another change is that
|
||||
we have support for libnice by a request of a user from Japan. We added the sdp_example.nim converted from
|
||||
we have support for libnice by a request of a user from Japan now. As he intents to use libnice on Windows 8.1
|
||||
with only glib and gobject installed, but with no gtk installed, we had to break module gimpl.nim
|
||||
into two units called gimplgobj.nim and gimplgtk.nim, and we added a module called dummygtk.nim
|
||||
which can be imported to make the connect() macro available while a real gtk module is not available.
|
||||
Please let us know if these changes should break something for ordinary gtk users.
|
||||
To test libnice we added the sdp_example.nim converted from
|
||||
a C example, it seems to compile and run. And finally with v0.8.3 the examples from the GTK4 book should work.
|
||||
For the GTK3 examples we had to do some minimal fixes, so you may have to do similar fixes for your own code as well.
|
||||
For gintro/examples/gtk3 this was
|
||||
|
|
|
|||
|
|
@ -9,12 +9,22 @@
|
|||
# ./sdp-example 0 $(host -4 -t A stun.stunprotocol.org | awk '{ print $4 }')
|
||||
# ./sdp-example 1 $(host -4 -t A stun.stunprotocol.org | awk '{ print $4 }')
|
||||
|
||||
import gintro/[gtk, glib, gobject, nice]
|
||||
import gintro/gio except stdin
|
||||
|
||||
# https://forum.nim-lang.org/t/3752
|
||||
when (compiles do: import gintro/gtk):
|
||||
import gintro/[gtk, glib, gobject, gio, nice]
|
||||
else:
|
||||
import gintro/[dummygtk, glib, gobject, gio, nice] # For windows with glib but no gtk
|
||||
|
||||
from strutils import `%`
|
||||
from os import paramCount, paramStr
|
||||
from strutils import parseInt
|
||||
|
||||
when defined(windows):
|
||||
import winlean
|
||||
else:
|
||||
discard # import posix
|
||||
|
||||
var
|
||||
gloop: glib.MainLoop
|
||||
stunAddr: string
|
||||
|
|
@ -70,7 +80,7 @@ proc cbComponentStateChanged(agent: nice.Agent; streamID: int; componentID: int;
|
|||
glib.quit(gloop)
|
||||
|
||||
# proc nice_agent_attach_recv*(self: ptr Agent00; streamID: cuint; componentID: cuint; ctx: ptr glib.MainContext;
|
||||
# fn: AgentRecvFunc; data: pointer): gboolean {.importc, libprag.}
|
||||
# fn: AgentRecvFunc; data: pointer): gboolean {.importc, libprag.}
|
||||
#
|
||||
# this has to be a low level function!
|
||||
# AgentRecvFunc* = proc (agent: ptr Agent00; streamId: uint32; componentId: uint32; len: uint32;
|
||||
|
|
@ -89,10 +99,13 @@ proc exampleThread(data: pointer): pointer {.cdecl.} =
|
|||
line: string
|
||||
sdp: string
|
||||
sdp64: string
|
||||
#when defined(G_OS_WIN32):
|
||||
# io_stdin = g_io_channel_win32_new_fd(_fileno(stdin))
|
||||
#else:
|
||||
ioStdin = unixNew(getFileHandle(stdin))
|
||||
|
||||
# https://gist.github.com/demotomohiro/c9d9ad7e17639c6acb9bd2be7c204f3f
|
||||
when hostOS == "windows":
|
||||
ioStdin = win32NewFd(system.stdin.getFileHandle)
|
||||
else:
|
||||
ioStdin = unixNew(system.stdin.getFileHandle)
|
||||
|
||||
discard setFlags(ioStdin, glib.IOFlags.nonBlock)
|
||||
# Create the nice agent
|
||||
agent = nice.newAgent(glib.getContext(gloop), nice.CompatibilityRfc5245)
|
||||
|
|
@ -141,8 +154,7 @@ proc exampleThread(data: pointer): pointer {.cdecl.} =
|
|||
var s: IOStatus = readLine(ioStdin, line, length, terminatorPos)
|
||||
if s == IOStatus.normal:
|
||||
var sdpLen: uint64
|
||||
let sdpxxx = base64Decode(line, sdpLen) #seq[uint8]
|
||||
sdp = cast[string](sdpxxx)
|
||||
let sdp = cast[string](base64Decode(line, sdpLen)) #seq[uint8]
|
||||
# Parse remote candidate list and set it on the agent
|
||||
if sdp.len > 0 and parseRemoteSdp(agent, sdp) > 0:
|
||||
break
|
||||
|
|
@ -183,9 +195,9 @@ proc exampleThread(data: pointer): pointer {.cdecl.} =
|
|||
return nil
|
||||
|
||||
proc main =
|
||||
echo paramCount()
|
||||
for i in 0 .. paramCount():
|
||||
echo paramStr(i)
|
||||
#echo paramCount()
|
||||
#for i in 0 .. paramCount():
|
||||
# echo paramStr(i)
|
||||
let argc = paramCount() + 1
|
||||
var argv = newSeq[string](argc)
|
||||
for i in 0 ..< argc:
|
||||
|
|
|
|||
6
gintro/dummygtk.nim
Normal file
6
gintro/dummygtk.nim
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import gobject
|
||||
import macros, strutils
|
||||
|
||||
include gisup3
|
||||
include gimplgobj
|
||||
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#from sequtils import keepItIf
|
||||
import sequtils
|
||||
import macros, sequtils
|
||||
from strutils import startsWith, replace
|
||||
const RecSep = "!" # Record separator for entries in gisup.nim, also defined in gen.nim
|
||||
|
||||
# caution: $$ due to string interpolation
|
||||
|
|
@ -359,122 +360,6 @@ $1($4)
|
|||
""" % [$procName, ats, $procNameCdecl, $arg]
|
||||
result = parseStmt(r1s & r2s)
|
||||
|
||||
###################################################
|
||||
# 362 lines
|
||||
|
||||
### CellDataFunc,
|
||||
# see https://developer.gnome.org/gtk3/stable/GtkTreeViewColumn.html#gtk-tree-view-column-set-cell-data-func
|
||||
|
||||
# the low level GTK interface:
|
||||
# proc cellDataFunc(column00: ptr TreeViewColumn00; renderer00: ptr CellRenderer00;
|
||||
# model00: ptr TreeModel00; iter: TreeIter; data: pointer) {.cdecl.}
|
||||
|
||||
# unset -- the macro can do this already
|
||||
proc unsetCellDataFunc*(column: TreeViewColumn; renderer: CellRenderer) =
|
||||
setCellDataFunc(column, renderer, nil, nil, nil)
|
||||
|
||||
# set a function with this parameter list and one more optional argument
|
||||
# proc cellDataFunc(column: TreeViewColumn; renderer: CellRenderer; model: TreeModel; iter: TreeIter)
|
||||
# if there is no optional arg, then we make it a pointer with nil value.
|
||||
# if arg is a ref, then we apply GC_ref() and pass it
|
||||
# if arg is a ptr, then we pass it. (but we never free that object)
|
||||
# if arg is a value type, then we replace it with a copy of a ref type to guaranty lifetime
|
||||
macro setCellDataFunc*(column: TreeViewColumn; renderer: CellRenderer; fn: untyped = nil; arg: typed = nil): untyped =
|
||||
|
||||
if fn == nil: # unset
|
||||
result = parseStmt("setCellDataFunc($1, $2, nil, nil, nil)" % [$column, $renderer])
|
||||
return
|
||||
|
||||
var CdfID {.compileTime, global.}: int # unique id for our generated cell data functions
|
||||
inc(CdfID)
|
||||
var ats: string # the type of optional argument as string (arg type string)
|
||||
var argStr: string # the value of optional argument as string
|
||||
var atsfix: string # we have to prefix with "ref " if arg is avalue type
|
||||
if arg == nil: # no optional argument, so fake a nil pointer
|
||||
argStr = "nil"
|
||||
ats = "pointer"
|
||||
else:
|
||||
argStr = $(arg.toStrLit)
|
||||
ats = $getTypeInst(arg).toStrLit
|
||||
|
||||
if getTypeInst(arg).typeKind != ntyRef and getTypeInst(arg).typeKind != ntyPtr:
|
||||
atsFix = "ref "
|
||||
|
||||
let procName = "celldatafunc_" & $CdfID # our init code
|
||||
let procNameCdecl = "celldatafunc_cdecl_" & $CdfID # the proc that is called from GTK
|
||||
var procNameDestroy: string # the proc that GTK calls when we unset the cellDataFunc
|
||||
# first we generate the destroy proc
|
||||
var r0s: string
|
||||
|
||||
# GTK should unref the optional argument later, so we generate a destroy proc which GTK can call
|
||||
if arg != nil and getTypeInst(arg).typeKind != ntyPtr:
|
||||
procNameDestroy = "celldatafunc_destroy" & $CdfID
|
||||
r0s ="""
|
||||
proc $1(p: pointer) {.cdecl.} =
|
||||
# echo "GC_Unref(arg)"
|
||||
GC_Unref(cast[$2](p))
|
||||
""" % [$procNameDestroy, atsFix & ats]
|
||||
else:
|
||||
procNameDestroy = "nil"
|
||||
r0s = ""
|
||||
|
||||
# now we generate the proc which GTK will call for each cell of the treeview. g_object_get_qdata() is
|
||||
# the GTK function which retrieves the Nim proxy objects from the plain GTK data objects.
|
||||
var r1s = """
|
||||
proc $1(column00: ptr TreeViewColumn00; renderer00: ptr CellRenderer00;
|
||||
model00: ptr TreeModel00; iter: TreeIter; pdata: pointer) {.cdecl.} =
|
||||
let column = cast[TreeViewColumn](g_object_get_qdata(column00, Quark))
|
||||
let renderer = cast[CellRenderer](g_object_get_qdata(renderer00, Quark))
|
||||
let model = cast[TreeModel](g_object_get_qdata(model00, Quark))
|
||||
""" % [$procNameCdecl]
|
||||
if arg == nil:
|
||||
r1s.add """
|
||||
$1(column, renderer, model, iter) # call the user provided Nim proc
|
||||
""" % [$fn]
|
||||
elif getTypeInst(arg).typeKind == ntyRef or getTypeInst(arg).typeKind == ntyPtr:
|
||||
r1s.add """
|
||||
let a = cast[$2](pdata)
|
||||
$1(column, renderer, model, iter, a) # call the user provided Nim proc
|
||||
""" % [$fn, ats]
|
||||
else: # arg was a value type, but we pass a copy of ref type
|
||||
r1s.add """
|
||||
let a = cast[ref $2](pdata)[]
|
||||
$1(column, renderer, model, iter, a) # call the user provided Nim proc
|
||||
""" % [$fn, ats]
|
||||
|
||||
# this is basically only a code block which is called for initialization, mostly
|
||||
# making a deep copy of optional argument when argumant is not a ref
|
||||
var r2s: string
|
||||
if arg == nil:
|
||||
r2s ="""
|
||||
proc $1(column: TreeViewColumn; renderer: CellRenderer; pdata: $2) =
|
||||
setCellDataFunc($3, $4, $5, nil, nil)
|
||||
$1(column, renderer, $6)
|
||||
""" % [$procName, ats, $column, $renderer, $procNameCdecl, argStr, $procNameDestroy]
|
||||
elif getTypeInst(arg).typeKind == ntyPtr:
|
||||
r2s ="""
|
||||
proc $1(column: TreeViewColumn; renderer: CellRenderer; pdata: $2) =
|
||||
setCellDataFunc($3, $4, $5, cast[pointer](pdata), $7)
|
||||
$1(column, renderer, $6)
|
||||
""" % [$procName, ats, $column, $renderer, $procNameCdecl, argStr, $procNameDestroy]
|
||||
elif getTypeInst(arg).typeKind == ntyRef:
|
||||
r2s ="""
|
||||
proc $1(column: TreeViewColumn; renderer: CellRenderer; pdata: $2) =
|
||||
if not pdata.isNil: # or pdata is pointer):
|
||||
GC_ref(pdata)
|
||||
setCellDataFunc($3, $4, $5, cast[pointer](pdata), $7)
|
||||
$1(column, renderer, $6)
|
||||
""" % [$procName, ats, $column, $renderer, $procNameCdecl, argStr, $procNameDestroy]
|
||||
else: # arg is value object
|
||||
r2s ="""
|
||||
proc $1(column: TreeViewColumn; renderer: CellRenderer; pdata: $2) =
|
||||
var ar: ref $2
|
||||
new(ar)
|
||||
#deepCopy(ar[], pdata)
|
||||
ar[] = pdata
|
||||
GC_ref(ar)
|
||||
setCellDataFunc($3, $4, $5, cast[pointer](ar), $7)
|
||||
$1(column, renderer, $6)
|
||||
""" % [$procName, ats, $column, $renderer, $procNameCdecl, argStr, $procNameDestroy]
|
||||
|
||||
result = parseStmt(r0s & r1s & r2s)
|
||||
# 429 lines echo
|
||||
117
gintro/gimplgtk.nim
Normal file
117
gintro/gimplgtk.nim
Normal file
|
|
@ -0,0 +1,117 @@
|
|||
### CellDataFunc,
|
||||
# see https://developer.gnome.org/gtk3/stable/GtkTreeViewColumn.html#gtk-tree-view-column-set-cell-data-func
|
||||
|
||||
# the low level GTK interface:
|
||||
# proc cellDataFunc(column00: ptr TreeViewColumn00; renderer00: ptr CellRenderer00;
|
||||
# model00: ptr TreeModel00; iter: TreeIter; data: pointer) {.cdecl.}
|
||||
|
||||
# unset -- the macro can do this already
|
||||
proc unsetCellDataFunc*(column: TreeViewColumn; renderer: CellRenderer) =
|
||||
setCellDataFunc(column, renderer, nil, nil, nil)
|
||||
|
||||
# set a function with this parameter list and one more optional argument
|
||||
# proc cellDataFunc(column: TreeViewColumn; renderer: CellRenderer; model: TreeModel; iter: TreeIter)
|
||||
# if there is no optional arg, then we make it a pointer with nil value.
|
||||
# if arg is a ref, then we apply GC_ref() and pass it
|
||||
# if arg is a ptr, then we pass it. (but we never free that object)
|
||||
# if arg is a value type, then we replace it with a copy of a ref type to guaranty lifetime
|
||||
macro setCellDataFunc*(column: TreeViewColumn; renderer: CellRenderer; fn: untyped = nil; arg: typed = nil): untyped =
|
||||
|
||||
if fn == nil: # unset
|
||||
result = parseStmt("setCellDataFunc($1, $2, nil, nil, nil)" % [$column, $renderer])
|
||||
return
|
||||
|
||||
var CdfID {.compileTime, global.}: int # unique id for our generated cell data functions
|
||||
inc(CdfID)
|
||||
var ats: string # the type of optional argument as string (arg type string)
|
||||
var argStr: string # the value of optional argument as string
|
||||
var atsfix: string # we have to prefix with "ref " if arg is avalue type
|
||||
if arg == nil: # no optional argument, so fake a nil pointer
|
||||
argStr = "nil"
|
||||
ats = "pointer"
|
||||
else:
|
||||
argStr = $(arg.toStrLit)
|
||||
ats = $getTypeInst(arg).toStrLit
|
||||
|
||||
if getTypeInst(arg).typeKind != ntyRef and getTypeInst(arg).typeKind != ntyPtr:
|
||||
atsFix = "ref "
|
||||
|
||||
let procName = "celldatafunc_" & $CdfID # our init code
|
||||
let procNameCdecl = "celldatafunc_cdecl_" & $CdfID # the proc that is called from GTK
|
||||
var procNameDestroy: string # the proc that GTK calls when we unset the cellDataFunc
|
||||
# first we generate the destroy proc
|
||||
var r0s: string
|
||||
|
||||
# GTK should unref the optional argument later, so we generate a destroy proc which GTK can call
|
||||
if arg != nil and getTypeInst(arg).typeKind != ntyPtr:
|
||||
procNameDestroy = "celldatafunc_destroy" & $CdfID
|
||||
r0s ="""
|
||||
proc $1(p: pointer) {.cdecl.} =
|
||||
# echo "GC_Unref(arg)"
|
||||
GC_Unref(cast[$2](p))
|
||||
""" % [$procNameDestroy, atsFix & ats]
|
||||
else:
|
||||
procNameDestroy = "nil"
|
||||
r0s = ""
|
||||
|
||||
# now we generate the proc which GTK will call for each cell of the treeview. g_object_get_qdata() is
|
||||
# the GTK function which retrieves the Nim proxy objects from the plain GTK data objects.
|
||||
var r1s = """
|
||||
proc $1(column00: ptr TreeViewColumn00; renderer00: ptr CellRenderer00;
|
||||
model00: ptr TreeModel00; iter: TreeIter; pdata: pointer) {.cdecl.} =
|
||||
let column = cast[TreeViewColumn](g_object_get_qdata(column00, Quark))
|
||||
let renderer = cast[CellRenderer](g_object_get_qdata(renderer00, Quark))
|
||||
let model = cast[TreeModel](g_object_get_qdata(model00, Quark))
|
||||
""" % [$procNameCdecl]
|
||||
if arg == nil:
|
||||
r1s.add """
|
||||
$1(column, renderer, model, iter) # call the user provided Nim proc
|
||||
""" % [$fn]
|
||||
elif getTypeInst(arg).typeKind == ntyRef or getTypeInst(arg).typeKind == ntyPtr:
|
||||
r1s.add """
|
||||
let a = cast[$2](pdata)
|
||||
$1(column, renderer, model, iter, a) # call the user provided Nim proc
|
||||
""" % [$fn, ats]
|
||||
else: # arg was a value type, but we pass a copy of ref type
|
||||
r1s.add """
|
||||
let a = cast[ref $2](pdata)[]
|
||||
$1(column, renderer, model, iter, a) # call the user provided Nim proc
|
||||
""" % [$fn, ats]
|
||||
|
||||
# this is basically only a code block which is called for initialization, mostly
|
||||
# making a deep copy of optional argument when argumant is not a ref
|
||||
var r2s: string
|
||||
if arg == nil:
|
||||
r2s ="""
|
||||
proc $1(column: TreeViewColumn; renderer: CellRenderer; pdata: $2) =
|
||||
setCellDataFunc($3, $4, $5, nil, nil)
|
||||
$1(column, renderer, $6)
|
||||
""" % [$procName, ats, $column, $renderer, $procNameCdecl, argStr, $procNameDestroy]
|
||||
elif getTypeInst(arg).typeKind == ntyPtr:
|
||||
r2s ="""
|
||||
proc $1(column: TreeViewColumn; renderer: CellRenderer; pdata: $2) =
|
||||
setCellDataFunc($3, $4, $5, cast[pointer](pdata), $7)
|
||||
$1(column, renderer, $6)
|
||||
""" % [$procName, ats, $column, $renderer, $procNameCdecl, argStr, $procNameDestroy]
|
||||
elif getTypeInst(arg).typeKind == ntyRef:
|
||||
r2s ="""
|
||||
proc $1(column: TreeViewColumn; renderer: CellRenderer; pdata: $2) =
|
||||
if not pdata.isNil: # or pdata is pointer):
|
||||
GC_ref(pdata)
|
||||
setCellDataFunc($3, $4, $5, cast[pointer](pdata), $7)
|
||||
$1(column, renderer, $6)
|
||||
""" % [$procName, ats, $column, $renderer, $procNameCdecl, argStr, $procNameDestroy]
|
||||
else: # arg is value object
|
||||
r2s ="""
|
||||
proc $1(column: TreeViewColumn; renderer: CellRenderer; pdata: $2) =
|
||||
var ar: ref $2
|
||||
new(ar)
|
||||
#deepCopy(ar[], pdata)
|
||||
ar[] = pdata
|
||||
GC_ref(ar)
|
||||
setCellDataFunc($3, $4, $5, cast[pointer](ar), $7)
|
||||
$1(column, renderer, $6)
|
||||
""" % [$procName, ats, $column, $renderer, $procNameCdecl, argStr, $procNameDestroy]
|
||||
|
||||
result = parseStmt(r0s & r1s & r2s)
|
||||
# 117 lines
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
# High level gobject-introspection based GTK3/GTK4 bindings for the Nim programming language
|
||||
# nimpretty --maxLineLen:130 gen.nim
|
||||
# v 0.8.3 2020-OCT-21
|
||||
# v 0.8.3 2020-OCT-26
|
||||
# (c) S. Salewski 2018
|
||||
|
||||
# usefull for finding death code:
|
||||
|
|
@ -2678,6 +2678,8 @@ proc seq2GList*[T](s: seq[T]): ptr glib.List =
|
|||
discard # make it compile for these cases, of course will not work
|
||||
return l
|
||||
|
||||
#include gimplgobj
|
||||
|
||||
"""
|
||||
|
||||
# for v0.8.2 we create this manually, as gst_structure_from_string() is a constructor
|
||||
|
|
@ -2711,11 +2713,12 @@ proc attachRecv*(self: Agent; streamID: int; componentID: int; ctx: MainContext;
|
|||
|
||||
const GLib_EPI = """
|
||||
|
||||
proc g_thread_new(name: cstring; fn: ThreadFunc; data:pointer): ptr Thread00 {.importc, libprag.}
|
||||
when not defined(g_thread_new):
|
||||
proc g_thread_new(name: cstring; fn: ThreadFunc; data:pointer): ptr Thread00 {.importc, libprag.}
|
||||
|
||||
proc newThread*(name: string; fn: ThreadFunc; data:pointer): Thread =
|
||||
fnew(result, finalizerunref)
|
||||
result.impl = g_thread_new(name, fn, data)
|
||||
proc newThread*(name: string; fn: ThreadFunc; data:pointer): Thread =
|
||||
fnew(result, finalizerunref)
|
||||
result.impl = g_thread_new(name, fn, data)
|
||||
|
||||
"""
|
||||
|
||||
|
|
@ -3244,10 +3247,12 @@ proc init* =
|
|||
output.write(GTK_EPI % fixedModName("gtk"))
|
||||
if ISGTK3:
|
||||
output.write("include gisup3\n")
|
||||
output.write("include gimpl\n")
|
||||
output.write("include gimplgobj\n")
|
||||
output.write("include gimplgtk\n")
|
||||
else:
|
||||
output.write("include gisup4\n")
|
||||
output.write("include gimpl\n")
|
||||
output.write("include gimplgobj\n")
|
||||
output.write("include gimplgtk\n")
|
||||
buildableList.add("MenuModel")
|
||||
for i in buildableList:
|
||||
var prefix = "gtk"
|
||||
|
|
@ -3450,7 +3455,7 @@ launch()
|
|||
# if not xcallerAlloc.contains(el):
|
||||
# echo el
|
||||
|
||||
# 3453 lines
|
||||
# 3453 lines include
|
||||
# troubles: gTypeFundamental(gRegisteredTypeInfoGetGType(info)) == G_TYPE_BOXED:
|
||||
#[
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue