~ehmry/nim_tox

c4e39e7ae94e8e23be5e2c390f9e9bcef6f18b7d — Emery Hemingway 5 months ago 35e68c9
Refactor error checks
2 files changed, 158 insertions(+), 200 deletions(-)

M src/toxcore.nim
M src/toxcore/av.nim
M src/toxcore.nim => src/toxcore.nim +133 -172
@@ 13,8 13,14 @@ import std/strutils

type ToxError* = object of CatchableError

template ctoxAssert(good, value: untyped) =
  if value != good: raise newException(ToxError, $value)
template ctoxCheck(ok, body: untyped) =
  block:
    var
      res {.inject.} = ok
      err {.inject.} = addr res
    body
    if res != ok:
      raise newException(ToxError, $res)

proc ctoxString(buf: ptr uint8; len: csize): string =
  ## Copy a buffer from the core to a Nim string.


@@ 373,22 379,19 @@ proc newTox*(configure: proc (opt: Options)): Tox =
  proc options_new(error: ptr ERR_OPTIONS_NEW): Options {.ctoxProc.}
  proc options_default(options: Options) {.ctoxProc.}
  proc options_free(options: Options) {.ctoxProc.}
  var err: ERR_OPTIONS_NEW
  let opt = options_new(addr err)
  ctoxAssert(TOX_ERR_OPTIONS_NEW_OK, err)
  var opt: Options
  ctoxCheck(TOX_ERR_OPTIONS_NEW_OK) do:
    opt = options_new(err)
  defer: options_free(opt)
  options_default(opt)
  configure(opt)
  block:
    var err: ERR_NEW
    result = Tox(core: tox_new(opt, addr err))
    ctoxAssert(TOX_ERR_NEW_OK, err)
  ctoxCheck(TOX_ERR_NEW_OK) do:
    result = Tox(core: tox_new(opt, err))

proc newTox*(): Tox =
  ## Create a new Tox instance.
  var err: ERR_NEW
  result = Tox(core: tox_new(nil, addr err))
  ctoxAssert(TOX_ERR_NEW_OK, err)
  ctoxCheck(TOX_ERR_NEW_OK) do:
    result = Tox(core: tox_new(nil, err))

proc close*(tox: Tox) {.tags: [IOEffect].} =
  ## Shutdown and destroy a Tox instance.


@@ 427,18 430,16 @@ proc bootstrap*(tox: Tox; host: string; key: PublicKey; port = defaultPort) {.
  proc bootstrap(
    core: Core; host: cstring; port: uint16;
    public_key: ptr uint8; error: ptr Err_Bootstrap): bool {.ctoxProc.}
  var err = TOX_ERR_BOOTSTRAP_OK
  discard bootstrap(tox.core, host, port, unsafeAddr key.bytes[0], addr err)
  ctoxAssert(TOX_ERR_BOOTSTRAP_OK, err)
  ctoxCheck(TOX_ERR_BOOTSTRAP_OK) do:
    discard bootstrap(tox.core, host, port, unsafeAddr key.bytes[0], err)

proc addTcpRelay*(tox: Tox; host: string; port: uint16; key: PublicKey) =
  ## Add a TCP relay to `tox`.
  proc add_tcp_relay(
    core: Core; host: cstring; port: uint16;
    public_key: ptr uint8; error: ptr Err_Bootstrap): bool {.ctoxProc.}
  var err = TOX_ERR_BOOTSTRAP_OK
  discard tox.core.add_tcp_relay(host, port, unsafeAddr key.bytes[0], addr err)
  ctoxAssert(TOX_ERR_BOOTSTRAP_OK, err)
  ctoxCheck(TOX_ERR_BOOTSTRAP_OK) do:
    discard tox.core.add_tcp_relay(host, port, unsafeAddr key.bytes[0], err)

template callbackSetter(name, body: untyped) =
  ## Magic for installing Nim closure callbacks into c-toxcore.


@@ 514,9 515,8 @@ proc `name=`*(tox: Tox; name: string) {.tags: [IOEffect].} =
  proc self_set_name(
    core: Core; name: cstring; length: csize;
    error: ptr Err_Set_Info): bool {.ctoxProc.}
  var err = TOX_ERR_SET_INFO_OK
  discard tox.core.self_set_name(name, name.len, nil)
  ctoxAssert(TOX_ERR_SET_INFO_OK, err)
  ctoxCheck(TOX_ERR_SET_INFO_OK) do:
    discard tox.core.self_set_name(name, name.len, err)

proc name*(tox: Tox): string =
  ## Retrieve the display name of `tox` instance.


@@ 531,9 531,8 @@ proc `statusMessage=`*(tox: Tox; msg: string) {.tags: [IOEffect].} =
  proc self_set_status_message(
    core: Core; status_message: cstring;
    length: csize; error: ptr Err_Set_Info): bool {.ctoxProc.}
  var err = TOX_ERR_SET_INFO_OK
  discard tox.core.self_set_status_message(msg, msg.len, addr err)
  ctoxAssert(TOX_ERR_SET_INFO_OK, err)
  ctoxCheck(TOX_ERR_SET_INFO_OK) do:
    discard tox.core.self_set_status_message(msg, msg.len, err)

proc statusMessage*(tox: Tox): string {.tags: [IOEffect].} =
  ## Retrieve the status message of `tox` instance.


@@ 569,19 568,17 @@ proc addFriend*(tox: Tox; id: Address; msg: string): Friend {.tags: [IOEffect].}
  proc friend_add(
    core: Core; address: ptr uint8; message: cstring;
    length: csize; error: ptr ERR_FRIEND_ADD): Friend {.ctoxProc.}
  var err = TOX_ERR_FRIEND_ADD_OK
  result = tox.core.friend_add(unsafeAddr id.bytes[0], msg, msg.len, addr err)
  ctoxAssert(TOX_ERR_FRIEND_ADD_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_ADD_OK) do:
    result = tox.core.friend_add(unsafeAddr id.bytes[0], msg, msg.len, err)

proc addFriendNoRequest*(tox: Tox; key: PublicKey): Friend {.tags: [IOEffect].} =
  ## Respond to a friend request and return a token for the new friend.
  proc friend_add_norequest(
    core: Core; public_key: ptr uint8;
    error: ptr ERR_FRIEND_ADD): Friend {.ctoxProc.}
  var err = TOX_ERR_FRIEND_ADD_OK
  result = tox.core.friend_add_norequest(
    unsafeAddr key.bytes[0], addr err)
  ctoxAssert(TOX_ERR_FRIEND_ADD_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_ADD_OK) do:
    result = tox.core.friend_add_norequest(
      unsafeAddr key.bytes[0], err)

type
  Err_Friend_Delete {.ctoxEnum.} = enum


@@ 593,9 590,8 @@ proc delete*(tox: Tox; friend: Friend): bool {.tags: [IOEffect].} =
  proc friend_delete(
    core: Core; friend: Friend;
    error: ptr Err_Friend_Delete): bool {.ctoxProc.}
  var err = TOX_ERR_FRIEND_DELETE_OK
  discard tox.core.friend_delete(friend, addr err)
  ctoxAssert(TOX_ERR_FRIEND_DELETE_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_DELETE_OK) do:
    discard tox.core.friend_delete(friend, err)

type Err_Friend_By_Public_Key {.ctoxEnum.} = enum
  TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK,


@@ 607,9 603,8 @@ proc friend*(tox: Tox; key: PublicKey): Friend =
  proc friend_by_public_key(
    core: Core; public_key: ptr uint8;
    error: ptr Err_Friend_By_Public_Key): Friend {.ctoxProc.}
  var err = TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK
  result = tox.core.friend_by_public_key(unsafeAddr key.bytes[0], addr err)
  ctoxAssert(TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_BY_PUBLIC_KEY_OK) do:
    result = tox.core.friend_by_public_key(unsafeAddr key.bytes[0], err)

proc exists*(tox: Tox; friend: Friend): bool =
  ## Test if a friend exists.


@@ 634,9 629,8 @@ proc publicKey*(tox: Tox; friend: Friend): PublicKey =
    core: Core; friend: Friend;
    public_key: ptr uint8;
    error: ptr Err_Friend_Get_Public_Key): bool {.ctoxProc.}
  var err = TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK
  discard tox.core.friend_get_public_key(friend, addr result.bytes[0], addr err)
  ctoxAssert(TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_GET_PUBLIC_KEY_OK) do:
    discard tox.core.friend_get_public_key(friend, addr result.bytes[0], err)

type Err_Friend_Get_Last_Online {.ctoxEnum.} = enum
  TOX_ERR_FRIEND_GET_LAST_ONLINE_OK,


@@ 647,9 641,8 @@ proc lastOnline*(tox: Tox; friend: Friend): uint64 =
  proc friend_get_last_online(
    core: Core; friend: Friend;
    error: ptr Err_Friend_Get_Last_Online): uint64 {.ctoxProc.}
  var err = TOX_ERR_FRIEND_GET_LAST_ONLINE_OK
  result = tox.core.friend_get_last_online(friend, addr err)
  ctoxAssert(TOX_ERR_FRIEND_GET_LAST_ONLINE_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_GET_LAST_ONLINE_OK) do:
    result = tox.core.friend_get_last_online(friend, err)

type Err_Friend_Query {.ctoxEnum.} = enum
  TOX_ERR_FRIEND_QUERY_OK,


@@ 664,12 657,11 @@ proc name*(tox: Tox; friend: Friend): string =
  proc friend_get_name(
    core: Core; friend: Friend; name: ptr char;
    error: ptr Err_Friend_Query): bool {.ctoxProc.}
  var err = TOX_ERR_FRIEND_QUERY_OK
  result = newString(tox.core.friend_get_name_size(friend, addr err))
  ctoxAssert(TOX_ERR_FRIEND_QUERY_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
    result = newString(tox.core.friend_get_name_size(friend, err))
  if 0 < result.len:
    discard tox.core.friend_get_name(friend, addr result[0], addr err)
    ctoxAssert(TOX_ERR_FRIEND_QUERY_OK, err)
    ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
      discard tox.core.friend_get_name(friend, addr result[0], err)

callbackSetter friend_name:
  ## Install a callback for friend name updates.


@@ 690,12 682,11 @@ proc statusMessage*(tox: Tox; friend: Friend): string =
    core: Core; friend: Friend;
    status_message: ptr char;
    error: ptr Err_Friend_Query): bool {.ctoxProc.}
  var err = TOX_ERR_FRIEND_QUERY_OK
  result = newString(tox.core.friend_get_status_message_size(friend, addr err))
  ctoxAssert(TOX_ERR_FRIEND_QUERY_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
    result = newString(tox.core.friend_get_status_message_size(friend, err))
  if 0 < result.len:
    discard tox.core.friend_get_status_message(friend, addr result[0], addr err)
    ctoxAssert(TOX_ERR_FRIEND_QUERY_OK, err)
    ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
      discard tox.core.friend_get_status_message(friend, addr result[0], err)

callbackSetter friend_status_message:
  ## Install a callback for friend status messages.


@@ 714,9 705,8 @@ proc status*(tox: Tox; friend: Friend): UserStatus =
  proc friend_get_status(
    core: Core; friend: Friend;
    error: ptr Err_Friend_Query): UserStatus {.ctoxProc.}
  var err: Err_Friend_Query
  result = tox.core.friend_get_status(friend, addr err)
  ctoxAssert(TOX_ERR_FRIEND_QUERY_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
    result = tox.core.friend_get_status(friend, err)

callbackSetter friend_status:
  ## Install a callback for friend statuses.


@@ 733,9 723,8 @@ proc connectionStatus*(tox: Tox; friend: Friend): Connection =
  proc friend_get_connection_status(
    core: Core; friend: Friend;
    error: ptr Err_Friend_Query): Connection {.ctoxProc.}
  var err = TOX_ERR_FRIEND_QUERY_OK
  result = tox.core.friend_get_connection_status(friend, addr err)
  ctoxAssert(TOX_ERR_FRIEND_QUERY_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
    result = tox.core.friend_get_connection_status(friend, err)

callbackSetter friend_connection_status:
  ## Install a callback for friend connection statuses.


@@ 754,9 743,8 @@ proc typing*(tox: Tox; friend: Friend): bool =
  proc friend_get_typing(
    core: Core; friend: Friend;
    error: ptr Err_Friend_Query): bool {.ctoxProc.}
  var err = TOX_ERR_FRIEND_QUERY_OK
  result = tox.core.friend_get_typing(friend, addr err)
  ctoxAssert(TOX_ERR_FRIEND_QUERY_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_QUERY_OK) do:
    result = tox.core.friend_get_typing(friend, err)

callbackSetter friend_typing:
  ## Install a callback for friend typing statuses.


@@ 780,9 768,8 @@ proc typing*(tox: Tox; friend: Friend; typing: bool) {.tags: [IOEffect].} =
  proc self_set_typing(
    core: Core; friend: Friend; typing: bool;
    error: ptr Err_Set_Typing): bool {.ctoxProc.}
  var err = TOX_ERR_SET_TYPING_OK
  discard tox.core.self_set_typing(friend, typing, addr err)
  ctoxAssert(TOX_ERR_SET_TYPING_OK, err)
  ctoxCheck(TOX_ERR_SET_TYPING_OK) do:
    discard tox.core.self_set_typing(friend, typing, err)

type Err_Friend_Send_Message {.ctoxEnum.} = enum
  TOX_ERR_FRIEND_SEND_MESSAGE_OK,


@@ 800,9 787,8 @@ proc send*(tox: Tox; friend: Friend; msg: string;
    core: Core; friend: Friend;
    kind: MessageType; message: cstring;
    length: csize; error: ptr ERR_FRIEND_SEND_MESSAGE): MessageId {.ctoxProc.}
  var err = TOX_ERR_FRIEND_SEND_MESSAGE_OK
  result = tox.core.friend_send_message(friend, kind, msg, msg.len, addr err)
  ctoxAssert(TOX_ERR_FRIEND_SEND_MESSAGE_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_SEND_MESSAGE_OK) do:
    result = tox.core.friend_send_message(friend, kind, msg, msg.len, err)

callbackSetter friend_read_receipt:
  ## Install a callback for message read receipts.


@@ 866,9 852,8 @@ proc control*(tox: Tox; friend: Friend; file: FileTransfer;
    core: Core; friend: Friend; file: FileTransfer;
    control: FileControl;
    error: ptr ERR_FILE_CONTROL): bool {.ctoxProc.}
  var err: Err_File_Control
  discard tox.core.file_control(friend, file, control, addr err)
  ctoxAssert(TOX_ERR_FILE_CONTROL_OK, err)
  ctoxCheck(TOX_ERR_FILE_CONTROL_OK) do:
    discard tox.core.file_control(friend, file, control, err)

callbackSetter file_recv_control:
  type cbType = proc (


@@ 894,9 879,8 @@ proc seek*(tox: Tox; friend: Friend; file: FileTransfer; pos: uint64) {.tags: [I
  proc file_seek(
    core: Core; friend: Friend; file: FileTransfer;
    position: uint64; error: ptr Err_File_Seek): bool {.ctoxProc.}
  var err: Err_File_Seek
  discard tox.core.file_seek(friend, file, pos, addr err)
  ctoxAssert(TOX_ERR_FILE_SEEK_OK, err)
  ctoxCheck(TOX_ERR_FILE_SEEK_OK) do:
    discard tox.core.file_seek(friend, file, pos, err)

type Err_File_Get {.ctoxEnum.} = enum
  TOX_ERR_FILE_GET_OK,


@@ 911,9 895,8 @@ proc id*(tox: Tox; friend: Friend; file: FileTransfer): FileId =
    core: Core; friend: Friend;
    file: FileTransfer; file_id: ptr uint8;
    error: ptr Err_File_Get): bool {.ctoxProc.}
  var err: Err_File_Get
  discard tox.core.file_get_file_id(friend, file, addr result[0], addr err)
  ctoxAssert(TOX_ERR_FILE_GET_OK, err)
  ctoxCheck(TOX_ERR_FILE_GET_OK) do:
    discard tox.core.file_get_file_id(friend, file, addr result[0], err)

type Err_File_Send {.ctoxEnum.} = enum
  TOX_ERR_FILE_SEND_OK,


@@ 923,16 906,15 @@ type Err_File_Send {.ctoxEnum.} = enum
  TOX_ERR_FILE_SEND_NAME_TOO_LONG,
  TOX_ERR_FILE_SEND_TOO_MANY

proc send*(tox: Tox; friend: Friend; kind: uint32; size: BiggestInt; id : Hash;
proc send*(tox: Tox; friend: Friend; kind: uint32; size: BiggestInt; id: Hash;
    filename: string): FileTransfer {.tags: [IOEffect].} =
  proc file_send(
    core: Core; friend: Friend; kind: uint32;
    file_size: uint64; file_id: ptr uint8; filename: cstring;
    filename_length: csize; error: ptr Err_File_Send): FileTransfer {.ctoxProc.}
  var err: Err_File_Send
  result = tox.core.file_send(
    friend, kind, size.uint64, unsafeAddr id.bytes[0], filename, filename.len, addr err)
  ctoxAssert(TOX_ERR_FILE_SEND_OK, err)
  ctoxCheck(TOX_ERR_FILE_SEND_OK) do:
    result = tox.core.file_send(
      friend, kind, size.uint64, unsafeAddr id.bytes[0], filename, filename.len, err)

proc send*(tox: Tox; friend: Friend; kind: uint32; size: BiggestInt;
    filename: string): FileTransfer {.tags: [IOEffect].} =


@@ 940,10 922,9 @@ proc send*(tox: Tox; friend: Friend; kind: uint32; size: BiggestInt;
    core: Core; friend: Friend; kind: uint32;
    file_size: uint64; file_id: ptr uint8; filename: cstring;
    filename_length: csize; error: ptr Err_File_Send): FileTransfer {.ctoxProc.}
  var err: Err_File_Send
  result = tox.core.file_send(
    friend, kind, size.uint64, nil, filename, filename.len, addr err)
  ctoxAssert(TOX_ERR_FILE_SEND_OK, err)
  ctoxCheck(TOX_ERR_FILE_SEND_OK) do:
    result = tox.core.file_send(
      friend, kind, size.uint64, nil, filename, filename.len, err)

type Err_File_Send_Chunk {.ctoxEnum.} = enum
  TOX_ERR_FILE_SEND_CHUNK_OK,


@@ 963,9 944,8 @@ proc sendChunk*(tox: Tox; friend: Friend; file: FileTransfer; pos: uint64;
    file: FileTransfer; position: uint64;
    data: pointer; length: csize;
    error: ptr Err_File_Send_Chunk): bool {.ctoxProc.}
  var err: Err_File_Send_Chunk
  discard tox.core.file_send_chunk(friend, file, pos, data, size, addr err)
  ctoxAssert(TOX_ERR_FILE_SEND_CHUNK_OK, err)
  ctoxCheck(TOX_ERR_FILE_SEND_CHUNK_OK) do:
    discard tox.core.file_send_chunk(friend, file, pos, data, size, err)

proc sendChunk*(tox: Tox; friend: Friend; file: FileTransfer; pos: uint64;
    data: string) =


@@ 1078,9 1058,8 @@ type Err_Conference_New {.ctoxEnum.} = enum
proc newConference*(tox: Tox): Conference {.tags: [IOEffect].} =
  proc conference_new(
    core: Core; error: ptr Err_Conference_New): Conference {.ctoxProc.}
  var err: Err_Conference_New
  result = tox.core.conference_new(addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_NEW_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_NEW_OK) do:
    result = tox.core.conference_new(err)

type Err_Conference_Delete {.ctoxEnum.} = enum
  TOX_ERR_CONFERENCE_DELETE_OK,


@@ 1090,9 1069,8 @@ proc delete*(tox: Tox; conf: Conference) {.tags: [IOEffect].} =
  proc tox_conference_delete(
    core: Core; conference: Conference;
    error: ptr Err_Conference_Delete): bool {.ctoxProc.}
  var err: Err_Conference_Delete
  discard tox.core.tox_conference_delete(conf, addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_DELETE_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_DELETE_OK) do:
    discard tox.core.tox_conference_delete(conf, err)

type
  Err_Conference_Peer_Query {.ctoxEnum.} = enum


@@ 1105,9 1083,8 @@ proc peerCount*(tox: Tox; conf: Conference): uint32 =
  proc conference_peer_count(
    core: Core; conf: Conference;
    error: ptr Err_Conference_Peer_Query): uint32 {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_PEER_QUERY_OK
  result = tox.core.conference_peer_count(conf, addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_PEER_QUERY_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
    result = tox.core.conference_peer_count(conf, err)

proc peerName*(tox: Tox; conf: Conference; peer: Peer): string =
  proc conference_peer_get_name_size(


@@ 1116,37 1093,33 @@ proc peerName*(tox: Tox; conf: Conference; peer: Peer): string =
  proc conference_peer_get_name(
    core: Core; conf: Conference; peer: Peer; name: ptr char;
    error: ptr Err_Conference_Peer_Query): bool {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_PEER_QUERY_OK
  result = newString(tox.core.conference_peer_get_name_size(conf, peer, addr err))
  ctoxAssert(TOX_ERR_CONFERENCE_PEER_QUERY_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
    result = newString(tox.core.conference_peer_get_name_size(conf, peer, err))
  if 0 < result.len:
    discard tox.core.conference_peer_get_name(conf, peer, addr result[0], addr err)
    ctoxAssert(TOX_ERR_CONFERENCE_PEER_QUERY_OK, err)
    ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
      discard tox.core.conference_peer_get_name(conf, peer, addr result[0], err)

proc peerPublicKey*(tox: Tox; conf: Conference; peer: Peer): PublicKey =
  proc conference_peer_get_public_key(
    core: Core; conf: Conference; peer: Peer; public_key: ptr uint8;
    error: ptr Err_Conference_Peer_Query): bool {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_PEER_QUERY_OK
  discard tox.core.conference_peer_get_public_key(conf, peer, addr result.bytes[
      0], addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_PEER_QUERY_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
    discard tox.core.conference_peer_get_public_key(
        conf, peer, addr result.bytes[0], err)

proc peerNumberIsOurs*(tox: Tox; conf: Conference; peer: Peer): bool =
  proc conference_peer_number_is_ours(
    core: Core; conf: Conference; peer: Peer;
    error: ptr Err_Conference_Peer_Query): bool {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_PEER_QUERY_OK
  result = tox.core.conference_peer_number_is_ours(conf, peer, addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_PEER_QUERY_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
    result = tox.core.conference_peer_number_is_ours(conf, peer, err)

proc offlinePeerCount*(tox: Tox; conf: Conference): uint32 =
  proc conference_offline_peer_count(
    core: Core; conf: Conference;
    error: ptr Err_Conference_Peer_Query): uint32 {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_PEER_QUERY_OK
  result = tox.core.conference_offline_peer_count(conf, addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_PEER_QUERY_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
    result = tox.core.conference_offline_peer_count(conf, err)

proc offlinePeerName*(tox: Tox; conf: Conference; peer: Peer): string =
  proc conference_offline_peer_get_name_size(


@@ 1155,30 1128,27 @@ proc offlinePeerName*(tox: Tox; conf: Conference; peer: Peer): string =
  proc conference_offline_peer_get_name(core: Core;
      conf: Conference; offline_peer: Peer; name: ptr char;
      error: ptr Err_Conference_Peer_Query): bool {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_PEER_QUERY_OK
  result = newString(tox.core.conference_offline_peer_get_name_size(conf, peer, addr err))
  ctoxAssert(TOX_ERR_CONFERENCE_PEER_QUERY_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
    result = newString(tox.core.conference_offline_peer_get_name_size(conf, peer, err))
  if 0 < result.len:
    discard tox.core.conference_offline_peer_get_name(conf, peer, addr result[
        0], addr err)
    ctoxAssert(TOX_ERR_CONFERENCE_PEER_QUERY_OK, err)
    ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
      discard tox.core.conference_offline_peer_get_name(
          conf, peer, addr result[0], err)

proc offlinePeerPublicKey*(tox: Tox; conf: Conference; peer: Peer): PublicKey =
  proc conference_offline_peer_get_public_key(
    core: Core; conf: Conference; offline_peer: Peer; public_key: ptr uint8;
    error: ptr Err_Conference_Peer_Query): bool {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_PEER_QUERY_OK
  discard tox.core.conference_offline_peer_get_public_key(
    conf, peer, addr result.bytes[0], addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_PEER_QUERY_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
    discard tox.core.conference_offline_peer_get_public_key(
        conf, peer, addr result.bytes[0], err)

proc offlinePeerLastActive*(tox: Tox; conf: Conference; peer: Peer): uint64 =
  proc conference_offline_peer_get_last_active(
    core: Core; conf: Conference; offline_peer: Peer;
    error: ptr Err_Conference_Peer_Query): uint64 {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_PEER_QUERY_OK
  result = tox.core.conference_offline_peer_get_last_active(conf, peer, addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_PEER_QUERY_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_PEER_QUERY_OK) do:
    result = tox.core.conference_offline_peer_get_last_active(conf, peer, err)

type Err_Conference_Set_Max_Offline {.ctoxEnum.} = enum
  TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK,


@@ 1189,9 1159,8 @@ proc `maxOffline=`*(tox: Tox; conf: Conference; peers: uint32) =
    core: Core; conf: Conference;
    max_offline_peers: uint32;
    error: ptr Err_Conference_Set_Max_Offline): bool {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK
  discard tox.core.conference_set_max_offline(conf, peers, addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_SET_MAX_OFFLINE_OK) do:
    discard tox.core.conference_set_max_offline(conf, peers, err)

type Err_Conference_Invite {.ctoxEnum.} = enum
  TOX_ERR_CONFERENCE_INVITE_OK,


@@ 1204,9 1173,8 @@ proc invite*(tox: Tox; friend: Friend; conf: Conference) {.tags: [IOEffect].} =
    core: Core; friend: Friend;
    conference: Conference;
    error: ptr Err_Conference_Invite): bool {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_INVITE_OK
  discard tox.core.conference_invite(friend, conf, addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_INVITE_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_INVITE_OK) do:
    discard tox.core.conference_invite(friend, conf, err)

type Err_Conference_Join {.ctoxEnum.} = enum
  TOX_ERR_CONFERENCE_JOIN_OK,


@@ 1221,9 1189,8 @@ proc join*(tox: Tox; friend: Friend; cookie: string): Conference {.tags: [IOEffe
  proc conference_join(
    core: Core; friend: Friend; cookie: cstring;
    length: csize; error: ptr Err_Conference_Join): Conference {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_JOIN_OK
  result = tox.core.conference_join(friend, cookie, cookie.len, addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_JOIN_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_JOIN_OK) do:
    result = tox.core.conference_join(friend, cookie, cookie.len, err)

type Err_Conference_Send_Message {.ctoxEnum.} = enum
  TOX_ERR_CONFERENCE_SEND_MESSAGE_OK,


@@ 1232,17 1199,16 @@ type Err_Conference_Send_Message {.ctoxEnum.} = enum
  TOX_ERR_CONFERENCE_SEND_MESSAGE_NO_CONNECTION,
  TOX_ERR_CONFERENCE_SEND_MESSAGE_FAIL_SEND

proc send*(tox: Tox; conf: Conference; msg: string; kind = TOX_MESSAGE_TYPE_NORMAL): bool {.
    tags: [IOEffect].} =
proc send*(tox: Tox; conf: Conference; msg: string;
    kind = TOX_MESSAGE_TYPE_NORMAL): bool {.tags: [IOEffect].} =
  proc conference_send_message(
    core: Core; conf: Conference;
    kind: MessageType; message: cstring;
    length: csize;
    error: ptr Err_Conference_Send_Message): bool {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_SEND_MESSAGE_OK
  result = tox.core.conference_send_message(
    conf, kind, msg, msg.len, addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_SEND_MESSAGE_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_SEND_MESSAGE_OK) do:
    result = tox.core.conference_send_message(
      conf, kind, msg, msg.len, err)

type Err_Conference_Title {.ctoxEnum.} = enum
  TOX_ERR_CONFERENCE_TITLE_OK,


@@ 1257,21 1223,21 @@ proc title*(tox: Tox; conf: Conference): string =
  proc conference_get_title(
    core: Core; conf: Conference; title: ptr char;
    error: ptr Err_Conference_Title): bool {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_TITLE_OK
  result = newString(tox.core.conference_get_title_size(conf, addr err))
  ctoxAssert(TOX_ERR_CONFERENCE_TITLE_OK, err)
  var titleLen: int
  ctoxCheck(TOX_ERR_CONFERENCE_TITLE_OK) do:
    titleLen = tox.core.conference_get_title_size(conf, err)
  result = newString(titleLen)
  if 0 < result.len:
    discard tox.core.conference_get_title(conf, addr result[0], addr err)
    ctoxAssert(TOX_ERR_CONFERENCE_TITLE_OK, err)
    ctoxCheck(TOX_ERR_CONFERENCE_TITLE_OK) do:
      discard tox.core.conference_get_title(conf, addr result[0], err)

proc `title=`*(tox: Tox; conf: Conference; s: string) {.tags: [IOEffect].} =
  proc conference_set_title(
    core: Core; conf: Conference;
    title: cstring; length: csize;
    error: ptr Err_Conference_Title): bool {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_TITLE_OK
  discard tox.core.conference_set_title(conf, s, s.len, addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_TITLE_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_TITLE_OK) do:
    discard tox.core.conference_set_title(conf, s, s.len, err)

proc conferences*(tox: Tox): seq[Conference] =
  proc conference_get_chatlist_size(core: Core): csize {.ctoxProc.}


@@ 1288,13 1254,13 @@ proc kind*(tox: Tox; conf: Conference): ConferenceType =
  proc conference_get_type(
    core: Core; conf: Conference;
    error: ptr Err_Conference_Get_Type): ConferenceType {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_GET_TYPE_OK
  result = tox.core.conference_get_type(conf, addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_GET_TYPE_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_GET_TYPE_OK) do:
    result = tox.core.conference_get_type(conf, err)

proc id*(tox: Tox; conf: Conference): ConferenceId =
  proc conference_get_id(core: Core; conf: Conference; id: ptr uint8): bool {.ctoxProc.}
  ctoxAssert(true, tox.core.conference_get_id(conf, addr result.bytes[0]))
  if not tox.core.conference_get_id(conf, addr result.bytes[0]):
    raise newException(ToxError, "conference_get_id failed")

type Err_Conference_By_Id {.ctoxEnum.} = enum
  TOX_ERR_CONFERENCE_BY_ID_OK,


@@ 1305,14 1271,14 @@ proc conference*(tox: Tox; id: ConferenceId): Conference =
  proc conference_by_id(
    core: Core; id: ptr uint8;
    error: ptr ERR_CONFERENCE_BY_ID): Conference {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_BY_ID_OK
  result = tox.core.conference_by_id(unsafeAddr id.bytes[0], addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_BY_ID_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_BY_ID_OK) do:
    result = tox.core.conference_by_id(unsafeAddr id.bytes[0], err)

proc uid*(tox: Tox; conf: Conference): ConferenceUid =
  proc conference_get_uid(
    core: Core; conf: Conference; uid: ptr uint8): bool {.ctoxProc.}
  ctoxAssert(true, tox.core.conference_get_uid(conf, addr result.bytes[0]))
  if not tox.core.conference_get_uid(conf, addr result.bytes[0]):
    raise newException(ToxError, "conference_get_id failed")

type Err_Conference_By_Uid {.ctoxEnum.} = enum
  TOX_ERR_CONFERENCE_BY_UID_OK,


@@ 1323,9 1289,8 @@ proc conference*(tox: Tox; uid: ConferenceUid): Conference =
  proc conference_by_uid(
    core: Core; uid: ptr uint8;
    error: ptr Err_Conference_By_Uid): Conference {.ctoxProc.}
  var err = TOX_ERR_CONFERENCE_BY_UID_OK
  result = tox.core.conference_by_uid(unsafeAddr uid.bytes[0], addr err)
  ctoxAssert(TOX_ERR_CONFERENCE_BY_UID_OK, err)
  ctoxCheck(TOX_ERR_CONFERENCE_BY_UID_OK) do:
    result = tox.core.conference_by_uid(unsafeAddr uid.bytes[0], err)

type Err_Friend_Custom_Packet {.ctoxEnum.} = enum
  TOX_ERR_FRIEND_CUSTOM_PACKET_OK,


@@ 1343,9 1308,8 @@ proc sendLossyPacket*(tox: Tox; friend: Friend; data: pointer; size: int) {.
    core: Core; friend: Friend;
    data: pointer; length: csize;
    error: ptr Err_Friend_Custom_Packet): bool {.ctoxProc.}
  var err = TOX_ERR_FRIEND_CUSTOM_PACKET_OK
  discard tox.core.friend_send_lossy_packet(friend, data, size, addr err)
  ctoxAssert(TOX_ERR_FRIEND_CUSTOM_PACKET_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_CUSTOM_PACKET_OK) do:
    discard tox.core.friend_send_lossy_packet(friend, data, size, err)

proc sendLosslessPacket*(tox: Tox; friend: Friend; data: pointer; size: int) {.
    tags: [IOEffect].} =


@@ 1353,9 1317,8 @@ proc sendLosslessPacket*(tox: Tox; friend: Friend; data: pointer; size: int) {.
    core: Core; friend: Friend;
    data: pointer; length: csize;
    error: ptr Err_Friend_Custom_Packet): bool {.ctoxProc.}
  var err = TOX_ERR_FRIEND_CUSTOM_PACKET_OK
  discard tox.core.friend_send_lossless_packet(friend, data, size, addr err)
  ctoxAssert(TOX_ERR_FRIEND_CUSTOM_PACKET_OK, err)
  ctoxCheck(TOX_ERR_FRIEND_CUSTOM_PACKET_OK) do:
    discard tox.core.friend_send_lossless_packet(friend, data, size, err)

callbackSetter friend_lossy_packet:
  type cbType = proc (


@@ 1390,13 1353,11 @@ type Err_Get_Port {.ctoxEnum.} = enum
proc udpPort*(tox: Tox): uint16 =
  proc self_get_udp_port(
    core: Core; error: ptr Err_Get_Port): uint16 {.ctoxProc.}
  var err = TOX_ERR_GET_PORT_OK
  result = tox.core.self_get_udp_port(addr err)
  ctoxAssert(TOX_ERR_GET_PORT_OK, err)
  ctoxCheck(TOX_ERR_GET_PORT_OK) do:
    result = tox.core.self_get_udp_port(err)

proc tcpPort*(tox: Tox): uint16 =
  proc self_get_tcp_port(
    core: Core; error: ptr Err_Get_Port): uint16 {.ctoxProc.}
  var err = TOX_ERR_GET_PORT_OK
  result = tox.core.self_get_tcp_port(addr err)
  ctoxAssert(TOX_ERR_GET_PORT_OK, err)
  ctoxCheck(TOX_ERR_GET_PORT_OK) do:
    result = tox.core.self_get_tcp_port(err)

M src/toxcore/av.nim => src/toxcore/av.nim +25 -28
@@ 10,8 10,14 @@ import ../toxcore
{.pragma: ctoxCallbackProc, ctoxHeader, importc: "toxav_callback_$1".}
{.pragma: ctoxConst, ctoxHeader, importc: "TOXAV_$1".}

template ctoxAssert(good, value: untyped) =
  if value != good: raise newException(ToxError, $value)
template ctoxCheck(ok, body: untyped) =
  block:
    var
      res {.inject.} = ok
      err {.inject.} = addr res
    body
    if res != ok:
      raise newException(ToxError, $res)

type
  Samples* = ptr UncheckedArray[int16]


@@ 157,9 163,8 @@ proc newAv*(tox: Tox): ToxAV =
  ## Start new A/V session. There can only be only one session per Tox instance.
  proc toxav_new(tox: Core; error: ptr Err_New): AvCore {.
    importc, ctoxHeader.}
  var err: ERR_NEW
  result = ToxAv(core: toxav_new(tox.core, addr err))
  ctoxAssert(TOXAV_ERR_NEW_OK, err)
  ctoxCheck(TOXAV_ERR_NEW_OK) do:
    result = ToxAv(core: toxav_new(tox.core, err))

proc kill*(av: ToxAV) =
  proc kill(av: AvCore) {.ctoxProc.}


@@ 214,10 219,8 @@ proc call*(av: ToxAV; friend: Friend; audioBitRate = 0; videoBitRate = 0): bool 
  ## receiving are both enabled by default.
  proc call(av: AvCore; friend: Friend; audio_bit_rate: uint32;
      video_bit_rate: uint32; error: ptr Err_Call): bool {.ctoxProc.}
  var err: Err_Call
  result = call(av.core, friend, (uint32)audioBitRate, (uint32)videoBitRate, addr err)
  ctoxAssert(TOXAV_ERR_CALL_OK, err)

  ctoxCheck(TOXAV_ERR_CALL_OK) do:
    result = call(av.core, friend, (uint32)audioBitRate, (uint32)videoBitRate, err)

type Err_Answer* {.ctoxError.} = enum
  TOXAV_ERR_ANSWER_OK,


@@ 248,9 251,8 @@ proc answer*(av: ToxAV; friend: Friend;
  proc answer(
    av: AvCore; friend: Friend; audio_bit_rate: uint32;
    video_bit_rate: uint32; error: ptr Err_Answer): bool {.ctoxProc.}
  var err: Err_Answer
  result = answer(av.core, friend, audioBitRate.uint32, videoBitRate.uint32, addr err)
  ctoxAssert(TOXAV_ERR_ANSWER_OK, err)
  ctoxCheck(TOXAV_ERR_ANSWER_OK) do:
    result = answer(av.core, friend, audioBitRate.uint32, videoBitRate.uint32, err)

var
  FRIEND_CALL_STATE_NONE* {.ctoxConst.}: uint32


@@ 316,9 318,8 @@ proc callControl*(av: ToxAV; friend: Friend; control: CallControl): bool =
  proc call_control(
    av: AvCore; friend: Friend; control: CALL_CONTROL;
    error: ptr Err_Call_Control): bool {.ctoxProc.}
  var err: Err_Call_Control
  result = call_control(av.core, friend, control, addr err)
  ctoxAssert(TOXAV_ERR_CALL_CONTROL_OK, err)
  ctoxCheck(TOXAV_ERR_CALL_CONTROL_OK) do:
    result = call_control(av.core, friend, control, err)


type Err_Bit_Rate_Set* {.ctoxError.} = enum


@@ 379,10 380,9 @@ proc audioSendFrame*(
    sample_count: csize_t; channels: uint8;
    sampling_rate: uint32;
    error: ptr Err_Send_Frame): bool {.ctoxProc.}
  var err: Err_Send_Frame
  result = audio_send_frame(av.core, friend, pcm, sampleCount, channels,
      samplingRate, addr err)
  ctoxAssert(TOXAV_ERR_SEND_FRAME_OK, err)
  ctoxCheck(TOXAV_ERR_SEND_FRAME_OK) do:
    result = audio_send_frame(
        av.core, friend, pcm, sampleCount, channels, samplingRate, err)


proc audioSetBitRate*(av: ToxAv; friend: Friend; bitRate: uint32): bool =


@@ 391,9 391,8 @@ proc audioSetBitRate*(av: ToxAv; friend: Friend; bitRate: uint32): bool =
  proc audio_set_bit_rate(
    av: AvCore; friend: Friend;
    bit_rate: uint32; error: ptr Err_Bit_Rate_Set): bool {.ctoxProc.}
  var err: Err_Bit_Rate_Set
  result = audio_set_bit_rate(av.core, friend, bitRate, addr err)
  ctoxAssert(TOXAV_ERR_BIT_RATE_SET_OK, err)
  ctoxCheck(TOXAV_ERR_BIT_RATE_SET_OK) do:
    result = audio_set_bit_rate(av.core, friend, bitRate, err)


proc videoSendFrame*(


@@ 409,9 408,8 @@ proc videoSendFrame*(
  proc video_send_frame(
      av: AvCore; friend: Friend; width: uint16;
      height: uint16; y, u, v: ptr uint8; error: ptr Err_Send_Frame): bool {.ctoxProc.}
  var err: Err_Send_Frame
  result = video_send_frame(av.core, friend, width, height, y, u, v, addr err)
  ctoxAssert(TOXAV_ERR_SEND_FRAME_OK, err)
  ctoxCheck(TOXAV_ERR_SEND_FRAME_OK) do:
    result = video_send_frame(av.core, friend, width, height, y, u, v, err)

proc videoSetBitRate*(av: ToxAv; friend: Friend; bitRate: uint32): bool =
  ## Set the bit rate to be used in subsequent video frames.


@@ 419,9 417,8 @@ proc videoSetBitRate*(av: ToxAv; friend: Friend; bitRate: uint32): bool =
  proc video_set_bit_rate(
      av: AvCore; friend: Friend;
      bit_rate: uint32; error: ptr Err_Bit_Rate_Set): bool {.ctoxProc.}
  var err: Err_Bit_Rate_Set
  result = video_set_bit_rate(av.core, friend, bitRate, addr err)
  ctoxAssert(TOXAV_ERR_BIT_RATE_SET_OK, err)
  ctoxCheck(TOXAV_ERR_BIT_RATE_SET_OK) do:
    result = video_set_bit_rate(av.core, friend, bitRate, err)

proc groupSendAudio*(
    av: ToxAv; group: Conference; pcm: ptr int16;