iaxclient_lib.c

00001 /*
00002  * iaxclient: a cross-platform IAX softphone library
00003  *
00004  * Copyrights:
00005  * Copyright (C) 2003-2006, Horizon Wimba, Inc.
00006  * Copyright (C) 2007, Wimba, Inc.
00007  *
00008  * Contributors:
00009  * Steve Kann <stevek@stevek.com>
00010  * Michael Van Donselaar <mvand@vandonselaar.org>
00011  * Shawn Lawrence <shawn.lawrence@terracecomm.com>
00012  * Frik Strecker <frik@gatherworks.com>
00013  * Mihai Balea <mihai AT hates DOT ms>
00014  * Peter Grayson <jpgrayson@gmail.com>
00015  * Bill Cholewka <bcholew@gmail.com>
00016  *
00017  * This program is free software, distributed under the terms of
00018  * the GNU Lesser (Library) General Public License.
00019  */
00020 
00021 #include <assert.h>
00022 
00023 #if defined(WIN32) || defined(_WIN32_WCE)
00024 #include <stdlib.h>
00025 #endif
00026 
00027 /* Win32 has _vsnprintf instead of vsnprintf */
00028 #if ! HAVE_VSNPRINTF
00029 # if HAVE__VSNPRINTF
00030 #  define vsnprintf _vsnprintf
00031 # endif
00032 #endif
00033 
00034 #include "iaxclient_lib.h"
00035 #include "audio_portaudio.h"
00036 #include "audio_encode.h"
00037 #ifdef USE_VIDEO
00038 #include "video.h"
00039 #endif
00040 #include "iax-client.h"
00041 #include "jitterbuf.h"
00042 
00043 #if STDC_HEADERS
00044 # include <stdarg.h>
00045 #else
00046 # if HAVE_VARARGS_H
00047 #  include <varargs.h>
00048 # endif
00049 #endif
00050 
00051 #ifdef AUDIO_ALSA
00052 #include "audio_alsa.h"
00053 #endif
00054 
00055 #define IAXC_ERROR  IAXC_TEXT_TYPE_ERROR
00056 #define IAXC_STATUS IAXC_TEXT_TYPE_STATUS
00057 #define IAXC_NOTICE IAXC_TEXT_TYPE_NOTICE
00058 
00059 #define DEFAULT_CALLERID_NAME    "Not Available"
00060 #define DEFAULT_CALLERID_NUMBER  "7005551212"
00061 
00062 #undef JB_DEBUGGING
00063 
00064 /* configurable jitterbuffer options */
00065 static long jb_target_extra = -1;
00066 
00067 struct iaxc_registration
00068 {
00069         struct iax_session *session;
00070         struct timeval last;
00071         char host[256];
00072         char user[256];
00073         char pass[256];
00074         long refresh;
00075         int id;
00076         struct iaxc_registration *next;
00077 };
00078 
00079 static int next_registration_id = 0;
00080 static struct iaxc_registration *registrations = NULL;
00081 
00082 static struct iaxc_audio_driver audio_driver;
00083 
00084 static int audio_format_capability;
00085 static int audio_format_preferred;
00086 
00087 // Audio callback behavior
00088 // By default apps should let iaxclient handle audio
00089 static unsigned int audio_prefs = 0;
00090 
00091 void * post_event_handle = NULL;
00092 int post_event_id = 0;
00093 
00094 static int minimum_outgoing_framesize = 160; /* 20ms */
00095 
00096 static MUTEX iaxc_lock;
00097 static MUTEX event_queue_lock;
00098 
00099 static short iaxci_bound_port = -1;
00100 
00101 // default to use port 4569 unless set by iaxc_set_preferred_source_udp_port
00102 static int source_udp_port = IAX_DEFAULT_PORTNO;
00103 
00104 int iaxci_audio_output_mode = 0; // Normal
00105 
00106 int selected_call; // XXX to be protected by mutex?
00107 struct iaxc_call* calls;
00108 int max_calls; // number of calls for this library session
00109 
00110 static void service_network();
00111 static int service_audio();
00112 
00113 /* external global networking replacements */
00114 static iaxc_sendto_t iaxc_sendto = (iaxc_sendto_t)sendto;
00115 static iaxc_recvfrom_t iaxc_recvfrom = (iaxc_recvfrom_t)recvfrom;
00116 
00117 
00118 static THREAD main_proc_thread;
00119 #ifdef USE_VIDEO
00120 static THREAD video_proc_thread;
00121 #endif
00122 #if defined(WIN32) || defined(_WIN32_WCE)
00123 static THREADID main_proc_thread_id;
00124 #ifdef USE_VIDEO
00125 static THREADID video_proc_thread_id;
00126 #endif
00127 #endif
00128 
00129 /* 0 running, 1 should quit, -1 not running */
00130 static int main_proc_thread_flag = -1;
00131 #ifdef USE_VIDEO
00132 static int video_proc_thread_flag = -1;
00133 #endif
00134 
00135 static iaxc_event_callback_t iaxc_event_callback = NULL;
00136 
00137 // Internal queue of events, waiting to be posted once the library
00138 // lock is released.
00139 static iaxc_event *event_queue = NULL;
00140 
00141 // Lock the library
00142 static void get_iaxc_lock()
00143 {
00144         MUTEXLOCK(&iaxc_lock);
00145 }
00146 
00147 // Unlock the library and post any events that were queued in the meantime
00148 static void put_iaxc_lock()
00149 {
00150         iaxc_event *prev, *event;
00151 
00152         MUTEXLOCK(&event_queue_lock);
00153         event = event_queue;
00154         event_queue = NULL;
00155         MUTEXUNLOCK(&event_queue_lock);
00156 
00157         MUTEXUNLOCK(&iaxc_lock);
00158 
00159         while (event)
00160         {
00161                 iaxci_post_event(*event);
00162                 prev = event;
00163                 event = event->next;
00164                 free(prev);
00165         }
00166 }
00167 
00168 EXPORT void iaxc_set_audio_output(int mode)
00169 {
00170         iaxci_audio_output_mode = mode;
00171 }
00172 
00173 long iaxci_usecdiff(struct timeval * t0, struct timeval * t1)
00174 {
00175         return (t0->tv_sec - t1->tv_sec) * 1000000L + t0->tv_usec - t1->tv_usec;
00176 }
00177 
00178 long iaxci_msecdiff(struct timeval * t0, struct timeval * t1)
00179 {
00180         return iaxci_usecdiff(t0, t1) / 1000L;
00181 }
00182 
00183 EXPORT void iaxc_set_event_callback(iaxc_event_callback_t func)
00184 {
00185         iaxc_event_callback = func;
00186 }
00187 
00188 EXPORT int iaxc_set_event_callpost(void *handle, int id)
00189 {
00190         post_event_handle = handle;
00191         post_event_id = id;
00192         iaxc_event_callback = iaxci_post_event_callback;
00193         return 0;
00194 }
00195 
00196 EXPORT void iaxc_free_event(iaxc_event *e)
00197 {
00198         free(e);
00199 }
00200 
00201 EXPORT struct iaxc_ev_levels *iaxc_get_event_levels(iaxc_event *e)
00202 {
00203         return &e->ev.levels;
00204 }
00205 
00206 EXPORT struct iaxc_ev_text *iaxc_get_event_text(iaxc_event *e)
00207 {
00208         return &e->ev.text;
00209 }
00210 
00211 EXPORT struct iaxc_ev_call_state *iaxc_get_event_state(iaxc_event *e)
00212 {
00213         return &e->ev.call;
00214 }
00215 
00216 // Messaging functions
00217 static void default_message_callback(const char * message)
00218 {
00219         fprintf(stderr, "IAXCLIENT: %s\n", message);
00220 }
00221 
00222 // Post Events back to clients
00223 void iaxci_post_event(iaxc_event e)
00224 {
00225         if ( e.type == 0 )
00226         {
00227                 iaxci_usermsg(IAXC_ERROR,
00228                         "Error: something posted to us an invalid event");
00229                 return;
00230         }
00231 
00232         if ( MUTEXTRYLOCK(&iaxc_lock) )
00233         {
00234                 iaxc_event **tail;
00235 
00236                 /* We could not obtain the lock. Queue the event. */
00237                 MUTEXLOCK(&event_queue_lock);
00238                 tail = &event_queue;
00239                 e.next = NULL;
00240                 while ( *tail )
00241                         tail = &(*tail)->next;
00242                 *tail = (iaxc_event *)malloc(sizeof(iaxc_event));
00243                 memcpy(*tail, &e, sizeof(iaxc_event));
00244                 MUTEXUNLOCK(&event_queue_lock);
00245                 return;
00246         }
00247 
00248         /* TODO: This is not the best. Since we were able to get the
00249          * lock, we decide that it is okay to go ahead and do the
00250          * callback to the application. This is really nasty because
00251          * it gives the appearance of serialized callbacks, but in
00252          * reality, we could callback an application multiple times
00253          * simultaneously. So, as things stand, an application must
00254          * do some locking in their callback function to make it
00255          * reentrant. Barf. More ideally, iaxclient would guarantee
00256          * serialized callbacks to the application.
00257          */
00258         MUTEXUNLOCK(&iaxc_lock);
00259 
00260         if ( iaxc_event_callback )
00261         {
00262                 int rv;
00263 
00264                 rv = iaxc_event_callback(e);
00265 
00266                 if ( e.type == IAXC_EVENT_VIDEO )
00267                 {
00268                         /* We can free the frame data once it is off the
00269                          * event queue and has been processed by the client.
00270                          */
00271                         free(e.ev.video.data);
00272                 }
00273                 else if ( e.type == IAXC_EVENT_AUDIO )
00274                 {
00275                         free(e.ev.audio.data);
00276                 }
00277 
00278                 if ( rv < 0 )
00279                         default_message_callback(
00280                                 "IAXCLIENT: BIG PROBLEM, event callback returned failure!");
00281                 // > 0 means processed
00282                 if ( rv > 0 )
00283                         return;
00284 
00285                 // else, fall through to "defaults"
00286         }
00287 
00288         switch ( e.type )
00289         {
00290                 case IAXC_EVENT_TEXT:
00291                         default_message_callback(e.ev.text.message);
00292                         // others we just ignore too
00293                         return;
00294         }
00295 }
00296 
00297 
00298 void iaxci_usermsg(int type, const char *fmt, ...)
00299 {
00300         va_list args;
00301         iaxc_event e;
00302 
00303         e.type = IAXC_EVENT_TEXT;
00304         e.ev.text.type = type;
00305         e.ev.text.callNo = -1;
00306         va_start(args, fmt);
00307         vsnprintf(e.ev.text.message, IAXC_EVENT_BUFSIZ, fmt, args);
00308         va_end(args);
00309 
00310         iaxci_post_event(e);
00311 }
00312 
00313 
00314 void iaxci_do_levels_callback(float input, float output)
00315 {
00316         iaxc_event e;
00317         e.type = IAXC_EVENT_LEVELS;
00318         e.ev.levels.input = input;
00319         e.ev.levels.output = output;
00320         iaxci_post_event(e);
00321 }
00322 
00323 void iaxci_do_state_callback(int callNo)
00324 {
00325         iaxc_event e;
00326         if ( callNo < 0 || callNo >= max_calls )
00327                 return;
00328         e.type = IAXC_EVENT_STATE;
00329         e.ev.call.callNo = callNo;
00330         e.ev.call.state = calls[callNo].state;
00331         e.ev.call.format = calls[callNo].format;
00332         e.ev.call.vformat = calls[callNo].vformat;
00333         strncpy(e.ev.call.remote,        calls[callNo].remote,        IAXC_EVENT_BUFSIZ);
00334         strncpy(e.ev.call.remote_name,   calls[callNo].remote_name,   IAXC_EVENT_BUFSIZ);
00335         strncpy(e.ev.call.local,         calls[callNo].local,         IAXC_EVENT_BUFSIZ);
00336         strncpy(e.ev.call.local_context, calls[callNo].local_context, IAXC_EVENT_BUFSIZ);
00337         iaxci_post_event(e);
00338 }
00339 
00340 void iaxci_do_registration_callback(int id, int reply, int msgcount)
00341 {
00342         iaxc_event e;
00343         e.type = IAXC_EVENT_REGISTRATION;
00344         e.ev.reg.id = id;
00345         e.ev.reg.reply = reply;
00346         e.ev.reg.msgcount = msgcount;
00347         iaxci_post_event(e);
00348 }
00349 
00350 void iaxci_do_audio_callback(int callNo, unsigned int ts, int source,
00351                 int encoded, int format, int size, unsigned char *data)
00352 {
00353         iaxc_event e;
00354 
00355         e.type = IAXC_EVENT_AUDIO;
00356         e.ev.audio.ts = ts;
00357         e.ev.audio.encoded = encoded;
00358         assert(source == IAXC_SOURCE_REMOTE || source == IAXC_SOURCE_LOCAL);
00359         e.ev.audio.source = source;
00360         e.ev.audio.size = size;
00361         e.ev.audio.callNo = callNo;
00362         e.ev.audio.format = format;
00363 
00364         e.ev.audio.data = (unsigned char *)malloc(size);
00365 
00366         if ( !e.ev.audio.data )
00367         {
00368                 iaxci_usermsg(IAXC_ERROR,
00369                                 "failed to allocate memory for audio event");
00370                 return;
00371         }
00372 
00373         memcpy(e.ev.audio.data, data, size);
00374 
00375         iaxci_post_event(e);
00376 }
00377 
00378 static int iaxc_remove_registration_by_id(int id)
00379 {
00380         struct iaxc_registration *curr, *prev;
00381         int count = 0;
00382         for ( prev = NULL, curr = registrations; curr != NULL;
00383                         prev = curr, curr = curr->next )
00384         {
00385                 if ( curr->id == id )
00386                 {
00387                         count++;
00388                         if ( curr->session != NULL )
00389                                 iax_destroy( curr->session );
00390                         if ( prev != NULL )
00391                                 prev->next = curr->next;
00392                         else
00393                                 registrations = curr->next;
00394                         free( curr );
00395                         break;
00396                 }
00397         }
00398         return count;
00399 }
00400 
00401 EXPORT int iaxc_first_free_call()
00402 {
00403         int i;
00404         for ( i = 0; i < max_calls; i++ )
00405                 if ( calls[i].state == IAXC_CALL_STATE_FREE )
00406                         return i;
00407 
00408         return -1;
00409 }
00410 
00411 
00412 static void iaxc_clear_call(int toDump)
00413 {
00414         // XXX libiax should handle cleanup, I think..
00415         calls[toDump].state = IAXC_CALL_STATE_FREE;
00416         calls[toDump].format = 0;
00417         calls[toDump].vformat = 0;
00418         calls[toDump].session = NULL;
00419         iaxci_do_state_callback(toDump);
00420 }
00421 
00422 /* select a call.  */
00423 /* XXX Locking??  Start/stop audio?? */
00424 EXPORT int iaxc_select_call(int callNo)
00425 {
00426         // continue if already selected?
00427         //if ( callNo == selected_call ) return;
00428 
00429         if ( callNo >= max_calls )
00430         {
00431                 iaxci_usermsg(IAXC_ERROR, "Error: tried to select out_of_range call %d", callNo);
00432                 return -1;
00433         }
00434 
00435         // callNo < 0 means no call selected (i.e. all on hold)
00436         if ( callNo < 0 )
00437         {
00438                 if ( selected_call >= 0 )
00439                 {
00440                         calls[selected_call].state &= ~IAXC_CALL_STATE_SELECTED;
00441                 }
00442                 selected_call = callNo;
00443                 return 0;
00444         }
00445 
00446         // de-select and notify the old call if not also the new call
00447         if ( callNo != selected_call )
00448         {
00449                 if ( selected_call >= 0 )
00450                 {
00451                         calls[selected_call].state &= ~IAXC_CALL_STATE_SELECTED;
00452                         iaxci_do_state_callback(selected_call);
00453                 }
00454                 selected_call = callNo;
00455                 calls[selected_call].state |= IAXC_CALL_STATE_SELECTED;
00456         }
00457 
00458         // if it's an incoming call, and ringing, answer it.
00459         if ( !(calls[selected_call].state & IAXC_CALL_STATE_OUTGOING) &&
00460               (calls[selected_call].state & IAXC_CALL_STATE_RINGING) )
00461         {
00462                 iaxc_answer_call(selected_call);
00463         } else
00464         {
00465                 // otherwise just update state (answer does this for us)
00466                 iaxci_do_state_callback(selected_call);
00467         }
00468 
00469         return 0;
00470 }
00471 
00472 /* external API accessor */
00473 EXPORT int iaxc_selected_call()
00474 {
00475         return selected_call;
00476 }
00477 
00478 EXPORT void iaxc_set_networking(iaxc_sendto_t st, iaxc_recvfrom_t rf)
00479 {
00480         iaxc_sendto = st;
00481         iaxc_recvfrom = rf;
00482 }
00483 
00484 EXPORT void iaxc_set_jb_target_extra( long value )
00485 {
00486         /* store in jb_target_extra, a static global */
00487         jb_target_extra = value;
00488 }
00489 
00490 static void jb_errf(const char *fmt, ...)
00491 {
00492         va_list args;
00493         char buf[1024];
00494 
00495         va_start(args, fmt);
00496         vsnprintf(buf, 1024, fmt, args);
00497         va_end(args);
00498 
00499         iaxci_usermsg(IAXC_ERROR, buf);
00500 }
00501 
00502 static void jb_warnf(const char *fmt, ...)
00503 {
00504         va_list args;
00505         char buf[1024];
00506 
00507         va_start(args, fmt);
00508         vsnprintf(buf, 1024, fmt, args);
00509         va_end(args);
00510 
00511         iaxci_usermsg(IAXC_NOTICE, buf);
00512 }
00513 
00514 #ifdef JB_DEBUGGING
00515 static void jb_dbgf(const char *fmt, ...)
00516 {
00517         va_list args;
00518 
00519         va_start(args, fmt);
00520         vfprintf(stderr, fmt, args);
00521         va_end(args);
00522 }
00523 #endif
00524 
00525 static void setup_jb_output()
00526 {
00527 #ifdef JB_DEBUGGING
00528         jb_setoutput(jb_errf, jb_warnf, jb_dbgf);
00529 #else
00530         jb_setoutput(jb_errf, jb_warnf, NULL);
00531 #endif
00532 }
00533 
00534 // Note: Must be called before iaxc_initialize()
00535 EXPORT void iaxc_set_preferred_source_udp_port(int port)
00536 {
00537         source_udp_port = port;
00538 }
00539 
00540 /* For "slow" systems. See iax.c code */
00541 EXPORT int iaxc_video_bypass_jitter(int mode)
00542 {
00543         /* TODO:
00544          * 1. When switching from jitter to no-jitter the buffer must be
00545          *    flushed of queued video packet and must be sent a key-frame
00546          *    to redraw the screen (partially done).
00547          * 2. When switching from no-jitter to jitter we must drop all
00548          *    enqueued events prior the mode change (must be touched
00549          *    iax_sched_del and iax_get_event).
00550          */
00551         return iax_video_bypass_jitter(calls[selected_call].session,mode);
00552 }
00553 
00554 EXPORT short iaxc_get_bind_port()
00555 {
00556         return iaxci_bound_port;
00557 }
00558 
00559 EXPORT int iaxc_initialize(int num_calls)
00560 {
00561         int i;
00562         int port;
00563 
00564         os_init();
00565 
00566         setup_jb_output();
00567 
00568         MUTEXINIT(&iaxc_lock);
00569         MUTEXINIT(&event_queue_lock);
00570 
00571         iaxc_set_audio_prefs(0);
00572 
00573         if ( iaxc_recvfrom != (iaxc_recvfrom_t)recvfrom )
00574                 iax_set_networking(iaxc_sendto, iaxc_recvfrom);
00575 
00576         /* Note that iax_init() only sets up the receive port when the
00577          * sendto/recvfrom functions have not been replaced. We need
00578          * to call iaxc_init in either case because there is other
00579          * initialization beyond the socket setup that needs to be done.
00580          */
00581         if ( (port = iax_init(source_udp_port)) < 0 )
00582         {
00583                 iaxci_usermsg(IAXC_ERROR,
00584                                 "Fatal error: failed to initialize iax with port %d",
00585                                 port);
00586                 return -1;
00587         }
00588 
00589         if ( iaxc_recvfrom == (iaxc_recvfrom_t)recvfrom )
00590                 iaxci_bound_port = (short)port;
00591         else
00592                 iaxci_bound_port = -1;
00593 
00594         /* tweak the jitterbuffer settings */
00595         iax_set_jb_target_extra( jb_target_extra );
00596 
00597         max_calls = num_calls;
00598         /* initialize calls */
00599         if ( max_calls <= 0 )
00600                 max_calls = 1; /* 0 == Default? */
00601 
00602         /* calloc zeroes for us */
00603         calls = (struct iaxc_call *)calloc(sizeof(struct iaxc_call), max_calls);
00604         if ( !calls )
00605         {
00606                 iaxci_usermsg(IAXC_ERROR, "Fatal error: can't allocate memory");
00607                 return -1;
00608         }
00609 
00610         selected_call = -1;
00611 
00612         for ( i = 0; i < max_calls; i++ )
00613         {
00614                 strncpy(calls[i].callerid_name,   DEFAULT_CALLERID_NAME,   IAXC_EVENT_BUFSIZ);
00615                 strncpy(calls[i].callerid_number, DEFAULT_CALLERID_NUMBER, IAXC_EVENT_BUFSIZ);
00616         }
00617 
00618 #ifndef AUDIO_ALSA
00619         if ( pa_initialize(&audio_driver, 8000) )
00620         {
00621                 iaxci_usermsg(IAXC_ERROR, "failed pa_initialize");
00622                 return -1;
00623         }
00624 #else
00625         /* TODO: It is unknown whether this stuff for direct access to
00626          * alsa should be left in iaxclient. We're leaving it in here for
00627          * the time being, but unless it becomes clear that someone cares
00628          * about having it, it will be removed. Also note that portaudio
00629          * is capable of using alsa. This is another reason why this
00630          * direct alsa access may be unneeded.
00631          */
00632         if ( alsa_initialize(&audio_driver, 8000) )
00633                 return -1;
00634 #endif
00635 
00636         audio_format_capability =
00637                 IAXC_FORMAT_ULAW |
00638                 IAXC_FORMAT_ALAW |
00639 #ifdef CODEC_GSM
00640                 IAXC_FORMAT_GSM |
00641 #endif
00642                 IAXC_FORMAT_SPEEX;
00643         audio_format_preferred = IAXC_FORMAT_SPEEX;
00644 
00645 #ifdef USE_VIDEO
00646         if ( video_initialize() )
00647         {
00648                 iaxci_usermsg(IAXC_ERROR,
00649                                 "iaxc_initialize: cannot initialize video!\n");
00650         }
00651 #endif
00652 
00653         return 0;
00654 }
00655 
00656 EXPORT void iaxc_shutdown()
00657 {
00658         iaxc_dump_all_calls();
00659 
00660         get_iaxc_lock();
00661 
00662         audio_driver.destroy(&audio_driver);
00663 #ifdef USE_VIDEO
00664         video_destroy();
00665 #endif
00666 
00667         put_iaxc_lock();
00668 #ifdef WIN32
00669         closesocket(iax_get_fd()); //fd:
00670 #endif
00671 
00672         free(calls);
00673 
00674         MUTEXDESTROY(&event_queue_lock);
00675         MUTEXDESTROY(&iaxc_lock);
00676 }
00677 
00678 
00679 EXPORT void iaxc_set_formats(int preferred, int allowed)
00680 {
00681         audio_format_capability = allowed;
00682         audio_format_preferred = preferred;
00683 }
00684 
00685 EXPORT void iaxc_set_min_outgoing_framesize(int samples)
00686 {
00687         minimum_outgoing_framesize = samples;
00688 }
00689 
00690 EXPORT void iaxc_set_callerid(const char * name, const char * number)
00691 {
00692         int i;
00693 
00694         for ( i = 0; i < max_calls; i++ )
00695         {
00696                 strncpy(calls[i].callerid_name,   name,   IAXC_EVENT_BUFSIZ);
00697                 strncpy(calls[i].callerid_number, number, IAXC_EVENT_BUFSIZ);
00698         }
00699 }
00700 
00701 static void iaxc_note_activity(int callNo)
00702 {
00703         if ( callNo < 0 )
00704                 return;
00705         gettimeofday(&calls[callNo].last_activity, NULL);
00706 }
00707 
00708 static void iaxc_refresh_registrations()
00709 {
00710         struct iaxc_registration *cur;
00711         struct timeval now;
00712 
00713         gettimeofday(&now,NULL);
00714 
00715         for ( cur = registrations; cur != NULL; cur = cur->next )
00716         {
00717                 // If there is less than one second before the registration is about
00718                 // to expire, renew it.
00719                 if ( iaxci_usecdiff(&now, &cur->last) > cur->refresh - 1 * 1000 *1000 )
00720                 {
00721                         if ( cur->session != NULL )
00722                         {
00723                                 iax_destroy( cur->session );
00724                         }
00725                         cur->session = iax_session_new();
00726                         if ( !cur->session )
00727                         {
00728                                 iaxci_usermsg(IAXC_ERROR, "Can't make new registration session");
00729                                 return;
00730                         }
00731                         iax_register(cur->session, cur->host, cur->user, cur->pass, 60);
00732                         cur->last = now;
00733                 }
00734         }
00735 }
00736 
00737 #define LOOP_SLEEP 5 // In ms
00738 static THREADFUNCDECL(main_proc_thread_func)
00739 {
00740         static int refresh_registration_count = 0;
00741 
00742         THREADFUNCRET(ret);
00743 
00744         /* Increase Priority */
00745         iaxci_prioboostbegin();
00746 
00747         while ( !main_proc_thread_flag )
00748         {
00749                 get_iaxc_lock();
00750 
00751                 service_network();
00752                 service_audio();
00753 
00754                 // Check registration refresh once a second
00755                 if ( refresh_registration_count++ > 1000/LOOP_SLEEP )
00756                 {
00757                         iaxc_refresh_registrations();
00758                         refresh_registration_count = 0;
00759                 }
00760 
00761                 put_iaxc_lock();
00762 
00763                 iaxc_millisleep(LOOP_SLEEP);
00764         }
00765 
00766         /* Decrease priority */
00767         iaxci_prioboostend();
00768 
00769         main_proc_thread_flag = -1;
00770 
00771         return ret;
00772 }
00773 
00774 #ifdef USE_VIDEO
00775 static THREADFUNCDECL(video_proc_thread_func)
00776 {
00777         struct iaxc_call *call;
00778 
00779         while ( !video_proc_thread_flag )
00780         {
00781                 if (selected_call >= 0)
00782                         call = &calls[selected_call];
00783                 else
00784                         call = NULL;
00785 
00786                 video_send_video(call, selected_call);
00787                 video_send_stats(call);
00788 
00789                 // Tight spinloops are bad, mmmkay?
00790                 iaxc_millisleep(LOOP_SLEEP);
00791         }
00792 
00793         video_proc_thread_flag = -1;
00794 
00795         return 0;
00796 }
00797 #endif
00798 
00799 EXPORT int iaxc_start_processing_thread()
00800 {
00801         main_proc_thread_flag = 0;
00802 
00803         if ( THREADCREATE(main_proc_thread_func, NULL, main_proc_thread,
00804                                 main_proc_thread_id) == THREADCREATE_ERROR)
00805                 return -1;
00806 
00807 #ifdef USE_VIDEO
00808         video_proc_thread_flag = 0;
00809 
00810         if ( THREADCREATE(video_proc_thread_func, NULL, video_proc_thread,
00811                                 video_proc_thread_id) == THREADCREATE_ERROR)
00812                 return -1;
00813 #endif
00814 
00815         return 0;
00816 }
00817 
00818 EXPORT int iaxc_stop_processing_thread()
00819 {
00820         if ( main_proc_thread_flag >= 0 )
00821         {
00822                 main_proc_thread_flag = 1;
00823                 THREADJOIN(main_proc_thread);
00824         }
00825 
00826 #ifdef USE_VIDEO
00827         if ( video_proc_thread_flag >= 0 )
00828         {
00829                 video_proc_thread_flag = 1;
00830                 THREADJOIN(video_proc_thread);
00831         }
00832 #endif
00833 
00834         return 0;
00835 }
00836 
00837 static int service_audio()
00838 {
00839         /* TODO: maybe we shouldn't allocate 8kB on the stack here. */
00840         short buf [4096];
00841 
00842         int want_send_audio =
00843                 selected_call >= 0 &&
00844                 ((calls[selected_call].state & IAXC_CALL_STATE_OUTGOING) ||
00845                  (calls[selected_call].state & IAXC_CALL_STATE_COMPLETE))
00846                 && !(audio_prefs & IAXC_AUDIO_PREF_SEND_DISABLE);
00847 
00848         int want_local_audio =
00849                 (audio_prefs & IAXC_AUDIO_PREF_RECV_LOCAL_RAW) ||
00850                 (audio_prefs & IAXC_AUDIO_PREF_RECV_LOCAL_ENCODED);
00851 
00852         if ( want_local_audio || want_send_audio )
00853         {
00854                 for ( ;; )
00855                 {
00856                         int to_read;
00857                         int cmin;
00858 
00859                         audio_driver.start(&audio_driver);
00860 
00861                         /* use codec minimum if higher */
00862                         cmin = want_send_audio && calls[selected_call].encoder ?
00863                                 calls[selected_call].encoder->minimum_frame_size :
00864                                 1;
00865 
00866                         to_read = cmin > minimum_outgoing_framesize ?
00867                                 cmin : minimum_outgoing_framesize;
00868 
00869                         /* Round up to the next multiple */
00870                         if ( to_read % cmin )
00871                                 to_read += cmin - (to_read % cmin);
00872 
00873                         if ( to_read > (int)(sizeof(buf) / sizeof(short)) )
00874                         {
00875                                 fprintf(stderr,
00876                                         "internal error: to_read > sizeof(buf)\n");
00877                                 exit(1);
00878                         }
00879 
00880                         /* Currently pa gives us either all the bits we ask for or none */
00881                         if ( audio_driver.input(&audio_driver, buf, &to_read) )
00882                         {
00883                                 iaxci_usermsg(IAXC_ERROR, "ERROR reading audio\n");
00884                                 break;
00885                         }
00886 
00887                         /* Frame was not available */
00888                         if ( !to_read )
00889                                 break;
00890 
00891                         if ( audio_prefs & IAXC_AUDIO_PREF_RECV_LOCAL_RAW )
00892                                 iaxci_do_audio_callback(selected_call, 0,
00893                                                 IAXC_SOURCE_LOCAL, 0, 0,
00894                                                 to_read * 2, (unsigned char *)buf);
00895 
00896                         if ( want_send_audio )
00897                                 audio_send_encoded_audio(&calls[selected_call],
00898                                                 selected_call, buf,
00899                                                 calls[selected_call].format &
00900                                                         IAXC_AUDIO_FORMAT_MASK,
00901                                                 to_read);
00902                 }
00903         }
00904         else
00905         {
00906                 static int i = 0;
00907 
00908                 audio_driver.stop(&audio_driver);
00909 
00921                 if ( i++ % 50 == 0 )
00922                         iaxci_do_levels_callback(-99,-99);
00923         }
00924 
00925         return 0;
00926 }
00927 
00928 /* handle IAX text events */
00929 static void handle_text_event(struct iax_event *e, int callNo)
00930 {
00931         iaxc_event ev;
00932         int        len;
00933 
00934         if ( callNo < 0 )
00935                 return;
00936 
00937         memset(&ev, 0, sizeof(iaxc_event));
00938         ev.type = IAXC_EVENT_TEXT;
00939         ev.ev.text.type = IAXC_TEXT_TYPE_IAX;
00940         ev.ev.text.callNo = callNo;
00941 
00942         len = e->datalen <= IAXC_EVENT_BUFSIZ - 1 ? e->datalen : IAXC_EVENT_BUFSIZ - 1;
00943         strncpy(ev.ev.text.message, (char *) e->data, len);
00944         iaxci_post_event(ev);
00945 }
00946 
00947 /* handle IAX URL events */
00948 void handle_url_event( struct iax_event *e, int callNo )
00949 {
00950         iaxc_event ev;
00951 
00952         if ( callNo < 0 )
00953                 return;
00954 
00955         ev.ev.url.callNo = callNo;
00956         ev.type = IAXC_EVENT_URL;
00957         strcpy( ev.ev.url.url, "" );
00958 
00959         switch ( e->subclass )
00960         {
00961                 case AST_HTML_URL:
00962                         ev.ev.url.type = IAXC_URL_URL;
00963                         if ( e->datalen )
00964                         {
00965                                 if ( e->datalen > IAXC_EVENT_BUFSIZ )
00966                                 {
00967                                         fprintf( stderr, "ERROR: URL too long %d > %d\n",
00968                                                         e->datalen, IAXC_EVENT_BUFSIZ );
00969                                 } else
00970                                 {
00971                                         strncpy( ev.ev.url.url, (char *) e->data, e->datalen );
00972                                 }
00973                         }
00974                         /* fprintf( stderr, "URL:%s\n", ev.ev.url.url ); */
00975                         break;
00976                 case AST_HTML_LINKURL:
00977                         ev.ev.url.type = IAXC_URL_LINKURL;
00978                         /* fprintf( stderr, "LINKURL event\n" ); */
00979                         break;
00980                 case AST_HTML_LDCOMPLETE:
00981                         ev.ev.url.type = IAXC_URL_LDCOMPLETE;
00982                         /* fprintf( stderr, "LDCOMPLETE event\n" ); */
00983                         break;
00984                 case AST_HTML_UNLINK:
00985                         ev.ev.url.type = IAXC_URL_UNLINK;
00986                         /* fprintf( stderr, "UNLINK event\n" ); */
00987                         break;
00988                 case AST_HTML_LINKREJECT:
00989                         ev.ev.url.type = IAXC_URL_LINKREJECT;
00990                         /* fprintf( stderr, "LINKREJECT event\n" ); */
00991                         break;
00992                 default:
00993                         fprintf( stderr, "Unknown URL event %d\n", e->subclass );
00994                         break;
00995         }
00996         iaxci_post_event( ev );
00997 }
00998 
00999 /* DANGER: bad things can happen if iaxc_netstat != iax_netstat.. */
01000 EXPORT int iaxc_get_netstats(int call, int *rtt, struct iaxc_netstat *local,
01001                 struct iaxc_netstat *remote)
01002 {
01003         return iax_get_netstats(calls[call].session, rtt,
01004                         (struct iax_netstat *)local,
01005                         (struct iax_netstat *)remote);
01006 }
01007 
01008 /* handle IAX text events */
01009 static void generate_netstat_event(int callNo)
01010 {
01011         iaxc_event ev;
01012 
01013         if ( callNo < 0 )
01014                 return;
01015 
01016         ev.type = IAXC_EVENT_NETSTAT;
01017         ev.ev.netstats.callNo = callNo;
01018 
01019         /* only post the event if the session is valid, etc */
01020         if ( !iaxc_get_netstats(callNo, &ev.ev.netstats.rtt,
01021                                 &ev.ev.netstats.local, &ev.ev.netstats.remote))
01022                 iaxci_post_event(ev);
01023 }
01024 
01025 static void handle_audio_event(struct iax_event *e, int callNo)
01026 {
01027         int total_consumed = 0;
01028         short fr[4096];
01029         const int fr_samples = sizeof(fr) / sizeof(short);
01030         int samples, format;
01031 #ifdef WIN32
01032         int cycles_max = 100; //fd:
01033 #endif
01034         struct iaxc_call *call;
01035 
01036         if ( callNo < 0 )
01037                 return;
01038 
01039         call = &calls[callNo];
01040 
01041         if ( callNo != selected_call )
01042         {
01043             /* drop audio for unselected call? */
01044             return;
01045         }
01046 
01047         samples = fr_samples;
01048         format = call->format & IAXC_AUDIO_FORMAT_MASK;
01049 
01050         do
01051         {
01052                 int bytes_decoded;
01053 
01054                 int mainbuf_delta = fr_samples - samples;
01055 
01056                 bytes_decoded = audio_decode_audio(call,
01057                                 fr,
01058                                 e->data + total_consumed,
01059                                 e->datalen - total_consumed,
01060                                 format,
01061                                 &samples);
01062 
01063                 if ( bytes_decoded < 0 )
01064                 {
01065                         iaxci_usermsg(IAXC_STATUS,
01066                                 "Bad or incomplete voice packet. Unable to decode. dropping");
01067                         return;
01068                 }
01069 
01070                 /* Pass encoded audio back to the app if required */
01071                 if ( audio_prefs & IAXC_AUDIO_PREF_RECV_REMOTE_ENCODED )
01072                         iaxci_do_audio_callback(callNo, e->ts, IAXC_SOURCE_REMOTE,
01073                                         1, format & IAXC_AUDIO_FORMAT_MASK,
01074                                         e->datalen - total_consumed,
01075                                         e->data + total_consumed);
01076 
01077 #ifdef WIN32
01078                 //fd: start: for some reason it loops here. Try to avoid it
01079                 cycles_max--;
01080                 if (cycles_max<0)
01081                 {
01082                         iaxc_millisleep(0);
01083                 }
01084                 //fd: end
01085 #endif
01086                 total_consumed += bytes_decoded;
01087                 if ( audio_prefs & IAXC_AUDIO_PREF_RECV_REMOTE_RAW )
01088                 {
01089                         // audio_decode_audio returns the number of samples.
01090                         // We are using 16 bit samples, so we need to double
01091                         // the number to obtain the size in bytes.
01092                         // format will also be 0 since this is raw audio
01093                         int size = (fr_samples - samples - mainbuf_delta) * 2;
01094                         iaxci_do_audio_callback(callNo, e->ts, IAXC_SOURCE_REMOTE,
01095                                         0, 0, size, (unsigned char *)fr);
01096                 }
01097 
01098                 if ( iaxci_audio_output_mode )
01099                         continue;
01100 
01101                 audio_driver.output(&audio_driver, fr,
01102                                 fr_samples - samples - mainbuf_delta);
01103         } while ( total_consumed < e->datalen );
01104 }
01105 
01106 #ifdef USE_VIDEO
01107 static void handle_video_event(struct iax_event *e, int callNo)
01108 {
01109         struct iaxc_call *call;
01110 
01111         if ( callNo < 0 )
01112                 return;
01113 
01114         if ( e->datalen == 0 )
01115         {
01116                 iaxci_usermsg(IAXC_STATUS, "Received 0-size packet. Unable to decode.");
01117                 return;
01118         }
01119 
01120         call = &calls[callNo];
01121 
01122         if ( callNo != selected_call )
01123         {
01124                 /* drop video for unselected call? */
01125                 return;
01126         }
01127 
01128         if ( call->vformat )
01129         {
01130                 if ( video_recv_video(call, selected_call, e->data,
01131                                         e->datalen, e->ts, call->vformat) < 0 )
01132                 {
01133                         iaxci_usermsg(IAXC_STATUS,
01134                                 "Bad or incomplete video packet. Unable to decode.");
01135                         return;
01136                 }
01137         }
01138 }
01139 #endif  /* USE_VIDEO */
01140 
01141 static void iaxc_handle_network_event(struct iax_event *e, int callNo)
01142 {
01143         if ( callNo < 0 )
01144                 return;
01145 
01146         iaxc_note_activity(callNo);
01147 
01148         switch ( e->etype )
01149         {
01150         case IAX_EVENT_NULL:
01151                 break;
01152         case IAX_EVENT_HANGUP:
01153                 iaxci_usermsg(IAXC_STATUS, "Call disconnected by remote");
01154                 // XXX does the session go away now?
01155                 iaxc_clear_call(callNo);
01156                 break;
01157         case IAX_EVENT_REJECT:
01158                 iaxci_usermsg(IAXC_STATUS, "Call rejected by remote");
01159                 iaxc_clear_call(callNo);
01160                 break;
01161         case IAX_EVENT_ACCEPT:
01162                 calls[callNo].format = e->ies.format & IAXC_AUDIO_FORMAT_MASK;
01163                 calls[callNo].vformat = e->ies.format & IAXC_VIDEO_FORMAT_MASK;
01164                 if ( !(e->ies.format & IAXC_VIDEO_FORMAT_MASK) )
01165                 {
01166                         iaxci_usermsg(IAXC_NOTICE,
01167                                         "Failed video codec negotiation.");
01168                 }
01169                 iaxci_usermsg(IAXC_STATUS,"Call %d accepted", callNo);
01170                 break;
01171         case IAX_EVENT_ANSWER:
01172                 calls[callNo].state &= ~IAXC_CALL_STATE_RINGING;
01173                 calls[callNo].state |= IAXC_CALL_STATE_COMPLETE;
01174                 iaxci_do_state_callback(callNo);
01175                 iaxci_usermsg(IAXC_STATUS,"Call %d answered", callNo);
01176                 //iaxc_answer_call(callNo);
01177                 // notify the user?
01178                 break;
01179         case IAX_EVENT_BUSY:
01180                 calls[callNo].state &= ~IAXC_CALL_STATE_RINGING;
01181                 calls[callNo].state |= IAXC_CALL_STATE_BUSY;
01182                 iaxci_do_state_callback(callNo);
01183                 iaxci_usermsg(IAXC_STATUS, "Call %d busy", callNo);
01184                 break;
01185         case IAX_EVENT_VOICE:
01186                 handle_audio_event(e, callNo);
01187                 if ((calls[callNo].state & IAXC_CALL_STATE_OUTGOING) && 
01188                     (calls[callNo].state & IAXC_CALL_STATE_RINGING) )
01189                 {
01190                         calls[callNo].state &= ~IAXC_CALL_STATE_RINGING;
01191                         iaxci_do_state_callback(callNo);
01192                         iaxci_usermsg(IAXC_STATUS,"Call %d progress",
01193                                      callNo);
01194                 }
01195                 break;
01196 #ifdef USE_VIDEO
01197         case IAX_EVENT_VIDEO:
01198                 // Mihai: why do we need to lower priority here?
01199                 // TODO: investigate
01200                 //iaxci_prioboostend();
01201                 handle_video_event(e, callNo);
01202                 //iaxci_prioboostbegin();
01203                 break;
01204 #endif
01205         case IAX_EVENT_TEXT:
01206                 handle_text_event(e, callNo);
01207                 break;
01208         case IAX_EVENT_RINGA:
01209                 calls[callNo].state |= IAXC_CALL_STATE_RINGING;
01210                 iaxci_do_state_callback(callNo);
01211                 iaxci_usermsg(IAXC_STATUS,"Call %d ringing", callNo);
01212                 break;
01213         case IAX_EVENT_PONG:
01214                 generate_netstat_event(callNo);
01215                 break;
01216         case IAX_EVENT_URL:
01217                 handle_url_event(e, callNo);
01218                 break;
01219         case IAX_EVENT_CNG:
01220                 /* ignore? */
01221                 break;
01222         case IAX_EVENT_TIMEOUT:
01223                 iax_hangup(e->session, "Call timed out");
01224                 iaxci_usermsg(IAXC_STATUS, "Call %d timed out.", callNo);
01225                 iaxc_clear_call(callNo);
01226                 break;
01227         case IAX_EVENT_TRANSFER:
01228                 calls[callNo].state |= IAXC_CALL_STATE_TRANSFER;
01229                 iaxci_do_state_callback(callNo);
01230                 iaxci_usermsg(IAXC_STATUS,"Call %d transfer released", callNo);
01231                 break;
01232         default:
01233                 iaxci_usermsg(IAXC_STATUS, "Unknown event: %d for call %d", e->etype, callNo);
01234                 break;
01235         }
01236 }
01237 
01238 EXPORT int iaxc_unregister( int id )
01239 {
01240         int count = 0;
01241         get_iaxc_lock();
01242         count = iaxc_remove_registration_by_id(id);
01243         put_iaxc_lock();
01244         return count;
01245 }
01246 
01247 EXPORT int iaxc_register(const char * user, const char * pass, const char * host)
01248 {
01249         struct iaxc_registration *newreg;
01250 
01251         newreg = (struct iaxc_registration *)malloc(sizeof (struct iaxc_registration));
01252         if ( !newreg )
01253         {
01254                 iaxci_usermsg(IAXC_ERROR, "Can't make new registration");
01255                 return -1;
01256         }
01257 
01258         get_iaxc_lock();
01259         newreg->session = iax_session_new();
01260         if ( !newreg->session )
01261         {
01262                 iaxci_usermsg(IAXC_ERROR, "Can't make new registration session");
01263                 put_iaxc_lock();
01264                 return -1;
01265         }
01266 
01267         gettimeofday(&newreg->last,NULL);
01268         newreg->refresh = 60*1000*1000;  /* 60 seconds, in usecs */
01269 
01270         strncpy(newreg->host, host, 256);
01271         strncpy(newreg->user, user, 256);
01272         strncpy(newreg->pass, pass, 256);
01273 
01274         /* send out the initial registration timeout 300 seconds */
01275         iax_register(newreg->session, host, user, pass, 300);
01276 
01277         /* add it to the list; */
01278         newreg->id = ++next_registration_id;
01279         newreg->next = registrations;
01280         registrations = newreg;
01281 
01282         put_iaxc_lock();
01283         return newreg->id;
01284 }
01285 
01286 static void codec_destroy( int callNo )
01287 {
01288         if ( calls[callNo].encoder )
01289         {
01290                 calls[callNo].encoder->destroy( calls[callNo].encoder );
01291                 calls[callNo].encoder = NULL;
01292         }
01293         if ( calls[callNo].decoder )
01294         {
01295                 calls[callNo].decoder->destroy( calls[callNo].decoder );
01296                 calls[callNo].decoder = NULL;
01297         }
01298         if ( calls[callNo].vdecoder )
01299         {
01300                 calls[callNo].vdecoder->destroy(calls[callNo].vdecoder);
01301                 calls[callNo].vdecoder = NULL;
01302         }
01303         if ( calls[callNo].vencoder )
01304         {
01305                 calls[callNo].vencoder->destroy(calls[callNo].vencoder);
01306                 calls[callNo].vencoder = NULL;
01307         }
01308 }
01309 
01310 EXPORT int iaxc_call(const char * num)
01311 {
01312         return iaxc_call_ex(num, NULL, NULL, 1);
01313 }
01314 
01315 EXPORT int iaxc_call_ex(const char *num, const char* callerid_name, const char* callerid_number, int video)
01316 {
01317         int video_format_capability = 0;
01318         int video_format_preferred = 0;
01319         int callNo = -1;
01320         struct iax_session *newsession;
01321         char *ext = strstr(num, "/");
01322 
01323         get_iaxc_lock();
01324 
01325         // if no call is selected, get a new appearance
01326         if (selected_call < 0)
01327         {
01328                 callNo = iaxc_first_free_call();
01329         } else
01330         {
01331                 // use selected call if not active, otherwise, get a new appearance
01332                 if (calls[selected_call].state  & IAXC_CALL_STATE_ACTIVE)
01333                 {
01334                         callNo = iaxc_first_free_call();
01335                 } else
01336                 {
01337                         callNo = selected_call;
01338                 }
01339         }
01340 
01341         if (callNo < 0)
01342         {
01343                 iaxci_usermsg(IAXC_STATUS, "No free call appearances");
01344                 goto iaxc_call_bail;
01345         }
01346 
01347         newsession = iax_session_new();
01348         if (!newsession)
01349         {
01350                 iaxci_usermsg(IAXC_ERROR, "Can't make new session");
01351                 goto iaxc_call_bail;
01352         }
01353 
01354         calls[callNo].session = newsession;
01355 
01356         codec_destroy( callNo );
01357 
01358         if (ext)
01359         {
01360                 strncpy(calls[callNo].remote_name, num, IAXC_EVENT_BUFSIZ);
01361                 strncpy(calls[callNo].remote,    ++ext, IAXC_EVENT_BUFSIZ);
01362         } else
01363         {
01364                 strncpy(calls[callNo].remote_name, num, IAXC_EVENT_BUFSIZ);
01365                 strncpy(calls[callNo].remote,      "" , IAXC_EVENT_BUFSIZ);
01366         }
01367 
01368         if (callerid_number != NULL)
01369                 strncpy(calls[callNo].callerid_number, callerid_number, IAXC_EVENT_BUFSIZ);
01370                 
01371         if (callerid_name != NULL)
01372                 strncpy(calls[callNo].callerid_name, callerid_name, IAXC_EVENT_BUFSIZ);
01373 
01374         strncpy(calls[callNo].local        , calls[callNo].callerid_name, IAXC_EVENT_BUFSIZ);
01375         strncpy(calls[callNo].local_context, "default", IAXC_EVENT_BUFSIZ);
01376 
01377         calls[callNo].state = IAXC_CALL_STATE_ACTIVE | IAXC_CALL_STATE_OUTGOING;
01378 
01379         /* reset activity and ping "timers" */
01380         iaxc_note_activity(callNo);
01381         calls[callNo].last_ping = calls[callNo].last_activity;
01382 
01383 #ifdef USE_VIDEO
01384         if (video)
01385                 iaxc_video_format_get_cap(&video_format_preferred, &video_format_capability);
01386 #endif
01387 
01388         iaxci_usermsg(IAXC_NOTICE, "Originating an %s call",
01389                         video_format_preferred ? "audio+video" : "audio only");
01390         iax_call(calls[callNo].session, calls[callNo].callerid_number,
01391                         calls[callNo].callerid_name, num, NULL, 0,
01392                         audio_format_preferred | video_format_preferred,
01393                         audio_format_capability | video_format_capability);
01394 
01395         // does state stuff also
01396         iaxc_select_call(callNo);
01397 
01398 iaxc_call_bail:
01399         put_iaxc_lock();
01400 
01401         return callNo;
01402 }
01403 
01404 EXPORT void iaxc_send_busy_on_incoming_call(int callNo)
01405 {
01406         if ( callNo < 0 )
01407                 return;
01408 
01409         iax_busy(calls[callNo].session);
01410 }
01411 
01412 EXPORT void iaxc_answer_call(int callNo)
01413 {
01414         if (callNo < 0) return;
01415 
01416         calls[callNo].state |= IAXC_CALL_STATE_COMPLETE;
01417         calls[callNo].state &= ~IAXC_CALL_STATE_RINGING;
01418         iax_answer(calls[callNo].session);
01419         iaxci_do_state_callback(callNo);
01420 }
01421 
01422 EXPORT void iaxc_blind_transfer_call(int callNo, const char * dest_extension)
01423 {
01424         if ((callNo < 0) ||
01425                         !(calls[callNo].state & IAXC_CALL_STATE_ACTIVE))
01426                 return;
01427 
01428         iax_transfer(calls[callNo].session, dest_extension);
01429 }
01430 
01431 EXPORT void iaxc_setup_call_transfer(int sourceCallNo, int targetCallNo)
01432 {
01433         if ((sourceCallNo < 0) || (targetCallNo < 0) ||
01434                         ((calls[sourceCallNo].state & IAXC_CALL_STATE_ACTIVE) == 0) || 
01435                         ((calls[targetCallNo].state & IAXC_CALL_STATE_ACTIVE) == 0))
01436                 return;
01437 
01438         iax_setup_transfer(calls[sourceCallNo].session, calls[targetCallNo].session);
01439 }
01440 
01441 static void iaxc_dump_one_call(int callNo)
01442 {
01443         if (callNo < 0)
01444                 return;
01445         if (calls[callNo].state == IAXC_CALL_STATE_FREE)
01446                 return;
01447 
01448         iax_hangup(calls[callNo].session,"Dumped Call");
01449         iaxci_usermsg(IAXC_STATUS, "Hanging up call %d", callNo);
01450         iaxc_clear_call(callNo);
01451 }
01452 
01453 EXPORT void iaxc_dump_all_calls(void)
01454 {
01455         int callNo;
01456         get_iaxc_lock();
01457         for ( callNo = 0; callNo < max_calls; callNo++ )
01458                 iaxc_dump_one_call(callNo);
01459         put_iaxc_lock();
01460 }
01461 
01462 
01463 EXPORT void iaxc_dump_call(void)
01464 {
01465         if (selected_call >= 0)
01466         {
01467                 get_iaxc_lock();
01468                 iaxc_dump_one_call(selected_call);
01469                 put_iaxc_lock();
01470         }
01471 }
01472 
01473 EXPORT void iaxc_reject_call(void)
01474 {
01475         if (selected_call >= 0)
01476         {
01477                 iaxc_reject_call_number(selected_call);
01478         }
01479 }
01480 
01481 EXPORT void iaxc_reject_call_number( int callNo )
01482 {
01483         if (callNo >= 0)
01484         {
01485                 get_iaxc_lock();
01486                 iax_reject(calls[callNo].session, "Call rejected manually.");
01487                 iaxc_clear_call(callNo);
01488                 put_iaxc_lock();
01489         }
01490 }
01491 
01492 EXPORT void iaxc_send_dtmf(char digit)
01493 {
01494         if (selected_call >= 0)
01495         {
01496                 get_iaxc_lock();
01497                 if (calls[selected_call].state & IAXC_CALL_STATE_ACTIVE)
01498                         iax_send_dtmf(calls[selected_call].session,digit);
01499                 put_iaxc_lock();
01500         }
01501 }
01502 
01503 EXPORT void iaxc_send_text(const char * text)
01504 {
01505         if (selected_call >= 0)
01506         {
01507                 get_iaxc_lock();
01508                 if (calls[selected_call].state & IAXC_CALL_STATE_ACTIVE)
01509                         iax_send_text(calls[selected_call].session, text);
01510                 put_iaxc_lock();
01511         }
01512 }
01513 
01514 EXPORT void iaxc_send_url(const char * url, int link)
01515 {
01516         if (selected_call >= 0)
01517         {
01518                 get_iaxc_lock();
01519                 if (calls[selected_call].state & IAXC_CALL_STATE_ACTIVE)
01520                         iax_send_url(calls[selected_call].session, url, link);
01521                 put_iaxc_lock();
01522         }
01523 }
01524 
01525 static int iaxc_find_call_by_session(struct iax_session *session)
01526 {
01527         int i;
01528         for ( i = 0; i < max_calls; i++ )
01529                 if (calls[i].session == session)
01530                         return i;
01531         return -1;
01532 }
01533 
01534 static struct iaxc_registration *iaxc_find_registration_by_session(
01535                 struct iax_session *session)
01536 {
01537         struct iaxc_registration *reg;
01538         for (reg = registrations; reg != NULL; reg = reg->next)
01539                 if (reg->session == session) break;
01540         return reg;
01541 }
01542 
01543 static void iaxc_handle_regreply(struct iax_event *e, struct iaxc_registration *reg)
01544 {
01545         iaxci_do_registration_callback(reg->id, e->etype, e->ies.msgcount);
01546 
01547         // XXX I think the session is no longer valid.. at least, that's
01548         // what miniphone does, and re-using the session doesn't seem to
01549         // work!
01550         iax_destroy(reg->session);
01551         reg->session = NULL;
01552 
01553         if (e->etype == IAX_EVENT_REGREJ)
01554         {
01555                 // we were rejected, so end the registration
01556                 iaxc_remove_registration_by_id(reg->id);
01557         }
01558 }
01559 
01560 /* this is what asterisk does */
01561 static int iaxc_choose_codec(int formats)
01562 {
01563         int i;
01564         static int codecs[] =
01565         {
01566                 IAXC_FORMAT_ULAW,
01567                 IAXC_FORMAT_ALAW,
01568                 IAXC_FORMAT_SLINEAR,
01569                 IAXC_FORMAT_G726,
01570                 IAXC_FORMAT_ADPCM,
01571                 IAXC_FORMAT_GSM,
01572                 IAXC_FORMAT_ILBC,
01573                 IAXC_FORMAT_SPEEX,
01574                 IAXC_FORMAT_LPC10,
01575                 IAXC_FORMAT_G729A,
01576                 IAXC_FORMAT_G723_1,
01577 
01578                 /* To negotiate video codec */
01579                 IAXC_FORMAT_JPEG,
01580                 IAXC_FORMAT_PNG,
01581                 IAXC_FORMAT_H261,
01582                 IAXC_FORMAT_H263,
01583                 IAXC_FORMAT_H263_PLUS,
01584                 IAXC_FORMAT_MPEG4,
01585                 IAXC_FORMAT_H264,
01586                 IAXC_FORMAT_THEORA,
01587         };
01588         for ( i = 0; i < (int)(sizeof(codecs) / sizeof(int)); i++ )
01589                 if ( codecs[i] & formats )
01590                         return codecs[i];
01591         return 0;
01592 }
01593 
01594 static void iaxc_handle_connect(struct iax_event * e)
01595 {
01596 #ifdef USE_VIDEO
01597         int video_format_capability;
01598         int video_format_preferred;
01599 #endif
01600         int video_format = 0;
01601         int format = 0;
01602         int callno;
01603 
01604         callno = iaxc_first_free_call();
01605 
01606         if ( callno < 0 )
01607         {
01608                 iaxci_usermsg(IAXC_STATUS,
01609                                 "%i \n Incoming Call, but no appearances",
01610                                 callno);
01611                 // XXX Reject this call!, or just ignore?
01612                 //iax_reject(e->session, "Too many calls, we're busy!");
01613                 iax_accept(e->session, audio_format_preferred & e->ies.capability);
01614                 iax_busy(e->session);
01615                 return;
01616         }
01617 
01618         /* negotiate codec */
01619         /* first, try _their_ preferred format */
01620         format = audio_format_capability & e->ies.format;
01621         if ( !format )
01622         {
01623                 /* then, try our preferred format */
01624                 format = audio_format_preferred & e->ies.capability;
01625         }
01626 
01627         if ( !format )
01628         {
01629                 /* finally, see if we have one in common */
01630                 format = audio_format_capability & e->ies.capability;
01631 
01632                 /* now choose amongst these, if we got one */
01633                 if ( format )
01634                 {
01635                         format = iaxc_choose_codec(format);
01636                 }
01637         }
01638 
01639         if ( !format )
01640         {
01641                 iax_reject(e->session, "Could not negotiate common codec");
01642                 return;
01643         }
01644 
01645 #ifdef USE_VIDEO
01646         iaxc_video_format_get_cap(&video_format_preferred,
01647                         &video_format_capability);
01648 
01649         /* first, see if they even want video */
01650         video_format = (e->ies.format & IAXC_VIDEO_FORMAT_MASK);
01651 
01652         if (video_format)
01653         {
01654                 /* next, try _their_ preferred format */
01655                 video_format &= video_format_capability;
01656 
01657                 if ( !video_format )
01658                 {
01659                         /* then, try our preferred format */
01660                         video_format = video_format_preferred &
01661                                 (e->ies.capability & IAXC_VIDEO_FORMAT_MASK);
01662                 }
01663 
01664                 if ( !video_format )
01665                 {
01666                         /* finally, see if we have one in common */
01667                         video_format = video_format_capability &
01668                                 (e->ies.capability & IAXC_VIDEO_FORMAT_MASK);
01669                         
01670                         /* now choose amongst these, if we got one */
01671                         if ( video_format )
01672                         {
01673                                 video_format = iaxc_choose_codec(video_format);
01674                         }
01675                 }
01676 
01677                 /* All video negotiations failed, then warn */
01678                 if ( !video_format )
01679                 {
01680                         iaxci_usermsg(IAXC_NOTICE,
01681                                                                                 "Notice: could not negotiate common video codec");
01682                         iaxci_usermsg(IAXC_NOTICE,
01683                                                                                 "Notice: switching to audio-only call");
01684                 }
01685         }
01686 #endif  /* USE_VIDEO */
01687 
01688         calls[callno].vformat = video_format;
01689         calls[callno].format = format;
01690 
01691         if ( e->ies.called_number )
01692                 strncpy(calls[callno].local, e->ies.called_number,
01693                                 IAXC_EVENT_BUFSIZ);
01694         else
01695                 strncpy(calls[callno].local, "unknown",
01696                                 IAXC_EVENT_BUFSIZ);
01697 
01698         if ( e->ies.called_context )
01699                 strncpy(calls[callno].local_context, e->ies.called_context,
01700                                 IAXC_EVENT_BUFSIZ);
01701         else
01702                 strncpy(calls[callno].local_context, "",
01703                                 IAXC_EVENT_BUFSIZ);
01704 
01705         if ( e->ies.calling_number )
01706                 strncpy(calls[callno].remote, e->ies.calling_number,
01707                                 IAXC_EVENT_BUFSIZ);
01708         else
01709                 strncpy(calls[callno].remote, "unknown",
01710                                 IAXC_EVENT_BUFSIZ);
01711 
01712         if ( e->ies.calling_name )
01713                 strncpy(calls[callno].remote_name, e->ies.calling_name,
01714                                 IAXC_EVENT_BUFSIZ);
01715         else
01716                 strncpy(calls[callno].remote_name, "unknown",
01717                                 IAXC_EVENT_BUFSIZ);
01718 
01719         iaxc_note_activity(callno);
01720         iaxci_usermsg(IAXC_STATUS, "Call from (%s)", calls[callno].remote);
01721 
01722         codec_destroy( callno );
01723 
01724         calls[callno].session = e->session;
01725         calls[callno].state = IAXC_CALL_STATE_ACTIVE|IAXC_CALL_STATE_RINGING;
01726 
01727         iax_accept(calls[callno].session, format | video_format);
01728         iax_ring_announce(calls[callno].session);
01729 
01730         iaxci_do_state_callback(callno);
01731 
01732         iaxci_usermsg(IAXC_STATUS, "Incoming call on line %d", callno);
01733 }
01734 
01735 static void service_network()
01736 {
01737         struct iax_event *e = 0;
01738         int callNo;
01739         struct iaxc_registration *reg;
01740 
01741         while ( (e = iax_get_event(0)) )
01742         {
01743 #ifdef WIN32
01744                 iaxc_millisleep(0); //fd:
01745 #endif
01746                 // first, see if this is an event for one of our calls.
01747                 callNo = iaxc_find_call_by_session(e->session);
01748                 if (callNo >= 0)
01749                 {
01750                         iaxc_handle_network_event(e, callNo);
01751                 } else if ((reg = iaxc_find_registration_by_session(e->session)) != NULL)
01752                 {
01753                         iaxc_handle_regreply(e,reg);
01754                 } else if ((e->etype == IAX_EVENT_REGACK) || (e->etype == IAX_EVENT_REGREJ))
01755                 {
01756                         iaxci_usermsg(IAXC_ERROR, "Unexpected registration reply");
01757                 } else if (e->etype == IAX_EVENT_REGREQ)
01758                 {
01759                         iaxci_usermsg(IAXC_ERROR,
01760                                         "Registration requested by someone, but we don't understand!");
01761                 } else if (e->etype == IAX_EVENT_CONNECT)
01762                 {
01763                         iaxc_handle_connect(e);
01764                 } else if (e->etype == IAX_EVENT_TIMEOUT)
01765                 {
01766                         iaxci_usermsg(IAXC_STATUS,
01767                                         "Timeout for a non-existant session. Dropping",
01768                                         e->etype);
01769                 } else if ( e->etype == IAX_EVENT_NULL )
01770                 {
01771                         // Should we do something here?
01772                         // Right now we do nothing, just go with the flow
01773                         // and let the event be deallocated.
01774                 } else
01775                 {
01776                         iaxci_usermsg(IAXC_STATUS,
01777                                         "Event (type %d) for a non-existant session. Dropping",
01778                                         e->etype);
01779                 }
01780                 iax_event_free(e);
01781         }
01782 }
01783 
01784 EXPORT int iaxc_audio_devices_get(struct iaxc_audio_device **devs, int *nDevs,
01785                 int *input, int *output, int *ring)
01786 {
01787         *devs = audio_driver.devices;
01788         *nDevs = audio_driver.nDevices;
01789         audio_driver.selected_devices(&audio_driver, input, output, ring);
01790         return 0;
01791 }
01792 
01793 EXPORT int iaxc_audio_devices_set(int input, int output, int ring)
01794 {
01795         int ret = 0;
01796         get_iaxc_lock();
01797         ret = audio_driver.select_devices(&audio_driver, input, output, ring);
01798         put_iaxc_lock();
01799         return ret;
01800 }
01801 
01802 EXPORT float iaxc_input_level_get()
01803 {
01804         return audio_driver.input_level_get(&audio_driver);
01805 }
01806 
01807 EXPORT float iaxc_output_level_get()
01808 {
01809         return audio_driver.output_level_get(&audio_driver);
01810 }
01811 
01812 EXPORT int iaxc_input_level_set(float level)
01813 {
01814         return audio_driver.input_level_set(&audio_driver, level);
01815 }
01816 
01817 EXPORT int iaxc_output_level_set(float level)
01818 {
01819         return audio_driver.output_level_set(&audio_driver, level);
01820 }
01821 
01822 EXPORT int iaxc_play_sound(struct iaxc_sound *s, int ring)
01823 {
01824         int ret = 0;
01825         get_iaxc_lock();
01826         ret = audio_driver.play_sound(s,ring);
01827         put_iaxc_lock();
01828         return ret;
01829 }
01830 
01831 EXPORT int iaxc_stop_sound(int id)
01832 {
01833         int ret = 0;
01834         get_iaxc_lock();
01835         ret = audio_driver.stop_sound(id);
01836         put_iaxc_lock();
01837         return ret;
01838 }
01839 
01840 EXPORT int iaxc_quelch(int callNo, int MOH)
01841 {
01842         struct iax_session *session = calls[callNo].session;
01843         if (!session)
01844                 return -1;
01845 
01846         return iax_quelch_moh(session, MOH);
01847 }
01848 
01849 EXPORT int iaxc_unquelch(int call)
01850 {
01851         return iax_unquelch(calls[call].session);
01852 }
01853 
01854 EXPORT int iaxc_mic_boost_get( void )
01855 {
01856         return audio_driver.mic_boost_get( &audio_driver ) ;
01857 }
01858 
01859 EXPORT int iaxc_mic_boost_set( int enable )
01860 {
01861         return audio_driver.mic_boost_set( &audio_driver, enable ) ;
01862 }
01863 
01864 #ifdef LIBVER
01865 
01866 EXPORT char* iaxc_version(char * ver)
01867 {
01868         strncpy(ver, LIBVER, IAXC_EVENT_BUFSIZ);
01869         return ver;
01870 }
01871 
01872 #endif
01873 
01874 EXPORT unsigned int iaxc_get_audio_prefs(void)
01875 {
01876         return audio_prefs;
01877 }
01878 
01879 EXPORT int iaxc_set_audio_prefs(unsigned int prefs)
01880 {
01881         unsigned int prefs_mask =
01882                 IAXC_AUDIO_PREF_RECV_LOCAL_RAW      |
01883                 IAXC_AUDIO_PREF_RECV_LOCAL_ENCODED  |
01884                 IAXC_AUDIO_PREF_RECV_REMOTE_RAW     |
01885                 IAXC_AUDIO_PREF_RECV_REMOTE_ENCODED |
01886                 IAXC_AUDIO_PREF_SEND_DISABLE;
01887 
01888         if ( prefs & ~prefs_mask )
01889                 return -1;
01890 
01891         audio_prefs = prefs;
01892         return 0;
01893 }

Generated on Mon Sep 24 15:43:29 2007 for IAXClient by  doxygen 1.5.3