openbsd-ports/telephony/asterisk/patches/patch-channels_chan_unistim_c
sthen f3ee3a920c update Asterisk to 1.8.8.0
- various fixes, including a range of possible deadlocks
2011-12-16 14:50:09 +00:00

4371 lines
160 KiB
Plaintext

$OpenBSD: patch-channels_chan_unistim_c,v 1.6 2011/12/16 14:50:09 sthen Exp $
Patch is from https://issues.asterisk.org/jira/browse/18229
https://issues.asterisk.org/jira/secure/attachment/38296/chan_unistim.c.1.8.2.2-9.diff
--- channels/chan_unistim.c.orig Fri Sep 9 17:09:09 2011
+++ channels/chan_unistim.c Sat Dec 10 14:34:33 2011
@@ -73,6 +73,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.6 $")
#include "asterisk/musiconhold.h"
#include "asterisk/causes.h"
#include "asterisk/indications.h"
+#include "asterisk/features.h"
+#include "asterisk/astobj2.h"
/*! Beware, G729 and G723 are not supported by asterisk, except with the proper licence */
#define CAPABILITY AST_FORMAT_ALAW | AST_FORMAT_ULAW /* | AST_FORMAT_G729A | AST_FORMAT_G723_1 */
@@ -82,11 +84,14 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.6 $")
#define DEFAULTCALLERNAME " "
#define DEFAULTHEIGHT 3
#define USTM_LOG_DIR "unistimHistory"
+#define USTM_LANG_DIR "unistimLang"
/*! Size of the transmit buffer */
#define MAX_BUF_SIZE 64
/*! Number of slots for the transmit queue */
#define MAX_BUF_NUMBER 50
+/*! Number of digits displayed on screen */
+#define MAX_SCREEN_NUMBER 15
/*! Try x times before removing the phone */
#define NB_MAX_RETRANSMIT 8
/*! Nb of milliseconds waited when no events are scheduled */
@@ -103,8 +108,9 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision: 1.6 $")
#define MAX_ENTRY_LOG 30
#define SUB_REAL 0
-#define SUB_THREEWAY 1
-#define MAX_SUBS 2
+#define SUB_RING 1
+#define SUB_THREEWAY 2
+#define SUB_ONHOLD 3
enum autoprovision {
AUTOPROVISIONING_NO = 0,
@@ -185,6 +191,14 @@ enum autoprov_extn {
#define FAV_MAX_LENGTH 0x0A
+#define FAVNUM 6
+#define FAV_LINE_ICON FAV_ICON_ONHOOK_BLACK
+
+#define CALL_TIMER_START 0x01
+#define CALL_TIMER_RESET 0x02
+#define CALL_TIMER_DISPLAY 0x04
+#define CALL_TIMER_DELAY 0x08
+
static void dummy(char *unused, ...)
{
return;
@@ -222,7 +236,7 @@ static struct {
} qos = { 0, 0, 0, 0 };
static struct io_context *io;
-static struct sched_context *sched;
+static struct ast_sched_context *sched;
static struct sockaddr_in public_ip = { 0, };
/*! give the IP address for the last packet received */
static struct sockaddr_in address_from;
@@ -256,7 +270,10 @@ enum phone_state {
STATE_DIALPAGE,
STATE_RINGING,
STATE_CALL,
+ STATE_SELECTOPTION,
STATE_SELECTCODEC,
+ STATE_SELECTCONTRAST,
+ STATE_SELECTLANGUAGE,
STATE_CLEANING,
STATE_HISTORY
};
@@ -307,45 +324,17 @@ enum phone_key {
KEY_INDEX = 0x7f
};
-struct tone_zone_unistim {
- char country[3];
- int freq1;
- int freq2;
+enum charset {
+ LANG_DEFAULT,
+ ISO_8859_1,
+ ISO_8859_2,
+ ISO_8859_4,
+ ISO_8859_5,
+ ISO_2022_JP,
};
-static const struct tone_zone_unistim frequency[] = {
- {"us", 350, 440},
- {"fr", 440, 0},
- {"au", 413, 438},
- {"nl", 425, 0},
- {"uk", 350, 440},
- {"fi", 425, 0},
- {"es", 425, 0},
- {"jp", 400, 0},
- {"no", 425, 0},
- {"at", 420, 0},
- {"nz", 400, 0},
- {"tw", 350, 440},
- {"cl", 400, 0},
- {"se", 425, 0},
- {"be", 425, 0},
- {"sg", 425, 0},
- {"il", 414, 0},
- {"br", 425, 0},
- {"hu", 425, 0},
- {"lt", 425, 0},
- {"pl", 425, 0},
- {"za", 400, 0},
- {"pt", 425, 0},
- {"ee", 425, 0},
- {"mx", 425, 0},
- {"in", 400, 0},
- {"de", 425, 0},
- {"ch", 425, 0},
- {"dk", 425, 0},
- {"cn", 450, 0},
- {"--", 0, 0}
-};
+static const int dtmf_row[] = { 697, 770, 852, 941 };
+static const float dtmf_col[] = { 1209, 1336, 1477, 1633 };
struct wsabuf {
u_long len;
@@ -365,7 +354,7 @@ struct systemtime {
struct unistim_subchannel {
ast_mutex_t lock;
- /*! SUBS_REAL or SUBS_THREEWAY */
+ /*! SUB_REAL, SUB_THREEWAY or SUB_ONHOLD */
unsigned int subtype;
/*! Asterisk channel used by the subchannel */
struct ast_channel *owner;
@@ -373,9 +362,14 @@ struct unistim_subchannel {
struct unistim_line *parent;
/*! RTP handle */
struct ast_rtp_instance *rtp;
+ /*! Softkey assigned */
+ int softkey;
+ time_t start_call_timestamp; /*!< timestamp for the length calculation of the call */
int alreadygone;
char ringvolume;
char ringstyle;
+ int moh; /*!< Music on hold in progress */
+ AST_LIST_ENTRY(unistim_subchannel) list;
};
/*!
@@ -387,14 +381,10 @@ struct unistim_line {
char name[80];
/*! Like USTM/200\@black */
char fullname[80];
- /*! pointer to our current connection, channel... */
- struct unistim_subchannel *subs[MAX_SUBS];
/*! Extension where to start */
char exten[AST_MAX_EXTENSION];
/*! Context to start in */
char context[AST_MAX_EXTENSION];
- /*! Language for asterisk sounds */
- char language[MAX_LANGUAGE];
/*! CallerID Number */
char cid_num[AST_MAX_EXTENSION];
/*! Mailbox for MWI */
@@ -419,6 +409,7 @@ struct unistim_line {
char parkinglot[AST_MAX_CONTEXT];
struct unistim_line *next;
struct unistim_device *parent;
+ AST_LIST_ENTRY(unistim_line) list;
};
/*!
@@ -427,19 +418,21 @@ struct unistim_line {
static struct unistim_device {
int receiver_state; /*!< state of the receiver (see ReceiverState) */
int size_phone_number; /*!< size of the phone number */
- char phone_number[16]; /*!< the phone number entered by the user */
- char redial_number[16]; /*!< the last phone number entered by the user */
+ char phone_number[AST_MAX_EXTENSION]; /*!< the phone number entered by the user */
+ char redial_number[AST_MAX_EXTENSION]; /*!< the last phone number entered by the user */
int phone_current; /*!< Number of the current phone */
int pos_fav; /*!< Position of the displayed favorites (used for scrolling) */
char id[18]; /*!< mac address of the current phone in ascii */
char name[DEVICE_NAME_LEN]; /*!< name of the device */
- int softkeylinepos; /*!< position of the line softkey (default 0) */
- char softkeylabel[6][11]; /*!< soft key label */
- char softkeynumber[6][16]; /*!< number dialed when the soft key is pressed */
- char softkeyicon[6]; /*!< icon number */
- char softkeydevice[6][16]; /*!< name of the device monitored */
- struct unistim_device *sp[6]; /*!< pointer to the device monitored by this soft key */
- int height; /*!< The number of lines the phone can display */
+ char softkeylabel[FAVNUM][11]; /*!< soft key label */
+ char softkeynumber[FAVNUM][AST_MAX_EXTENSION]; /*!< number dialed when the soft key is pressed */
+ char softkeyicon[FAVNUM]; /*!< icon number */
+ char softkeydevice[FAVNUM][16]; /*!< name of the device monitored */
+ struct unistim_subchannel *ssub[FAVNUM];
+ struct unistim_line *sline[FAVNUM];
+ struct unistim_device *sp[FAVNUM]; /*!< pointer to the device monitored by this soft key */
+ char language[MAX_LANGUAGE]; /*!< Language for asterisk sounds */
+ int height; /*!< The number of lines the phone can display */
char maintext0[25]; /*!< when the phone is idle, display this string on line 0 */
char maintext1[25]; /*!< when the phone is idle, display this string on line 1 */
char maintext2[25]; /*!< when the phone is idle, display this string on line 2 */
@@ -450,12 +443,16 @@ static struct unistim_device {
struct ast_tone_zone *tz; /*!< Tone zone for res_indications (ring, busy, congestion) */
char ringvolume; /*!< Ring volume */
char ringstyle; /*!< Ring melody */
- int rtp_port; /*!< RTP port used by the phone */
+ char cwvolume; /*!< Ring volume on call waiting */
+ char cwstyle; /*!< Ring melody on call waiting */
+ int rtp_port; /*!< RTP port used by the phone */
int rtp_method; /*!< Select the unistim data used to establish a RTP session */
int status_method; /*!< Select the unistim packet used for sending status text */
char codec_number; /*!< The current codec used to make calls */
int missed_call; /*!< Number of call unanswered */
int callhistory; /*!< Allowed to record call history */
+ int selected; /*!< softkey selected */
+ int sharp_dial; /*!< Execute Dial on '#' or not */
char lst_cid[TEXT_LENGTH_MAX]; /*!< Last callerID received */
char lst_cnm[TEXT_LENGTH_MAX]; /*!< Last callername recevied */
char call_forward[AST_MAX_EXTENSION]; /*!< Forward number */
@@ -463,15 +460,14 @@ static struct unistim_device {
int previous_output; /*!< Previous output */
int volume; /*!< Default volume */
int mute; /*!< Mute mode */
- int moh; /*!< Music on hold in progress */
int nat; /*!< Used by the obscure ast_rtp_setnat */
enum autoprov_extn extension; /*!< See ifdef EXTENSION for valid values */
char extension_number[11]; /*!< Extension number entered by the user */
char to_delete; /*!< Used in reload */
- time_t start_call_timestamp; /*!< timestamp for the length calculation of the call */
struct ast_silence_generator *silence_generator;
- struct unistim_line *lines;
- struct ast_ha *ha;
+ AST_LIST_HEAD(,unistim_subchannel) subs; /*!< pointer to our current connection, channel... */
+ AST_LIST_HEAD(,unistim_line) lines;
+ struct ast_ha *ha;
struct unistimsession *session;
struct unistim_device *next;
} *devices = NULL;
@@ -494,9 +490,23 @@ static struct unistimsession {
struct wsabuf wsabufsend[MAX_BUF_NUMBER]; /*!< Size of each paquet stored in the buffer array & pointer to this buffer */
unsigned char buf[MAX_BUF_NUMBER][MAX_BUF_SIZE]; /*!< Buffer array used to keep the lastest non-acked paquets */
struct unistim_device *device;
- struct unistimsession *next;
+ struct unistim_subchannel *active_sub; /*!< Active subchannel for detect active softkey */
+ struct unistimsession *next;
} *sessions = NULL;
+struct unistim_menu_item {
+ char *label;
+ int state;
+ void (*handle_option)(struct unistimsession *);
+};
+
+struct unistim_languages {
+ char *label;
+ char *lang_short;
+ int encoding;
+ struct ao2_container *trans;
+};
+
/*!
* \page Unistim datagram formats
*
@@ -628,10 +638,14 @@ static const unsigned char packet_send_date_time2[] =
};
static const unsigned char packet_send_Contrast[] =
{ 0x17, 0x04, 0x24, /*Contrast */ 0x08 };
-static const unsigned char packet_send_StartTimer[] =
- { 0x17, 0x05, 0x0b, 0x05, 0x00, 0x17, 0x08, 0x16, /* Text */ 0x44, 0x75, 0x72, 0xe9,
-0x65 };
-static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, 0x02, 0x00 };
+static const unsigned char packet_send_start_timer[] =
+ { 0x17, 0x05, 0x0b, /*Timer option*/0x05, /* Timer ID */0x00, 0x17, 0x08, 0x16,
+ /* Text */ 0x44, 0x75, 0x72, 0xe9, 0x65 };
+
+static const unsigned char packet_send_delay_timer[] = { 0x17, 0x04, 0x0d, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+static const unsigned char packet_send_hide_timer[] = { 0x17, 0x05, 0x0b, CALL_TIMER_RESET, 0x00 };
+static const unsigned char packet_send_show_timer[] = { 0x17, 0x05, 0x0b, 0x05 & CALL_TIMER_DELAY, 0x00 };
+static const unsigned char packet_send_stop_timer[] = { 0x17, 0x05, 0x0b, CALL_TIMER_RESET, 0x00 };
static const unsigned char packet_send_icon[] = { 0x17, 0x05, 0x14, /*pos */ 0x00, /*icon */ 0x25 }; /* display an icon in front of the text zone */
static const unsigned char packet_send_S7[] = { 0x17, 0x06, 0x0f, 0x30, 0x07, 0x07 };
static const unsigned char packet_send_set_pos_cursor[] =
@@ -662,6 +676,23 @@ static const unsigned char packet_send_status2[] =
{ 0x17, 0x0b, 0x19, /* pos [08|28|48|68] */ 0x00, /* text */ 0x20, 0x20, 0x20, 0x20,
0x20, 0x20, 0x20 /* end_text */ };
+/* Multiple character set support */
+/* ISO-8859-1 - Western European) */
+static const unsigned char packet_send_charset_iso_8859_1[] =
+ { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x41, 0x1b, 0x00 };
+/* ISO-8859-2 - Central European) */
+static const unsigned char packet_send_charset_iso_8859_2[] =
+ { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x42, 0x1b, 0x00 };
+/* ISO-8859-4 - Baltic) */
+static const unsigned char packet_send_charset_iso_8859_4[] =
+ { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x44, 0x1b, 0x00 };
+/* ISO 8859-5 - cyrilic */
+static const unsigned char packet_send_charset_iso_8859_5[] =
+ { 0x17, 0x08, 0x21, 0x1b, 0x2d, 0x4c, 0x1b, 0x00 };
+/* Japaneese (ISO-2022-JP ?) */
+static const unsigned char packet_send_charset_iso_2022_jp[] =
+ { 0x17, 0x08, 0x21, 0x1b, 0x29, 0x49, 0x1b, 0x7e };
+
static const unsigned char packet_send_led_update[] = { 0x19, 0x04, 0x00, 0x00 };
static const unsigned char packet_send_query_basic_manager_04[] = { 0x1a, 0x04, 0x01, 0x04 };
@@ -722,15 +753,125 @@ static const struct ast_channel_tech unistim_tech = {
.bridge = ast_rtp_instance_bridge,
};
-static void display_last_error(const char *sz_msg)
+static void send_start_rtp(struct unistim_subchannel *);
+
+static void send_callerid_screen(struct unistimsession *, struct unistim_subchannel *sub);
+static void key_favorite(struct unistimsession *, char);
+
+static void handle_select_codec(struct unistimsession *);
+static void handle_select_contrast(struct unistimsession *);
+static void handle_select_language(struct unistimsession *);
+static int find_language(const char*);
+
+struct unistim_menu_item options_menu[] =
{
- time_t cur_time;
-
- time(&cur_time);
+ {"Change codec", STATE_SELECTCODEC, handle_select_codec},
+ {"Contrast", STATE_SELECTCONTRAST, handle_select_contrast},
+ {"Language", STATE_SELECTLANGUAGE, handle_select_language},
+ {NULL, 0, NULL}
+};
+struct unistim_languages options_languages[] =
+{
+ {"English", "en", ISO_8859_1, NULL},
+ {"Russian", "ru", ISO_8859_5, NULL},
+ {NULL, NULL, 0, NULL}
+};
+
+struct ustm_lang_entry {
+ const char *str_orig;
+ const char *str_trans;
+};
+
+static void lang_entry_destructor(void *obj)
+{
+ return;
+}
+
+static int lang_hash_fn(const void *obj, const int flags)
+{
+ const struct ustm_lang_entry *entry = obj;
+ return ast_str_hash(entry->str_orig);
+}
+
+static int lang_cmp_fn(void *obj, void *arg, int flags)
+{
+ struct ustm_lang_entry *entry1 = obj;
+ struct ustm_lang_entry *entry2 = arg;
+
+ return (!strcmp(entry1->str_orig, entry2->str_orig)) ? (CMP_MATCH | CMP_STOP) : 0;
+}
+
+static const char *ustmtext(const char *str, struct unistimsession *pte) {
+ struct ustm_lang_entry *lang_entry;
+ struct ustm_lang_entry le_search;
+ struct unistim_languages *lang;
+
+ lang = &options_languages[find_language(pte->device->language)];
+ if (!lang)
+ return str;
+ /* Check if specified language exists */
+ if (!lang->trans) {
+ char tmp[1024], *p, *p_orig = NULL, *p_trans = NULL;
+ FILE *f;
+
+ lang->trans = ao2_container_alloc(8, lang_hash_fn, lang_cmp_fn);
+ snprintf(tmp, sizeof(tmp), "%s/%s/%s.po", ast_config_AST_VAR_DIR,
+ USTM_LANG_DIR, lang->lang_short);
+ f = fopen(tmp, "r");
+ if (!f) {
+ return str;
+ }
+ while (fgets(tmp, sizeof(tmp), f)) {
+ if (!(p = strchr(tmp, '\n'))) {
+ ast_log(LOG_ERROR, "input line too long.\n");
+ }
+ *p = '\0';
+ if (tmp == strstr(tmp, "msgid")) {
+ p_orig = ast_strdup(strchr(tmp, '"') + 1);
+ p = strchr(p_orig, '"');
+ *p = '\0';
+ } else if (tmp == strstr(tmp, "msgstr")) {
+ p_trans = ast_strdup(strchr(tmp, '"') + 1);
+ p = strchr(p_trans, '"');
+ *p = '\0';
+ } else {
+ continue;
+ }
+ if (!p_trans || !p_orig)
+ continue;
+ if (!strlen(p_trans)) {
+ p_trans = NULL;
+ p_orig = NULL;
+ continue;
+ }
+ if (!(lang_entry = ao2_alloc(sizeof(*lang_entry), lang_entry_destructor))) {
+ return str;
+ }
+
+ lang_entry->str_trans = p_trans;
+ lang_entry->str_orig = p_orig;
+ ao2_link(lang->trans, lang_entry);
+ p_trans = NULL;
+ p_orig = NULL;
+ }
+
+ fclose(f);
+ }
+
+ le_search.str_orig = ast_strdup(str);
+ lang_entry = ao2_find(lang->trans, &le_search, OBJ_POINTER);
+ //lang_entry = NULL;
+ if (lang_entry)
+ return lang_entry->str_trans;
+
+ return str;
+}
+
+static void display_last_error(const char *sz_msg)
+{
/* Display the error message */
- ast_log(LOG_WARNING, "%s %s : (%u) %s\n", ctime(&cur_time), sz_msg, errno,
- strerror(errno));
+ ast_log(LOG_WARNING, "%s : (%u) %s\n", sz_msg, errno, strerror(errno));
}
static unsigned int get_tick_count(void)
@@ -955,10 +1096,44 @@ static void send_start_timer(struct unistimsession *pt
BUFFSEND;
if (unistimdebug)
ast_verb(0, "Sending start timer\n");
- memcpy(buffsend + SIZE_HEADER, packet_send_StartTimer, sizeof(packet_send_StartTimer));
- send_client(SIZE_HEADER + sizeof(packet_send_StartTimer), buffsend, pte);
+ memcpy(buffsend + SIZE_HEADER, packet_send_start_timer, sizeof(packet_send_start_timer));
+ send_client(SIZE_HEADER + sizeof(packet_send_start_timer), buffsend, pte);
}
+static void send_start_timer_id(struct unistimsession *pte, const int id)
+{
+ BUFFSEND;
+ if (unistimdebug)
+ ast_verb(0, "Sending start timer\n");
+ memcpy(buffsend + SIZE_HEADER, packet_send_start_timer, sizeof(packet_send_start_timer));
+ //buffsend[10] = id;
+ send_client(SIZE_HEADER + sizeof(packet_send_start_timer), buffsend, pte);
+}
+
+static void send_hide_timer_id(struct unistimsession *pte, const int id)
+{
+ BUFFSEND;
+ if (unistimdebug)
+ ast_verb(0, "Sending start timer\n");
+ memcpy(buffsend + SIZE_HEADER, packet_send_hide_timer, sizeof(packet_send_hide_timer));
+ //buffsend[10] = id;
+ send_client(SIZE_HEADER + sizeof(packet_send_hide_timer), buffsend, pte);
+}
+
+static void send_show_timer_id(struct unistimsession *pte, const int id)
+{
+ BUFFSEND;
+ if (unistimdebug)
+ ast_verb(0, "Sending start timer\n");
+ memcpy(buffsend + SIZE_HEADER, packet_send_delay_timer, sizeof(packet_send_delay_timer));
+ //buffsend[10] = id;
+ send_client(SIZE_HEADER + sizeof(packet_send_delay_timer), buffsend, pte);
+
+ memset(buffsend + SIZE_HEADER, 0, sizeof(packet_send_delay_timer));
+ memcpy(buffsend + SIZE_HEADER, packet_send_show_timer, sizeof(packet_send_show_timer));
+ send_client(SIZE_HEADER + sizeof(packet_send_show_timer), buffsend, pte);
+}
+
static void send_stop_timer(struct unistimsession *pte)
{
BUFFSEND;
@@ -968,7 +1143,7 @@ static void send_stop_timer(struct unistimsession *pte
send_client(SIZE_HEADER + sizeof(packet_send_stop_timer), buffsend, pte);
}
-static void Sendicon(unsigned char pos, unsigned char status, struct unistimsession *pte)
+static void send_icon(unsigned char pos, unsigned char status, struct unistimsession *pte)
{
BUFFSEND;
if (unistimdebug)
@@ -1026,9 +1201,9 @@ static void send_tone(struct unistimsession *pte, uint
/* Positions for favorites
|--------------------|
- | 5 2 |
- | 4 1 |
- | 3 0 |
+ | 5 2 | <-- not on screen in i2002
+ | 4 1 |
+ | 3 0 |
*/
/* status (icons) : 00 = nothing, 2x/3x = see parser.h, 4x/5x = blink fast, 6x/7x = blink slow */
@@ -1045,44 +1220,122 @@ send_favorite(unsigned char pos, unsigned char status,
buffsend[10] = pos;
buffsend[24] = pos;
buffsend[25] = status;
- i = strlen(text);
+ i = strlen(ustmtext(text, pte));
if (i > FAV_MAX_LENGTH)
i = FAV_MAX_LENGTH;
- memcpy(buffsend + FAV_MAX_LENGTH + 1, text, i);
+ memcpy(buffsend + FAV_MAX_LENGTH + 1, ustmtext(text, pte), i);
send_client(SIZE_HEADER + sizeof(packet_send_favorite), buffsend, pte);
}
+static void send_favorite_short(unsigned char pos, unsigned char status, struct unistimsession *pte) {
+ send_favorite(pos, status, pte, pte->device->softkeylabel[pos]);
+ return;
+}
+
+static void send_favorite_selected(unsigned char status, struct unistimsession *pte) {
+ if (pte->device->selected != -1)
+ send_favorite(pte->device->selected, status, pte, pte->device->softkeylabel[pte->device->selected]);
+ return;
+}
+
+static int soft_key_visible(struct unistim_device* d, int num)
+{
+ if(d->height == 1 && num%3 == 2) {
+ return 0;
+ }
+ return 1;
+}
+
static void refresh_all_favorite(struct unistimsession *pte)
{
int i = 0;
if (unistimdebug)
ast_verb(0, "Refreshing all favorite\n");
- for (i = 0; i < 6; i++) {
- if ((pte->device->softkeyicon[i] <= FAV_ICON_HEADPHONES_ONHOLD) &&
- (pte->device->softkeylinepos != i))
- send_favorite((unsigned char) i, pte->device->softkeyicon[i] + 1, pte,
- pte->device->softkeylabel[i]);
+ for (i = 0; i < FAVNUM; i++) {
+ if (!soft_key_visible(pte->device, i))
+ continue;
+ /* XXX Here icon for the lines displayed */
+ if ((pte->device->softkeyicon[i] <= FAV_ICON_HEADPHONES_ONHOLD)/* &&
+ (pte->device->softkeylinepos != i)*/)
+ send_favorite_short((unsigned char) i, pte->device->softkeyicon[i]/* + 1*/, pte);
else
- send_favorite((unsigned char) i, pte->device->softkeyicon[i], pte,
- pte->device->softkeylabel[i]);
+ send_favorite_short((unsigned char) i, pte->device->softkeyicon[i], pte);
}
}
+static int is_key_favorite(struct unistim_device *d, int fav)
+{
+ if ((fav < 0) && (fav > 5))
+ return 0;
+ if (d->sline[fav])
+ return 0;
+ if (d->softkeynumber[fav][0] == '\0')
+ return 0;
+ return 1;
+}
+
+static int is_key_line(struct unistim_device *d, int fav)
+{
+ if ((fav < 0) && (fav > 5))
+ return 0;
+ if (!d->sline[fav])
+ return 0;
+ if (is_key_favorite(d, fav))
+ return 0;
+
+ return 1;
+}
+
+static int get_active_softkey(struct unistimsession *pte)
+{
+ return pte->device->selected;
+}
+
+static int get_avail_softkey(struct unistimsession *pte, const char* name)
+{
+ int i;
+
+ if (!is_key_line(pte->device, pte->device->selected)) {
+ pte->device->selected = -1;
+ }
+ for (i = 0; i < FAVNUM; i++) {
+ if (pte->device->selected != -1 && pte->device->selected != i) {
+ continue;
+ }
+ if (!soft_key_visible(pte->device, i))
+ continue;
+ if (pte->device->ssub[i])
+ continue;
+ if (is_key_line(pte->device, i)) {
+ if (name && strcmp(name, pte->device->sline[i]->name)) {
+ continue;
+ }
+ if (unistimdebug)
+ ast_verb(0, "Found softkey %d for device %s\n", i, name);
+ return i;
+ }
+ }
+ return -1;
+}
+
+
/* Change the status for this phone (pte) and update for each phones where pte is bookmarked
* use FAV_ICON_*_BLACK constant in status parameters */
static void change_favorite_icon(struct unistimsession *pte, unsigned char status)
{
struct unistim_device *d = devices;
int i;
- /* Update the current phone */
- if (pte->state != STATE_CLEANING)
- send_favorite(pte->device->softkeylinepos, status, pte,
- pte->device->softkeylabel[pte->device->softkeylinepos]);
+ /* Update the current phone line softkey icon */
+ if (pte->state != STATE_CLEANING) {
+ int softkeylinepos = get_active_softkey(pte);
+ if (softkeylinepos != -1)
+ send_favorite_short(softkeylinepos, status, pte);
+ }
/* Notify other phones if we're in their bookmark */
while (d) {
- for (i = 0; i < 6; i++) {
+ for (i = 0; i < FAVNUM; i++) {
if (d->sp[i] == pte->device) { /* It's us ? */
if (d->softkeyicon[i] != status) { /* Avoid resending the same icon */
d->softkeyicon[i] = status;
@@ -1095,30 +1348,40 @@ static void change_favorite_icon(struct unistimsession
}
}
-static int RegisterExtension(const struct unistimsession *pte)
+/* XXX Check all places where get_main_line used, as it is a hack and may be better usage possible */
+static struct unistim_line* get_main_line(const struct unistim_device *d)
{
+ return AST_LIST_FIRST(&d->lines);
+}
+
+static int register_extension(const struct unistimsession *pte)
+{
+ struct unistim_line *line;
+ line = get_main_line(pte->device);
if (unistimdebug)
ast_verb(0, "Trying to register extension '%s' into context '%s' to %s\n",
- pte->device->extension_number, pte->device->lines->context,
- pte->device->lines->fullname);
- return ast_add_extension(pte->device->lines->context, 0,
+ pte->device->extension_number, line->context,
+ line->fullname);
+ return ast_add_extension(line->context, 0,
pte->device->extension_number, 1, NULL, NULL, "Dial",
- pte->device->lines->fullname, 0, "Unistim");
+ line->fullname, 0, "Unistim");
}
-static int UnregisterExtension(const struct unistimsession *pte)
+static int unregister_extension(const struct unistimsession *pte)
{
+ struct unistim_line *line;
+ line = get_main_line(pte->device);
if (unistimdebug)
ast_verb(0, "Trying to unregister extension '%s' context '%s'\n",
- pte->device->extension_number, pte->device->lines->context);
- return ast_context_remove_extension(pte->device->lines->context,
+ pte->device->extension_number, line->context);
+ return ast_context_remove_extension(line->context,
pte->device->extension_number, 1, "Unistim");
}
/* Free memory allocated for a phone */
static void close_client(struct unistimsession *s)
{
- struct unistim_subchannel *sub;
+ struct unistim_subchannel *sub = NULL;
struct unistimsession *cur, *prev = NULL;
ast_mutex_lock(&sessionlock);
cur = sessions;
@@ -1132,12 +1395,11 @@ static void close_client(struct unistimsession *s)
if (cur) { /* Session found ? */
if (cur->device) { /* This session was registered ? */
s->state = STATE_CLEANING;
- if (unistimdebug)
+ /* !!! sub seems to be never used and uninitialized */
+ if (unistimdebug)
ast_verb(0, "close_client session %p device %p lines %p sub %p\n",
- s, s->device, s->device->lines,
- s->device->lines->subs[SUB_REAL]);
+ s, s->device, get_main_line(s->device), sub);
change_favorite_icon(s, FAV_ICON_NONE);
- sub = s->device->lines->subs[SUB_REAL];
if (sub) {
if (sub->owner) { /* Call in progress ? */
if (unistimdebug)
@@ -1147,7 +1409,7 @@ static void close_client(struct unistimsession *s)
} else
ast_log(LOG_WARNING, "Freeing a client with no subchannel !\n");
if (!ast_strlen_zero(s->device->extension_number))
- UnregisterExtension(s);
+ unregister_extension(s);
cur->device->session = NULL;
} else {
if (unistimdebug)
@@ -1211,6 +1473,12 @@ send_text(unsigned char pos, unsigned char inverse, st
{
int i;
BUFFSEND;
+ if (!text) {
+ ast_log(LOG_ERROR, "Asked to display NULL text (pos %d, inverse flag %d)\n", pos, inverse);
+ return;
+ }
+ if (pte->device->height == 1 && pos != TEXT_LINE0)
+ return;
if (unistimdebug)
ast_verb(0, "Sending text at pos %d, inverse flag %d\n", pos, inverse);
memcpy(buffsend + SIZE_HEADER, packet_send_text, sizeof(packet_send_text));
@@ -1370,12 +1638,21 @@ static void send_texttitle(struct unistimsession *pte,
}
+static void send_idle_clock(struct unistimsession *pte)
+{
+ char text[2];
+
+ memset(text, 0x00, 2);
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
+}
+
static void send_date_time(struct unistimsession *pte)
{
BUFFSEND;
struct timeval now = ast_tvnow();
struct ast_tm atm = { 0, };
+ ast_log(LOG_WARNING, "Time Received\n");
if (unistimdebug)
ast_verb(0, "Sending Time & Date\n");
memcpy(buffsend + SIZE_HEADER, packet_send_date_time, sizeof(packet_send_date_time));
@@ -1448,6 +1725,43 @@ static void send_cursor_pos(struct unistimsession *pte
return;
}
+static void send_charset_update(struct unistimsession *pte, int charset)
+{
+ const unsigned char* packet_send_charset;
+ int packet_size;
+ BUFFSEND;
+ if (unistimdebug)
+ ast_verb(0, "Sending set default charset\n");
+ if (charset == LANG_DEFAULT) {
+ charset = options_languages[find_language(pte->device->language)].encoding;
+ }
+ switch (charset) {
+ case ISO_8859_2:
+ packet_send_charset = packet_send_charset_iso_8859_2;
+ packet_size = sizeof(packet_send_charset_iso_8859_2);
+ break;
+ case ISO_8859_4:
+ packet_send_charset = packet_send_charset_iso_8859_4;
+ packet_size = sizeof(packet_send_charset_iso_8859_4);
+ break;
+ case ISO_8859_5:
+ packet_send_charset = packet_send_charset_iso_8859_5;
+ packet_size = sizeof(packet_send_charset_iso_8859_5);
+ break;
+ case ISO_2022_JP:
+ packet_send_charset = packet_send_charset_iso_2022_jp;
+ packet_size = sizeof(packet_send_charset_iso_2022_jp);
+ break;
+ case ISO_8859_1:
+ default:
+ packet_send_charset = packet_send_charset_iso_8859_1;
+ packet_size = sizeof(packet_send_charset_iso_8859_1);
+ }
+ memcpy(buffsend + SIZE_HEADER, packet_send_charset, packet_size);
+ send_client(SIZE_HEADER + packet_size, buffsend, pte);
+ return;
+}
+
static void rcv_resume_connection_with_server(struct unistimsession *pte)
{
BUFFSEND;
@@ -1488,37 +1802,91 @@ static int unistim_register(struct unistimsession *s)
return 1;
}
-static int alloc_sub(struct unistim_line *l, int x)
+static struct unistim_subchannel *alloc_sub(struct unistim_device *d, int x)
{
struct unistim_subchannel *sub;
if (!(sub = ast_calloc(1, sizeof(*sub))))
- return 0;
+ return NULL;
if (unistimdebug)
- ast_verb(3, "Allocating UNISTIM subchannel #%d on %s@%s ptr=%p\n", x, l->name, l->parent->name, sub);
- sub->parent = l;
+ ast_verb(3, "Allocating UNISTIM subchannel #%d on %s ptr=%p\n", x, d->name, sub);
+ sub->parent = NULL;
sub->subtype = x;
- l->subs[x] = sub;
+ AST_LIST_LOCK(&d->subs);
+ AST_LIST_INSERT_TAIL(&d->subs, sub, list);
+ AST_LIST_UNLOCK(&d->subs);
ast_mutex_init(&sub->lock);
- return 1;
+ return sub;
}
-static int unalloc_sub(struct unistim_line *p, int x)
+static int unalloc_sub(struct unistim_device *d, struct unistim_subchannel *sub)
{
- if (!x) {
- ast_log(LOG_WARNING, "Trying to unalloc the real channel %s@%s?!?\n", p->name,
- p->parent->name);
- return -1;
- }
- if (unistimdebug)
- ast_debug(1, "Released sub %d of channel %s@%s\n", x, p->name,
- p->parent->name);
- ast_mutex_destroy(&p->lock);
- ast_free(p->subs[x]);
- p->subs[x] = 0;
- return 0;
+ struct unistim_subchannel *s;
+
+ AST_LIST_LOCK(&d->subs);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, s, list) {
+ if (!s)
+ continue;
+ if (s != sub)
+ continue;
+ AST_LIST_REMOVE_CURRENT(list);
+ if (unistimdebug)
+ ast_debug(1, "Released sub %d of channel %s@%s\n", sub->subtype, sub->parent->name, d->name);
+
+ ast_free(sub);
+ }
+ AST_LIST_TRAVERSE_SAFE_END;
+ AST_LIST_UNLOCK(&d->subs);
+ //ast_mutex_destroy(&p->lock); TODO
+ return 0;
}
+static const char *subtype_tostr(const int type) {
+ switch (type) {
+ case SUB_REAL:
+ return "REAL";
+ case SUB_ONHOLD:
+ return "ONHOLD";
+ case SUB_RING:
+ return "RINGING";
+ case SUB_THREEWAY:
+ return "THREEWAY";
+ }
+ return "UNKNOWN";
+}
+
+static const char *ptestate_tostr(const int type) {
+ switch (type) {
+ case STATE_INIT:
+ return "INIT";
+ case STATE_AUTHDENY:
+ return "AUTHDENY";
+ case STATE_MAINPAGE:
+ return "MAINPAGE";
+ case STATE_EXTENSION:
+ return "EXTENSION";
+ case STATE_DIALPAGE:
+ return "DIALPAGE";
+ case STATE_RINGING:
+ return "RINGING";
+ case STATE_CALL:
+ return "CALL";
+ case STATE_SELECTOPTION:
+ return "SELECTOPTION";
+ case STATE_SELECTCODEC:
+ return "SELECTCODEC";
+ case STATE_SELECTCONTRAST:
+ return "SELECTCONTRAST";
+ case STATE_SELECTLANGUAGE:
+ return "SELECTLANGUAGE";
+ case STATE_CLEANING:
+ return "CLEARING";
+ case STATE_HISTORY:
+ return "HISTORY";
+ }
+ return "UNKNOWN";
+}
+
static void rcv_mac_addr(struct unistimsession *pte, const unsigned char *buf)
{
BUFFSEND;
@@ -1552,6 +1920,7 @@ static void rcv_mac_addr(struct unistimsession *pte, c
d = devices;
while (d) {
if (!strcasecmp(d->name, "template")) {
+ struct unistim_line *l;
/* Found, cloning this entry */
if (!(newd = ast_malloc(sizeof(*newd)))) {
ast_mutex_unlock(&devicelock);
@@ -1565,8 +1934,9 @@ static void rcv_mac_addr(struct unistimsession *pte, c
return;
}
- memcpy(newl, d->lines, sizeof(*newl));
- if (!alloc_sub(newl, SUB_REAL)) {
+ l = get_main_line(d);
+ memcpy(newl, l, sizeof(*newl));
+ if (!alloc_sub(newd, SUB_REAL)) {
ast_free(newd);
ast_free(newl);
ast_mutex_unlock(&devicelock);
@@ -1577,16 +1947,16 @@ static void rcv_mac_addr(struct unistimsession *pte, c
ast_copy_string(newd->name, addrmac, sizeof(newd->name));
if (newd->extension == EXTENSION_NONE)
newd->extension = EXTENSION_ASK;
- newd->lines = newl;
+ //newd->lines = newl; TODO
newd->receiver_state = STATE_ONHOOK;
newd->session = pte;
newd->to_delete = -1;
pte->device = newd;
newd->next = NULL;
newl->parent = newd;
- strcpy(newl->name, d->lines->name);
- snprintf(d->lines->name, sizeof(d->lines->name), "%d",
- atoi(d->lines->name) + 1);
+ strcpy(newl->name, l->name);
+ snprintf(l->name, sizeof(l->name), "%d",
+ atoi(l->name) + 1);
snprintf(newl->fullname, sizeof(newl->fullname), "USTM/%s@%s",
newl->name, newd->name);
/* Go to the end of the linked chain */
@@ -1630,16 +2000,16 @@ static void rcv_mac_addr(struct unistimsession *pte, c
pte->state = STATE_EXTENSION;
else {
/* Yes, because of a phone reboot. We don't ask again for the TN */
- if (RegisterExtension(pte))
+ if (register_extension(pte))
pte->state = STATE_EXTENSION;
else
pte->state = STATE_MAINPAGE;
}
break;
case EXTENSION_LINE:
- ast_copy_string(pte->device->extension_number, pte->device->lines->name,
+ ast_copy_string(pte->device->extension_number, get_main_line(pte->device)->name,
sizeof(pte->device->extension_number));
- if (RegisterExtension(pte))
+ if (register_extension(pte))
pte->state = STATE_EXTENSION;
else
pte->state = STATE_MAINPAGE;
@@ -1724,20 +2094,18 @@ static int write_history(struct unistimsession *pte, c
snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_LOG_DIR, USTM_LOG_DIR);
if (ast_mkdir(tmp, 0770)) {
- if (errno != EEXIST) {
- display_last_error("Unable to create directory for history");
- return -1;
- }
+ ast_log(LOG_WARNING, "Unable to create directory for history");
+ return -1;
}
ast_localtime(&now, &atm, NULL);
if (ismissed) {
if (way == 'i')
- strcpy(tmp2, "Miss");
+ strcpy(tmp2, ustmtext("Miss", pte));
else
- strcpy(tmp2, "Fail");
+ strcpy(tmp2, ustmtext("Fail", pte));
} else
- strcpy(tmp2, "Answ");
+ strcpy(tmp2, ustmtext("Answ", pte));
snprintf(line1, sizeof(line1), "%04d/%02d/%02d %02d:%02d:%02d %s",
atm.tm_year + 1900, atm.tm_mon + 1, atm.tm_mday, atm.tm_hour,
atm.tm_min, atm.tm_sec, tmp2);
@@ -1855,41 +2223,14 @@ static int write_history(struct unistimsession *pte, c
return 0;
}
-static void cancel_dial(struct unistimsession *pte)
+static void unistim_quiet_chan(struct ast_channel *chan)
{
- send_no_ring(pte);
- pte->device->missed_call++;
- write_history(pte, 'i', 1);
- show_main_page(pte);
- return;
-}
-
-static void swap_subs(struct unistim_line *p, int a, int b)
-{
-/* struct ast_channel *towner; */
- struct ast_rtp_instance *rtp;
- int fds;
-
- if (unistimdebug)
- ast_verb(0, "Swapping %d and %d\n", a, b);
-
- if ((!p->subs[a]->owner) || (!p->subs[b]->owner)) {
- ast_log(LOG_WARNING,
- "Attempted to swap subchannels with a null owner : sub #%d=%p sub #%d=%p\n",
- a, p->subs[a]->owner, b, p->subs[b]->owner);
- return;
+ if (chan && chan->_state == AST_STATE_UP) {
+ if (ast_test_flag(chan, AST_FLAG_MOH))
+ ast_moh_stop(chan);
+ else if (chan->generatordata)
+ ast_deactivate_generator(chan);
}
- rtp = p->subs[a]->rtp;
- p->subs[a]->rtp = p->subs[b]->rtp;
- p->subs[b]->rtp = rtp;
-
- fds = p->subs[a]->owner->fds[0];
- p->subs[a]->owner->fds[0] = p->subs[b]->owner->fds[0];
- p->subs[b]->owner->fds[0] = fds;
-
- fds = p->subs[a]->owner->fds[1];
- p->subs[a]->owner->fds[1] = p->subs[b]->owner->fds[1];
- p->subs[b]->owner->fds[1] = fds;
}
static int attempt_transfer(struct unistim_subchannel *p1, struct unistim_subchannel *p2)
@@ -1919,25 +2260,13 @@ static int attempt_transfer(struct unistim_subchannel
}
if (peera && peerb && peerc && (peerb != peerc)) {
- /*ast_quiet_chan(peera);
- ast_quiet_chan(peerb);
- ast_quiet_chan(peerc);
- ast_quiet_chan(peerd); */
+ unistim_quiet_chan(peera);
+ unistim_quiet_chan(peerb);
+ unistim_quiet_chan(peerc);
+ /* if (peerd)
+ unistim_quiet_chan(peerd); */
- if (peera->cdr && peerb->cdr) {
- peerb->cdr = ast_cdr_append(peerb->cdr, peera->cdr);
- } else if (peera->cdr) {
- peerb->cdr = peera->cdr;
- }
- peera->cdr = NULL;
-
- if (peerb->cdr && peerc->cdr) {
- peerb->cdr = ast_cdr_append(peerb->cdr, peerc->cdr);
- } else if (peerc->cdr) {
- peerb->cdr = peerc->cdr;
- }
- peerc->cdr = NULL;
-
+ ast_debug(4, "UNISTIM transfer: trying to masquerade %s into %s\n", peerc->name, peerb->name);
if (ast_channel_masquerade(peerb, peerc)) {
ast_log(LOG_WARNING, "Failed to masquerade %s into %s\n", peerb->name,
peerc->name);
@@ -1975,32 +2304,122 @@ void change_callerid(struct unistimsession *pte, int t
memcpy(data, callerid, size);
}
+static struct unistim_subchannel* get_sub(struct unistim_device *device, int type) {
+ struct unistim_subchannel *sub = NULL;
+
+ AST_LIST_LOCK(&device->subs);
+ AST_LIST_TRAVERSE(&device->subs, sub, list) {
+ if (!sub)
+ continue;
+ if (sub->subtype == type) {
+ break;
+ }
+ }
+ AST_LIST_UNLOCK(&device->subs);
+
+ return sub;
+}
+
+static void sub_start_silence(struct unistimsession *pte, struct unistim_subchannel *sub) {
+ /* Silence our channel */
+ if (!pte->device->silence_generator) {
+ pte->device->silence_generator =
+ ast_channel_start_silence_generator(sub->owner);
+ if (pte->device->silence_generator == NULL)
+ ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
+ else if (unistimdebug)
+ ast_verb(0, "Starting silence generator\n");
+ }
+
+}
+
+static void sub_stop_silence(struct unistimsession *pte, struct unistim_subchannel *sub) {
+ /* Stop the silence generator */
+ if (pte->device->silence_generator) {
+ if (unistimdebug)
+ ast_verb(0, "Stopping silence generator\n");
+ if (sub->owner)
+ ast_channel_stop_silence_generator(sub->owner, pte->device->silence_generator);
+ else
+ ast_log(LOG_WARNING, "Trying to stop silence generator on a null channel !\n");
+ pte->device->silence_generator = NULL;
+ }
+}
+
+static void sub_hold(struct unistimsession *pte, struct unistim_subchannel *sub) {
+ if (!sub) {
+ return;
+ }
+ sub->moh = 1;
+ sub->subtype = SUB_ONHOLD;
+ send_favorite_short(sub->softkey, FAV_ICON_ONHOLD_BLACK + FAV_BLINK_SLOW, pte);
+ send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
+ send_hide_timer_id(pte, sub->softkey);
+ if (sub->owner) {
+ ast_queue_control_data(sub->owner, AST_CONTROL_HOLD, NULL, 0);
+ send_end_call(pte);
+ }
+ return;
+}
+
+static void sub_unhold(struct unistimsession *pte, struct unistim_subchannel *sub) {
+ struct unistim_subchannel *sub_real;
+
+ sub_real = get_sub(pte->device, SUB_REAL);
+ if (sub_real) {
+ sub_hold(pte, sub_real);
+ }
+
+ sub->moh = 0;
+ sub->subtype = SUB_REAL;
+ send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, pte);
+ send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
+ send_show_timer_id(pte, sub->softkey);
+ if (sub->owner) {
+ ast_queue_control_data(sub->owner, AST_CONTROL_UNHOLD, NULL, 0);
+ if (sub->rtp)
+ send_start_rtp(sub);
+ }
+ return;
+}
+
static void close_call(struct unistimsession *pte)
{
- struct unistim_subchannel *sub;
- struct unistim_line *l = pte->device->lines;
+ struct unistim_subchannel *sub, *sub_transf;
- sub = pte->device->lines->subs[SUB_REAL];
+ sub = get_sub(pte->device, SUB_REAL);
+ sub_transf = get_sub(pte->device, SUB_THREEWAY);
send_stop_timer(pte);
+ if (!sub) {
+ ast_log(LOG_WARNING, "Close call without sub\n");
+ return;
+ }
+ send_favorite_short(sub->softkey, FAV_LINE_ICON, pte);
if (sub->owner) {
sub->alreadygone = 1;
- if (l->subs[SUB_THREEWAY]) {
- l->subs[SUB_THREEWAY]->alreadygone = 1;
- if (attempt_transfer(sub, l->subs[SUB_THREEWAY]) < 0)
+ if (sub_transf) {
+ sub_transf->alreadygone = 1;
+ ast_moh_stop(ast_bridged_channel(sub_transf->owner));
+ sub_transf->moh = 0;
+ if (attempt_transfer(sub, sub_transf) < 0)
ast_verb(0, "attempt_transfer failed.\n");
} else
ast_queue_hangup(sub->owner);
} else {
- if (l->subs[SUB_THREEWAY]) {
- if (l->subs[SUB_THREEWAY]->owner)
- ast_queue_hangup_with_cause(l->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
+ if (sub_transf) {
+ if (sub_transf->owner)
+ ast_queue_hangup_with_cause(sub_transf->owner, AST_CAUSE_NORMAL_CLEARING);
else
ast_log(LOG_WARNING, "threeway sub without owner\n");
- } else
+ } else {
ast_verb(0, "USTM(%s@%s-%d) channel already destroyed\n", sub->parent->name,
- sub->parent->parent->name, sub->subtype);
- }
- change_callerid(pte, 0, pte->device->redial_number);
+ pte->device->name, sub->softkey);
+ /* XXX Crash because of outputing strings in log? probably sub->parent->name going wrong
+ * when buttons very fast pressed
+ */
+ }
+ }
+ change_callerid(pte, 0, pte->device->redial_number);
change_callerid(pte, 1, "");
write_history(pte, 'o', pte->device->missed_call);
pte->device->missed_call = 0;
@@ -2008,9 +2427,10 @@ static void close_call(struct unistimsession *pte)
return;
}
-static void IgnoreCall(struct unistimsession *pte)
+static void ignore_call(struct unistimsession *pte)
{
send_no_ring(pte);
+ /* XXX Add option to hangup incoming call or forward it to voicemail/exten */
return;
}
@@ -2022,7 +2442,7 @@ static void *unistim_ss(void *data)
struct unistimsession *s = l->parent->session;
int res;
- ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->subtype, s->device->phone_number);
+ ast_verb(3, "Starting switch on '%s@%s-%d' to %s\n", l->name, l->parent->name, sub->softkey, s->device->phone_number);
ast_copy_string(chan->exten, s->device->phone_number, sizeof(chan->exten));
ast_copy_string(s->device->redial_number, s->device->phone_number,
sizeof(s->device->redial_number));
@@ -2030,85 +2450,50 @@ static void *unistim_ss(void *data)
res = ast_pbx_run(chan);
if (res) {
ast_log(LOG_WARNING, "PBX exited non-zero\n");
- send_tone(s, 1000, 0);;
+ send_tone(s, 1000, 0);
}
return NULL;
}
-static void start_rtp(struct unistim_subchannel *sub)
-{
+static int find_rtp_port(struct unistim_subchannel *s) {
+ struct unistim_subchannel *sub = NULL;
+ int rtp_start = s->parent->parent->rtp_port;
+ struct ast_sockaddr us_tmp;
+ struct sockaddr_in us = { 0, };
+
+ AST_LIST_LOCK(&s->parent->parent->subs);
+ AST_LIST_TRAVERSE(&s->parent->parent->subs, sub, list) {
+ if (!sub)
+ continue;
+ if (sub->rtp) {
+ ast_rtp_instance_get_remote_address(sub->rtp, &us_tmp);
+ ast_sockaddr_to_sin(&us_tmp, &us);
+ if (htons(us.sin_port)) {
+ rtp_start = htons(us.sin_port) + 1;
+ break;
+ }
+ }
+ }
+ AST_LIST_UNLOCK(&s->parent->parent->subs);
+ return rtp_start;
+}
+
+static void send_start_rtp(struct unistim_subchannel *sub) {
BUFFSEND;
- struct sockaddr_in us = { 0, };
+
+ format_t codec;
struct sockaddr_in public = { 0, };
+ struct sockaddr_in us = { 0, };
struct sockaddr_in sin = { 0, };
- format_t codec;
- struct sockaddr_in sout = { 0, };
struct ast_sockaddr us_tmp;
struct ast_sockaddr sin_tmp;
- struct ast_sockaddr sout_tmp;
+ struct unistimsession *pte;
- /* Sanity checks */
- if (!sub) {
- ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
- return;
- }
- if (!sub->parent) {
- ast_log(LOG_WARNING, "start_rtp with a null line !\n");
- return;
- }
- if (!sub->parent->parent) {
- ast_log(LOG_WARNING, "start_rtp with a null device !\n");
- return;
- }
- if (!sub->parent->parent->session) {
- ast_log(LOG_WARNING, "start_rtp with a null session !\n");
- return;
- }
- sout = sub->parent->parent->session->sout;
-
- ast_mutex_lock(&sub->lock);
- /* Allocate the RTP */
- if (unistimdebug)
- ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
- ast_sockaddr_from_sin(&sout_tmp, &sout);
- sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
- if (!sub->rtp) {
- ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
- strerror(errno), ast_inet_ntoa(sout.sin_addr));
- ast_mutex_unlock(&sub->lock);
- return;
- }
- ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
- if (sub->owner) {
- sub->owner->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
- sub->owner->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
- }
- ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
- ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
-
- /* Create the RTP connection */
ast_rtp_instance_get_local_address(sub->rtp, &us_tmp);
ast_sockaddr_to_sin(&us_tmp, &us);
- sin.sin_family = AF_INET;
- /* Setting up RTP for our side */
- memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
- sizeof(sin.sin_addr));
- sin.sin_port = htons(sub->parent->parent->rtp_port);
- ast_sockaddr_from_sin(&sin_tmp, &sin);
- ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
- if (!(sub->owner->nativeformats & sub->owner->readformat)) {
- format_t fmt;
- char tmp[256];
- fmt = ast_best_codec(sub->owner->nativeformats);
- ast_log(LOG_WARNING,
- "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
- ast_getformatname(sub->owner->readformat),
- ast_getformatname(fmt),
- ast_getformatname_multiple(tmp, sizeof(tmp), sub->owner->nativeformats));
- sub->owner->readformat = fmt;
- sub->owner->writeformat = fmt;
- }
- codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, sub->owner->readformat);
+ ast_rtp_instance_get_remote_address(sub->rtp, &sin_tmp);
+ ast_sockaddr_to_sin(&sin_tmp, &sin);
+
/* Setting up RTP of the phone */
if (public_ip.sin_family == 0) /* NAT IP override ? */
memcpy(&public, &us, sizeof(public)); /* No defined, using IP from recvmsg */
@@ -2121,35 +2506,35 @@ static void start_rtp(struct unistim_subchannel *sub)
ast_verb(0, "Starting phone RTP stack. Our public IP is %s\n",
ast_inet_ntoa(public.sin_addr));
}
- if ((sub->owner->readformat == AST_FORMAT_ULAW) ||
+
+ pte = sub->parent->parent->session;
+ codec = ast_rtp_codecs_payload_code(ast_rtp_instance_get_codecs(sub->rtp), 1, sub->owner->readformat);
+ if ((sub->owner->readformat == AST_FORMAT_ULAW) ||
(sub->owner->readformat == AST_FORMAT_ALAW)) {
if (unistimdebug)
ast_verb(0, "Sending packet_send_rtp_packet_size for codec %s\n", ast_getformatname(codec));
memcpy(buffsend + SIZE_HEADER, packet_send_rtp_packet_size,
sizeof(packet_send_rtp_packet_size));
buffsend[10] = (int) codec & 0xffffffffLL;
- send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend,
- sub->parent->parent->session);
+ send_client(SIZE_HEADER + sizeof(packet_send_rtp_packet_size), buffsend, pte);
}
if (unistimdebug)
ast_verb(0, "Sending Jitter Buffer Parameters Configuration\n");
memcpy(buffsend + SIZE_HEADER, packet_send_jitter_buffer_conf,
sizeof(packet_send_jitter_buffer_conf));
- send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend,
- sub->parent->parent->session);
- if (sub->parent->parent->rtp_method != 0) {
+ send_client(SIZE_HEADER + sizeof(packet_send_jitter_buffer_conf), buffsend, pte);
+ if (pte->device->rtp_method != 0) {
uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
if (unistimdebug)
- ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n",
- sub->parent->parent->rtp_method);
- if (sub->parent->parent->rtp_method == 3)
+ ast_verb(0, "Sending OpenAudioStreamTX using method #%d\n", pte->device->rtp_method);
+ if (pte->device->rtp_method == 3)
memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx3,
sizeof(packet_send_open_audio_stream_tx3));
else
memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_tx,
sizeof(packet_send_open_audio_stream_tx));
- if (sub->parent->parent->rtp_method != 2) {
+ if (pte->device->rtp_method != 2) {
memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
buffsend[21] = (htons(sin.sin_port) & 0x00ff);
@@ -2168,18 +2553,17 @@ static void start_rtp(struct unistim_subchannel *sub)
buffsend[11] = codec;
}
buffsend[12] = codec;
- send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend,
- sub->parent->parent->session);
+ send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_tx), buffsend, pte);
if (unistimdebug)
ast_verb(0, "Sending OpenAudioStreamRX\n");
- if (sub->parent->parent->rtp_method == 3)
+ if (pte->device->rtp_method == 3)
memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx3,
sizeof(packet_send_open_audio_stream_rx3));
else
memcpy(buffsend + SIZE_HEADER, packet_send_open_audio_stream_rx,
sizeof(packet_send_open_audio_stream_rx));
- if (sub->parent->parent->rtp_method != 2) {
+ if (pte->device->rtp_method != 2) {
memcpy(buffsend + 28, &public.sin_addr, sizeof(public.sin_addr));
buffsend[20] = (htons(sin.sin_port) & 0xff00) >> 8;
buffsend[21] = (htons(sin.sin_port) & 0x00ff);
@@ -2198,8 +2582,7 @@ static void start_rtp(struct unistim_subchannel *sub)
buffsend[12] = codec;
}
buffsend[11] = codec;
- send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend,
- sub->parent->parent->session);
+ send_client(SIZE_HEADER + sizeof(packet_send_open_audio_stream_rx), buffsend, pte);
} else {
uint16_t rtcpsin_port = htons(us.sin_port) + 1; /* RTCP port is RTP + 1 */
@@ -2233,73 +2616,152 @@ static void start_rtp(struct unistim_subchannel *sub)
buffsend[46] = (htons(sin.sin_port) & 0x00ff);
buffsend[47] = (rtcpsin_port & 0xff00) >> 8;
buffsend[48] = (rtcpsin_port & 0x00ff);
- send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend,
- sub->parent->parent->session);
+ send_client(SIZE_HEADER + sizeof(packet_send_call), buffsend, pte);
}
- ast_mutex_unlock(&sub->lock);
}
-static void SendDialTone(struct unistimsession *pte)
+static void start_rtp(struct unistim_subchannel *sub)
{
- int i;
- /* No country defined ? Using US tone */
- if (ast_strlen_zero(pte->device->country)) {
- if (unistimdebug)
- ast_verb(0, "No country defined, using US tone\n");
- send_tone(pte, 350, 440);
+ struct sockaddr_in sin = { 0, };
+ struct sockaddr_in sout = { 0, };
+ struct ast_sockaddr sin_tmp;
+ struct ast_sockaddr sout_tmp;
+
+ /* Sanity checks */
+ if (!sub) {
+ ast_log(LOG_WARNING, "start_rtp with a null subchannel !\n");
return;
}
- if (strlen(pte->device->country) != 2) {
- if (unistimdebug)
- ast_verb(0, "Country code != 2 char, using US tone\n");
- send_tone(pte, 350, 440);
+ if (!sub->parent) {
+ ast_log(LOG_WARNING, "start_rtp with a null line!\n");
return;
}
- i = 0;
- while (frequency[i].freq1) {
- if ((frequency[i].country[0] == pte->device->country[0]) &&
- (frequency[i].country[1] == pte->device->country[1])) {
- if (unistimdebug)
- ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
- frequency[i].country, frequency[i].freq1, frequency[i].freq2);
- send_tone(pte, frequency[i].freq1, frequency[i].freq2);
- }
- i++;
+ if (!sub->parent->parent) {
+ ast_log(LOG_WARNING, "start_rtp with a null device!\n");
+ return;
}
+ if (!sub->parent->parent->session) {
+ ast_log(LOG_WARNING, "start_rtp with a null session!\n");
+ return;
+ }
+ if (!sub->owner) {
+ ast_log(LOG_WARNING, "start_rtp with a null asterisk channel!\n");
+ return;
+ }
+ sout = sub->parent->parent->session->sout;
+ sout.sin_family = AF_INET;
+ ast_mutex_lock(&sub->lock);
+ /* Allocate the RTP */
+ if (unistimdebug)
+ ast_verb(0, "Starting RTP. Bind on %s\n", ast_inet_ntoa(sout.sin_addr));
+ ast_sockaddr_from_sin(&sout_tmp, &sout);
+ sub->rtp = ast_rtp_instance_new("asterisk", sched, &sout_tmp, NULL);
+ if (!sub->rtp) {
+ ast_log(LOG_WARNING, "Unable to create RTP session: %s binaddr=%s\n",
+ strerror(errno), ast_inet_ntoa(sout.sin_addr));
+ ast_mutex_unlock(&sub->lock);
+ return;
+ }
+ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_RTCP, 1);
+ sub->owner->fds[0] = ast_rtp_instance_fd(sub->rtp, 0);
+ sub->owner->fds[1] = ast_rtp_instance_fd(sub->rtp, 1);
+ ast_rtp_instance_set_qos(sub->rtp, qos.tos_audio, qos.cos_audio, "UNISTIM RTP");
+ ast_rtp_instance_set_prop(sub->rtp, AST_RTP_PROPERTY_NAT, sub->parent->parent->nat);
+
+ /* Create the RTP connection */
+ sin.sin_family = AF_INET;
+ /* Setting up RTP for our side */
+ memcpy(&sin.sin_addr, &sub->parent->parent->session->sin.sin_addr,
+ sizeof(sin.sin_addr));
+
+ sin.sin_port = htons(find_rtp_port(sub));
+ ast_sockaddr_from_sin(&sin_tmp, &sin);
+ ast_rtp_instance_set_remote_address(sub->rtp, &sin_tmp);
+ if (!(sub->owner->nativeformats & sub->owner->readformat)) {
+ format_t fmt;
+ char tmp[256];
+ fmt = ast_best_codec(sub->owner->nativeformats);
+ ast_log(LOG_WARNING,
+ "Our read/writeformat has been changed to something incompatible: %s, using %s best codec from %s\n",
+ ast_getformatname(sub->owner->readformat),
+ ast_getformatname(fmt),
+ ast_getformatname_multiple(tmp, sizeof(tmp), sub->owner->nativeformats));
+ sub->owner->readformat = fmt;
+ sub->owner->writeformat = fmt;
+ }
+
+ send_start_rtp(sub);
+
+ ast_mutex_unlock(&sub->lock);
}
+static void send_dial_tone(struct unistimsession *pte)
+{
+ struct ast_tone_zone_sound *ts = NULL;
+ struct ast_tone_zone_part tone_data;
+ char *s = NULL;
+ char *ind;
+
+ if ((ts = ast_get_indication_tone(pte->device->tz, "dial"))) {
+ ind = ast_strdupa(ts->data);
+ s = strsep(&ind, ",");
+ ast_tone_zone_part_parse(s, &tone_data);
+ if (tone_data.modulate)
+ tone_data.freq2 = 0;
+
+ send_tone(pte, tone_data.freq1, tone_data.freq2);
+ if (unistimdebug)
+ ast_verb(0, "Country code found (%s), freq1=%d freq2=%d\n",
+ pte->device->tz->country, tone_data.freq1, tone_data.freq2);
+
+ ts = ast_tone_zone_sound_unref(ts);
+ }
+}
+
+static void show_phone_number(struct unistimsession *pte)
+{
+ char tmp[TEXT_LENGTH_MAX + 1];
+ const char *tmp_number = ustmtext("Number:", pte);
+ int line, offset = 0, i;
+
+ pte->device->phone_number[pte->device->size_phone_number] = '\0';
+ if (pte->device->size_phone_number > MAX_SCREEN_NUMBER) {
+ offset = pte->device->size_phone_number - MAX_SCREEN_NUMBER - 1;
+ if (offset > strlen(tmp_number))
+ offset = strlen(tmp_number);
+ memcpy(tmp, tmp_number + offset, strlen(tmp_number) - offset + 1);
+ } else {
+ strcpy(tmp, tmp_number);
+ }
+
+ offset = (pte->device->size_phone_number >= TEXT_LENGTH_MAX) ? (pte->device->size_phone_number - TEXT_LENGTH_MAX +1) : 0;
+ if (pte->device->size_phone_number)
+ memcpy(tmp + strlen(tmp), pte->device->phone_number + offset, pte->device->size_phone_number - offset + 1);
+ offset = strlen(tmp);
+
+ for (i = strlen(tmp); i < TEXT_LENGTH_MAX; i++) {
+ tmp[i] = '.';
+ }
+ tmp[i] = '\0';
+
+ line = (pte->device->height == 1) ? TEXT_LINE0 : TEXT_LINE2;
+ send_text(line, TEXT_NORMAL, pte, tmp);
+ send_blink_cursor(pte);
+ send_cursor_pos(pte, (unsigned char) (line + offset));
+ send_led_update(pte, 0);
+}
+
static void handle_dial_page(struct unistimsession *pte)
{
pte->state = STATE_DIALPAGE;
if (pte->device->call_forward[0] == -1) {
send_text(TEXT_LINE0, TEXT_NORMAL, pte, "");
- send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Enter forward");
- send_text_status(pte, "ForwardCancel BackSpcErase");
+ send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Enter forward", pte));
+ send_text_status(pte, ustmtext("Fwd Cancel BackSp Erase", pte));
if (pte->device->call_forward[1] != 0) {
- char tmp[TEXT_LENGTH_MAX + 1];
-
ast_copy_string(pte->device->phone_number, pte->device->call_forward + 1,
sizeof(pte->device->phone_number));
- pte->device->size_phone_number = strlen(pte->device->phone_number);
- if (pte->device->size_phone_number > 15)
- pte->device->size_phone_number = 15;
- strcpy(tmp, "Number : ...............");
- memcpy(tmp + 9, pte->device->phone_number, pte->device->size_phone_number);
-
- if (pte->device->height == 1) {
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp);
- send_blink_cursor(pte);
- send_cursor_pos(pte,
- (unsigned char) (TEXT_LINE0 + 0x09 +
- pte->device->size_phone_number));
- } else {
- send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
- send_blink_cursor(pte);
- send_cursor_pos(pte,
- (unsigned char) (TEXT_LINE2 + 0x09 +
- pte->device->size_phone_number));
- }
-
+ show_phone_number(pte);
send_led_update(pte, 0);
return;
}
@@ -2309,191 +2771,268 @@ static void handle_dial_page(struct unistimsession *pt
send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
else
send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
- SendDialTone(pte);
+ send_dial_tone(pte);
if (pte->device->height > 1) {
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Enter the number to dial");
- send_text(TEXT_LINE1, TEXT_NORMAL, pte, "and press Call");
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Enter the number to dial", pte));
+ send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("and press Call", pte));
}
- send_text_status(pte, "Call Redial BackSpcErase");
+ send_text_status(pte, ustmtext("Call Redial BackSp Erase", pte));
}
- if (pte->device->height == 1) {
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
- send_blink_cursor(pte);
- send_cursor_pos(pte, TEXT_LINE0 + 0x09);
- } else {
- send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
- send_blink_cursor(pte);
- send_cursor_pos(pte, TEXT_LINE2 + 0x09);
- }
pte->device->size_phone_number = 0;
pte->device->phone_number[0] = 0;
- change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
- Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
+ show_phone_number(pte);
+ change_favorite_icon(pte, FAV_ICON_PHONE_BLACK);
+ send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
pte->device->missed_call = 0;
send_led_update(pte, 0);
return;
}
+static void swap_subs(struct unistim_subchannel *a, struct unistim_subchannel *b)
+{
+/* struct ast_channel *towner; */
+ struct ast_rtp_instance *rtp;
+ int fds;
+
+ if (unistimdebug)
+ ast_verb(0, "Swapping %p and %p\n", a, b);
+
+ if ((!a->owner) || (!b->owner)) {
+ ast_log(LOG_WARNING,
+ "Attempted to swap subchannels with a null owner : sub #%p=%p sub #%p=%p\n",
+ a, a->owner, b, b->owner);
+ return;
+ }
+ rtp = a->rtp;
+ a->rtp = b->rtp;
+ b->rtp = rtp;
+
+ fds = a->owner->fds[0];
+ a->owner->fds[0] = b->owner->fds[0];
+ b->owner->fds[0] = fds;
+
+ fds = a->owner->fds[1];
+ a->owner->fds[1] = b->owner->fds[1];
+ b->owner->fds[1] = fds;
+}
+
/* Step 1 : Music On Hold for peer, Dialing screen for us */
-static void TransferCallStep1(struct unistimsession *pte)
+static void transfer_call_step1(struct unistimsession *pte)
{
- struct unistim_subchannel *sub;
- struct unistim_line *p = pte->device->lines;
+ struct unistim_subchannel *sub, *sub_trans;
+ struct unistim_device *d = pte->device;
- sub = p->subs[SUB_REAL];
+ sub = get_sub(d, SUB_REAL);
+ sub_trans = get_sub(d, SUB_THREEWAY);
- if (!sub->owner) {
+ if (!sub || !sub->owner) {
ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
return;
}
- if (p->subs[SUB_THREEWAY]) {
+ if (sub_trans) {
if (unistimdebug)
ast_verb(0, "Transfer canceled, hangup our threeway channel\n");
- if (p->subs[SUB_THREEWAY]->owner)
- ast_queue_hangup_with_cause(p->subs[SUB_THREEWAY]->owner, AST_CAUSE_NORMAL_CLEARING);
- else
+ if (sub->owner) {
+ swap_subs(sub, sub_trans);
+ ast_moh_stop(ast_bridged_channel(sub_trans->owner));
+ sub_trans->moh = 0;
+ sub_trans->subtype = SUB_REAL;
+ ast_queue_hangup_with_cause(sub->owner, AST_CAUSE_NORMAL_CLEARING);
+ } else
ast_log(LOG_WARNING, "Canceling a threeway channel without owner\n");
return;
}
/* Start music on hold if appropriate */
- if (pte->device->moh)
+ if (sub->moh)
ast_log(LOG_WARNING, "Transfer with peer already listening music on hold\n");
else {
- if (ast_bridged_channel(p->subs[SUB_REAL]->owner)) {
- ast_moh_start(ast_bridged_channel(p->subs[SUB_REAL]->owner),
- pte->device->lines->musicclass, NULL);
- pte->device->moh = 1;
+ if (ast_bridged_channel(sub->owner)) {
+ ast_moh_start(ast_bridged_channel(sub->owner),
+ sub->parent->musicclass, NULL);
+ sub->moh = 1;
+ sub->subtype = SUB_THREEWAY;
} else {
ast_log(LOG_WARNING, "Unable to find peer subchannel for music on hold\n");
return;
}
}
- /* Silence our channel */
- if (!pte->device->silence_generator) {
- pte->device->silence_generator =
- ast_channel_start_silence_generator(p->subs[SUB_REAL]->owner);
- if (pte->device->silence_generator == NULL)
- ast_log(LOG_WARNING, "Unable to start a silence generator.\n");
- else if (unistimdebug)
- ast_verb(0, "Starting silence generator\n");
- }
+ sub_start_silence(pte, sub);
handle_dial_page(pte);
}
/* From phone to PBX */
-static void HandleCallOutgoing(struct unistimsession *s)
+static void handle_call_outgoing(struct unistimsession *s)
{
struct ast_channel *c;
struct unistim_subchannel *sub;
+ int softkey;
pthread_t t;
+
s->state = STATE_CALL;
- sub = s->device->lines->subs[SUB_REAL];
- if (!sub) {
- ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
- return;
- }
+ s->sout.sin_family = AF_INET;
+
+ sub = get_sub(s->device, SUB_THREEWAY);
+ if (sub) {
+ /* If sub for threway call created than we use transfer behaviuor */
+ struct unistim_subchannel *sub_trans = NULL;
+ struct unistim_device *d = s->device;
+
+ sub_trans = get_sub(d, SUB_REAL);
+ if (sub_trans) {
+ ast_log(LOG_WARNING,
+ "Can't transfer while active subchannel exists!\n");
+ return;
+ }
+ if (!sub->owner) {
+ ast_log(LOG_WARNING, "Unable to find subchannel with music on hold\n");
+ return;
+ }
+
+ sub_trans = alloc_sub(d, SUB_REAL);
+ sub_trans->parent = sub->parent;
+ if (!sub_trans) {
+ ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
+ return;
+ }
+ sub_stop_silence(s, sub);
+ send_tone(s, 0, 0);
+ /* Make new channel */
+ c = unistim_new(sub_trans, AST_STATE_DOWN, NULL);
+ if (!c) {
+ ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", sub->parent);
+ return;
+ }
+ /* Swap things around between the three-way and real call */
+ swap_subs(sub, sub_trans);
+ send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
+ if (s->device->height == 1) {
+ send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
+ } else {
+ send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling (pre-transfer)", s));
+ send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
+ send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
+ }
+ send_text_status(s, ustmtext("TransfrCancel", s));
+
+ if (ast_pthread_create(&t, NULL, unistim_ss, c)) {
+ ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", c);
+ ast_hangup(c);
+ return;
+ }
+ if (unistimdebug)
+ ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
+ sub_trans->owner, sub_trans->owner->name, sub_trans->subtype);
+ return;
+ }
+
+ softkey = get_avail_softkey(s, NULL);
+ if (softkey == -1) {
+ ast_log(LOG_WARNING, "Have no avail softkey for calling\n");
+ return;
+ }
+ sub = get_sub(s->device, SUB_REAL);
+ if (sub) { /* have already call assigned */
+ sub_hold(s, sub); /* Need to put on hold */
+ }
+ sub = alloc_sub(s->device, SUB_REAL);
+ sub->parent = s->device->sline[softkey];
+ s->device->ssub[softkey] = sub;
+ sub->softkey = softkey;
+
+ if (unistimdebug)
+ ast_verb(0, "Using softkey %d, line %p\n", sub->softkey, sub->parent);
+ send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
+ s->device->selected = -1;
if (!sub->owner) { /* A call is already in progress ? */
c = unistim_new(sub, AST_STATE_DOWN, NULL); /* No, starting a new one */
- if (c) {
- /* Need to start RTP before calling ast_pbx_run */
- if (!sub->rtp)
- start_rtp(sub);
- send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
+ if (!sub->rtp) /* Need to start RTP before calling ast_pbx_run */
+ start_rtp(sub);
+ if (!strcmp(s->device->phone_number, ast_pickup_ext())) {
+ if (unistimdebug)
+ ast_verb(0, "Try to pickup in unistim_new\n");
+ send_text(TEXT_LINE0, TEXT_NORMAL, s, "");
+ send_text_status(s, ustmtext("Hangup Transf", s));
+ send_start_timer_id(s, sub->softkey);
+ if (ast_pickup_call(c)) {
+ ast_log(LOG_NOTICE, "Nothing to pick up\n");
+ c->hangupcause = AST_CAUSE_CALL_REJECTED;
+ } else {
+ c->hangupcause = AST_CAUSE_NORMAL_CLEARING;
+ }
+ ast_hangup(c);
+ c = NULL;
+ } else if (c) {
+ send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
+ send_tone(s, 0, 0); /* Dialing empty number should also stop dial tone */
if (s->device->height == 1) {
- send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
+ if (strlen(s->device->phone_number) > 0) {
+ send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
+ } else {
+ send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling...", s));
+ }
} else {
- send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling :");
+ send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Calling :", s));
send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
- send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
+ send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Dialing...", s));
}
- send_text_status(s, "Hangup");
+ send_text_status(s, ustmtext("Hangup", s));
/* start switch */
if (ast_pthread_create(&t, NULL, unistim_ss, c)) {
- display_last_error("Unable to create switch thread");
+ ast_log(LOG_WARNING, "Unable to create switch thread\n");
ast_queue_hangup_with_cause(c, AST_CAUSE_SWITCH_CONGESTION);
}
} else
ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n",
sub->parent->name, s->device->name);
- } else { /* We already have a call, so we switch in a threeway call */
-
- if (s->device->moh) {
- struct unistim_subchannel *subchannel;
- struct unistim_line *p = s->device->lines;
- subchannel = p->subs[SUB_REAL];
-
- if (!subchannel->owner) {
- ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
- return;
- }
- if (p->subs[SUB_THREEWAY]) {
- ast_log(LOG_WARNING,
- "Can't transfer while an another transfer is taking place\n");
- return;
- }
- if (!alloc_sub(p, SUB_THREEWAY)) {
- ast_log(LOG_WARNING, "Unable to allocate three-way subchannel\n");
- return;
- }
- /* Stop the silence generator */
- if (s->device->silence_generator) {
- if (unistimdebug)
- ast_verb(0, "Stopping silence generator\n");
- ast_channel_stop_silence_generator(subchannel->owner,
- s->device->silence_generator);
- s->device->silence_generator = NULL;
- }
- send_tone(s, 0, 0);
- /* Make new channel */
- c = unistim_new(p->subs[SUB_THREEWAY], AST_STATE_DOWN, NULL);
- if (!c) {
- ast_log(LOG_WARNING, "Cannot allocate new structure on channel %p\n", p);
- return;
- }
- /* Swap things around between the three-way and real call */
- swap_subs(p, SUB_THREEWAY, SUB_REAL);
- send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
-
- if (s->device->height == 1) {
- send_text(TEXT_LINE0, TEXT_NORMAL, s, s->device->phone_number);
- } else {
- send_text(TEXT_LINE0, TEXT_NORMAL, s, "Calling (pre-transfer)");
- send_text(TEXT_LINE1, TEXT_NORMAL, s, s->device->phone_number);
- send_text(TEXT_LINE2, TEXT_NORMAL, s, "Dialing...");
- }
- send_text_status(s, "TransfrCancel");
-
- if (ast_pthread_create(&t, NULL, unistim_ss, p->subs[SUB_THREEWAY]->owner)) {
- ast_log(LOG_WARNING, "Unable to start simple switch on channel %p\n", p);
- ast_hangup(c);
- return;
- }
- if (unistimdebug)
- ast_verb(0, "Started three way call on channel %p (%s) subchan %d\n",
- p->subs[SUB_THREEWAY]->owner, p->subs[SUB_THREEWAY]->owner->name,
- p->subs[SUB_THREEWAY]->subtype);
- } else
- ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
+ } else {
+ ast_debug(1, "Current sub [%s] already has owner\n", sub->owner->name);
}
return;
}
/* From PBX to phone */
-static void HandleCallIncoming(struct unistimsession *s)
+static void handle_call_incoming(struct unistimsession *s)
{
- struct unistim_subchannel *sub;
+ struct unistim_subchannel *sub = NULL;
+ int i;
+
s->state = STATE_CALL;
s->device->missed_call = 0;
send_no_ring(s);
- sub = s->device->lines->subs[SUB_REAL];
+ sub = get_sub(s->device, SUB_RING); /* Put other SUB_REAL call on hold */
if (!sub) {
- ast_log(LOG_NOTICE, "No available lines on: %s\n", s->device->name);
+ ast_log(LOG_WARNING, "No ringing lines on: %s\n", s->device->name);
return;
- } else if (unistimdebug)
+ }
+ /* Change icons for all ringing keys */
+ for (i = 0; i < FAVNUM; i++) {
+ if (!s->device->ssub[i]) /* No sub assigned - skip */
+ continue;
+ if (s->device->ssub[i]->subtype == SUB_REAL)
+ sub_hold(s, s->device->ssub[i]);
+ if (s->device->ssub[i] != sub)
+ continue;
+ if (sub->softkey == i) /* If softkey assigned at this moment - do not erase */
+ continue;
+ if (sub->softkey < 0) { /* If softkey not defined - first one used */
+ sub->softkey = i;
+ continue;
+ }
+ send_favorite_short(i, FAV_LINE_ICON, s);
+ s->device->ssub[i] = NULL;
+ }
+ if (sub->softkey < 0) {
+ ast_log(LOG_WARNING, "Can not assign softkey for incoming call on: %s\n", s->device->name);
+ return;
+ }
+ send_favorite_short(sub->softkey, FAV_ICON_OFFHOOK_BLACK, s);
+ sub->parent = s->device->sline[sub->softkey];
+ sub->subtype = SUB_REAL;
+ if (unistimdebug)
ast_verb(0, "Handle Call Incoming for %s@%s\n", sub->parent->name,
s->device->name);
start_rtp(sub);
@@ -2501,16 +3040,16 @@ static void HandleCallIncoming(struct unistimsession *
ast_log(LOG_WARNING, "Unable to create channel for %s@%s\n", sub->parent->name,
s->device->name);
ast_queue_control(sub->owner, AST_CONTROL_ANSWER);
- send_text(TEXT_LINE2, TEXT_NORMAL, s, "is on-line");
- send_text_status(s, "Hangup Transf");
- send_start_timer(s);
+ send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is on-line", s));
+ send_text_status(s, ustmtext("Hangup Transf", s));
+ send_start_timer_id(s, sub->softkey);
if ((s->device->output == OUTPUT_HANDSET) &&
(s->device->receiver_state == STATE_ONHOOK))
send_select_output(s, OUTPUT_SPEAKER, s->device->volume, MUTE_OFF);
else
send_select_output(s, s->device->output, s->device->volume, MUTE_OFF);
- s->device->start_call_timestamp = time(0);
+ sub->start_call_timestamp = time(0);
write_history(s, 'i', 0);
return;
}
@@ -2519,8 +3058,10 @@ static int unistim_do_senddigit(struct unistimsession
{
struct ast_frame f = { .frametype = AST_FRAME_DTMF, .subclass.integer = digit, .src = "unistim" };
struct unistim_subchannel *sub;
- sub = pte->device->lines->subs[SUB_REAL];
- if (!sub->owner || sub->alreadygone) {
+ int row, col;
+
+ sub = get_sub(pte->device, SUB_REAL);
+ if (!sub || !sub->owner || sub->alreadygone) {
ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit\n");
return -1;
}
@@ -2530,65 +3071,80 @@ static int unistim_do_senddigit(struct unistimsession
if (unistimdebug)
ast_verb(0, "Send Digit %c\n", digit);
- switch (digit) {
- case '0':
- send_tone(pte, 941, 1336);
- break;
- case '1':
- send_tone(pte, 697, 1209);
- break;
- case '2':
- send_tone(pte, 697, 1336);
- break;
- case '3':
- send_tone(pte, 697, 1477);
- break;
- case '4':
- send_tone(pte, 770, 1209);
- break;
- case '5':
- send_tone(pte, 770, 1336);
- break;
- case '6':
- send_tone(pte, 770, 1477);
- break;
- case '7':
- send_tone(pte, 852, 1209);
- break;
- case '8':
- send_tone(pte, 852, 1336);
- break;
- case '9':
- send_tone(pte, 852, 1477);
- break;
- case 'A':
- send_tone(pte, 697, 1633);
- break;
- case 'B':
- send_tone(pte, 770, 1633);
- break;
- case 'C':
- send_tone(pte, 852, 1633);
- break;
- case 'D':
- send_tone(pte, 941, 1633);
- break;
- case '*':
- send_tone(pte, 941, 1209);
- break;
- case '#':
- send_tone(pte, 941, 1477);
- break;
- default:
- send_tone(pte, 500, 2000);
- }
+
+ row = (digit-'1')%3;
+ col = (digit-'1'-row)/3;
+ if (digit >= '1' && digit <='9')
+ send_tone(pte, dtmf_row[row], dtmf_col[col]);
+ else if (digit >= 'A' && digit <= 'D')
+ send_tone(pte, dtmf_row[digit-'A'], dtmf_col[3]);
+ else if (digit == '*')
+ send_tone(pte, dtmf_row[3], dtmf_col[0]);
+ else if (digit == '0')
+ send_tone(pte, dtmf_row[3], dtmf_col[1]);
+ else if (digit == '#')
+ send_tone(pte, dtmf_row[3], dtmf_col[2]);
+ else
+ send_tone(pte, 500, 2000);
+
usleep(150000); /* XXX Less than perfect, blocking an important thread is not a good idea */
send_tone(pte, 0, 0);
return 0;
}
+static void handle_key_fav(struct unistimsession *pte, char keycode) {
+ int keynum = keycode - KEY_FAV0;
+ struct unistim_subchannel *sub;
+
+ sub = get_sub(pte->device, SUB_REAL);
+
+ /* Make an action on selected favorite key */
+ if (!pte->device->ssub[keynum]) { /* Key have no assigned call */
+ send_favorite_selected(FAV_LINE_ICON, pte);
+ if (is_key_line(pte->device, keynum)) {
+ if (unistimdebug)
+ ast_verb(0, "Handle line w/o sub - dialpage\n");
+ pte->device->selected = keynum;
+ sub_hold(pte, sub); /* Put active call on hold */
+ send_stop_timer(pte);
+ handle_dial_page(pte);
+ } else if (is_key_favorite(pte->device, keynum)) {
+ /* Put active call on hold in handle_call_outgoing function, after preparation and
+ checking if lines available for calling */
+ if (unistimdebug)
+ ast_verb(0, "Handle favorite w/o sub - dialing\n");
+ if ((pte->device->output == OUTPUT_HANDSET) &&
+ (pte->device->receiver_state == STATE_ONHOOK))
+ send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
+ else
+ send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
+
+ key_favorite(pte, keycode);
+ }
+ } else {
+ sub = pte->device->ssub[keynum];
+ /* Favicon have assigned sub, activate it and put current on hold */
+ if (sub->subtype == SUB_REAL) {
+ sub_hold(pte, sub);
+ show_main_page(pte);
+ } else if (sub->subtype == SUB_RING) {
+ sub->softkey = keynum;
+ handle_call_incoming(pte);
+ } else if (sub->subtype == SUB_ONHOLD) {
+ if (pte->state == STATE_DIALPAGE){
+ send_tone(pte, 0, 0);
+ }
+ send_callerid_screen(pte, sub);
+ //send_start_timer_id(pte, sub->softkey);
+ sub_unhold(pte, sub);
+ pte->state = STATE_CALL;
+ }
+ }
+}
+
static void key_call(struct unistimsession *pte, char keycode)
{
+ struct unistim_subchannel *sub = NULL;
if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
if (keycode == KEY_SHARP)
keycode = '#';
@@ -2605,9 +3161,17 @@ static void key_call(struct unistimsession *pte, char
close_call(pte);
break;
case KEY_FUNC2:
- TransferCallStep1(pte);
+ transfer_call_step1(pte);
break;
- case KEY_HEADPHN:
+ case KEY_FAV0:
+ case KEY_FAV1:
+ case KEY_FAV2:
+ case KEY_FAV3:
+ case KEY_FAV4:
+ case KEY_FAV5:
+ handle_key_fav(pte, keycode);
+ break;
+ case KEY_HEADPHN:
if (pte->device->output == OUTPUT_HEADPHONE)
send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
else
@@ -2621,82 +3185,71 @@ static void key_call(struct unistimsession *pte, char
MUTE_OFF);
break;
case KEY_MUTE:
- if (!pte->device->moh) {
- if (pte->device->mute == MUTE_ON)
- send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
- else
- send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
- break;
- }
+ sub = get_sub(pte->device, SUB_REAL);
+ if (!sub || !sub->owner) {
+ ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
+ return;
+ }
+ if (!sub->moh) {
+ if (pte->device->mute == MUTE_ON)
+ send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
+ else
+ send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON);
+ break;
+ }
+ break;
case KEY_ONHOLD:
- {
- struct unistim_subchannel *sub;
- struct ast_channel *bridgepeer = NULL;
- sub = pte->device->lines->subs[SUB_REAL];
- if (!sub->owner) {
- ast_log(LOG_WARNING, "Unable to find subchannel for music on hold\n");
- return;
- }
- if ((bridgepeer = ast_bridged_channel(sub->owner))) {
- if (pte->device->moh) {
- ast_moh_stop(bridgepeer);
- pte->device->moh = 0;
- send_select_output(pte, pte->device->output, pte->device->volume,
- MUTE_OFF);
- } else {
- ast_moh_start(bridgepeer, pte->device->lines->musicclass, NULL);
- pte->device->moh = 1;
- send_select_output(pte, pte->device->output, pte->device->volume,
- MUTE_ON);
- }
- } else
- ast_log(LOG_WARNING,
- "Unable to find peer subchannel for music on hold\n");
- break;
- }
+ sub = get_sub(pte->device, SUB_REAL);
+ if (!sub) {
+ if(pte->device->ssub[pte->device->selected]) {
+ sub_hold(pte, pte->device->ssub[pte->device->selected]);
+ }
+ } else
+ sub_hold(pte, sub);
+ break;
}
return;
}
static void key_ringing(struct unistimsession *pte, char keycode)
{
- if (keycode == KEY_FAV0 + pte->device->softkeylinepos) {
- HandleCallIncoming(pte);
- return;
- }
switch (keycode) {
+ case KEY_FAV0:
+ case KEY_FAV1:
+ case KEY_FAV2:
+ case KEY_FAV3:
+ case KEY_FAV4:
+ case KEY_FAV5:
+ handle_key_fav(pte, keycode);
+ break;
case KEY_HANGUP:
case KEY_FUNC4:
- IgnoreCall(pte);
+ ignore_call(pte);
break;
case KEY_FUNC1:
- HandleCallIncoming(pte);
+ handle_call_incoming(pte);
break;
}
return;
}
-static void Keyfavorite(struct unistimsession *pte, char keycode)
+static void key_favorite(struct unistimsession *pte, char keycode)
{
- int fav;
-
- if ((keycode < KEY_FAV1) && (keycode > KEY_FAV5)) {
- ast_log(LOG_WARNING, "It's not a favorite key\n");
- return;
- }
- if (keycode == KEY_FAV0)
- return;
- fav = keycode - KEY_FAV0;
- if (pte->device->softkeyicon[fav] == 0)
- return;
+ int fav = keycode - KEY_FAV0;
+ if (!is_key_favorite(pte->device, fav)) {
+ ast_log(LOG_WARNING, "It's not a favorite key\n");
+ return;
+ }
ast_copy_string(pte->device->phone_number, pte->device->softkeynumber[fav],
sizeof(pte->device->phone_number));
- HandleCallOutgoing(pte);
+ handle_call_outgoing(pte);
return;
}
static void key_dial_page(struct unistimsession *pte, char keycode)
{
+ struct unistim_subchannel *sub = get_sub(pte->device, SUB_REAL);
+
if (keycode == KEY_FUNC3) {
if (pte->device->size_phone_number <= 1)
keycode = KEY_FUNC4;
@@ -2705,50 +3258,32 @@ static void key_dial_page(struct unistimsession *pte,
keycode = pte->device->phone_number[pte->device->size_phone_number] + 0x10;
}
}
+ if (keycode == KEY_SHARP && pte->device->sharp_dial == 1) {
+ keycode = KEY_FUNC1;
+ }
if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
- char tmpbuf[] = "Number : ...............";
- int i = 0;
+ int i = pte->device->size_phone_number;
- if (pte->device->size_phone_number >= 15)
- return;
if (pte->device->size_phone_number == 0)
send_tone(pte, 0, 0);
- while (i < pte->device->size_phone_number) {
- tmpbuf[i + 9] = pte->device->phone_number[i];
- i++;
- }
- if (keycode == KEY_SHARP)
- keycode = '#';
+
+ if (keycode == KEY_SHARP)
+ keycode = '#';
else if (keycode == KEY_STAR)
keycode = '*';
else
keycode -= 0x10;
- tmpbuf[i + 9] = keycode;
pte->device->phone_number[i] = keycode;
pte->device->size_phone_number++;
pte->device->phone_number[i + 1] = 0;
- if (pte->device->height == 1) {
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
- } else {
- send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
- }
- send_blink_cursor(pte);
- send_cursor_pos(pte, (unsigned char) (TEXT_LINE2 + 0x0a + i));
+
+ show_phone_number(pte);
return;
}
if (keycode == KEY_FUNC4) {
-
pte->device->size_phone_number = 0;
- if (pte->device->height == 1) {
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Number : ...............");
- send_blink_cursor(pte);
- send_cursor_pos(pte, TEXT_LINE0 + 0x09);
- } else {
- send_text(TEXT_LINE2, TEXT_NORMAL, pte, "Number : ...............");
- send_blink_cursor(pte);
- send_cursor_pos(pte, TEXT_LINE2 + 0x09);
- }
- return;
+ show_phone_number(pte);
+ return;
}
if (pte->device->call_forward[0] == -1) {
@@ -2758,7 +3293,9 @@ static void key_dial_page(struct unistimsession *pte,
show_main_page(pte);
} else if ((keycode == KEY_FUNC2) || (keycode == KEY_HANGUP)) {
pte->device->call_forward[0] = '\0';
- show_main_page(pte);
+ send_led_update(pte, 0x08);
+ send_led_update(pte, 0x10);
+ show_main_page(pte);
}
return;
}
@@ -2769,40 +3306,43 @@ static void key_dial_page(struct unistimsession *pte,
ast_copy_string(pte->device->phone_number, pte->device->redial_number,
sizeof(pte->device->phone_number));
case KEY_FUNC1:
- HandleCallOutgoing(pte);
+ handle_call_outgoing(pte);
break;
case KEY_HANGUP:
- if (pte->device->lines->subs[SUB_REAL]->owner) {
- /* Stop the silence generator */
- if (pte->device->silence_generator) {
- if (unistimdebug)
- ast_verb(0, "Stopping silence generator\n");
- ast_channel_stop_silence_generator(pte->device->lines->subs[SUB_REAL]->
- owner, pte->device->silence_generator);
- pte->device->silence_generator = NULL;
- }
- send_tone(pte, 0, 0);
- ast_moh_stop(ast_bridged_channel(pte->device->lines->subs[SUB_REAL]->owner));
- pte->device->moh = 0;
+ if (sub && sub->owner) {
+ struct ast_channel *bridgepeer = NULL;
+
+ sub_stop_silence(pte, sub);
+ send_tone(pte, 0, 0);
+ if ((bridgepeer = ast_bridged_channel(sub->owner))) {
+ ast_moh_stop(bridgepeer);
+ }
+ get_sub(pte->device, SUB_REAL)->moh = 0;
pte->state = STATE_CALL;
if (pte->device->height == 1) {
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dial Cancel,back to priv. call.");
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Dial Cancel,back to priv. call.", pte));
} else {
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Dialing canceled,");
- send_text(TEXT_LINE1, TEXT_NORMAL, pte, "switching back to");
- send_text(TEXT_LINE2, TEXT_NORMAL, pte, "previous call.");
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Dialing canceled,", pte));
+ send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("switching back to", pte));
+ send_text(TEXT_LINE2, TEXT_NORMAL, pte, ustmtext("previous call.", pte));
}
- send_text_status(pte, "Hangup Transf");
- } else
+ send_text_status(pte, ustmtext("Hangup Transf", pte));
+ } else {
+ send_led_update(pte, 0x08);
+ send_led_update(pte, 0x10);
show_main_page(pte);
+ }
break;
- case KEY_FAV1:
+ case KEY_FAV0:
+ case KEY_FAV1:
case KEY_FAV2:
case KEY_FAV3:
case KEY_FAV4:
case KEY_FAV5:
- Keyfavorite(pte, keycode);
+ send_favorite_selected(FAV_LINE_ICON, pte);
+ pte->device->selected = -1;
+ handle_key_fav(pte, keycode);
break;
case KEY_LOUDSPK:
if (pte->device->output == OUTPUT_SPEAKER) {
@@ -2827,16 +3367,56 @@ static void key_dial_page(struct unistimsession *pte,
return;
}
+static void handle_select_option(struct unistimsession *pte)
+{
+ char tmp[128];
+
+ if (pte->state != STATE_SELECTOPTION) {
+ pte->state = STATE_SELECTOPTION;
+ pte->size_buff_entry = 1;
+ pte->buff_entry[0] = 0; /* Position in menu */
+ }
+ sprintf(tmp, "%d. %s", pte->buff_entry[0] + 1, ustmtext(options_menu[(int)pte->buff_entry[0]].label, pte));
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp);
+ send_text_status(pte, ustmtext("Select Cancel", pte));
+ return;
+}
+
+static void key_select_option(struct unistimsession *pte, char keycode)
+{
+ switch (keycode) {
+ case KEY_DOWN:
+ pte->buff_entry[0]++;
+ if (options_menu[(int)pte->buff_entry[0]].label == NULL)
+ pte->buff_entry[0]--;
+ break;
+ case KEY_UP:
+ if (pte->buff_entry[0] > 0)
+ pte->buff_entry[0]--;
+ break;
+ case KEY_FUNC1:
+ options_menu[(int)pte->buff_entry[0]].handle_option(pte);
+ return;
+ case KEY_HANGUP:
+ case KEY_FUNC4:
+ show_main_page(pte);
+ return;
+ }
+
+ handle_select_option(pte);
+ return;
+}
+
#define SELECTCODEC_START_ENTRY_POS 15
#define SELECTCODEC_MAX_LENGTH 2
#define SELECTCODEC_MSG "Codec number : .."
-static void HandleSelectCodec(struct unistimsession *pte)
+static void handle_select_codec(struct unistimsession *pte)
{
char buf[30], buf2[5];
pte->state = STATE_SELECTCODEC;
- strcpy(buf, "Using codec ");
- sprintf(buf2, "%d", pte->device->codec_number);
+ strcpy(buf, ustmtext("Using codec", pte));
+ sprintf(buf2, " %d", pte->device->codec_number);
strcat(buf, buf2);
strcat(buf, " (G711u=0,");
@@ -2846,7 +3426,7 @@ static void HandleSelectCodec(struct unistimsession *p
send_blink_cursor(pte);
send_cursor_pos(pte, TEXT_LINE2 + SELECTCODEC_START_ENTRY_POS);
pte->size_buff_entry = 0;
- send_text_status(pte, "Select BackSpcErase Cancel");
+ send_text_status(pte, ustmtext("Select BackSp Erase Cancel", pte));
return;
}
@@ -2904,19 +3484,110 @@ static void key_select_codec(struct unistimsession *pt
return;
}
+static void handle_select_contrast(struct unistimsession *pte)
+{
+ return;
+}
+
+static void key_select_contrast(struct unistimsession *pte, char keycode)
+{
+ switch (keycode) {
+ case KEY_DOWN:
+ pte->buff_entry[0]++;
+ break;
+ case KEY_UP:
+ if (pte->buff_entry[0] > 0)
+ pte->buff_entry[0]--;
+ break;
+ case KEY_FUNC1:
+ show_main_page(pte);
+ return;
+ case KEY_HANGUP:
+ case KEY_FUNC4:
+ handle_select_option(pte);
+ return;
+ }
+
+ handle_select_contrast(pte);
+ return;
+}
+
+static int find_language(const char* lang)
+{
+ int i = 0;
+ while (options_languages[i].lang_short != NULL) {
+ if(!strcmp(options_languages[i].lang_short, lang))
+ return i;
+ i++;
+ }
+ return 0;
+}
+
+static void handle_select_language(struct unistimsession *pte)
+{
+ char tmp_language[40];
+ struct unistim_languages lang;
+
+ if (pte->state != STATE_SELECTLANGUAGE) {
+ pte->state = STATE_SELECTLANGUAGE;
+ pte->size_buff_entry = 1;
+ pte->buff_entry[0] = find_language(pte->device->language);
+ }
+ lang = options_languages[(int)pte->buff_entry[0]];
+ strcpy(tmp_language, pte->device->language);
+ strcpy(pte->device->language, lang.lang_short);
+ send_charset_update(pte, lang.encoding);
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext(lang.label, pte));
+
+ strcpy(pte->device->language, tmp_language);
+ lang = options_languages[find_language(pte->device->language)];
+ send_charset_update(pte, lang.encoding);
+ send_text_status(pte, ustmtext("Select Cancel", pte));
+ return;
+}
+
+static void key_select_language(struct unistimsession *pte, char keycode)
+{
+ switch (keycode) {
+ case KEY_DOWN:
+ pte->buff_entry[0]++;
+ if (options_languages[(int)pte->buff_entry[0]].label == NULL)
+ pte->buff_entry[0]--;
+ break;
+ case KEY_UP:
+ if (pte->buff_entry[0] > 0)
+ pte->buff_entry[0]--;
+ break;
+ case KEY_FUNC1:
+ ast_copy_string(pte->device->language, options_languages[(int)pte->buff_entry[0]].lang_short, sizeof(pte->device->language));
+ send_charset_update(pte, options_languages[(int)pte->buff_entry[0]].encoding);
+ refresh_all_favorite(pte);
+ show_main_page(pte);
+ return;
+ case KEY_HANGUP:
+ case KEY_FUNC4:
+ handle_select_option(pte);
+ return;
+ }
+
+ handle_select_language(pte);
+ return;
+}
+
+
#define SELECTEXTENSION_START_ENTRY_POS 0
#define SELECTEXTENSION_MAX_LENGTH 10
#define SELECTEXTENSION_MSG ".........."
-static void ShowExtensionPage(struct unistimsession *pte)
+static void show_extension_page(struct unistimsession *pte)
{
pte->state = STATE_EXTENSION;
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Please enter a Terminal");
- send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Number (TN) :");
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Please enter a Terminal", pte));
+ send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Number (TN) :", pte));
send_text(TEXT_LINE2, TEXT_NORMAL, pte, SELECTEXTENSION_MSG);
send_blink_cursor(pte);
send_cursor_pos(pte, TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS);
- send_text_status(pte, "Enter BackSpcErase");
+ send_text_status(pte, ustmtext("Enter BackSpcErase", pte));
pte->size_buff_entry = 0;
return;
}
@@ -2988,8 +3659,8 @@ static void key_select_extension(struct unistimsession
d = d->next;
}
ast_mutex_unlock(&devicelock);
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid Terminal Number.");
- send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Invalid Terminal Number.", pte));
+ send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Please try again :", pte));
send_cursor_pos(pte,
(unsigned char) (TEXT_LINE2 + SELECTEXTENSION_START_ENTRY_POS +
pte->size_buff_entry));
@@ -2997,9 +3668,9 @@ static void key_select_extension(struct unistimsession
} else {
ast_copy_string(pte->device->extension_number, pte->buff_entry,
pte->size_buff_entry + 1);
- if (RegisterExtension(pte)) {
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Invalid extension.");
- send_text(TEXT_LINE1, TEXT_NORMAL, pte, "Please try again :");
+ if (register_extension(pte)) {
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Invalid extension.", pte));
+ send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("Please try again :", pte));
send_cursor_pos(pte,
(unsigned char) (TEXT_LINE2 +
SELECTEXTENSION_START_ENTRY_POS +
@@ -3019,12 +3690,13 @@ static void key_select_extension(struct unistimsession
return;
}
-static int ReformatNumber(char *number)
+static int reformat_number(char *number)
{
int pos = 0, i = 0, size = strlen(number);
for (; i < size; i++) {
- if ((number[i] >= '0') && (number[i] <= '9')) {
+ if (((number[i] >= '0') && (number[i] <= '9')) ||
+ (number[i] == '*') || (number[i] == '#')) {
if (i == pos) {
pos++;
continue;
@@ -3048,22 +3720,37 @@ static void show_entry_history(struct unistimsession *
return;
}
line[sizeof(line) - 1] = '\0';
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
- if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
+ if (pte->device->height == 1) {
+ if (pte->buff_entry[3] == 1)
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
+ } else {
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
+ }
+ if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
display_last_error("Can't read callerid entry");
fclose(*f);
return;
}
line[sizeof(line) - 1] = '\0';
ast_copy_string(pte->device->lst_cid, line, sizeof(pte->device->lst_cid));
- send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
- if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
+ if (pte->device->height == 1) {
+ if (pte->buff_entry[3] == 2)
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
+ } else {
+ send_text(TEXT_LINE1, TEXT_NORMAL, pte, line);
+ }
+ if (fread(line, TEXT_LENGTH_MAX, 1, *f) != 1) {
display_last_error("Can't read callername entry");
fclose(*f);
return;
}
line[sizeof(line) - 1] = '\0';
- send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
+ if (pte->device->height == 1) {
+ if (pte->buff_entry[3] == 3)
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, line);
+ } else {
+ send_text(TEXT_LINE2, TEXT_NORMAL, pte, line);
+ }
fclose(*f);
snprintf(line, sizeof(line), "Call %03d/%03d", pte->buff_entry[2],
@@ -3073,20 +3760,20 @@ static void show_entry_history(struct unistimsession *
if (pte->buff_entry[2] == 1)
strcpy(func1, " ");
else
- strcpy(func1, "Prvious");
+ strcpy(func1, ustmtext("Prev ", pte));
if (pte->buff_entry[2] >= pte->buff_entry[1])
strcpy(func2, " ");
else
- strcpy(func2, "Next ");
- if (ReformatNumber(pte->device->lst_cid))
- strcpy(func3, "Redial ");
+ strcpy(func2, ustmtext("Next ", pte));
+ if (reformat_number(pte->device->lst_cid))
+ strcpy(func3, ustmtext("Redial ", pte));
else
strcpy(func3, " ");
- snprintf(status, sizeof(status), "%s%s%sCancel", func1, func2, func3);
+ snprintf(status, sizeof(status), ustmtext("%s%s%sCancel", pte), func1, func2, func3);
send_text_status(pte, status);
}
-static char OpenHistory(struct unistimsession *pte, char way, FILE ** f)
+static char open_history(struct unistimsession *pte, char way, FILE ** f)
{
char tmp[AST_CONFIG_MAX_PATH];
char count;
@@ -3121,12 +3808,13 @@ static void show_history(struct unistimsession *pte, c
return;
if (!pte->device->callhistory)
return;
- count = OpenHistory(pte, way, &f);
+ count = open_history(pte, way, &f);
if (!count)
return;
pte->buff_entry[0] = way;
pte->buff_entry[1] = count;
pte->buff_entry[2] = 1;
+ pte->buff_entry[3] = 1;
show_entry_history(pte, &f);
pte->state = STATE_HISTORY;
}
@@ -3134,60 +3822,73 @@ static void show_history(struct unistimsession *pte, c
static void show_main_page(struct unistimsession *pte)
{
char tmpbuf[TEXT_LENGTH_MAX + 1];
+ const char *text;
-
if ((pte->device->extension == EXTENSION_ASK) &&
(ast_strlen_zero(pte->device->extension_number))) {
- ShowExtensionPage(pte);
+ show_extension_page(pte);
return;
}
pte->state = STATE_MAINPAGE;
send_tone(pte, 0, 0);
+ send_stop_timer(pte); /* case of holding call */
send_select_output(pte, pte->device->output, pte->device->volume, MUTE_ON_DISCRET);
- pte->device->lines->lastmsgssent = 0;
- send_favorite(pte->device->softkeylinepos, FAV_ICON_ONHOOK_BLACK, pte,
- pte->device->softkeylabel[pte->device->softkeylinepos]);
+ send_led_update(pte, 0x08);
+ send_led_update(pte, 0x10);
+ get_main_line(pte->device)->lastmsgssent = 0;
if (!ast_strlen_zero(pte->device->call_forward)) {
if (pte->device->height == 1) {
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Forwarding ON");
+ char tmp_field[100];
+ sprintf(tmp_field, ustmtext("Fwd to: %s", pte), pte->device->call_forward);
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmp_field);
} else {
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Call forwarded to :");
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Call forwarded to :", pte));
send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->call_forward);
}
- Sendicon(TEXT_LINE0, FAV_ICON_REFLECT + FAV_BLINK_SLOW, pte);
- send_text_status(pte, "Dial Redial NoForwd");
+ send_icon(TEXT_LINE0, FAV_ICON_REFLECT + FAV_BLINK_SLOW, pte);
+ send_text_status(pte, ustmtext("Dial Redial NoFwd ", pte));
} else {
if ((pte->device->extension == EXTENSION_ASK) ||
(pte->device->extension == EXTENSION_TN))
- send_text_status(pte, "Dial Redial ForwardUnregis");
+ send_text_status(pte, ustmtext("Dial Recal Fwd Unregis", pte));
else
- send_text_status(pte, "Dial Redial Forward");
+ send_text_status(pte, ustmtext("Dial Recal Fwd Pickup", pte));
send_text(TEXT_LINE1, TEXT_NORMAL, pte, pte->device->maintext1);
- if (pte->device->missed_call == 0)
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, pte->device->maintext0);
- else {
- sprintf(tmpbuf, "%d unanswered call(s)", pte->device->missed_call);
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
- Sendicon(TEXT_LINE0, FAV_ICON_CALL_CENTER + FAV_BLINK_SLOW, pte);
+ if (pte->device->missed_call == 0) {
+ send_date_time2(pte);
+ send_idle_clock(pte);
+ if (strlen(pte->device->maintext0))
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, pte->device->maintext0);
+ } else {
+ if (pte->device->missed_call == 1)
+ text = ustmtext("%d unanswered call", pte);
+ else
+ text = ustmtext("%d unanswered calls", pte);
+ sprintf(tmpbuf, text, pte->device->missed_call);
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpbuf);
+ send_icon(TEXT_LINE0, FAV_ICON_CALL_CENTER + FAV_BLINK_SLOW, pte);
}
}
- if (ast_strlen_zero(pte->device->maintext2)) {
- strcpy(tmpbuf, "IP : ");
- strcat(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
- send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
- } else
- send_text(TEXT_LINE2, TEXT_NORMAL, pte, pte->device->maintext2);
+ if (pte->device->height > 1) {
+ if (ast_strlen_zero(pte->device->maintext2)) {
+ strcpy(tmpbuf, "IP : ");
+ strcat(tmpbuf, ast_inet_ntoa(pte->sin.sin_addr));
+ send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmpbuf);
+ } else
+ send_text(TEXT_LINE2, TEXT_NORMAL, pte, pte->device->maintext2);
+ }
+
send_texttitle(pte, pte->device->titledefault);
- change_favorite_icon(pte, FAV_ICON_ONHOOK_BLACK);
+ change_favorite_icon(pte, FAV_LINE_ICON);
}
static void key_main_page(struct unistimsession *pte, char keycode)
{
if (pte->device->missed_call) {
- Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
+ send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
pte->device->missed_call = 0;
}
if ((keycode >= KEY_0) && (keycode <= KEY_SHARP)) {
@@ -3197,6 +3898,7 @@ static void key_main_page(struct unistimsession *pte,
}
switch (keycode) {
case KEY_FUNC1:
+ pte->device->selected = get_avail_softkey(pte, NULL);
handle_dial_page(pte);
break;
case KEY_FUNC2:
@@ -3210,7 +3912,7 @@ static void key_main_page(struct unistimsession *pte,
ast_copy_string(pte->device->phone_number, pte->device->redial_number,
sizeof(pte->device->phone_number));
- HandleCallOutgoing(pte);
+ handle_call_outgoing(pte);
break;
case KEY_FUNC3:
if (!ast_strlen_zero(pte->device->call_forward)) {
@@ -3218,7 +3920,7 @@ static void key_main_page(struct unistimsession *pte,
memmove(pte->device->call_forward + 1, pte->device->call_forward,
sizeof(pte->device->call_forward));
pte->device->call_forward[0] = '\0';
- Sendicon(TEXT_LINE0, FAV_ICON_NONE, pte);
+ send_icon(TEXT_LINE0, FAV_ICON_NONE, pte);
pte->device->output = OUTPUT_HANDSET; /* Seems to be reseted somewhere */
show_main_page(pte);
break;
@@ -3228,9 +3930,9 @@ static void key_main_page(struct unistimsession *pte,
break;
case KEY_FUNC4:
if (pte->device->extension == EXTENSION_ASK) {
- UnregisterExtension(pte);
+ unregister_extension(pte);
pte->device->extension_number[0] = '\0';
- ShowExtensionPage(pte);
+ show_extension_page(pte);
} else if (pte->device->extension == EXTENSION_TN) {
ast_mutex_lock(&devicelock);
strcpy(pte->device->id, pte->device->extension_number);
@@ -3239,26 +3941,25 @@ static void key_main_page(struct unistimsession *pte,
pte->device->session = NULL;
pte->device = NULL;
ast_mutex_unlock(&devicelock);
- ShowExtensionPage(pte);
- }
+ show_extension_page(pte);
+ } else { /* Pickup function */
+ pte->device->selected = -1;
+ ast_copy_string(pte->device->phone_number, ast_pickup_ext(),
+ sizeof(pte->device->phone_number));
+ handle_call_outgoing(pte);
+
+ }
break;
- case KEY_FAV0:
- handle_dial_page(pte);
- break;
+ case KEY_FAV0:
case KEY_FAV1:
case KEY_FAV2:
case KEY_FAV3:
case KEY_FAV4:
case KEY_FAV5:
- if ((pte->device->output == OUTPUT_HANDSET) &&
- (pte->device->receiver_state == STATE_ONHOOK))
- send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
- else
- send_select_output(pte, pte->device->output, pte->device->volume, MUTE_OFF);
- Keyfavorite(pte, keycode);
+ handle_key_fav(pte, keycode);
break;
case KEY_CONF:
- HandleSelectCodec(pte);
+ handle_select_option(pte);
break;
case KEY_LOUDSPK:
send_select_output(pte, OUTPUT_SPEAKER, pte->device->volume, MUTE_OFF);
@@ -3283,44 +3984,41 @@ static void key_history(struct unistimsession *pte, ch
FILE *f;
char count;
long offset;
+ int flag = 0;
switch (keycode) {
+ case KEY_LEFT:
+ if (pte->device->height == 1) {
+ if (pte->buff_entry[3] <= 1)
+ return;
+ pte->buff_entry[3]--;
+ flag = 1;
+ break;
+ }
case KEY_UP:
- case KEY_LEFT:
case KEY_FUNC1:
if (pte->buff_entry[2] <= 1)
return;
pte->buff_entry[2]--;
- count = OpenHistory(pte, pte->buff_entry[0], &f);
- if (!count)
- return;
- offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
- if (fseek(f, offset, SEEK_CUR)) {
- display_last_error("Unable to seek history entry.");
- fclose(f);
- return;
- }
- show_entry_history(pte, &f);
+ flag = 1;
break;
- case KEY_DOWN:
- case KEY_RIGHT:
+ case KEY_RIGHT:
+ if (pte->device->height == 1) {
+ if (pte->buff_entry[3] == 3)
+ return;
+ pte->buff_entry[3]++;
+ flag = 1;
+ break;
+ }
+ case KEY_DOWN:
case KEY_FUNC2:
if (pte->buff_entry[2] >= pte->buff_entry[1])
return;
pte->buff_entry[2]++;
- count = OpenHistory(pte, pte->buff_entry[0], &f);
- if (!count)
- return;
- offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
- if (fseek(f, offset, SEEK_CUR)) {
- display_last_error("Unable to seek history entry.");
- fclose(f);
- return;
- }
- show_entry_history(pte, &f);
+ flag = 1;
break;
case KEY_FUNC3:
- if (!ReformatNumber(pte->device->lst_cid))
+ if (!reformat_number(pte->device->lst_cid))
break;
ast_copy_string(pte->device->redial_number, pte->device->lst_cid,
sizeof(pte->device->redial_number));
@@ -3343,6 +4041,20 @@ static void key_history(struct unistimsession *pte, ch
show_history(pte, 'i');
break;
}
+
+ if (flag) {
+ count = open_history(pte, pte->buff_entry[0], &f);
+ if (!count)
+ return;
+ offset = ((pte->buff_entry[2] - 1) * TEXT_LENGTH_MAX * 3);
+ if (fseek(f, offset, SEEK_CUR)) {
+ display_last_error("Unable to seek history entry.");
+ fclose(f);
+ return;
+ }
+ show_entry_history(pte, &f);
+ }
+
return;
}
@@ -3353,7 +4065,7 @@ static void init_phone_step2(struct unistimsession *pt
ast_verb(0, "Sending S4\n");
memcpy(buffsend + SIZE_HEADER, packet_send_s4, sizeof(packet_send_s4));
send_client(SIZE_HEADER + sizeof(packet_send_s4), buffsend, pte);
- send_date_time2(pte);
+ send_date_time2(pte);
send_date_time3(pte);
if (unistimdebug)
ast_verb(0, "Sending S7\n");
@@ -3378,9 +4090,13 @@ static void init_phone_step2(struct unistimsession *pt
send_client(SIZE_HEADER + sizeof(packet_send_S7), buffsend, pte);
send_led_update(pte, 0);
send_ping(pte);
- if (pte->state < STATE_MAINPAGE) {
+ if (unistimdebug)
+ ast_verb(0, "Sending init language\n");
+ send_charset_update(pte, options_languages[find_language(pte->device->language)].encoding);
+
+ if (pte->state < STATE_MAINPAGE) {
if (autoprovisioning == AUTOPROVISIONING_TN) {
- ShowExtensionPage(pte);
+ show_extension_page(pte);
return;
} else {
int i;
@@ -3388,8 +4104,8 @@ static void init_phone_step2(struct unistimsession *pt
for (i = 1; i < 6; i++)
send_favorite(i, 0, pte, "");
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Sorry, this phone is not");
- send_text(TEXT_LINE1, TEXT_NORMAL, pte, "registered in unistim.cfg");
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Sorry, this phone is not", pte));
+ send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext("registered in unistim.cfg", pte));
strcpy(tmp, "MAC = ");
strcat(tmp, pte->macaddr);
send_text(TEXT_LINE2, TEXT_NORMAL, pte, tmp);
@@ -3443,8 +4159,8 @@ static void process_request(int size, unsigned char *b
char keycode = buf[13];
if (unistimdebug)
- ast_verb(0, "Key pressed : keycode = 0x%.2x - current state : %d\n", keycode,
- pte->state);
+ ast_verb(0, "Key pressed: keycode = 0x%.2x - current state: %s\n", keycode,
+ ptestate_tostr(pte->state));
switch (pte->state) {
case STATE_INIT:
@@ -3470,10 +4186,19 @@ static void process_request(int size, unsigned char *b
case STATE_EXTENSION:
key_select_extension(pte, keycode);
break;
+ case STATE_SELECTOPTION:
+ key_select_option(pte, keycode);
+ break;
case STATE_SELECTCODEC:
key_select_codec(pte, keycode);
break;
- case STATE_HISTORY:
+ case STATE_SELECTCONTRAST:
+ key_select_contrast(pte, keycode);
+ break;
+ case STATE_SELECTLANGUAGE:
+ key_select_language(pte, keycode);
+ break;
+ case STATE_HISTORY:
key_history(pte, keycode);
break;
default:
@@ -3491,13 +4216,15 @@ static void process_request(int size, unsigned char *b
send_select_output(pte, OUTPUT_HEADPHONE, pte->device->volume, MUTE_OFF);
else
send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
- if (pte->state == STATE_RINGING)
- HandleCallIncoming(pte);
- else if ((pte->state == STATE_DIALPAGE) || (pte->state == STATE_CALL))
+ if (pte->state == STATE_RINGING) {
+ handle_call_incoming(pte);
+
+ } else if ((pte->state == STATE_DIALPAGE) || (pte->state == STATE_CALL))
send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
else if (pte->state == STATE_EXTENSION) /* We must have a TN before calling */
return;
else {
+ pte->device->selected = get_avail_softkey(pte, NULL);
send_select_output(pte, OUTPUT_HANDSET, pte->device->volume, MUTE_OFF);
handle_dial_page(pte);
}
@@ -3511,7 +4238,7 @@ static void process_request(int size, unsigned char *b
pte->device->receiver_state = STATE_ONHOOK;
if (pte->state == STATE_CALL)
close_call(pte);
- else if (pte->device->lines->subs[SUB_REAL]->owner)
+ else if (get_sub(pte->device, SUB_REAL) && get_sub(pte->device, SUB_REAL)->owner)
close_call(pte);
else if (pte->state == STATE_EXTENSION)
return;
@@ -3709,13 +4436,52 @@ static struct unistimsession *channel_to_session(struc
return sub->parent->parent->session;
}
+static void send_callerid_screen(struct unistimsession *pte, struct unistim_subchannel *sub) {
+ char *cidname_str;
+ char *cidnum_str;
+
+ if (!sub)
+ return;
+ if (sub->owner) {
+ if (sub->owner->connected.id.number.valid && sub->owner->connected.id.number.str) {
+ cidnum_str = sub->owner->connected.id.number.str;
+ } else {
+ cidnum_str = DEFAULTCALLERID;
+ }
+ change_callerid(pte, 0, cidnum_str);
+ if (strlen(cidnum_str) == 0) {
+ cidnum_str = DEFAULTCALLERID;
+ }
+
+ if (sub->owner->connected.id.name.valid && sub->owner->connected.id.name.str) {
+ cidname_str = sub->owner->connected.id.name.str;
+ } else {
+ cidname_str = DEFAULTCALLERNAME;
+ }
+ change_callerid(pte, 1, cidname_str);
+ if (strlen(cidname_str) == 0) {
+ cidname_str = DEFAULTCALLERNAME;
+ }
+
+ if (pte->device->height == 1) {
+ char tmpstr[256];
+ sprintf(tmpstr, "%s %s", cidnum_str, ustmtext(cidname_str, pte));
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, tmpstr);
+ } else {
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, cidname_str);
+ send_text(TEXT_LINE1, TEXT_NORMAL, pte, ustmtext(cidnum_str, pte));
+ }
+ }
+}
+
/*--- unistim_call: Initiate UNISTIM call from PBX ---*/
/* used from the dial() application */
static int unistim_call(struct ast_channel *ast, char *dest, int timeout)
{
- int res = 0;
- struct unistim_subchannel *sub;
+ int res = 0, i;
+ struct unistim_subchannel *sub, *sub_real;
struct unistimsession *session;
+ char ringstyle, ringvolume;
session = channel_to_session(ast);
if (!session) {
@@ -3724,6 +4490,7 @@ static int unistim_call(struct ast_channel *ast, char
}
sub = ast->tech_pvt;
+ sub_real = get_sub(session->device, SUB_REAL);
if ((ast->_state != AST_STATE_DOWN) && (ast->_state != AST_STATE_RESERVED)) {
ast_log(LOG_WARNING, "unistim_call called on %s, neither down nor reserved\n",
ast->name);
@@ -3734,58 +4501,49 @@ static int unistim_call(struct ast_channel *ast, char
ast_verb(3, "unistim_call(%s)\n", ast->name);
session->state = STATE_RINGING;
- Sendicon(TEXT_LINE0, FAV_ICON_NONE, session);
+ //send_icon(TEXT_LINE0, FAV_ICON_NONE, session);
- if (sub->owner) {
- if (sub->owner->connected.id.number.valid
- && sub->owner->connected.id.number.str) {
- if (session->device->height == 1) {
- send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.number.str);
- } else {
- send_text(TEXT_LINE1, TEXT_NORMAL, session, sub->owner->connected.id.number.str);
- }
- change_callerid(session, 0, sub->owner->connected.id.number.str);
- } else {
- if (session->device->height == 1) {
- send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERID);
- } else {
- send_text(TEXT_LINE1, TEXT_NORMAL, session, DEFAULTCALLERID);
- }
- change_callerid(session, 0, DEFAULTCALLERID);
- }
- if (sub->owner->connected.id.name.valid
- && sub->owner->connected.id.name.str) {
- send_text(TEXT_LINE0, TEXT_NORMAL, session, sub->owner->connected.id.name.str);
- change_callerid(session, 1, sub->owner->connected.id.name.str);
- } else {
- send_text(TEXT_LINE0, TEXT_NORMAL, session, DEFAULTCALLERNAME);
- change_callerid(session, 1, DEFAULTCALLERNAME);
- }
- }
- send_text(TEXT_LINE2, TEXT_NORMAL, session, "is calling you.");
- send_text_status(session, "Accept Ignore");
+ send_callerid_screen(session, sub);
+ if (!strlen(ast->call_forward)) { /* Send ring only if no call forward, otherwise short ring will apear */
+ send_text(TEXT_LINE2, TEXT_NORMAL, session, ustmtext("is calling you.", session));
+ send_text_status(session, ustmtext("Accept Ignore", session));
- if (sub->ringstyle == -1)
- send_ring(session, session->device->ringvolume, session->device->ringstyle);
- else {
- if (sub->ringvolume == -1)
- send_ring(session, session->device->ringvolume, sub->ringstyle);
- else
- send_ring(session, sub->ringvolume, sub->ringstyle);
- }
- change_favorite_icon(session, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST);
-
- ast_setstate(ast, AST_STATE_RINGING);
- ast_queue_control(ast, AST_CONTROL_RINGING);
- return res;
+ if (sub_real) {
+ ringstyle = session->device->cwstyle;
+ ringvolume = session->device->cwvolume;
+ } else {
+ ringstyle = (sub->ringstyle == -1) ? session->device->ringstyle : sub->ringstyle;
+ ringvolume = (sub->ringvolume == -1) ? session->device->ringvolume : sub->ringvolume;
+ }
+ send_ring(session, ringvolume, ringstyle);
+ change_favorite_icon(session, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST);
+ /* Send call identification to all */
+ for (i = 0; i < FAVNUM; i++) {
+ if (!soft_key_visible(session->device, i))
+ continue;
+ if (session->device->ssub[i])
+ continue;
+ if (is_key_line(session->device, i) && !strcmp(sub->parent->name, session->device->sline[i]->name)) {
+ if (unistimdebug)
+ ast_verb(0, "Found softkey %d for line %s\n", i, sub->parent->name);
+ send_favorite_short(i, FAV_ICON_SPEAKER_ONHOOK_BLACK + FAV_BLINK_FAST, session);
+ session->device->ssub[i] = sub;
+ }
+ }
+ }
+ ast_setstate(ast, AST_STATE_RINGING);
+ ast_queue_control(ast, AST_CONTROL_RINGING);
+ return res;
}
/*--- unistim_hangup: Hangup UNISTIM call */
static int unistim_hangup(struct ast_channel *ast)
{
- struct unistim_subchannel *sub;
+ struct unistim_subchannel *sub = NULL, *sub_real = NULL, *sub_trans = NULL;
struct unistim_line *l;
- struct unistimsession *s;
+ struct unistim_device *d;
+ struct unistimsession *s;
+ int i;
s = channel_to_session(ast);
sub = ast->tech_pvt;
@@ -3805,32 +4563,43 @@ static int unistim_hangup(struct ast_channel *ast)
return 0;
}
l = sub->parent;
+ d = s->device;
if (unistimdebug)
ast_verb(0, "unistim_hangup(%s) on %s@%s\n", ast->name, l->name, l->parent->name);
-
- if ((l->subs[SUB_THREEWAY]) && (sub->subtype == SUB_REAL)) {
+ sub_trans = get_sub(d, SUB_THREEWAY);
+ if (sub_trans && sub_trans->owner && (sub->subtype == SUB_REAL)) { // (sub->alreadygone == 0)
if (unistimdebug)
- ast_verb(0, "Real call disconnected while talking to threeway\n");
+ ast_verb(0, "Threeway call disconnected, switching to real call\n");
+ if (ast_bridged_channel(sub_trans->owner)) {
+ ast_moh_stop(ast_bridged_channel(sub_trans->owner));
+ }
+ sub_trans->moh = 0;
+ sub_trans->subtype = SUB_REAL;
+ swap_subs(sub_trans, sub);
+
+ ast_mutex_lock(&sub->lock);
sub->owner = NULL;
ast->tech_pvt = NULL;
+ ast_mutex_unlock(&sub->lock);
+ unalloc_sub(d, sub);
return 0;
}
- if ((l->subs[SUB_REAL]->owner) && (sub->subtype == SUB_THREEWAY) &&
+ sub_real = get_sub(d, SUB_REAL);
+ if (sub_real && (sub_real->owner) && (sub->subtype == SUB_THREEWAY) &&
(sub->alreadygone == 0)) {
if (unistimdebug)
- ast_verb(0, "threeway call disconnected, switching to real call\n");
- send_text(TEXT_LINE0, TEXT_NORMAL, s, "Three way call canceled,");
- send_text(TEXT_LINE1, TEXT_NORMAL, s, "switching back to");
- send_text(TEXT_LINE2, TEXT_NORMAL, s, "previous call.");
- send_text_status(s, "Hangup Transf");
- ast_moh_stop(ast_bridged_channel(l->subs[SUB_REAL]->owner));
- swap_subs(l, SUB_THREEWAY, SUB_REAL);
- l->parent->moh = 0;
+ ast_verb(0, "Real call disconnected, stay in call\n");
+
+ send_text(TEXT_LINE0, TEXT_NORMAL, s, ustmtext("Three way call canceled", s));
+ send_text(TEXT_LINE1, TEXT_NORMAL, s, ustmtext("switching back", s));
+ send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("to previous call.", s));
+ send_text_status(s, ustmtext("Hangup Transf", s));
+
ast_mutex_lock(&sub->lock);
sub->owner = NULL;
ast->tech_pvt = NULL;
ast_mutex_unlock(&sub->lock);
- unalloc_sub(l, SUB_THREEWAY);
+ unalloc_sub(d, sub);
return 0;
}
ast_mutex_lock(&sub->lock);
@@ -3838,34 +4607,26 @@ static int unistim_hangup(struct ast_channel *ast)
ast->tech_pvt = NULL;
sub->alreadygone = 0;
ast_mutex_unlock(&sub->lock);
- if (!s) {
- if (unistimdebug)
- ast_verb(0, "Asked to hangup channel not connected (no session)\n");
- if (sub->rtp) {
- if (unistimdebug)
- ast_verb(0, "Destroying RTP session\n");
- ast_rtp_instance_destroy(sub->rtp);
- sub->rtp = NULL;
- }
- return 0;
- }
+
if (sub->subtype == SUB_REAL) {
- /* Stop the silence generator */
- if (s->device->silence_generator) {
- if (unistimdebug)
- ast_verb(0, "Stopping silence generator\n");
- if (sub->owner)
- ast_channel_stop_silence_generator(sub->owner,
- s->device->silence_generator);
- else
- ast_log(LOG_WARNING,
- "Trying to stop silence generator on a null channel !\n");
- s->device->silence_generator = NULL;
- }
- }
- l->parent->moh = 0;
- send_no_ring(s);
- send_end_call(s);
+ sub_stop_silence(s, sub);
+ send_end_call(s); /* Send end call packet only if ending active call, in other way sound should be loosed */
+ } else if (sub->subtype == SUB_RING) {
+ send_no_ring(s);
+ for (i = 0; i < FAVNUM; i++) {
+ if (!soft_key_visible(s->device, i))
+ continue;
+ if (d->ssub[i] != sub)
+ continue;
+ if (is_key_line(d, i) && !strcmp(l->name, d->sline[i]->name)) {
+ send_favorite_short(i, FAV_LINE_ICON, s);
+ d->ssub[i] = NULL;
+ }
+ }
+ }
+ sub->moh = 0;
+ if (sub->softkey >= 0)
+ send_favorite_short(sub->softkey, FAV_LINE_ICON, s);
if (sub->rtp) {
if (unistimdebug)
ast_verb(0, "Destroying RTP session\n");
@@ -3873,16 +4634,27 @@ static int unistim_hangup(struct ast_channel *ast)
sub->rtp = NULL;
} else if (unistimdebug)
ast_verb(0, "No RTP session to destroy\n");
- if (l->subs[SUB_THREEWAY]) {
- if (unistimdebug)
- ast_verb(0, "Cleaning other subchannels\n");
- unalloc_sub(l, SUB_THREEWAY);
- }
- if (s->state == STATE_RINGING)
- cancel_dial(s);
- else if (s->state == STATE_CALL)
- close_call(s);
-
+ /* Delete assign sub to softkey */
+ for (i = 0; i < FAVNUM; i++) {
+ if (d->ssub[i] == sub) {
+ d->ssub[i] = NULL;
+ break;
+ }
+ }
+ if (unistimdebug)
+ ast_verb(0, "Closing call while state STATE_%s\n", ptestate_tostr(s->state));
+ if (s->state == STATE_RINGING && sub->subtype == SUB_RING) {
+ send_no_ring(s);
+ d->missed_call++;
+ write_history(s, 'i', 1);
+ if (!sub_real)
+ show_main_page(s);
+ }
+ if (s->state == STATE_CALL && sub->subtype == SUB_REAL) {
+ close_call(s);
+ }
+ sub->softkey = -1;
+ unalloc_sub(d, sub);
return 0;
}
@@ -3892,6 +4664,7 @@ static int unistim_answer(struct ast_channel *ast)
int res = 0;
struct unistim_subchannel *sub;
struct unistim_line *l;
+ struct unistim_device *d;
struct unistimsession *s;
s = channel_to_session(ast);
@@ -3901,18 +4674,19 @@ static int unistim_answer(struct ast_channel *ast)
}
sub = ast->tech_pvt;
l = sub->parent;
+ d = l->parent;
- if ((!sub->rtp) && (!l->subs[SUB_THREEWAY]))
+ if ((!sub->rtp) && (!get_sub(d, SUB_THREEWAY)))
start_rtp(sub);
if (unistimdebug)
ast_verb(0, "unistim_answer(%s) on %s@%s-%d\n", ast->name, l->name,
- l->parent->name, sub->subtype);
- send_text(TEXT_LINE2, TEXT_NORMAL, l->parent->session, "is now on-line");
- if (l->subs[SUB_THREEWAY])
- send_text_status(l->parent->session, "Transf Cancel");
+ l->parent->name, sub->softkey);
+ send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("is now on-line", s));
+ if (get_sub(d, SUB_THREEWAY))
+ send_text_status(s, ustmtext("Transf Cancel", s));
else
- send_text_status(l->parent->session, "Hangup Transf");
- send_start_timer(l->parent->session);
+ send_text_status(s, ustmtext("Hangup Transf", s));
+ send_start_timer(s);
if (ast->_state != AST_STATE_UP)
ast_setstate(ast, AST_STATE_UP);
return res;
@@ -4050,14 +4824,16 @@ static int unistim_write(struct ast_channel *ast, stru
return 0;
}
} else {
- if (!(frame->subclass.codec & ast->nativeformats)) {
+ if (!(frame->subclass.codec & ast->nativeformats)) {
char tmp[256];
ast_log(LOG_WARNING,
- "Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)\n",
+ "Asked to transmit frame type %s, while native formats is %s (read/write = (%s/%s)) (raw read/write = (%s/%s))\n",
ast_getformatname(frame->subclass.codec),
ast_getformatname_multiple(tmp, sizeof(tmp), ast->nativeformats),
ast_getformatname(ast->readformat),
- ast_getformatname(ast->writeformat));
+ ast_getformatname(ast->writeformat),
+ ast_getformatname(ast->rawwriteformat),
+ ast_getformatname(ast->rawreadformat));
return -1;
}
}
@@ -4126,7 +4902,13 @@ static char *control2str(int ind)
return "Key Radio";
case AST_CONTROL_RADIO_UNKEY:
return "Un-Key Radio";
- case -1:
+ case AST_CONTROL_CONNECTED_LINE:
+ return "Remote end changed";
+ case AST_CONTROL_SRCCHANGE:
+ return "RTP source updated";
+ case AST_CONTROL_SRCUPDATE:
+ return "Source of media changed";
+ case -1:
return "Stop tone";
}
return "UNKNOWN";
@@ -4153,8 +4935,8 @@ static int unistim_indicate(struct ast_channel *ast, i
struct unistimsession *s;
if (unistimdebug) {
- ast_verb(3, "Asked to indicate '%s' condition on channel %s\n",
- control2str(ind), ast->name);
+ ast_verb(3, "Asked to indicate '%s' (%d) condition on channel %s\n",
+ control2str(ind), ind, ast->name);
}
s = channel_to_session(ast);
@@ -4167,7 +4949,7 @@ static int unistim_indicate(struct ast_channel *ast, i
switch (ind) {
case AST_CONTROL_RINGING:
if (ast->_state != AST_STATE_UP) {
- send_text(TEXT_LINE2, TEXT_NORMAL, s, "Ringing...");
+ send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Ringing...", s));
in_band_indication(ast, l->parent->tz, "ring");
s->device->missed_call = -1;
break;
@@ -4176,7 +4958,7 @@ static int unistim_indicate(struct ast_channel *ast, i
case AST_CONTROL_BUSY:
if (ast->_state != AST_STATE_UP) {
sub->alreadygone = 1;
- send_text(TEXT_LINE2, TEXT_NORMAL, s, "Busy");
+ send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Busy", s));
in_band_indication(ast, l->parent->tz, "busy");
s->device->missed_call = -1;
break;
@@ -4189,7 +4971,7 @@ static int unistim_indicate(struct ast_channel *ast, i
case AST_CONTROL_CONGESTION:
if (ast->_state != AST_STATE_UP) {
sub->alreadygone = 1;
- send_text(TEXT_LINE2, TEXT_NORMAL, s, "Congestion");
+ send_text(TEXT_LINE2, TEXT_NORMAL, s, ustmtext("Congestion", s));
in_band_indication(ast, l->parent->tz, "congestion");
s->device->missed_call = -1;
break;
@@ -4203,13 +4985,23 @@ static int unistim_indicate(struct ast_channel *ast, i
break;
case AST_CONTROL_PROGRESS:
case AST_CONTROL_SRCUPDATE:
+ case AST_CONTROL_PROCEEDING:
break;
case -1:
ast_playtones_stop(ast);
s->device->missed_call = 0;
break;
- case AST_CONTROL_PROCEEDING:
- break;
+ case AST_CONTROL_CONNECTED_LINE:
+ ast_log(LOG_NOTICE, "Connected party is now %s <%s>\n",
+ S_COR(ast->connected.id.name.valid, ast->connected.id.name.str, ""),
+ S_COR(ast->connected.id.number.valid, ast->connected.id.number.str, ""));
+ if (sub->subtype == SUB_REAL) {
+ send_callerid_screen(s, sub);
+ }
+ break;
+ case AST_CONTROL_SRCCHANGE:
+ ast_rtp_instance_change_source(sub->rtp);
+ break;
default:
ast_log(LOG_WARNING, "Don't know how to indicate condition %d\n", ind);
return -1;
@@ -4222,6 +5014,7 @@ static struct unistim_subchannel *find_subchannel_by_n
{
struct unistim_line *l;
struct unistim_device *d;
+ struct unistim_subchannel *sub = NULL;
char line[256];
char *at;
char *device;
@@ -4245,12 +5038,22 @@ static struct unistim_subchannel *find_subchannel_by_n
if (unistimdebug)
ast_verb(0, "Found device: %s\n", d->name);
/* Found the device */
- l = d->lines;
- while (l) {
+ AST_LIST_LOCK(&d->lines);
+ AST_LIST_TRAVERSE(&d->lines, l, list) {
/* Search for the right line */
if (!strcasecmp(l->name, line)) {
- l->subs[SUB_REAL]->ringvolume = -1;
- l->subs[SUB_REAL]->ringstyle = -1;
+ if (unistimdebug)
+ ast_verb(0, "Found line: %s\n", l->name);
+ sub = get_sub(d, SUB_REAL);
+ if (!sub) {
+ sub = alloc_sub(d, SUB_REAL);
+ }
+ if (sub->owner) {
+ /* Allocate additional channel if asterisk channel already here */
+ sub = alloc_sub(d, SUB_ONHOLD);
+ }
+ sub->ringvolume = -1;
+ sub->ringstyle = -1;
if (at) { /* Other options ? */
at++; /* Skip slash */
if (*at == 'r') { /* distinctive ring */
@@ -4266,16 +5069,20 @@ static struct unistim_subchannel *find_subchannel_by_n
if (unistimdebug)
ast_verb(0, "Distinctive ring : style #%d volume %d\n",
ring_style, ring_volume);
- l->subs[SUB_REAL]->ringvolume = ring_volume;
- l->subs[SUB_REAL]->ringstyle = ring_style;
+ sub->ringvolume = ring_volume;
+ sub->ringstyle = ring_style;
}
}
}
- ast_mutex_unlock(&devicelock);
- return l->subs[SUB_REAL];
+ sub->parent = l;
+ break;
}
- l = l->next;
}
+ AST_LIST_UNLOCK(&d->lines);
+ if (sub) {
+ ast_mutex_unlock(&devicelock);
+ return sub;
+ }
}
d = d->next;
}
@@ -4301,9 +5108,9 @@ static int unistim_senddigit_end(struct ast_channel *a
struct ast_frame f = { 0, };
struct unistim_subchannel *sub;
- sub = pte->device->lines->subs[SUB_REAL];
+ sub = get_sub(pte->device, SUB_REAL);
- if (!sub->owner || sub->alreadygone) {
+ if (!sub || !sub->owner || sub->alreadygone) {
ast_log(LOG_WARNING, "Unable to find subchannel in dtmf senddigit_end\n");
return -1;
}
@@ -4436,7 +5243,7 @@ static int unistim_sendtext(struct ast_channel *ast, c
if (pte->device->height == 1) {
send_text(TEXT_LINE0, TEXT_NORMAL, pte, text);
} else {
- send_text(TEXT_LINE0, TEXT_NORMAL, pte, "Message :");
+ send_text(TEXT_LINE0, TEXT_NORMAL, pte, ustmtext("Message :", pte));
send_text(TEXT_LINE1, TEXT_NORMAL, pte, text);
}
if (size <= TEXT_LENGTH_MAX) {
@@ -4464,7 +5271,7 @@ static int unistim_send_mwi_to_peer(struct unistimsess
struct ast_event *event;
int new;
char *mailbox, *context;
- struct unistim_line *peer = s->device->lines;
+ struct unistim_line *peer = get_main_line(s->device);
context = mailbox = ast_strdupa(peer->mailbox);
strsep(&context, "@");
@@ -4518,9 +5325,9 @@ static struct ast_channel *unistim_new(struct unistim_
}
l = sub->parent;
tmp = ast_channel_alloc(1, state, l->cid_num, NULL, l->accountcode, l->exten,
- l->context, linkedid, l->amaflags, "%s@%s-%d", l->name, l->parent->name, sub->subtype);
+ l->context, linkedid, l->amaflags, "USTM/%s@%s-%p", l->name, l->parent->name, sub);
if (unistimdebug)
- ast_verb(0, "unistim_new sub=%d (%p) chan=%p\n", sub->subtype, sub, tmp);
+ ast_verb(0, "unistim_new sub=%d (%p) chan=%p line=%s\n", sub->subtype, sub, tmp, l->name);
if (!tmp) {
ast_log(LOG_WARNING, "Unable to allocate channel structure\n");
return NULL;
@@ -4558,8 +5365,8 @@ static struct ast_channel *unistim_new(struct unistim_
tmp->rawreadformat = fmt;
tmp->tech_pvt = sub;
tmp->tech = &unistim_tech;
- if (!ast_strlen_zero(l->language))
- ast_string_field_set(tmp, language, l->language);
+ if (!ast_strlen_zero(l->parent->language))
+ ast_string_field_set(tmp, language, l->parent->language);
sub->owner = tmp;
ast_mutex_lock(&usecnt_lock);
usecnt++;
@@ -4583,14 +5390,14 @@ static struct ast_channel *unistim_new(struct unistim_
}
}
tmp->priority = 1;
- if (state != AST_STATE_DOWN) {
- if (unistimdebug)
- ast_verb(0, "Starting pbx in unistim_new\n");
- if (ast_pbx_start(tmp)) {
- ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
- ast_hangup(tmp);
- tmp = NULL;
- }
+ if (state != AST_STATE_DOWN) {
+ if (unistimdebug)
+ ast_verb(0, "Starting pbx in unistim_new\n");
+ if (ast_pbx_start(tmp)) {
+ ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmp->name);
+ ast_hangup(tmp);
+ tmp = NULL;
+ }
}
return tmp;
@@ -4639,8 +5446,8 @@ static void *do_monitor(void *data)
dw_timeout = cur->timeout - tick;
/* Checking if the phone is logged on for a new MWI */
if (cur->device) {
- if ((!ast_strlen_zero(cur->device->lines->mailbox)) &&
- ((tick >= cur->device->lines->nextmsgcheck))) {
+ if ((!ast_strlen_zero(get_main_line(cur->device)->mailbox)) &&
+ ((tick >= get_main_line(cur->device)->nextmsgcheck))) {
DEBUG_TIMER("Checking mailbox for MWI\n");
unistim_send_mwi_to_peer(cur, tick);
break;
@@ -4710,7 +5517,8 @@ static struct ast_channel *unistim_request(const char
int *cause)
{
format_t oldformat;
- struct unistim_subchannel *sub;
+ struct unistim_subchannel *sub, *sub_ring, *sub_trans;
+ struct unistim_device *d;
struct ast_channel *tmpc = NULL;
char tmp[256];
char *dest = data;
@@ -4734,22 +5542,39 @@ static struct ast_channel *unistim_request(const char
ast_log(LOG_NOTICE, "Unistim channels require a device\n");
return NULL;
}
-
sub = find_subchannel_by_name(tmp);
if (!sub) {
ast_log(LOG_NOTICE, "No available lines on: %s\n", dest);
*cause = AST_CAUSE_CONGESTION;
return NULL;
}
-
- ast_verb(3, "unistim_request(%s)\n", tmp);
- /* Busy ? */
- if (sub->owner) {
+ d = sub->parent->parent;
+ sub_ring = get_sub(d, SUB_RING);
+ sub_trans = get_sub(d, SUB_THREEWAY);
+ /* Another request already in progress */
+ if (!d->session) {
+ unalloc_sub(d, sub);
+ *cause = AST_CAUSE_CONGESTION;
+ return NULL;
+ }
+ if (sub_ring || sub_trans) {
if (unistimdebug)
- ast_verb(0, "Can't create channel : Busy !\n");
+ ast_verb(0, "Can't create channel, request already in progress: Busy!\n");
+ unalloc_sub(d, sub);
*cause = AST_CAUSE_BUSY;
return NULL;
}
+ if (get_avail_softkey(d->session, sub->parent->name) == -1) {
+ if (unistimdebug)
+ ast_verb(0, "Can't create channel for line %s, all lines busy\n", sub->parent->name);
+ unalloc_sub(d, sub);
+ *cause = AST_CAUSE_BUSY;
+ return NULL;
+ }
+
+ ast_verb(3, "unistim_request(%s)\n", tmp);
+ sub->subtype = SUB_RING;
+ sub->softkey = -1;
sub->parent->capability = format;
tmpc = unistim_new(sub, AST_STATE_DOWN, requestor ? requestor->linkedid : NULL);
if (!tmpc)
@@ -4768,7 +5593,6 @@ static char *unistim_info(struct ast_cli_entry *e, int
struct unistim_line *line;
struct unistim_subchannel *sub;
struct unistimsession *s;
- int i;
struct ast_channel *tmp;
switch (cmd) {
@@ -4786,44 +5610,55 @@ static char *unistim_info(struct ast_cli_entry *e, int
if (a->argc != e->args)
return CLI_SHOWUSAGE;
- ast_cli(a->fd, "Dumping internal structures :\ndevice\n->line\n-->sub\n");
+ ast_cli(a->fd, "Dumping internal structures :\ndevice\n->line\n-->sub\n==>key\n");
while (device) {
- ast_cli(a->fd, "\nname=%s id=%s line=%p ha=%p sess=%p device=%p\n",
- device->name, device->id, device->lines, device->ha, device->session,
- device);
- line = device->lines;
- while (line) {
+ int i;
+
+ ast_cli(a->fd, "\nname=%s id=%s ha=%p sess=%p device=%p selected=%d height=%d\n",
+ device->name, device->id, device->ha, device->session,
+ device, device->selected, device->height);
+ AST_LIST_LOCK(&device->lines);
+ AST_LIST_TRAVERSE(&device->lines,line,list) {
ast_cli(a->fd,
- "->name=%s fullname=%s exten=%s callid=%s cap=%" PRId64 " device=%p line=%p\n",
+ "->name=%s fullname=%s exten=%s callid=%s cap=%" PRId64 " line=%p\n",
line->name, line->fullname, line->exten, line->cid_num,
- line->capability, line->parent, line);
- for (i = 0; i < MAX_SUBS; i++) {
- sub = line->subs[i];
- if (!sub)
- continue;
- if (!sub->owner)
- tmp = (void *) -42;
- else
- tmp = sub->owner->_bridge;
- if (sub->subtype != i)
- ast_cli(a->fd, "Warning ! subchannel->subs[%d] have a subtype=%d\n", i,
- sub->subtype);
- ast_cli(a->fd,
- "-->subtype=%d chan=%p rtp=%p bridge=%p line=%p alreadygone=%d\n",
- sub->subtype, sub->owner, sub->rtp, tmp, sub->parent,
- sub->alreadygone);
- }
- line = line->next;
+ line->capability, line);
}
- device = device->next;
+ AST_LIST_UNLOCK(&device->lines);
+
+ AST_LIST_LOCK(&device->subs);
+ AST_LIST_TRAVERSE(&device->subs, sub, list) {
+ if (!sub)
+ continue;
+ if (!sub->owner)
+ tmp = (void *) -42;
+ else
+ tmp = sub->owner->_bridge;
+ ast_cli(a->fd,
+ "-->subtype=%s chan=%p rtp=%p bridge=%p line=%p alreadygone=%d softkey=%d\n",
+ subtype_tostr(sub->subtype), sub->owner, sub->rtp, tmp, sub->parent,
+ sub->alreadygone, sub->softkey);
+ }
+ AST_LIST_UNLOCK(&device->subs);
+
+ for (i = 0; i < FAVNUM; i++) {
+ if (!soft_key_visible(device, i)) {
+ continue;
+ }
+ ast_cli(a->fd, "==> %d. dev=%s icon=%#x label=%-8s number=%-5s sub=%p line=%p\n",
+ i, device->softkeydevice[i], device->softkeyicon[i], device->softkeylabel[i], device->softkeynumber[i],
+ device->ssub[i], device->sline[i]);
+ }
+
+ device = device->next;
}
ast_cli(a->fd, "\nSessions:\n");
ast_mutex_lock(&sessionlock);
s = sessions;
while (s) {
ast_cli(a->fd,
- "sin=%s timeout=%u state=%d macaddr=%s device=%p session=%p\n",
- ast_inet_ntoa(s->sin.sin_addr), s->timeout, s->state, s->macaddr,
+ "sin=%s timeout=%u state=%s macaddr=%s device=%p session=%p\n",
+ ast_inet_ntoa(s->sin.sin_addr), s->timeout, ptestate_tostr(s->state), s->macaddr,
s->device, s);
s = s->next;
}
@@ -4981,7 +5816,7 @@ static void unquote(char *out, const char *src, int ma
return;
}
-static int ParseBookmark(const char *text, struct unistim_device *d)
+static int parse_bookmark(const char *text, struct unistim_device *d)
{
char line[256];
char *at;
@@ -5056,7 +5891,7 @@ static int ParseBookmark(const char *text, struct unis
ast_copy_string(d->softkeylabel[p], line, sizeof(d->softkeylabel[p]));
ast_copy_string(d->softkeynumber[p], number, sizeof(d->softkeynumber[p]));
if (unistimdebug)
- ast_verb(0, "New bookmark at pos %d label='%s' number='%s' icon=%x\n",
+ ast_verb(0, "New bookmark at pos %d label='%s' number='%s' icon=%#x\n",
p, d->softkeylabel[p], d->softkeynumber[p], d->softkeyicon[p]);
return 1;
}
@@ -5087,15 +5922,29 @@ static void finish_bookmark(void)
}
}
+static struct unistim_line *find_line_by_number(struct unistim_device *d, const char *val) {
+ struct unistim_line *l, *ret = NULL;
+
+ AST_LIST_LOCK(&d->lines);
+ AST_LIST_TRAVERSE(&d->lines, l, list) {
+ if (!strcmp(l->name, val)) {
+ ret = l;
+ break;
+ }
+ }
+ AST_LIST_UNLOCK(&d->lines);
+ return ret;
+}
+
static struct unistim_device *build_device(const char *cat, const struct ast_variable *v)
{
struct unistim_device *d;
- struct unistim_line *l = NULL;
+ struct unistim_line *l = NULL, *lt = NULL;
int create = 1;
- int nbsoftkey, dateformat, timeformat, callhistory;
+ int nbsoftkey, dateformat, timeformat, callhistory, sharpdial;
char linelabel[AST_MAX_EXTENSION];
char context[AST_MAX_EXTENSION];
- char ringvolume, ringstyle;
+ char ringvolume, ringstyle, cwvolume, cwstyle;
/* First, we need to know if we already have this name in our list */
/* Get a lock for the device chained list */
@@ -5112,22 +5961,39 @@ static struct unistim_device *build_device(const char
}
/* we're reloading right now */
create = 0;
- l = d->lines;
+ /* l = d->lines;*/
break;
}
d = d->next;
}
+ if (!(lt = ast_calloc(1, sizeof(*lt)))) {
+ return NULL;
+ }
ast_mutex_unlock(&devicelock);
if (create) {
if (!(d = ast_calloc(1, sizeof(*d))))
return NULL;
+ ast_copy_string(d->name, cat, sizeof(d->name));
+ } else {
+ /* Delete existing line information */
+ AST_LIST_LOCK(&d->lines);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&d->lines, l, list){
+ AST_LIST_REMOVE_CURRENT(list);
+ ast_free(l);
+ }
+ AST_LIST_TRAVERSE_SAFE_END
+ AST_LIST_UNLOCK(&d->lines);
+ }
- if (!(l = ast_calloc(1, sizeof(*l)))) {
- ast_free(d);
- return NULL;
- }
- ast_copy_string(d->name, cat, sizeof(d->name));
- }
+ /* reset bookmarks */
+ memset(d->softkeylabel, 0, sizeof(d->softkeylabel));
+ memset(d->softkeynumber, 0, sizeof(d->softkeynumber));
+ memset(d->softkeyicon, 0, sizeof(d->softkeyicon));
+ memset(d->softkeydevice, 0, sizeof(d->softkeydevice));
+ memset(d->ssub, 0, sizeof(d->ssub));
+ memset(d->sline, 0, sizeof(d->sline));
+ memset(d->sp, 0, sizeof(d->sp));
+
ast_copy_string(context, DEFAULTCONTEXT, sizeof(context));
d->contrast = -1;
d->output = OUTPUT_HANDSET;
@@ -5135,12 +6001,16 @@ static struct unistim_device *build_device(const char
d->volume = VOLUME_LOW;
d->mute = MUTE_OFF;
d->height = DEFAULTHEIGHT;
+ d->selected = -1;
linelabel[0] = '\0';
dateformat = 1;
timeformat = 1;
ringvolume = 2;
+ cwvolume = 1;
callhistory = 1;
+ sharpdial = 0;
ringstyle = 3;
+ cwstyle = 2;
nbsoftkey = 0;
while (v) {
if (!strcasecmp(v->name, "rtp_port"))
@@ -5181,19 +6051,25 @@ static struct unistim_device *build_device(const char
ringvolume = atoi(v->value);
else if (!strcasecmp(v->name, "ringstyle"))
ringstyle = atoi(v->value);
- else if (!strcasecmp(v->name, "callhistory"))
+ else if (!strcasecmp(v->name, "cwvolume"))
+ cwvolume = atoi(v->value);
+ else if (!strcasecmp(v->name, "cwstyle"))
+ cwstyle = atoi(v->value);
+ else if (!strcasecmp(v->name, "callhistory"))
callhistory = atoi(v->value);
- else if (!strcasecmp(v->name, "callerid")) {
+ else if (!strcasecmp(v->name, "sharpdial")) {
+ sharpdial = ast_true(v->value) ? 1 : 0;
+ } else if (!strcasecmp(v->name, "callerid")) {
if (!strcasecmp(v->value, "asreceived"))
- l->cid_num[0] = '\0';
+ lt->cid_num[0] = '\0';
else
- ast_copy_string(l->cid_num, v->value, sizeof(l->cid_num));
+ ast_copy_string(lt->cid_num, v->value, sizeof(lt->cid_num));
} else if (!strcasecmp(v->name, "language"))
- ast_copy_string(l->language, v->value, sizeof(l->language));
+ ast_copy_string(d->language, v->value, sizeof(d->language));
else if (!strcasecmp(v->name, "country"))
ast_copy_string(d->country, v->value, sizeof(d->country));
else if (!strcasecmp(v->name, "accountcode"))
- ast_copy_string(l->accountcode, v->value, sizeof(l->accountcode));
+ ast_copy_string(lt->accountcode, v->value, sizeof(lt->accountcode));
else if (!strcasecmp(v->name, "amaflags")) {
int y;
y = ast_cdr_amaflags2int(v->value);
@@ -5201,17 +6077,17 @@ static struct unistim_device *build_device(const char
ast_log(LOG_WARNING, "Invalid AMA flags: %s at line %d\n", v->value,
v->lineno);
else
- l->amaflags = y;
+ lt->amaflags = y;
} else if (!strcasecmp(v->name, "musiconhold"))
- ast_copy_string(l->musicclass, v->value, sizeof(l->musicclass));
+ ast_copy_string(lt->musicclass, v->value, sizeof(lt->musicclass));
else if (!strcasecmp(v->name, "callgroup"))
- l->callgroup = ast_get_group(v->value);
+ lt->callgroup = ast_get_group(v->value);
else if (!strcasecmp(v->name, "pickupgroup"))
- l->pickupgroup = ast_get_group(v->value);
+ lt->pickupgroup = ast_get_group(v->value);
else if (!strcasecmp(v->name, "mailbox"))
- ast_copy_string(l->mailbox, v->value, sizeof(l->mailbox));
+ ast_copy_string(lt->mailbox, v->value, sizeof(lt->mailbox));
else if (!strcasecmp(v->name, "parkinglot"))
- ast_copy_string(l->parkinglot, v->value, sizeof(l->parkinglot));
+ ast_copy_string(lt->parkinglot, v->value, sizeof(lt->parkinglot));
else if (!strcasecmp(v->name, "linelabel"))
unquote(linelabel, v->value, sizeof(linelabel) - 1);
else if (!strcasecmp(v->name, "extension")) {
@@ -5228,103 +6104,93 @@ static struct unistim_device *build_device(const char
ast_log(LOG_WARNING,
"More than 6 softkeys defined. Ignoring new entries.\n");
else {
- if (ParseBookmark(v->value, d))
+ if (parse_bookmark(v->value, d))
nbsoftkey++;
}
} else if (!strcasecmp(v->name, "line")) {
- int len = strlen(linelabel);
+ int len = strlen(linelabel);
+ int create_line = 0;
+
+ l = find_line_by_number(d, v->value);
+ if (!l) { /* If line still not exists */
+ if (!(l = ast_calloc(1, sizeof(*l)))) {
+ ast_free(d);
+ return NULL;
+ }
+ memcpy(l, lt, sizeof(*l));
+ ast_mutex_init(&l->lock);
+ create_line = 1;
+ }
+ d->to_delete = 0;
- if (nbsoftkey) {
- ast_log(LOG_WARNING,
- "You must use bookmark AFTER line=>. Only one line is supported in this version\n");
- if (create) {
- ast_free(d);
- ast_free(l);
- }
- return NULL;
- }
- if (create) {
- ast_mutex_init(&l->lock);
- } else {
- d->to_delete = 0;
- /* reset bookmarks */
- memset(d->softkeylabel, 0, sizeof(d->softkeylabel));
- memset(d->softkeynumber, 0, sizeof(d->softkeynumber));
- memset(d->softkeyicon, 0, sizeof(d->softkeyicon));
- memset(d->softkeydevice, 0, sizeof(d->softkeydevice));
- memset(d->sp, 0, sizeof(d->sp));
- }
- ast_copy_string(l->name, v->value, sizeof(l->name));
- snprintf(l->fullname, sizeof(l->fullname), "USTM/%s@%s", l->name, d->name);
- d->softkeyicon[0] = FAV_ICON_ONHOOK_BLACK;
+ /* Set softkey info for new line*/
+ d->sline[nbsoftkey] = l;
+ d->softkeyicon[nbsoftkey] = FAV_LINE_ICON;
if (!len) /* label is undefined ? */
- ast_copy_string(d->softkeylabel[0], v->value, sizeof(d->softkeylabel[0]));
+ ast_copy_string(d->softkeylabel[nbsoftkey], v->value, sizeof(d->softkeylabel[nbsoftkey]));
else {
+ int softkeylinepos = 0;
if ((len > 2) && (linelabel[1] == '@')) {
- d->softkeylinepos = linelabel[0];
- if ((d->softkeylinepos >= '0') && (d->softkeylinepos <= '5')) {
- d->softkeylinepos -= '0';
- d->softkeyicon[0] = 0;
+ softkeylinepos = linelabel[0];
+ if ((softkeylinepos >= '0') && (softkeylinepos <= '5')) {
+ softkeylinepos -= '0';
+ d->softkeyicon[nbsoftkey] = FAV_ICON_NONE;
} else {
ast_log(LOG_WARNING,
"Invalid position for linelabel : must be between 0 and 5\n");
- d->softkeylinepos = 0;
}
- ast_copy_string(d->softkeylabel[d->softkeylinepos], linelabel + 2,
- sizeof(d->softkeylabel[d->softkeylinepos]));
- d->softkeyicon[d->softkeylinepos] = FAV_ICON_ONHOOK_BLACK;
+ ast_copy_string(d->softkeylabel[softkeylinepos], linelabel + 2,
+ sizeof(d->softkeylabel[softkeylinepos]));
+ d->softkeyicon[softkeylinepos] = FAV_LINE_ICON;
} else
- ast_copy_string(d->softkeylabel[0], linelabel,
- sizeof(d->softkeylabel[0]));
+ ast_copy_string(d->softkeylabel[nbsoftkey], linelabel,
+ sizeof(d->softkeylabel[nbsoftkey]));
}
nbsoftkey++;
- ast_copy_string(l->context, context, sizeof(l->context));
- if (!ast_strlen_zero(l->mailbox)) {
- if (unistimdebug)
- ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name);
- }
+
+ if (create_line) {
+ ast_copy_string(l->name, v->value, sizeof(l->name));
+ snprintf(l->fullname, sizeof(l->fullname), "USTM/%s@%s", l->name, d->name);
+ ast_copy_string(l->context, context, sizeof(l->context));
+ if (!ast_strlen_zero(l->mailbox)) {
+ if (unistimdebug)
+ ast_verb(3, "Setting mailbox '%s' on %s@%s\n", l->mailbox, d->name, l->name);
+ }
- l->capability = CAPABILITY;
- l->parent = d;
+ l->capability = CAPABILITY;
+ l->parent = d;
- if (create) {
- if (!alloc_sub(l, SUB_REAL)) {
- ast_mutex_destroy(&l->lock);
- ast_free(l);
- ast_free(d);
- return NULL;
- }
- l->next = d->lines;
- d->lines = l;
- }
- } else if (!strcasecmp(v->name, "height")) {
+ AST_LIST_LOCK(&d->lines);
+ AST_LIST_INSERT_TAIL(&d->lines, l, list);
+ AST_LIST_UNLOCK(&d->lines);
+ }
+
+ } else if (!strcasecmp(v->name, "height")) {
/* Allow the user to lower the expected display lines on the phone
- * For example the Nortal I2001 and I2002 only have one ! */
+ * For example the Nortel i2001 and i2002 only have one ! */
d->height = atoi(v->value);
} else
ast_log(LOG_WARNING, "Don't know keyword '%s' at line %d\n", v->name,
v->lineno);
v = v->next;
}
- d->ringvolume = ringvolume;
+ if (!get_main_line(d)) {
+ ast_log(LOG_ERROR, "An Unistim device must have at least one line!\n");
+ ast_free(d);
+ return NULL;
+ }
+ d->ringvolume = ringvolume;
d->ringstyle = ringstyle;
- d->callhistory = callhistory;
+ d->cwvolume = cwvolume;
+ d->cwstyle = cwstyle;
+ d->callhistory = callhistory;
+ d->sharp_dial = sharpdial;
d->tz = ast_get_indication_zone(d->country);
if ((d->tz == NULL) && !ast_strlen_zero(d->country))
ast_log(LOG_WARNING, "Country '%s' was not found in indications.conf\n",
d->country);
d->datetimeformat = 56 + (dateformat * 4);
d->datetimeformat += timeformat;
- if (!d->lines) {
- ast_log(LOG_ERROR, "An Unistim device must have at least one line!\n");
- ast_mutex_destroy(&l->lock);
- ast_free(l);
- if (d->tz) {
- d->tz = ast_tone_zone_unref(d->tz);
- }
- ast_free(d);
- return NULL;
- }
if ((autoprovisioning == AUTOPROVISIONING_TN) &&
(!ast_strlen_zero(d->extension_number))) {
d->extension = EXTENSION_TN;
@@ -5337,8 +6203,6 @@ static struct unistim_device *build_device(const char
} else if (ast_strlen_zero(d->id)) {
if (strcmp(d->name, "template")) {
ast_log(LOG_ERROR, "You must specify the mac address with device=\n");
- ast_mutex_destroy(&l->lock);
- ast_free(l);
if (d->tz) {
d->tz = ast_tone_zone_unref(d->tz);
}
@@ -5351,8 +6215,6 @@ static struct unistim_device *build_device(const char
d->rtp_port = 10000;
if (d->contrast == -1)
d->contrast = 8;
- if (ast_strlen_zero(d->maintext0))
- strcpy(d->maintext0, "Welcome");
if (ast_strlen_zero(d->maintext1))
strcpy(d->maintext1, d->name);
if (ast_strlen_zero(d->titledefault)) {
@@ -5360,7 +6222,7 @@ static struct unistim_device *build_device(const char
struct timeval cur_time = ast_tvnow();
if ((ast_localtime(&cur_time, &tm, 0)) == 0 || ast_strlen_zero(tm.tm_zone)) {
- display_last_error("Error in ast_localtime()");
+ ast_log(LOG_WARNING, "Error in ast_localtime()");
ast_copy_string(d->titledefault, "UNISTIM for*", 12);
} else {
if (strlen(tm.tm_zone) < 4) {
@@ -5438,8 +6300,13 @@ static int reload_config(void)
} else if (!strcasecmp(v->name, "cos_audio")) {
if (ast_str2cos(v->value, &qos.cos_audio))
ast_log(LOG_WARNING, "Invalid cos_audio value at line %d, refer to QoS documentation\n", v->lineno);
- } else if (!strcasecmp(v->name, "autoprovisioning")) {
+ } else if (!strcasecmp(v->name, "debug")) {
if (!strcasecmp(v->value, "no"))
+ unistimdebug = 0;
+ else if (!strcasecmp(v->value, "yes"))
+ unistimdebug = 1;
+ } else if (!strcasecmp(v->name, "autoprovisioning")) {
+ if (!strcasecmp(v->value, "no"))
autoprovisioning = AUTOPROVISIONING_NO;
else if (!strcasecmp(v->value, "yes"))
autoprovisioning = AUTOPROVISIONING_YES;
@@ -5497,44 +6364,57 @@ static int reload_config(void)
d = devices;
while (d) {
if (d->to_delete) {
- int i;
+ struct unistim_line *l;
+ struct unistim_subchannel *sub;
if (unistimdebug)
ast_verb(0, "Removing device '%s'\n", d->name);
- if (!d->lines) {
+ if (!get_main_line(d)) {
ast_log(LOG_ERROR, "Device '%s' without a line !, aborting\n", d->name);
ast_config_destroy(cfg);
return 0;
}
- if (!d->lines->subs[0]) {
- ast_log(LOG_ERROR, "Device '%s' without a subchannel !, aborting\n",
- d->name);
- ast_config_destroy(cfg);
- return 0;
- }
- if (d->lines->subs[0]->owner) {
- ast_log(LOG_WARNING,
- "Device '%s' was not deleted : a call is in progress. Try again later.\n",
- d->name);
- d = d->next;
- continue;
- }
- ast_mutex_destroy(&d->lines->subs[0]->lock);
- ast_free(d->lines->subs[0]);
- for (i = 1; i < MAX_SUBS; i++) {
- if (d->lines->subs[i]) {
- ast_log(LOG_WARNING,
- "Device '%s' with threeway call subchannels allocated, aborting.\n",
- d->name);
- break;
- }
- }
- if (i < MAX_SUBS) {
- d = d->next;
- continue;
- }
- ast_mutex_destroy(&d->lines->lock);
- ast_free(d->lines);
+
+ AST_LIST_LOCK(&d->subs);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&d->subs, sub, list){
+ if (sub->subtype == SUB_REAL) {
+ if (!sub) {
+ ast_log(LOG_ERROR, "Device '%s' without a subchannel !, aborting\n",
+ d->name);
+ ast_config_destroy(cfg);
+ return 0;
+ }
+ if (sub->owner) {
+ ast_log(LOG_WARNING,
+ "Device '%s' was not deleted : a call is in progress. Try again later.\n",
+ d->name);
+ d = d->next;
+ continue;
+ }
+ }
+ if (sub->subtype == SUB_THREEWAY) {
+ ast_log(LOG_WARNING,
+ "Device '%s' with threeway call subchannels allocated, aborting.\n",
+ d->name);
+ break;
+ }
+ AST_LIST_REMOVE_CURRENT(list);
+ ast_mutex_destroy(&sub->lock);
+ ast_free(sub);
+ }
+ AST_LIST_TRAVERSE_SAFE_END
+ AST_LIST_UNLOCK(&d->subs);
+
+
+ AST_LIST_LOCK(&d->lines);
+ AST_LIST_TRAVERSE_SAFE_BEGIN(&d->lines, l, list){
+ AST_LIST_REMOVE_CURRENT(list);
+ ast_mutex_destroy(&l->lock);
+ ast_free(l);
+ }
+ AST_LIST_TRAVERSE_SAFE_END
+ AST_LIST_UNLOCK(&d->lines);
+
if (d->session) {
if (sessions == d->session)
sessions = d->session->next;
@@ -5578,9 +6458,15 @@ static int reload_config(void)
ast_mutex_lock(&sessionlock);
s = sessions;
while (s) {
- if (s->device)
+ if (s->device) {
refresh_all_favorite(s);
- s = s->next;
+ if (ast_strlen_zero(s->device->language)) {
+ struct unistim_languages lang;
+ lang = options_languages[find_language(s->device->language)];
+ send_charset_update(s, lang.encoding);
+ }
+ }
+ s = s->next;
}
ast_mutex_unlock(&sessionlock);
/* We don't recreate a socket when reloading (locks would be necessary). */
@@ -5693,8 +6579,9 @@ buff_failed:
static int unload_module(void)
{
/* First, take us out of the channel loop */
- if (sched)
+ if (sched) {
sched_context_destroy(sched);
+ }
ast_cli_unregister_multiple(unistim_cli, ARRAY_LEN(unistim_cli));