Commit 6200531f authored by Alexandre Lision's avatar Alexandre Lision

call: add dialpad access

This commit adds the ability to dial dtmf tones during a call.
It is necessary for interacting with automated services.
RTP dtmf are not working in the daemon, so during SIP account creation
we switch to SIP dtmf.

Tuleap: #154
Change-Id: I9d6758af4bc0b44605dc4b17c08b9b4ceaee84bd
parent fcb4ca63
......@@ -152,6 +152,8 @@ SET(ringclient_CONTROLLERS
src/RingWizardLinkAccountVC.mm
src/RingWizardNewAccountVC.mm
src/RingWizardNewAccountVC.h
src/DialpadWC.mm
src/DialpadWC.h
)
SET(ringclient_BACKENDS
......@@ -216,7 +218,9 @@ SET(ringclient_XIBS
AccDevices
RingWizardLinkAccount
RingWizardNewAccount
RingWizardChoose)
RingWizardChoose
Dialpad
)
# Icons
# This part tells CMake where to find and install the file itself
......@@ -228,6 +232,8 @@ SET(ring_ICONS
${CMAKE_CURRENT_SOURCE_DIR}/data/symbol_name.png
${CMAKE_CURRENT_SOURCE_DIR}/data/symbol_blue.png
${CMAKE_CURRENT_SOURCE_DIR}/data/background_tile.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_more.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_dialpad.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_accept.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_arrow_back.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_call.png
......@@ -248,7 +254,6 @@ ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_transfer.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_add_participant.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_merge_calls.png
${CMAKE_CURRENT_SOURCE_DIR}/data/default_user_icon.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ancrage.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_send.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/audio.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_person_add.png
......
......@@ -175,6 +175,7 @@ NSInteger const TAG_TYPE = 400;
AccountModel::instance().protocolModel()->data(qIdx, Qt::DisplayRole).toString().toNSString(), nil];
auto acc = AccountModel::instance().add([newAccName UTF8String], qIdx);
acc->setDisplayName(acc->alias());
acc->setDTMFType(DtmfType::OverSip);
AccountModel::instance().save();
}
......
......@@ -26,6 +26,7 @@
- (void) showWizard;
- (void) showMainWindow;
- (void) showDialpad;
- (BOOL) checkForRingAccount;
@end
......@@ -35,6 +35,7 @@
#import "Constants.h"
#import "RingWizardWC.h"
#import "DialpadWC.h"
#if ENABLE_SPARKLE
@interface AppDelegate() <SUUpdaterDelegate>
......@@ -44,6 +45,7 @@
@property RingWindowController* ringWindowController;
@property RingWizardWC* wizard;
@property DialpadWC* dialpad;
@property (nonatomic, strong) dispatch_queue_t scNetworkQueue;
@property (nonatomic, assign) SCNetworkReachabilityRef currentReachability;
......@@ -198,13 +200,6 @@ static void ReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNet
}
}
/**
* click in MainMenu "Setup Ring"
*/
- (IBAction)showWizard:(id)sender {
[self showWizard];
}
- (void) showWizard
{
if(self.wizard == nil) {
......@@ -221,6 +216,15 @@ static void ReachabilityCallback(SCNetworkReachabilityRef __unused target, SCNet
[self.ringWindowController.window makeKeyAndOrderFront:self];
}
- (void) showDialpad
{
if (self.dialpad == nil) {
self.dialpad = [[DialpadWC alloc] initWithWindowNibName:@"Dialpad"];
}
[self.dialpad.window makeKeyAndOrderFront:self];
}
- (BOOL) checkForRingAccount
{
BOOL foundRingAcc = NO;
......
......@@ -40,6 +40,7 @@
#import <person.h>
#import <globalinstances.h>
#import "AppDelegate.h"
#import "views/ITProgressIndicator.h"
#import "views/CallView.h"
#import "delegates/ImageManipulationDelegate.h"
......@@ -74,6 +75,7 @@
// Call Controls
@property (unsafe_unretained) IBOutlet NSView* controlsPanel;
@property QHash<int, IconButton*> actionHash;
@property (unsafe_unretained) IBOutlet IconButton* holdOnOffButton;
@property (unsafe_unretained) IBOutlet IconButton* hangUpButton;
......@@ -86,6 +88,9 @@
@property (unsafe_unretained) IBOutlet IconButton* addParticipantButton;
@property (unsafe_unretained) IBOutlet IconButton* chatButton;
@property (unsafe_unretained) IBOutlet NSView* advancedPanel;
@property (unsafe_unretained) IBOutlet IconButton* advancedButton;
// Join call panel
@property (unsafe_unretained) IBOutlet NSView* joinPanel;
......@@ -120,7 +125,7 @@
@implementation CurrentCallVC
@synthesize personLabel, personPhoto, actionHash, stateLabel, holdOnOffButton, hangUpButton,
recordOnOffButton, pickUpButton, chatButton, transferButton, addParticipantButton, timeSpentLabel,
muteVideoButton, muteAudioButton, controlsPanel, headerContainer, videoView, incomingDisplayName, incomingPersonPhoto,
muteVideoButton, muteAudioButton, controlsPanel, advancedPanel, advancedButton, headerContainer, videoView, incomingDisplayName, incomingPersonPhoto,
previewView, splitView, loadingIndicator, ringingPanel, joinPanel, outgoingPanel;
@synthesize previewHolder;
......@@ -551,6 +556,9 @@
[timeSpentLabel setStringValue:@""];
[stateLabel setStringValue:@""];
[self.addContactButton setHidden:YES];
[advancedButton setPressed:NO];
[advancedPanel setHidden:YES];
}
-(void) animateOut
......@@ -661,6 +669,16 @@
CallModel::instance().getCall(CallModel::instance().selectionModel()->currentIndex()) << Call::Action::HOLD;
}
- (IBAction)toggleAdvancedControls:(id)sender {
[advancedButton setPressed:!advancedButton.isPressed];
[advancedPanel setHidden:![advancedButton isPressed]];
}
- (IBAction)showDialpad:(id)sender {
AppDelegate* appDelegate = (AppDelegate *)[[NSApplication sharedApplication] delegate];
[appDelegate showDialpad];
}
-(IBAction)toggleChat:(id)sender;
{
BOOL rightViewCollapsed = [[self splitView] isSubviewCollapsed:[[[self splitView] subviews] objectAtIndex: 1]];
......@@ -670,7 +688,7 @@
} else {
[self collapseRightView];
}
[chatButton setState:rightViewCollapsed];
[chatButton setPressed:rightViewCollapsed];
}
- (IBAction)muteAudio:(id)sender
......@@ -689,7 +707,7 @@
if (_brokerPopoverVC != nullptr) {
[_brokerPopoverVC performClose:self];
_brokerPopoverVC = NULL;
[self.transferButton setState:NSOffState];
[self.transferButton setPressed:NO];
} else {
auto* brokerVC = [[BrokerVC alloc] initWithMode:BrokerMode::TRANSFER];
_brokerPopoverVC = [[NSPopover alloc] init];
......@@ -707,7 +725,7 @@
if (_brokerPopoverVC != nullptr) {
[_brokerPopoverVC performClose:self];
_brokerPopoverVC = NULL;
[self.addParticipantButton setState:NSOffState];
[self.addParticipantButton setPressed:NO];
} else {
auto* brokerVC = [[BrokerVC alloc] initWithMode:BrokerMode::CONFERENCE];
_brokerPopoverVC = [[NSPopover alloc] init];
......@@ -744,8 +762,8 @@
self.addToContactPopover = NULL;
}
[self.addContactButton setState:NSOffState];
[self.transferButton setState:NSOffState];
[self.addContactButton setPressed:NO];
[self.transferButton setPressed:NO];
[self.addParticipantButton setState:NSOffState];
}
......
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import <Cocoa/Cocoa.h>
@interface DialpadWC : NSWindowController <NSWindowDelegate>
@end
/*
* Copyright (C) 2016 Savoir-faire Linux Inc.
* Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#import "DialpadWC.h"
///Qt
#import <QtCore/qitemselectionmodel.h>
///LRC
#import <callmodel.h>
@interface DialpadWC ()
@property (unsafe_unretained) IBOutlet NSTextField* composerField;
@end
@implementation DialpadWC
@synthesize composerField;
- (void)windowDidLoad {
[super windowDidLoad];
QObject::connect(CallModel::instance().selectionModel(),
&QItemSelectionModel::currentChanged,
[=](const QModelIndex &current, const QModelIndex &previous) {
[composerField setStringValue:@""];
[composerField setNeedsDisplay:YES];
if(!current.isValid()) {
[self.window close];
}
});
}
- (IBAction)dtmfPressed:(id)sender
{
[self sendDTMF:[sender title]];
}
- (void) keyDown:(NSEvent *)theEvent
{
NSString* characters = [theEvent characters];
if ([characters length] == 1) {
NSString* filter = @"0123456789*#";
if ([filter containsString:characters]) {
[self sendDTMF:characters];
}
}
}
- (void) sendDTMF:(NSString*) dtmf
{
if (auto current = CallModel::instance().selectedCall()) {
current->playDTMF(QString::fromUtf8([dtmf UTF8String]));
}
[composerField setStringValue:
[NSString stringWithFormat: @"%@ %@", [composerField stringValue], dtmf]];
}
///Accessibility
- (void)insertTab:(id)sender
{
if ([[self window] firstResponder] == self) {
[[self window] selectNextKeyView:self];
}
}
- (void)insertBacktab:(id)sender
{
if ([[self window] firstResponder] == self) {
[[self window] selectPreviousKeyView:self];
}
}
- (void) windowWillClose:(NSNotification *)notification
{
[composerField setStringValue:@""];
[composerField setNeedsDisplay:YES];
}
@end
......@@ -96,7 +96,7 @@
NSBezierPath* path = [NSBezierPath bezierPathWithRect:dirtyRect];
[path addClip];
[self setImagePosition:NSImageOnly];
[self setImagePosition:NSImageOverlaps];
auto rect = NSInsetRect(dirtyRect, self.imageInsets, self.imageInsets);
[[NSColor image:self.image tintedWithColor:tintColor] drawInRect:rect
......@@ -107,6 +107,23 @@
hints:nil];
[NSGraphicsContext restoreGraphicsState];
NSRect rect2;
NSDictionary *att = nil;
NSMutableParagraphStyle *style =
[[NSParagraphStyle defaultParagraphStyle] mutableCopy];
[style setLineBreakMode:NSLineBreakByWordWrapping];
[style setAlignment:NSCenterTextAlignment];
att = [[NSDictionary alloc] initWithObjectsAndKeys:
style, NSParagraphStyleAttributeName,
[NSColor whiteColor],
NSForegroundColorAttributeName, nil];
rect.size = [[self title] sizeWithAttributes:att];
rect.origin.x = floor( NSMidX([self bounds]) - rect.size.width / 2 );
rect.origin.y = floor( NSMidY([self bounds]) - rect.size.height / 2 );
[[self title] drawInRect:rect withAttributes:att];
}
}
......
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment