Skip to content

Commit

Permalink
ScreenSharing Demo added
Browse files Browse the repository at this point in the history
  • Loading branch information
VladimirBrejcha committed Jul 2, 2020
1 parent faa991b commit f4e966b
Show file tree
Hide file tree
Showing 55 changed files with 2,868 additions and 564 deletions.
129 changes: 60 additions & 69 deletions Conference/Stories/ConferenceCall/ConferenceCallViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,21 +27,75 @@ final class ConferenceCallViewController: UIViewController, AudioDeviceSelecting
super.viewDidLoad()

muteButton.state = .initial(model: CallOptionButtonModels.mute)
muteButton.touchUpHandler = muteHandler(_:)
muteButton.touchUpHandler = { [weak self] button in
guard let self = self else { return }
do {
try self.manageConference.mute(!self.muted)
self.muted.toggle()
button.state = self.muted ? .selected : .normal
} catch (let error) {
AlertHelper.showError(message: error.localizedDescription, on: self)
}
}

chooseAudioButton.state = .initial(model: CallOptionButtonModels.chooseAudio)
chooseAudioButton.touchUpHandler = chooseAudioHandler(_:)
chooseAudioButton.touchUpHandler = { [weak self] button in
self?.showAudioDevicesActionSheet(sourceView: button)
}

switchCameraButton.state = .initial(model: CallOptionButtonModels.switchCamera)
switchCameraButton.touchUpHandler = switchCameraHandler(_:)
switchCameraButton.touchUpHandler = { [weak self] _ in
self?.manageConference.switchCamera()
}

videoButton.state = .initial(model: CallOptionButtonModels.video)
videoButton.touchUpHandler = videoHandler(_:)
videoButton.touchUpHandler = { [weak self] button in
guard let self = self else { return }
let previousState = button.state
button.state = .unavailable
self.manageConference.sendVideo(!self.video) { [weak self] error in
guard let self = self else { return }
if let error = error {
AlertHelper.showError(message: error.localizedDescription, on: self)
button.state = previousState
} else {
self.video.toggle()
self.conferenceView.hideVideoRenderer(!self.video, for: myId)
button.state = self.video ? .normal : .selected
}
}
}

exitButton.state = .initial(model: CallOptionButtonModels.exit)
exitButton.touchUpHandler = exitHandler(_:)
exitButton.touchUpHandler = { [weak self] button in
guard let self = self else { return }
button.state = .unavailable
self.leftConference = true
self.leaveConference.execute { error in
if let error = error {
AlertHelper.showError(message: error.localizedDescription, on: self)
self.leftConference = false
button.state = .normal
} else {
self.dismiss(animated: true)
}
}
}

manageConference.conferenceDisconnectedHandler = disconnectedHandler(error:)
manageConference.conferenceDisconnectedHandler = { [weak self] error in
guard let self = self, !self.leftConference else { return }
self.leaveConference.execute { error in
if let error = error {
print("Got an error while leaving conference - \(error.localizedDescription)")
}
}
AlertHelper.showAlert(
title: "Disconnected",
message: "You've been disconnected \(error != nil ? error!.localizedDescription : "")",
actions: [UIAlertAction(title: "Close", style: .default) { _ in self.dismiss(animated: true) }],
on: self
)
}

manageConference.userAddedHandler = conferenceView.addParticipant(withID:displayName:)
manageConference.userUpdatedHandler = conferenceView.updateParticipant(withID:displayName:)
Expand All @@ -54,69 +108,6 @@ final class ConferenceCallViewController: UIViewController, AudioDeviceSelecting
conferenceView.updateParticipant(withID: myId, displayName: "\(name ?? "") (you)")
}

private func disconnectedHandler(error: Error?) {
if (self.leftConference) { return }
leaveConference.execute { error in
if let error = error {
print("Got an error while leaving conference - \(error.localizedDescription)")
}
}
AlertHelper.showAlert(
title: "Disconnected",
message: "You've been disconnected \(error != nil ? error!.localizedDescription : "")",
actions: [UIAlertAction(title: "Close", style: .default) { _ in self.dismiss(animated: true) }],
on: self
)
}

private func muteHandler(_ button: CallOptionButton) {
do {
try manageConference.mute(!muted)
muted.toggle()
button.state = muted ? .selected : .normal
} catch (let error) {
AlertHelper.showError(message: error.localizedDescription, on: self)
}
}

private func chooseAudioHandler(_ button: CallOptionButton) {
showAudioDevicesActionSheet(sourceView: button)
}

private func switchCameraHandler(_ button: CallOptionButton) {
manageConference.switchCamera()
}

private func videoHandler(_ button: CallOptionButton) {
let previousState = button.state
button.state = .unavailable
manageConference.sendVideo(!video) { [weak self] error in
guard let self = self else { return }
if let error = error {
AlertHelper.showError(message: error.localizedDescription, on: self)
button.state = previousState
} else {
self.video.toggle()
self.conferenceView.hideVideoRenderer(!self.video, for: myId)
button.state = self.video ? .normal : .selected
}
}
}

private func exitHandler(_ button: CallOptionButton) {
button.state = .unavailable
leftConference = true
leaveConference.execute { error in
if let error = error {
AlertHelper.showError(message: error.localizedDescription, on: self)
self.leftConference = false
button.state = .normal
} else {
self.dismiss(animated: true)
}
}
}

private func makeFormattedString(from device: VIAudioDevice, isCurrent: Bool) -> String {
let formattedString = String(describing: device).replacingOccurrences(of: "VIAudioDevice", with: "")
return isCurrent ? "\(formattedString) (Current)" : formattedString
Expand Down
52 changes: 52 additions & 0 deletions InAppScreenSharing/AppDelegate.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
* Copyright (c) 2011-2020, Zingaya, Inc. All rights reserved.
*/

import UIKit
import VoxImplantSDK

fileprivate let client: VIClient = VIClient(delegateQueue: DispatchQueue.main)
fileprivate let authService: AuthService = AuthService(client)
fileprivate let callManager: CallManager = CallManager(client, authService)
fileprivate let storyAssembler: StoryAssembler = StoryAssembler(authService: authService, callManager: callManager)

@UIApplicationMain
final class AppDelegate: UIResponder, UIApplicationDelegate, Loggable {
var window: UIWindow?
var appName: String { "InAppScreenSharing" }

override init() {
super.init()

configureDefaultLogging()
}

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
UIApplication.shared.isIdleTimerDisabled = true

window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = storyAssembler.login
window?.makeKeyAndVisible()

return true
}

// MARK: - AppLifeCycleDelegate -
func applicationWillResignActive(_ application: UIApplication) {
(window?.rootViewController?.toppestViewController as? AppLifeCycleDelegate)?.applicationWillResignActive(application)
UIApplication.shared.isIdleTimerDisabled = false
}

func applicationDidEnterBackground(_ application: UIApplication) {
(window?.rootViewController?.toppestViewController as? AppLifeCycleDelegate)?.applicationDidEnterBackground(application)
}

func applicationWillEnterForeground(_ application: UIApplication) {
(window?.rootViewController?.toppestViewController as? AppLifeCycleDelegate)?.applicationWillEnterForeground(application)
}

func applicationDidBecomeActive(_ application: UIApplication) {
(window?.rootViewController?.toppestViewController as? AppLifeCycleDelegate)?.applicationDidBecomeActive(application)
}
}

99 changes: 99 additions & 0 deletions InAppScreenSharing/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
# Voximplant InApp Screen Sharing Demo (iOS)

This demo demonstrates basic in-app screen sharing functionality of the Voximplant iOS SDK. The application supports video calls between this iOS app and other apps that use any Voximplant SDK.

#### Features
The application is able to:
- log in to the Voximplant Cloud
- auto login using access tokens
- make an video call
- receive an incoming call
- switch camera during a call
- enable/disable video during a call
- enable/disable screen sharing during a call
- auto reconnect/relogin


## Getting started

To get started, you'll need to [register](https://voximplant.com) a free Voximplant developer account.

You'll need the following:
- Voximplant application
- two Voximplant users
- VoxEngine scenario
- routing setup
- VoIP services certificate for push notifications. Follow [this tutorial](https://voximplant.com/docs/references/iossdk/push-notifications-for-ios) to upload the certificate to the Voximplant Control Panel

### Automatic
We've implemented a special template to enable you to quickly use the demo – just
install [SDK tutorial](https://manage.voximplant.com/marketplace/sdk_tutorial) from our marketplace:
![marketplace](Screenshots/market.png)

### Manual

You can set up it manually using our [quickstart guide](https://voximplant.com/docs/references/articles/quickstart) and tutorials

#### VoxEngine scenario example:
```
require(Modules.PushService);
VoxEngine.addEventListener(AppEvents.CallAlerting, (e) => {
const newCall = VoxEngine.callUserDirect(
e.call,
e.destination,
e.callerid,
e.displayName,
null
);
VoxEngine.easyProcess(e.call, newCall, ()=>{}, true);
});
```

## Installing

1. Clone this repo

1. Run `$ pod install` in the repo folder

1. Open the `Swift.xcworkspace` workspace

1. Target InAppScreenSharing and build the project using Xcode

## Usage

### User login
![login](Screenshots/login.png)

Log in using:
* Voximplant user name in the format `[email protected]`
* password

See the following classes for code details:
* [AuthService.swift](Services/AuthService.swift)
* [LoginViewController.swift](Stories/Login/LoginViewController.swift)

### Make or receive calls
![call](Screenshots/call.png)

Enter a Voximplant user name to the input field and press "Call" button to make a call.

See the following classes for code details:
- [CallManager.swift](Services/CallManager.swift)
- [MainViewController.swift](Stories/Main/MainViewController.swift)
- [IncomingCallViewController.swift](Stories/Main/IncomingCallViewController.swift)

### Call controls
![inCall](Screenshots/inCall.png)

Enable/disable video or screen sharing during a call.

See the following classes for code details:
- [CallViewController.swift](Stories/Call/CallViewController.swift)
* [CallManager.swift](Services/CallManager.swift)


## Useful links
1. [Getting started](https://voximplant.com/docs/introduction)
2. [Voximplant iOS SDK reference](https://voximplant.com/docs/references/iossdk)
3. [Installing the Voximplant iOS SDK](https://voximplant.com/docs/introduction/integration/adding_sdks/installing/ios_sdk)
4. [HowTo's](https://voximplant.com/docs/howtos)
60 changes: 60 additions & 0 deletions InAppScreenSharing/Resources/Info.plist
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>NSCameraUsageDescription</key>
<string>Camera is needed for video calls</string>
<key>NSMicrophoneUsageDescription</key>
<string>Microphone is needed for calls</string>
<key>UIBackgroundModes</key>
<array>
<string>audio</string>
</array>
<key>UILaunchStoryboardName</key>
<string>LaunchScreen</string>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIRequiresFullScreen</key>
<false/>
<key>UIStatusBarStyle</key>
<string>UIStatusBarStyleLightContent</string>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeRight</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UIViewControllerBasedStatusBarAppearance</key>
<false/>
</dict>
</plist>
Binary file added InAppScreenSharing/Screenshots/call.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added InAppScreenSharing/Screenshots/inCall.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added InAppScreenSharing/Screenshots/login.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
File renamed without changes
Loading

0 comments on commit f4e966b

Please sign in to comment.