Example #1
0
  /**
   * Removes the given call panel tab.
   *
   * @param callPanel the CallPanel to remove
   */
  private void removeCallPanel(CallPanel callPanel) {
    if (callPanel.getCall() != null && activeCalls.contains(callPanel.getCall())) {
      this.activeCalls.remove(callPanel.getCall());
    }

    mainFrame.removeCallPanel(callPanel);
    updateButtonsStateAccordingToSelectedPanel();
  }
Example #2
0
    public void run() {
      if (telephony == null) return;

      Call createdCall = null;

      if (contacts != null) {
        Contact contact = (Contact) contacts.get(0);

        // NOTE: The multi user call is not yet implemented!
        // We just get the first contact and create a call for him.
        try {
          createdCall = telephony.createCall(contact);
        } catch (OperationFailedException e) {
          logger.error("The call could not be created: " + e);

          callPanel.getParticipantPanel(contact.getDisplayName()).setState(e.getMessage());

          removeCallPanelWait(callPanel);
        }

        // If the call is successfully created we set the created
        // Call instance to the already existing CallPanel and we
        // add this call to the active calls.
        if (createdCall != null) {
          callPanel.setCall(createdCall, GuiCallParticipantRecord.OUTGOING_CALL);

          activeCalls.put(createdCall, callPanel);
        }
      } else {
        try {
          createdCall = telephony.createCall(stringContact);
        } catch (ParseException e) {
          logger.error("The call could not be created: " + e);

          callPanel.getParticipantPanel(stringContact).setState(e.getMessage());

          removeCallPanelWait(callPanel);
        } catch (OperationFailedException e) {
          logger.error("The call could not be created: " + e);

          callPanel.getParticipantPanel(stringContact).setState(e.getMessage());

          removeCallPanelWait(callPanel);
        }

        // If the call is successfully created we set the created
        // Call instance to the already existing CallPanel and we
        // add this call to the active calls.
        if (createdCall != null) {
          callPanel.setCall(createdCall, GuiCallParticipantRecord.OUTGOING_CALL);

          activeCalls.put(createdCall, callPanel);
        }
      }
    }
Example #3
0
  /**
   * Implements ChangeListener.stateChanged. Enables the hangup button if ones selects a tab in the
   * main tabbed pane that contains a call panel.
   */
  public void stateChanged(ChangeEvent e) {
    this.updateButtonsStateAccordingToSelectedPanel();

    Component selectedPanel = mainFrame.getSelectedTab();
    if (selectedPanel == null || !(selectedPanel instanceof CallPanel)) {
      Iterator callPanels = activeCalls.values().iterator();

      while (callPanels.hasNext()) {
        CallPanel callPanel = (CallPanel) callPanels.next();

        callPanel.removeDialogs();
      }
    }
  }
  /**
   * Updates this view i.e. <tt>OneToOneCallPeerPanel</tt> so that it depicts the current state of
   * its model i.e. <tt>callPeer</tt>. The update is performed in the AWT event dispatching thread.
   */
  private void updateViewFromModelInEventDispatchThread() {
    /*
     * We receive events/notifications from various threads and we respond
     * to them in the AWT event dispatching thread. It is possible to first
     * schedule an event to be brought to the AWT event dispatching thread,
     * then to have #dispose() invoked on this instance and, finally, to
     * receive the scheduled event in the AWT event dispatching thread. In
     * such a case, this disposed instance should not respond to the event
     * because it may, for example, steal a visual Components depicting
     * video (which cannot belong to more than one parent at a time) from
     * another non-disposed OneToOneCallPeerPanel.
     */
    if (disposed) return;

    /*
     * Update the display of visual <tt>Component</tt>s depicting video
     * streaming between the local peer/user and the remote peer(s).
     */

    OperationSetVideoTelephony videoTelephony =
        callPeer.getProtocolProvider().getOperationSet(OperationSetVideoTelephony.class);
    Component remoteVideo = null;
    Component localVideo = null;

    if (videoTelephony != null) {
      List<Component> remoteVideos = videoTelephony.getVisualComponents(callPeer);

      if ((remoteVideos != null) && !remoteVideos.isEmpty()) {
        /*
         * TODO OneToOneCallPeerPanel displays a one-to-one conversation
         * between the local peer/user and a specific remote peer. If
         * the remote peer is the focus of a telephony conference of its
         * own, it may be sending multiple videos to the local peer.
         * Switching to a user interface which displays multiple videos
         * is the responsibility of whoever decided that this
         * OneToOneCallPeerPanel is to be used to depict the current
         * state of the CallConference associated with the CallPeer
         * depicted by this instance. If that switching decides that
         * this instance is to continue being the user interface, then
         * we should probably pick up the remote video which is
         * generated by the remote peer and not one of its
         * ConferenceMembers.
         */
        remoteVideo = remoteVideos.get(0);
      }

      if (uiVideoHandler.isLocalVideoVisible()) {
        try {
          localVideo = videoTelephony.getLocalVisualComponent(callPeer);
        } catch (OperationFailedException ofe) {
          /*
           * Well, we cannot do much about the exception. We'll just
           * not display the local video.
           */
          logger.warn("Failed to retrieve local video to be displayed.", ofe);
        }
      }

      /*
       * Determine whether there is actually a change in the local and
       * remote videos which requires an update.
       */
      boolean localVideoChanged =
          ((localVideo != this.localVideo)
              || ((localVideo != null) && !UIVideoHandler2.isAncestor(center, localVideo)));
      boolean remoteVideoChanged =
          ((remoteVideo != this.remoteVideo)
              || ((remoteVideo != null) && !UIVideoHandler2.isAncestor(center, remoteVideo)));

      // If the remote video has changed, maybe the CallPanel can display
      // the LO/SD/HD button.
      if (remoteVideoChanged) {
        // Updates video component which may listen the mouse and key
        // events.
        if (desktopSharingMouseAndKeyboardListener != null) {
          desktopSharingMouseAndKeyboardListener.setVideoComponent(remoteVideo);
        }

        CallPanel callPanel = callRenderer.getCallContainer();
        // The remote video has been added, then tries to display the
        // LO/SD/HD button.
        if (remoteVideo != null) {
          callPanel.addRemoteVideoSpecificComponents(callPeer);
        }
        // The remote video has been removed, then hide the LO/SD/HD
        // button if it is currently displayed.
        else {
          callPanel.removeRemoteVideoSpecificComponents();
        }
      }

      if (localVideoChanged || remoteVideoChanged) {
        /*
         * VideoContainer and JAWTRenderer cannot handle random
         * additions of Components. Removing the localVideo when the
         * user has requests its hiding though, should work without
         * removing all Components from the VideoCotainer and adding
         * them again.
         */
        if (localVideoChanged && !remoteVideoChanged && (localVideo == null)) {
          if (this.localVideo != null) {
            center.remove(this.localVideo);
            this.localVideo = null;

            if (closeLocalVisualComponentButton != null)
              center.remove(closeLocalVisualComponentButton);
          }
        } else {
          center.removeAll();
          this.localVideo = null;
          this.remoteVideo = null;

          /*
           * AWT does not make a guarantee about the Z order even
           * within an operating system i.e. the order of adding the
           * Components to their Container does not mean that they
           * will be determinedly painted in that or reverse order.
           * Anyway, there appears to be an expectation among the
           * developers less acquainted with AWT that AWT paints the
           * Components of a Container in an order that is the reverse
           * of the order of their adding. In order to satisfy that
           * expectation and thus give at least some idea to the
           * developers reading the code bellow, do add the Components
           * according to that expectation.
           */

          if (localVideo != null) {
            if (closeLocalVisualComponentButton == null) {
              closeLocalVisualComponentButton = new CloseLocalVisualComponentButton(uiVideoHandler);
            }
            center.add(closeLocalVisualComponentButton, VideoLayout.CLOSE_LOCAL_BUTTON, -1);

            center.add(localVideo, VideoLayout.LOCAL, -1);
            this.localVideo = localVideo;
          }

          if (remoteVideo != null) {
            center.add(remoteVideo, VideoLayout.CENTER_REMOTE, -1);
            this.remoteVideo = remoteVideo;
          }
        }
      }
    }
  }
Example #5
0
  /**
   * Handles the <tt>ActionEvent</tt> generated when user presses one of the buttons in this panel.
   */
  public void actionPerformed(ActionEvent evt) {
    JButton button = (JButton) evt.getSource();
    String buttonName = button.getName();

    if (buttonName.equals("call")) {
      Component selectedPanel = mainFrame.getSelectedTab();

      // call button is pressed over an already open call panel
      if (selectedPanel != null
          && selectedPanel instanceof CallPanel
          && ((CallPanel) selectedPanel).getCall().getCallState()
              == CallState.CALL_INITIALIZATION) {

        NotificationManager.stopSound(NotificationManager.BUSY_CALL);
        NotificationManager.stopSound(NotificationManager.INCOMING_CALL);

        CallPanel callPanel = (CallPanel) selectedPanel;

        Iterator participantPanels = callPanel.getParticipantsPanels();

        while (participantPanels.hasNext()) {
          CallParticipantPanel panel = (CallParticipantPanel) participantPanels.next();

          panel.setState("Connecting");
        }

        Call call = callPanel.getCall();

        answerCall(call);
      }
      // call button is pressed over the call list
      else if (selectedPanel != null
          && selectedPanel instanceof CallListPanel
          && ((CallListPanel) selectedPanel).getCallList().getSelectedIndex() != -1) {

        CallListPanel callListPanel = (CallListPanel) selectedPanel;

        GuiCallParticipantRecord callRecord =
            (GuiCallParticipantRecord) callListPanel.getCallList().getSelectedValue();

        String stringContact = callRecord.getParticipantName();

        createCall(stringContact);
      }
      // call button is pressed over the contact list
      else if (selectedPanel != null && selectedPanel instanceof ContactListPanel) {
        // call button is pressed when a meta contact is selected
        if (isCallMetaContact) {
          Object[] selectedContacts =
              mainFrame.getContactListPanel().getContactList().getSelectedValues();

          Vector telephonyContacts = new Vector();

          for (int i = 0; i < selectedContacts.length; i++) {

            Object o = selectedContacts[i];

            if (o instanceof MetaContact) {

              Contact contact =
                  ((MetaContact) o).getDefaultContact(OperationSetBasicTelephony.class);

              if (contact != null) telephonyContacts.add(contact);
              else {
                new ErrorDialog(
                        this.mainFrame,
                        Messages.getI18NString("warning").getText(),
                        Messages.getI18NString(
                                "contactNotSupportingTelephony",
                                new String[] {((MetaContact) o).getDisplayName()})
                            .getText())
                    .showDialog();
              }
            }
          }

          if (telephonyContacts.size() > 0) createCall(telephonyContacts);

        } else if (!phoneNumberCombo.isComboFieldEmpty()) {

          // if no contact is selected checks if the user has chosen
          // or has
          // writen something in the phone combo box

          String stringContact = phoneNumberCombo.getEditor().getItem().toString();

          createCall(stringContact);
        }
      } else if (selectedPanel != null && selectedPanel instanceof DialPanel) {
        String stringContact = phoneNumberCombo.getEditor().getItem().toString();
        createCall(stringContact);
      }
    } else if (buttonName.equalsIgnoreCase("hangup")) {
      Component selectedPanel = this.mainFrame.getSelectedTab();

      if (selectedPanel != null && selectedPanel instanceof CallPanel) {

        NotificationManager.stopSound(NotificationManager.BUSY_CALL);
        NotificationManager.stopSound(NotificationManager.INCOMING_CALL);
        NotificationManager.stopSound(NotificationManager.OUTGOING_CALL);

        CallPanel callPanel = (CallPanel) selectedPanel;

        Call call = callPanel.getCall();

        if (removeCallTimers.containsKey(callPanel)) {
          ((Timer) removeCallTimers.get(callPanel)).stop();
          removeCallTimers.remove(callPanel);
        }

        removeCallPanel(callPanel);

        if (call != null) {
          ProtocolProviderService pps = call.getProtocolProvider();

          OperationSetBasicTelephony telephony = mainFrame.getTelephonyOpSet(pps);

          Iterator participants = call.getCallParticipants();

          while (participants.hasNext()) {
            try {
              // now we hang up the first call participant in the
              // call
              telephony.hangupCallParticipant((CallParticipant) participants.next());
            } catch (OperationFailedException e) {
              logger.error("Hang up was not successful: " + e);
            }
          }
        }
      }
    } else if (buttonName.equalsIgnoreCase("minimize")) {
      JCheckBoxMenuItem hideCallPanelItem =
          mainFrame.getMainMenu().getViewMenu().getHideCallPanelItem();

      if (!hideCallPanelItem.isSelected()) hideCallPanelItem.setSelected(true);

      this.setCallPanelVisible(false);
    } else if (buttonName.equalsIgnoreCase("restore")) {

      JCheckBoxMenuItem hideCallPanelItem =
          mainFrame.getMainMenu().getViewMenu().getHideCallPanelItem();

      if (hideCallPanelItem.isSelected()) hideCallPanelItem.setSelected(false);

      this.setCallPanelVisible(true);
    }
  }