TGC Codebase Backup



DBChat by moqzart

7th Nov 2006 5:13
Summary

A chat program with voice recording



Description

V 1.02 adds and mods
--------------------
* Now sends greeting sound named "<CLIENT NAME>.WAV" if file is present in working folder.
This sounds gets sent only when you join the session.
* Added "default.bmp" for client image where there isn't any client image file. Now there
will always be a client image sent.
* Moved client images to righthand side and adjusted printing of client names to suit.
* History array now changed to TYPE STRINGMSG which includes SENDER, RECEIVER and TIMESTAMP
values.
* SPAWN image is now just the DEFAULT image tinted blue.
Other notes and issues:
# When you spawn a new client process it will identify itself as "SPAWN" and will look for
"SPAWN.BMP" and "SPAWN.WAV" in the working directory and sends them if present. It seems
that you won't hear the sound unless you focus back to the process window it was spawned
from before it gets sent.
# Spawning more than one new client process may trigger the Data Execution Protection. I have
had this happen to other programs that I have written and even the DB Compiler has triggered
it. I have no idea what causes this to happen. If your hardware uses DEP, the OS will allow
you to exclude your program from DEP, but I have no idea how to turn off DEP globally.
I don't recommend that you use the spawn feature anyway since it's purpose is to allow me to
test the code.
# Voice Chat Mode will not work with the spawned client since you can't swap between windows
quick enough to hear what you are sending.
# Client image must be 134x174 pixels. Please keep to this standard.

V 1.01 adds and mods
--------------------
* Added sound recording for voice communication. (Can't get it to work properly yet).
* Added client image sending and receiving (client image must be in working folder and named
"<CLIENT NAME>.BMP". Your own client image is sent to all existing clients when you join the
session and sent to any new clients as they join the session.
* Modified spawned client chat, now automatically calls itself "SPAWNED".
* Dropped user select window sizing.
* Added Voice Status line at the top of display.

V 1.0 features
--------------
* Text input with cursor movement, backspace, delete.
* Message History stored in string array.
* Displays names of chat clients and host.
* Displays local time and date.
* F1 key spawns new instance of chat. This is to allow me to test chat features.
* User selected window sizing.



Code
                                    ` This code was downloaded from The Game Creators
                                    ` It is reproduced here with full permission
                                    ` http://www.thegamecreators.com
                                    
                                    REM Project: Dark Basic Chat
REM Created: 14/10/2006 8:26:58 PM
REM
REM ***** Main Source File *****
REM
REM CHAT PROGRAM BY MOQZART
REM
REM ------------------------------------------------------------
#CONSTANT KB_BKSPC     14
#CONSTANT KB_ENTER     28
#CONSTANT KB_DELETE   211
#CONSTANT KB_LTARROW  203
#CONSTANT KB_RTARROW  205
#CONSTANT KB_FUNC1     59
#CONSTANT KB_FUNC2     60
REM ------------------------------------------------------------
#CONSTANT NETMESSAGE_INTEGER  1
#CONSTANT NETMESSAGE_FLOAT    2
#CONSTANT NETMESSAGE_STRING   3
#CONSTANT NETMESSAGE_MEMBLOCK 4
#CONSTANT NETMESSAGE_IMAGE    5
#CONSTANT NETMESSAGE_BITMAP   6
#CONSTANT NETMESSAGE_SOUND    7
#CONSTANT NETMESSAGE_MESH     8
REM ------------------------------------------------------------
TYPE STRINGMSG
  SENDER    AS INTEGER
  RECEIVER  AS INTEGER
  MSG$      AS STRING
  TIMESTAMP AS DWORD
ENDTYPE
REM ------------------------------------------------------------
DIM HISTORY() AS STRINGMSG
VOICECHAT       AS BOOLEAN
SOUNDBUFSZ      AS INTEGER
`GLOBAL NAME$
`GLOBAL GAME$
REM ------------------------------------------------------------
scrWidth  = 800
scrHeight = 600
scrDepth  = 16
WDWWIDTH  = scrWidth
WDWHEIGHT = scrHeight
CopyRight$="©2006 - Moqzart."
Version$ = "Version 1.02"
Program$ = "DarkBASIC Chat"
REM ------------------------------------------------------------
SET DISPLAY MODE scrWidth,scrHeight,scrDepth
SET WINDOW ON
SET WINDOW POSITION 0,0
SET WINDOW SIZE WDWWIDTH,WDWHEIGHT
REM ------------------------------------------------------------
SET TEXT FONT "lucida console"
SET TEXT SIZE 11
SET TEXT TO NORMAL
SET TEXT OPAQUE
INK RGB(255,255,255),RGB(0,0,0)
REM ------------------------------------------------------------
DISPLAYCOLUMN = 0
DISPLAYTOPROW = TEXT HEIGHT(" ")
INPUTLINE = WDWHEIGHT - TEXT HEIGHT(" ")
MAXLINES = (INPUTLINE - 4) / TEXT HEIGHT(" ") - DISPLAYTOPROW
PLAYERCOLUMN = WDWWIDTH-134
MAXDISPLAYCHARS = PLAYERCOLUMN/TEXT WIDTH("O")
REM ------------------------------------------------------------
REM FIDDLE WITH THIS VALUE TO GET AN OPTIMUM RECORDING LENGTH
SOUNDBUFSZ = 2000 ` LENGTH OF SOUND IN MICROS (e.g. 100 = 1/10 SECOND)
ENDTIME = 0
REM ------------------------------------------------------------
CLS
IF CL$()="SPAWN"
  NAME$ = "Spawn"
ELSE
  INPUT "ENTER USER CHAT NAME: ",NAME$
ENDIF
IF NAME$ = "" THEN NAME$ = "Guest_"+STR$(TIMER())
GAME$ = Program$
SET WINDOW TITLE GAME$ + " - " + NAME$
REM ------------------------------------------------------------
MYNUMBER = DEFAULT NET GAME(GAME$,NAME$,255,1)
BMF$ = NAME$ + ".BMP" : SND$ = NAME$ + ".WAV" : DEF$="DEFAULT.BMP"
IF FILE EXIST(BMF$) THEN LOAD IMAGE BMF$,MYNUMBER,1
IF NOT IMAGE EXIST(MYNUMBER) THEN IF FILE EXIST(DEF$) THEN LOAD IMAGE DEF$,MYNUMBER,1
IF FILE EXIST(SND$) THEN LOAD SOUND SND$,MYNUMBER
REM ------------------------------------------------------------
IF NET GAME EXISTS() = 1
  EMPTY ARRAY HISTORY()
  BUFFER$ = ""
  CURSOR = 0
  MSG$ = NAME$ + " has joined session."
  MAKESTRINGMSG(MSG$,MYNUMBER,0)
  SEND NET MESSAGE STRING 0,HISTORY().MSG$
  IF IMAGE EXIST(MYNUMBER) THEN SEND NET MESSAGE IMAGE 0,MYNUMBER,1
  IF SOUND EXIST(MYNUMBER) THEN SEND NET MESSAGE SOUND 0,MYNUMBER,1 : DELETE SOUND MYNUMBER
ELSE
  PRINT "FAILED TO CONNECT!"
  WAIT KEY
  END
ENDIF
CLEAR ENTRY BUFFER
REM ------------------------------------------------------------
REM MAIN LOOP
REM ------------------------------------------------------------
SYNC ON
rem NOTE: Order of processing keyboard input is important as changing
rem       it can have a detrimental effect or it will simply not work
rem       properly.  It follows a logical order
DO
  CLS
  REM ------------------------------------------------------------
  REM CHECK STATUS
  REM ------------------------------------------------------------
  IF NET GAME LOST()
    MAKESTRINGMSG("YOU ARE NOW OFFLINE",0,MYNUMBER)
    MAKESTRINGMSG(" - PRESS ESCAPE KEY TO EXIT CHAT",0,MYNUMBER)
  ENDIF
  REM ------------------------------------------------------------
  REM CHECK FOR NEW CLIENT
  REM ------------------------------------------------------------
  NEW_CLIENT = NET PLAYER CREATED()
  IF NEW_CLIENT
    IF IMAGE EXIST(MYNUMBER) THEN SEND NET MESSAGE IMAGE NEW_CLIENT,MYNUMBER,1
  ENDIF
  REM ------------------------------------------------------------
  REM CHECK FOR CLIENT GONE
  REM ------------------------------------------------------------
  CLIENT = NET PLAYER DESTROYED()
  IF CLIENT
    IF IMAGE EXIST(CLIENT) THEN DELETE IMAGE CLIENT
  ENDIF
  REM ------------------------------------------------------------
  REM PROCESS HOST/CLIENT KEYBOARD INPUT
  REM ------------------------------------------------------------
  BUFFSZ = LEN(BUFFER$)
  S = SCANCODE()
  rem ------- process backspace, delete, cursor movement & non printables first
  SELECT S
    rem ------- delete char to left of cursor (backspace)
    CASE KB_BKSPC
      WHILE SCANCODE() = KB_BKSPC
      ENDWHILE
      IF CURSOR > 0
        IF CURSOR > BUFFSZ
          BUFFER$ = LEFT$(BUFFER$,BUFFSZ - 1)
        ELSE
          BUFFER$ = LEFT$(BUFFER$,CURSOR - 1) + RIGHT$(BUFFER$,BUFFSZ - CURSOR)
        ENDIF
        DEC CURSOR
      ENDIF
      CLEAR ENTRY BUFFER
    ENDCASE
    rem ------- delete character at cursor
    CASE KB_DELETE
      WHILE SCANCODE() = KB_DELETE
      ENDWHILE
      IF CURSOR <= BUFFSZ
        IF CURSOR = 1
          BUFFER$ = RIGHT$(BUFFER$,BUFFSZ - 1)
        ELSE
          BUFFER$ = LEFT$(BUFFER$,CURSOR) + RIGHT$(BUFFER$,BUFFSZ - CURSOR - 1)
        ENDIF
      ENDIF
      CLEAR ENTRY BUFFER
    ENDCASE
    rem ------ move cursor to the left
    CASE KB_LTARROW
      WHILE SCANCODE() = KB_LTARROW
      ENDWHILE
      IF CURSOR > 1 THEN DEC CURSOR
      CLEAR ENTRY BUFFER
    ENDCASE
    rem ------ move cursor to the right
    CASE KB_RTARROW
      `WHILE SCANCODE() = KB_RTARROW
      `ENDWHILE
      IF CURSOR < BUFFSZ THEN INC CURSOR
      CLEAR ENTRY BUFFER
    ENDCASE
    rem ------ spawn another chat
    CASE KB_FUNC1
      WHILE SCANCODE() = KB_FUNC1
      ENDWHILE
      CLEAR ENTRY BUFFER
      EXECUTE FILE "DBCHAT.EXE","SPAWN",""
    ENDCASE
    REM ------ TOGGLE VOICECHAT MODE
    CASE KB_FUNC2
      WHILE SCANCODE() = KB_FUNC2
      ENDWHILE
      CLEAR ENTRY BUFFER
      VOICECHAT = NOT VOICECHAT
      IF ENDTIME > 0
        STOP RECORDING SOUND
        SEND NET MESSAGE SOUND 0,MYNUMBER,1
        DELETE SOUND MYNUMBER
      ENDIF
    ENDCASE
    rem ------ add other keyboard shortcut commands here
  ENDSELECT
  REM ------------------------------------------------------------
  REM PROCESS PRINTABLE KETBOARD INPUT
  REM ------------------------------------------------------------
  BUFFSZ = LEN(BUFFER$)
  TMP$ = LEFT$(ENTRY$(),1)  ` take first character from buffer
  rem filter out non-printables
  IF TMP$ >= " " AND TMP$ <= "~"
    IF CURSOR > BUFFSZ
      BUFFER$ = BUFFER$ + TMP$
    ELSE
      BUFFER$ = LEFT$(BUFFER$,CURSOR) + TMP$ + RIGHT$(BUFFER$, BUFFSZ - CURSOR)
    ENDIF
    INC CURSOR
  ENDIF
  CLEAR ENTRY BUFFER `clear buffer
  REM ------------------------------------------------------------
  REM START VOICE RECORDING
  REM ------------------------------------------------------------
  IF VOICECHAT
    IF ENDTIME = 0
      ENDTIME = TIMER() + SOUNDBUFSZ       : REM SET BUFFER LENGTH
      RECORD SOUND MYNUMBER,SOUNDBUFSZ     : REM START RECORDING
    ENDIF
  ENDIF
  REM ------------------------------------------------------------
  REM STOP VOICE RECORDING
  REM ------------------------------------------------------------
  IF ENDTIME > 0
    IF TIMER() >= ENDTIME
      REM FILLED UP BUFFER SO SEND IT
      STOP RECORDING SOUND
      IF SOUND EXIST(MYNUMBER)
        SEND NET MESSAGE SOUND 0,MYNUMBER,1
        DELETE SOUND MYNUMBER
      ELSE
        MAKESTRINGMSG("SOUND ERROR",0,MYNUMBER)
      ENDIF
      ENDTIME = 0
    ENDIF
  ENDIF
  REM ------------------------------------------------------------
  REM DISPLAY HOST/CLIENT INPUT
  REM ------------------------------------------------------------
  TX = DISPLAYCOLUMN
  PROMPT$ = "> "
  TEXT TX,INPUTLINE,PROMPT$ : INC TX,TEXT WIDTH(PROMPT$)
  REM PRINT USER INPUT LINE --------------------------------------
  FOR I = 1 TO BUFFSZ
    TMP$ = MID$(BUFFER$,I)
    TEXT TX,INPUTLINE,TMP$
    INC TX,TEXT WIDTH(TMP$)
  NEXT I
  REM ------------------------------------------------------------
  REM DRAW THE CURSOR
  REM ------------------------------------------------------------
  X1 = TEXT WIDTH(PROMPT$+LEFT$(BUFFER$,CURSOR))
  X2 = X1
  Y1 = INPUTLINE
  Y2 = INPUTLINE + TEXT HEIGHT(PROMPT$)
  LINE X1,Y1,X2,Y2
  REM ------------------------------------------------------------
  REM HOST/CLIENT INPUT READY TO SEND
  REM ------------------------------------------------------------
  IF RETURNKEY() = 1
    WHILE RETURNKEY() = 1
    ENDWHILE
    IF BUFFER$ <> ""
      SENDSTRINGMSG(BUFFER$,MYNUMBER,0)
      BUFFER$ = ""
      CURSOR = 0
    ENDIF
    CLEAR ENTRY BUFFER
  ENDIF
  REM ------------------------------------------------------------
  REM PROCESS MESSAGES
  REM ------------------------------------------------------------
  GET NET MESSAGE
  PF = NET MESSAGE PLAYER FROM()
  PT = NET MESSAGE PLAYER TO()
  SELECT NET MESSAGE TYPE()
    CASE NETMESSAGE_STRING
      MSG$ = NET MESSAGE STRING$()
      IF MSG$<>""
        MAKESTRINGMSG(MSG$,PF,PT)
      ENDIF
    ENDCASE
    CASE NETMESSAGE_SOUND
      IF SOUND EXIST(PF) THEN STOP SOUND PF : DELETE SOUND PF : REM CATCH UP IF WE ARE TOO SLOW
      NET MESSAGE SOUND PF                                    : REM ALLOCATE THE SOUND
      IF SOUND EXIST(PF)
        PLAY SOUND PF                   : REM PLAY IT IF WE REALLY HAVE IT.
        MAKESTRINGMSG("SOUND #"+STR$(PF)+" BEING PLAYED",0,MYNUMBER)
      ENDIF
    ENDCASE
    CASE NETMESSAGE_IMAGE
      IF IMAGE EXIST(PF) THEN DELETE IMAGE PF
      NET MESSAGE IMAGE PF
    ENDCASE
  ENDSELECT
  REM ------------------------------------------------------------
  REM DISPLAY HOST/CLIENTS
  REM ------------------------------------------------------------
  TX = PLAYERCOLUMN
  TY = 0
  TMP$ = GET DATE$() + " " + GET TIME$()
  TEXT TX,TY,TMP$ : INC TY,TEXT HEIGHT(TMP$)
  TX = PLAYERCOLUMN
  TY = DISPLAYTOPROW
  PERFORM CHECKLIST FOR NET PLAYERS
  FOR I = 1 TO CHECKLIST QUANTITY()
    PN = CHECKLIST VALUE A(I)
    TMP$ = STR$(PN)
    TMP$ = TMP$ + ": " + CHECKLIST STRING$(I)
    IF CHECKLIST VALUE D(I) THEN TMP$ = TMP$ + " (host)"
    IF IMAGE EXIST(PN) THEN PASTE IMAGE PN,TX,TY : INC TY,174
    TEXT TX,TY,TMP$ : INC TY,TEXT HEIGHT(TMP$)
  NEXT I
  REM ------------------------------------------------------------
  REM DISPLAY STATUS LINE
  REM ------------------------------------------------------------
  TX = DISPLAYCOLUMN
  TY = 0
  T$ = "[F1=SPAWN] [F2=VOICE "
  IF VOICECHAT
    T$ = T$ + "OFF]"
  ELSE
    T$ = T$ + "ON ]"
  ENDIF
  IF ENDTIME > 0 THEN T$ = T$ + "Sbuf="+STR$(ENDTIME-TIMER())
  TEXT TX,TY,T$
  REM ------------------------------------------------------------
  REM DISPLAY MESSAGES
  REM ------------------------------------------------------------
  TX = DISPLAYCOLUMN
  TY = DISPLAYTOPROW
  COUNT = ARRAY COUNT(HISTORY())
  IF COUNT > MAXLINES THEN COUNT = MAXLINES
  FOR I = COUNT TO 0 STEP -1
    TEXT TX,TY,LEFT$(HISTORY(I).MSG$,MAXDISPLAYCHARS)
    INC TY,TEXT HEIGHT(HISTORY(I).MSG$)
  NEXT I
  SYNC
LOOP

FUNCTION SENDSTRINGMSG(MSG$,SENDER,RECEIVER)
  N$=GETPLAYERNAME(SENDER)
  ARRAY INSERT AT TOP HISTORY()
  HISTORY().TIMESTAMP = TIMER()
  HISTORY().SENDER = SENDER
  HISTORY().RECEIVER = RECEIVER
  HISTORY().MSG$ = N$ + ": " + MSG$
  SEND NET MESSAGE STRING RECEIVER,MSG$
ENDFUNCTION

FUNCTION MAKESTRINGMSG(MSG$,SENDER,RECEIVER)
  N$=GETPLAYERNAME(SENDER)
  ARRAY INSERT AT TOP HISTORY()
  HISTORY().TIMESTAMP = TIMER()
  HISTORY().SENDER = SENDER
  HISTORY().RECEIVER = RECEIVER
  HISTORY().MSG$ = N$ + ": " + MSG$
ENDFUNCTION

FUNCTION GETPLAYERNAME(PN)
  RETVAL$ = "???"
  IF PN = 0
    RETVAL$ = "SYSTEM"
  ELSE
    PERFORM CHECKLIST FOR NET PLAYERS
    FOR I = 1 TO CHECKLIST QUANTITY()
      P = CHECKLIST VALUE A(I)
      IF P = PN THEN RETVAL$ = CHECKLIST STRING$(I) : EXIT
    NEXT I
  ENDIF
ENDFUNCTION RETVAL$