Commit fbe1b2f8 authored by Kateryna Kostiuk's avatar Kateryna Kostiuk

conversation: send video/message

For now message could not be recorded during call.

Change-Id: If1d0e4755beeb0b9c215c618de03d15d85ddf8c2
parent b7f88b45
......@@ -176,6 +176,8 @@ SET(ringclient_CONTROLLERS
src/AccountSettingsVC.h
src/LeaveMessageVC.mm
src/LeaveMessageVC.h
src/RecordFileVC.mm
src/RecordFileVC.h
)
SET(ringclient_VIEWS
......@@ -274,6 +276,7 @@ SET(ringclient_XIBS
AddSIPAccountVC
AccountSettings
LeaveMessageVC
RecordFileVC
)
# Icons
......@@ -331,6 +334,7 @@ ${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_action_video.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/pending_contact_request.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_file_upload.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_record_stop.png
${CMAKE_CURRENT_SOURCE_DIR}/data/dark/ic_camera.png
${CMAKE_CURRENT_SOURCE_DIR}/data/light/ic_picture.png)
SET_SOURCE_FILES_PROPERTIES(${ring_ICONS} PROPERTIES
......
data/dark/ic_audio_file.png

756 Bytes | W: | H:

data/dark/ic_audio_file.png

1.11 KB | W: | H:

data/dark/ic_audio_file.png
data/dark/ic_audio_file.png
data/dark/ic_audio_file.png
data/dark/ic_audio_file.png
  • 2-up
  • Swipe
  • Onion skin
......@@ -37,7 +37,6 @@
#import "RingWindowController.h"
#import "NSString+Extensions.h"
#import "LeaveMessageVC.h"
#import "LeaveMessageVC.h"
@interface ConversationVC () <QLPreviewPanelDataSource, QLPreviewPanelDelegate>{
......@@ -85,6 +84,7 @@ NSInteger const SEND_PANEL_MAX_HEIGHT = 120;
[leaveMessageVC setAVModel: avModel];
leaveMessageConversations = [[NSMutableArray alloc] init];
leaveMessageVC.delegate = self;
[messagesViewVC setAVModel: avModel];
}
return self;
}
......@@ -212,6 +212,7 @@ NSInteger const SEND_PANEL_MAX_HEIGHT = 120;
- (IBAction)backPressed:(id)sender {
[delegate rightPanelClosed];
[self hideWithAnimation:false];
[messagesViewVC clearData];
}
# pragma mark private IN/OUT animations
......
......@@ -52,18 +52,6 @@ extern "C" {
#import "views/GradientView.h"
#import "views/MovableView.h"
@interface RendererConnectionsHolder : NSObject
@property QMetaObject::Connection frameUpdated;
@property QMetaObject::Connection started;
@property QMetaObject::Connection stopped;
@end
@implementation RendererConnectionsHolder
@end
@interface CurrentCallVC () <NSPopoverDelegate> {
std::string convUid_;
std::string callUid_;
......
......@@ -20,6 +20,7 @@
#import "LeaveMessageVC.h"
#import "views/NSColor+RingTheme.h"
#import "utils.h"
#import "NSString+Extensions.h"
//lrc
#import <api/avmodel.h>
......@@ -51,7 +52,6 @@ bool isRecording = false;
int recordingTime = 0;
NSTimer* refreshDurationTimer;
lrc::api::AVModel* avModel;
std::string fileName;
NSMutableDictionary *filesToSend;
std::string conversationUid;
lrc::api::ConversationModel* conversationModel;
......@@ -103,7 +103,7 @@ lrc::api::ConversationModel* conversationModel;
refreshDurationTimer = nil;
[timerBox setHidden:YES];
[sendBox setHidden: NO];
[sendFilename setStringValue:[self timeFormatted: recordingTime]];
[sendFilename setStringValue:[NSString formattedStringTimeFromSeconds: recordingTime]];
}
}
......@@ -127,7 +127,7 @@ lrc::api::ConversationModel* conversationModel;
- (void)clearData {
recordButton.image = [NSImage imageNamed:@"ic_action_audio.png"];
recordingTime = 0;
[timerLabel setStringValue: [self timeFormatted: recordingTime]];
[timerLabel setStringValue: [NSString formattedStringTimeFromSeconds: recordingTime]];
isRecording = false;
[timerBox setHidden:YES];
[sendBox setHidden: YES];
......@@ -140,14 +140,14 @@ lrc::api::ConversationModel* conversationModel;
- (void)viewWillHide {
recordButton.image = [NSImage imageNamed:@"ic_action_audio.png"];
if(filesToSend[@(conversationUid.c_str())]) {
[sendFilename setStringValue:[self timeFormatted: recordingTime]];
[sendFilename setStringValue:[NSString formattedStringTimeFromSeconds: recordingTime]];
[sendBox setHidden: NO];
} else {
[sendFilename setStringValue:@""];
[sendBox setHidden: YES];
}
recordingTime = 0;
[timerLabel setStringValue: [self timeFormatted: recordingTime]];
[timerLabel setStringValue: [NSString formattedStringTimeFromSeconds: recordingTime]];
isRecording = false;
[timerBox setHidden:YES];
[refreshDurationTimer invalidate];
......@@ -190,14 +190,7 @@ lrc::api::ConversationModel* conversationModel;
-(void) updateDurationLabel
{
recordingTime++;
[timerLabel setStringValue: [self timeFormatted: recordingTime]];
}
- (NSString *)timeFormatted:(int)totalSeconds
{
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
return [NSString stringWithFormat:@"%02d:%02d",minutes, seconds];
[timerLabel setStringValue: [NSString formattedStringTimeFromSeconds: recordingTime]];
}
@end
......@@ -20,8 +20,11 @@
#import <Cocoa/Cocoa.h>
#import <api/conversationmodel.h>
#import <api/conversation.h>
#import <api/avmodel.h>
#import "RecordFileVC.h"
@interface MessagesVC : NSViewController
@interface MessagesVC : NSViewController <RecordingViewDelegate>
-(void)setConversationUid:(const std::string)convUid model:(lrc::api::ConversationModel*)model;
-(void)clearData;
......@@ -33,4 +36,6 @@
*/
@property (retain) NSString* message;
-(void) setAVModel: (lrc::api::AVModel*) avmodel;
@end
......@@ -36,6 +36,9 @@
#import "views/IconButton.h"
#import <QuickLook/QuickLook.h>
#import <Quartz/Quartz.h>
#import <AVFoundation/AVFoundation.h>
#import "RecordFileVC.h"
@interface MessagesVC () <NSTableViewDelegate, NSTableViewDataSource, QLPreviewPanelDataSource> {
......@@ -44,12 +47,16 @@
__unsafe_unretained IBOutlet NSView* containerView;
__unsafe_unretained IBOutlet NSTextField* messageField;
__unsafe_unretained IBOutlet IconButton *sendFileButton;
__unsafe_unretained IBOutlet IconButton *recordVideoButton;
__unsafe_unretained IBOutlet IconButton *recordAudioButton;
__unsafe_unretained IBOutlet NSLayoutConstraint* sendPanelHeight;
__unsafe_unretained IBOutlet NSLayoutConstraint* messagesBottomMargin;
IBOutlet NSPopover *recordMessagePopover;
std::string convUid_;
lrc::api::ConversationModel* convModel_;
const lrc::api::conversation::Info* cachedConv_;
lrc::api::AVModel* avModel;
QMetaObject::Connection newInteractionSignal_;
// Both are needed to invalidate cached conversation as pointer
......@@ -59,9 +66,9 @@
QMetaObject::Connection interactionStatusUpdatedSignal_;
NSString* previewImage;
NSMutableDictionary *pendingMessagesToSend;
RecordFileVC * recordingController;
}
@end
// Tags for view
......@@ -113,6 +120,14 @@ typedef NS_ENUM(NSInteger, MessageSequencing) {
return self;
}
-(void) setAVModel: (lrc::api::AVModel*) avmodel {
avModel = avmodel;
if (recordingController == nil) {
recordingController = [[RecordFileVC alloc] initWithNibName:@"RecordFileVC" bundle:nil avModel: self->avModel];
recordingController.delegate = self;
}
}
- (void)setMessage:(NSString *)newValue {
_message = [newValue removeEmptyLinesAtBorders];
}
......@@ -129,6 +144,7 @@ typedef NS_ENUM(NSInteger, MessageSequencing) {
QObject::disconnect(filterChangedSignal_);
QObject::disconnect(interactionStatusUpdatedSignal_);
QObject::disconnect(newInteractionSignal_);
[self closeRecordingView];
}
-(void) scrollToBottom {
......@@ -921,6 +937,48 @@ typedef NS_ENUM(NSInteger, MessageSequencing) {
[NSApp orderFrontCharacterPalette: messageField];
}
- (IBAction)startVideoMessage:(id)sender
{
[self startRecording:NO];
}
- (IBAction)startAudioMessage:(id)sender
{
[self startRecording:YES];
}
-(void) startRecording:(BOOL)isAudio {
if (recordingController == nil) {
recordingController = [[RecordFileVC alloc] initWithNibName:@"RecordFileVC" bundle:nil avModel: self->avModel];
recordingController.delegate = self;
}
if(recordMessagePopover != nil)
{
[self closeRecordingView];
return;
}
recordMessagePopover = [[NSPopover alloc] init];
[recordingController prepareRecordingView: isAudio];
[recordMessagePopover setContentSize: recordingController.view.frame.size];
[recordMessagePopover setContentViewController:recordingController];
[recordMessagePopover setAnimates:YES];
NSButton *anchorButton = isAudio ? recordAudioButton : recordVideoButton;
[recordMessagePopover showRelativeToRect: anchorButton.bounds
ofView: anchorButton
preferredEdge: NSMaxYEdge];
}
-(void) sendFile:(NSString *) name withFilePath:(NSString *) path {
convModel_->sendFile(convUid_, [path UTF8String], [name UTF8String]);
}
-(void) closeRecordingView {
if(recordMessagePopover != nil) {
recordingController.stopRecordingView;
[recordMessagePopover close];
recordMessagePopover = nil;
}
}
- (IBAction)sendFile:(id)sender {
NSOpenPanel* filePicker = [NSOpenPanel openPanel];
[filePicker setCanChooseFiles:YES];
......
......@@ -23,5 +23,6 @@
- (NSString *) removeAllNewLinesAtTheEnd;
- (NSString *) removeEmptyLinesAtBorders;
+ (NSString *) formattedStringTimeFromSeconds:(int) totalSeconds;
@end
......@@ -74,4 +74,10 @@
return self;
}
+ (NSString *) formattedStringTimeFromSeconds:(int) totalSeconds {
int seconds = totalSeconds % 60;
int minutes = (totalSeconds / 60) % 60;
return [NSString stringWithFormat:@"%02d:%02d",minutes, seconds];
}
@end
/*
* Copyright (C) 2019 Savoir-faire Linux Inc.
* Author: Kateryna Kostiuk <kateryna.kostiuk@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>
#import "LrcModelsProtocol.h"
@protocol RecordingViewDelegate <NSObject>
-(void) closeRecordingView;
-(void) sendFile:(NSString *) name withFilePath:(NSString *) path;
@end
@interface RecordFileVC : NSViewController <LrcModelsProtocol>
@property (retain, nonatomic) id <RecordingViewDelegate> delegate;
-(void) prepareRecordingView:(BOOL)audioOnly;
-(void) stopRecordingView;
@end
This diff is collapsed.
......@@ -19,9 +19,18 @@
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#import <video/renderer.h>
struct AVFrame;
@interface RendererConnectionsHolder : NSObject
@property QMetaObject::Connection frameUpdated;
@property QMetaObject::Connection started;
@property QMetaObject::Connection stopped;
@end
@interface VideoCommon : NSObject
+ (void)copyLineByLineSrc:(uint8_t*)src
......@@ -32,6 +41,10 @@ struct AVFrame;
+ (void) fillPixelBuffr:(CVPixelBufferRef *)pixelBuffer
fromFrame:(const AVFrame*)frame
bufferPool:(CVPixelBufferPoolRef *)pixelBufferPool;
+ (CGSize) fillPixelBuffr:(CVPixelBufferRef *)pixelBuffer
fromRenderer:(const lrc::api::video::Renderer*)renderer
bufferPool:(CVPixelBufferPoolRef *)pixelBufferPool;
@end
......@@ -19,10 +19,18 @@
#import "VideoCommon.h"
#import <video/renderer.h>
#import <QSize>
extern "C" {
#import <libavutil/frame.h>
}
@implementation RendererConnectionsHolder
@end
@implementation VideoCommon
+ (void)copyLineByLineSrc:(uint8_t*)src
......@@ -120,4 +128,22 @@ extern "C" {
}
CVPixelBufferUnlockBaseAddress(pixelBuffer, 0);
}
+ (CGSize) fillPixelBuffr:(CVPixelBufferRef &)pixelBuffer
fromRenderer:(const lrc::api::video::Renderer*)renderer
bufferPool:(CVPixelBufferPoolRef &)pixelBufferPool{
auto framePtr = renderer->currentAVFrame();
auto frame = framePtr.get();
if(!frame || !frame->width || !frame->height) {
return CGSizeZero;
}
auto frameSize = CGSizeMake(frame->width, frame->height);
if (frame->data[3] != NULL && (CVPixelBufferRef)frame->data[3]) {
pixelBuffer = (CVPixelBufferRef)frame->data[3];
return frameSize;
}
[VideoCommon fillPixelBuffr:&pixelBuffer fromFrame:frame bufferPool:&pixelBufferPool];
return frameSize;
}
@end
This diff is collapsed.
......@@ -201,3 +201,18 @@
/* Backup enter password */
"Enter account password" = "Enter account password";
/* Error audio permission */
"Audio permission not granted" = "Audio permission not granted";
/* Error video permission */
"Video permission not granted" = "Video permission not granted";
/* Send button title */
"Send" = "Send";
/* Recording view explanation label */
"Press to start recording" = "Press to start recording";
/* Recording view explanation label */
"Could not record message during call" = "Could not record message during call";
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