void move_next(WINDOW *win, struct status_node *current, int direction) { if(!current) return; struct status_node *next = 0; struct status_node *boundary = 0; if(direction > 0) { next = current->next; boundary = timelines[current_tl_index]->current_bottom; } else { next = current->prev; boundary = timelines[current_tl_index]->current_top; } if(!next) { // reached the bottom if(direction > 0) notify_state_change(states[STATE_REACHED_BOTTOM]); else notify_state_change(states[STATE_REACHED_TOP]); return; } if(current != boundary) { wmove(win,current->y_min,0); show_status(win,current); } else move_next_page(win,current,direction); highlight_status(win,next); timelines[current_tl_index]->current = next; }
int compose_new_tweet(WINDOW *win,status *in_reply_to, int if_reply_to_all) { memset(newtext,'\0',(1+TWEET_MAX_LEN)*sizeof(wchar_t)); if(in_reply_to) { if(in_reply_to->retweeted_status) in_reply_to = in_reply_to->retweeted_status; wchar_t *ptr = newtext; *ptr ++ = '@'; mbstowcs(ptr,in_reply_to->composer->screen_name,strlen(in_reply_to->composer->screen_name)); ptr += wcslen(ptr); *ptr ++ = ' '; if(if_reply_to_all) { wchar_t wscreenname[ID_MAX_LEN+2]; wscreenname[0] = '@'; mbstowcs(wscreenname+1,me->screen_name,ID_MAX_LEN+1); for(entity *et = in_reply_to->entities; et; et = et->next) { if(et->type == ENTITY_TYPE_MENTION && wcscmp(et->text,wscreenname)) { wcscpy(ptr,et->text); ptr += wcslen(ptr); *ptr++ = ' '; } } } } int count = input_new_tweet(win); if(count > 0) { char text[TWEET_MAX_LEN * 4]; char *in_reply_to_status_id = NULL; if(in_reply_to) in_reply_to_status_id = in_reply_to->id; wcstombs(text,newtext,TWEET_MAX_LEN * 4); if(count <=140) notify_state_change("Sending......"); else notify_state_change("Longer than 140. Will be truncated."); update_status(text,in_reply_to_status_id); notify_state_change("Successfully updated."); } else notify_state_change(""); return 0; }
void JoinPBX::bridge(void) { struct join_relation *relation; struct lcr_msg *message; int numconnect = 0, relations = 0; class Endpoint *epoint; struct port_list *portlist; class Port *port; unsigned int bridge_id; class Join *join_3pty; class JoinPBX *joinpbx_3pty; #ifdef DEBUG_COREBRIDGE int allmISDN = 0; // never set for debug purpose #else int allmISDN = 1; // set until a non-mISDN relation is found #endif /* bridge id is the serial of join * if we have a 3pty with another join, we always use the lowest brigde id. * this way we use common ids, so both joins share same bridge */ if (j_3pty && j_3pty < j_serial) bridge_id = j_3pty; else bridge_id = j_serial; relation = j_relation; while(relation) { /* count all relations */ relations++; /* check for relation's objects */ epoint = find_epoint_id(relation->epoint_id); if (!epoint) { PERROR("software error: relation without existing endpoints.\n"); relation = relation->next; continue; } portlist = epoint->ep_portlist; if (!portlist) { PDEBUG(DEBUG_JOIN, "join%d ignoring relation without port object.\n", j_serial); //#warning testing: keep on hold until single audio stream available relation->channel_state = 0; relation = relation->next; continue; } if (portlist->next) { PDEBUG(DEBUG_JOIN, "join%d ignoring relation with ep%d due to port_list.\n", j_serial, epoint->ep_serial); //#warning testing: keep on hold until single audio stream available relation->channel_state = 0; relation = relation->next; continue; } port = find_port_id(portlist->port_id); if (!port) { PDEBUG(DEBUG_JOIN, "join%d ignoring relation without existing port object.\n", j_serial); relation = relation->next; continue; } if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN) { PDEBUG(DEBUG_JOIN, "join%d ignoring relation ep%d because it's port is not mISDN.\n", j_serial, epoint->ep_serial); if (allmISDN) { PDEBUG(DEBUG_JOIN, "join%d not all endpoints are mISDN.\n", j_serial); allmISDN = 0; } relation = relation->next; continue; } relation = relation->next; } /* check if 3pty members have no mISDN, so bridging via mISDN/lcr will be selected correctly */ join_3pty = find_join_id(j_3pty); if (join_3pty && join_3pty->j_type == JOIN_TYPE_PBX) { joinpbx_3pty = (class JoinPBX *)join_3pty; relation = joinpbx_3pty->j_relation; while(relation) { #if 0 no need to count, because j_3pty is taken into account below when checking relations /* count all relations */ relations++; #endif /* check for relation's objects */ epoint = find_epoint_id(relation->epoint_id); if (!epoint) { PERROR("software error: relation without existing endpoints.\n"); relation = relation->next; continue; } portlist = epoint->ep_portlist; if (!portlist) { PDEBUG(DEBUG_JOIN, "other 3pty join %d: ignoring relation without port object.\n", joinpbx_3pty->j_serial); //#warning testing: keep on hold until single audio stream available relation->channel_state = 0; relation = relation->next; continue; } if (portlist->next) { PDEBUG(DEBUG_JOIN, "other 3pty join %d: ignoring relation with ep%d due to port_list.\n", joinpbx_3pty->j_serial, epoint->ep_serial); //#warning testing: keep on hold until single audio stream available relation->channel_state = 0; relation = relation->next; continue; } port = find_port_id(portlist->port_id); if (!port) { PDEBUG(DEBUG_JOIN, "other 3pty join %d: ignoring relation without existing port object.\n", joinpbx_3pty->j_serial); relation = relation->next; continue; } if ((port->p_type&PORT_CLASS_MASK)!=PORT_CLASS_mISDN) { PDEBUG(DEBUG_JOIN, "other 3pty join %d: ignoring relation ep%d because it's port is not mISDN.\n", joinpbx_3pty->j_serial, epoint->ep_serial); if (allmISDN) { PDEBUG(DEBUG_JOIN, "other 3pty join %d: not all endpoints are mISDN.\n", joinpbx_3pty->j_serial); allmISDN = 0; } relation = relation->next; continue; } relation = relation->next; } } PDEBUG(DEBUG_JOIN, "join%d members=%d %s\n", j_serial, relations, (allmISDN)?"(all are mISDN-members)":"(not all are mISDN-members)"); /* we notify all relations about rxdata. */ relation = j_relation; while(relation) { /* count connected relations */ if ((relation->channel_state == 1) && (relation->rx_state != NOTIFY_STATE_SUSPEND) && (relation->rx_state != NOTIFY_STATE_HOLD)) numconnect ++; /* remove unconnected parties from conference, also remove remotely disconnected parties so conference will not be disturbed. */ /* mISDN */ if (relation->channel_state == 1 && relation->rx_state != NOTIFY_STATE_HOLD && relation->rx_state != NOTIFY_STATE_SUSPEND && relations>1 // no conf with one member && allmISDN) { // no conf if any member is not mISDN message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL); message->param.mISDNsignal.message = mISDNSIGNAL_CONF; message->param.mISDNsignal.conf = (bridge_id << 16) | j_pid; PDEBUG(DEBUG_JOIN, "join%d EP%d +on+ id: 0x%08x\n", j_serial, relation->epoint_id, message->param.mISDNsignal.conf); message_put(message); } else { message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_mISDNSIGNAL); message->param.mISDNsignal.message = mISDNSIGNAL_CONF; message->param.mISDNsignal.conf = 0; PDEBUG(DEBUG_JOIN, "join%d EP%d +off+ id: 0x%08x\n", j_serial, relation->epoint_id, message->param.mISDNsignal.conf); message_put(message); } /* core bridge */ if (relation->channel_state == 1 && relation->rx_state != NOTIFY_STATE_HOLD && relation->rx_state != NOTIFY_STATE_SUSPEND && relations>1 // no bridge with one member && !allmISDN) { // no bridge if all members are mISDN message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_BRIDGE); message->param.bridge_id = bridge_id; PDEBUG(DEBUG_JOIN, "join%u EP%u requests bridge=%u\n", j_serial, relation->epoint_id, bridge_id); message_put(message); } else { message = message_create(j_serial, relation->epoint_id, JOIN_TO_EPOINT, MESSAGE_BRIDGE); message->param.bridge_id = 0; PDEBUG(DEBUG_JOIN, "join%u EP%u drop bridge=%u\n", j_serial, relation->epoint_id, bridge_id); message_put(message); } relation = relation->next; } /* two people just exchange their states */ if (!j_3pty && relations==2 && !j_partyline) { PDEBUG(DEBUG_JOIN, "join%d 2 relations / no partyline\n", j_serial); relation = j_relation; relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, relation->next->rx_state); relation->next->tx_state = notify_state_change(j_serial, relation->next->epoint_id, relation->next->tx_state, relation->rx_state); } else /* one member in a join, so we put her on hold */ if (!j_3pty && (relations==1 || numconnect==1)/* && !j_partyline_jingle*/) { PDEBUG(DEBUG_JOIN, "join%d 1 member or only 1 connected, put on hold\n", j_serial); relation = j_relation; while(relation) { if ((relation->channel_state == 1) && (relation->rx_state != NOTIFY_STATE_SUSPEND) && (relation->rx_state != NOTIFY_STATE_HOLD)) relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_HOLD); relation = relation->next; } } else { /* if conference/partyline (or more than two members and more than one is connected), so we set conference state */ PDEBUG(DEBUG_JOIN, "join%d %d members, %d connected, signal conference\n", j_serial, relations, numconnect); relation = j_relation; while(relation) { if ((relation->channel_state == 1) && (relation->rx_state != NOTIFY_STATE_SUSPEND) && (relation->rx_state != NOTIFY_STATE_HOLD)) relation->tx_state = notify_state_change(j_serial, relation->epoint_id, relation->tx_state, NOTIFY_STATE_CONFERENCE); relation = relation->next; } } }
/** * Commands: * a -- * b -- * c -- conversation * d -- delete a tweet * e -- * f -- fav/unfav a tweet * g -- * h -- * i -- * j -- move down one tweet * J -- move down one page * k -- move up one tweet * K -- move up one page * l -- list * m -- direct message * n -- compose a new tweet * o -- * p -- * q -- quit * r -- reply * R -- reply to all * s -- search * t -- retweet * u -- * v -- move to the last viewed tweet * w -- * x -- * y -- * z -- * ? -- show shortcuts help * . -- refresh */ void wait_command(WINDOW *win) { char ch = '\0'; while((ch = getch()) != 'q') { switch(ch) { case 'n': // Compose new tweet notify_state_change(states[STATE_NORMAL]); compose_new_tweet(win,NULL,0); return_to_current_timeline(win); break; case 'J': // move down one page notify_state_change(states[STATE_NORMAL]); if(move_next_page(win,timelines[current_tl_index]->current_bottom,1) != -1) { timelines[current_tl_index]->current = timelines[current_tl_index]->current_top; highlight_status(win, timelines[current_tl_index]->current); } else notify_error_state(); break; case 'K': // move up one page notify_state_change(states[STATE_NORMAL]); if(move_next_page(win,timelines[current_tl_index]->current_top,-1)!= -1) { timelines[current_tl_index]->current = timelines[current_tl_index]->current_top; highlight_status(win, timelines[current_tl_index]->current); } else notify_error_state(); break; case 'j': // move down one tweet notify_state_change(states[STATE_NORMAL]); move_next(win, timelines[current_tl_index]->current,1); break; case 'k': // move up one tweet notify_state_change(states[STATE_NORMAL]); move_next(win, timelines[current_tl_index]->current,-1); break; case '.': // refresh the current timeline /* notify_state_change(states[STATE_RETRIEVING_UPDATES]); struct status_node *to_status = timelines[current_tl_index]->head; int res = update_timeline(current_tl_index,NULL,to_status); if(res >= 0){ char *state_str = malloc(20*sizeof(char)); memset(state_str,'\0',20); if(res == 0) sprintf(state_str,"%s","No updates."); else if(res == 1) sprintf(state_str,"%d new tweet.",res); else sprintf(state_str,"%d new tweets.",res); notify_state_change(state_str); free(state_str); } else notify_error_state(); */ merge_timeline_updates(current_tl_index); timelines[current_tl_index]->last_viewed = timelines[current_tl_index]->current; move_top(win); notify_timeline_updates(current_tl_index,0); break; case 'v': notify_state_change(states[STATE_NORMAL]); if(timelines[current_tl_index]->last_viewed) { int y,x; struct status_node *last_viewed = timelines[current_tl_index]->last_viewed; getmaxyx(win,y,x); timelines[current_tl_index]->current = last_viewed; timelines[current_tl_index]->current_top = last_viewed; timelines[current_tl_index]->current_bottom = show_timeline(win,last_viewed,y,x); highlight_status(win,last_viewed); } else notify_state_change(states[STATE_NO_LAST_VIEWED]); break; case 'r': compose_new_tweet(win,timelines[current_tl_index]->current->st,0); return_to_current_timeline(win); break; case 'R': compose_new_tweet(win,timelines[current_tl_index]->current->st,1); return_to_current_timeline(win); break; case 't': if(timelines[current_tl_index]->current->st) { status *st = timelines[current_tl_index]->current->st; if(st->retweeted_status) st = st->retweeted_status; if(IS_PROTECTED(st->composer->extra_info)) notify_state_change("This user is protected. Cannot retweet."); else retweet_status(st->id); } break; } } }