Building the Open-Source Conferencing App for iOS
Gone through the Quick Start with Mesibo Conferencing API - iOS and have a basic familiarity with mesibo conferencing APIs..
XCode Installed
An iPhone Device to run the app
Build Instructions
Building the code is as simple as:
- Launch Xcode
- Open the project ios/MesiboConference from the folder where you have downloaded the code using the menu
File -> Open - Build using menu
Product -> Build - It may take a while to build the project for the first time.
- Once the build is over, run on the device using the menu
Product -> Run - That’s it, you should see the welcome screen like below and then the login screen.
If you receive linker errors
If you receive linker errors, it means that your download was incomplete. One of the likely reasons is that you forgot to issue git lfs install. There are two ways to fix it:
- Delete the entire repository and download again (do not forget
git lfs install, as instructed above). Note that enablinggit lfs installafter partial download does not seem to work as expected. - OR, run
fetch_broken_download.shscript
./fetch_broken_download.sh
Refer to the source code here for an example on invoking the login REST API.
-(void) login:(NSString *)name email:(NSString *)email code:(NSString *)code handler:(SampleAPI_onResponse) handler {
NSMutableDictionary *post = [[NSMutableDictionary alloc] init];
[post setValue:@“login” forKey:@“op”];
[post setValue:name forKey:@“name”];
[post setValue:email forKey:@“email”];
if(nil != code) {
[post setValue:code forKey:@“code”];
}
NSString *packageName = [[NSBundle mainBundle] bundleIdentifier];
[post setValue:packageName forKey:@"appid"];
[self invokeApi:post filePath:nil handler:handler];
} If login is successful, your server will generate an access token using mesibo User Management API and send it to you in the response. You need to use this access token later while initializing the mesibo real-time API. Refer to the example source code here.
if([op isEqualToString:@“login”]) { mToken = (NSString *)[returnedDict objectForKeyOrNil:@“token”];
if(![SampleAPI isEmpty:mToken]) { [self save];
[MesiboInstance reset];
}
}
Refer to the source code here for an example on invoking the setgroup REST API.
-(void) createRoom:(NSString *)name resolutoon:(int)resolution handler:(SampleAPI_onResponse) handler { NSMutableDictionary *post = [[NSMutableDictionary alloc] init]; [post setValue:@“setgroup” forKey:@“op”]; [post setValue:[self getToken] forKey:@“token”]; [post setValue:name forKey:@“name”];
NSString *r = [NSString stringWithFormat:@"%d", resolution];
[post setValue:r forKey:@"resolution"];
[self invokeApi:post filePath:nil handler:handler];
}
If a room is created successfully using setgroup, you will receive the room pin and spin in the response. Refer to the source code here
(IBAction)onCreateRoom:(id)sender { if(_mRoom.text.length < 3) { [self showError:@“missing or too short room Name”]; return;; }
Resolution *r = [mResolutions objectAtIndex:mSelectedResolution];
[SampleAPIInstance createRoom:_mRoom.text resolutoon:r.resolution handler:^(int result, NSDictionary *response) {
if(SAMPLEAPP_RESULT_OK != result) { [self showError:@"Create Failed"]; return; } NSInteger gid = [[response objectForKey:@"gid"] longValue]; [self dismissViewControllerAnimated:NO completion:^{ [mParent groupCallUi:gid video:YES publish:YES]; }];}]; }
You can share the room-id and room-pin(either pin for active participants or spin for subscribe-only participants) with other users who you want to join the conference.
Refer to source code here for an example on invoking the joingroup REST API.
-(void) joinRoom:(NSString *)gid pin:(NSString *)pin handler:(SampleAPI_onResponse) handler {
NSMutableDictionary *post = [[NSMutableDictionary alloc] init];
[post setValue:@“joingroup” forKey:@“op”];
[post setValue:[self getToken] forKey:@“token”];
[post setValue:gid forKey:@“gid”];
[post setValue:pin forKey:@“pin”];
[self invokeApi:post filePath:nil handler:handler];
}
f joingroup is successful, you can join a group call. Refer to source code JoinRoomViewController.m
-(void) joinRoom:(NSString *)gid pin:(NSString *)pin {
[SampleAPIInstance joinRoom:gid pin:pin handler:^(int result, NSDictionary *response) {
if(SAMPLEAPP_RESULT_OK != result) {
[self showError:@"Joining Room Failed"];
return;
}
[self groupCallUi:gid video:YES publish:YES];
}];
}
The app launches MesiboGroupCallController to show the group call screen. This, in turn, loads GroupCallView and starts the group call.
Refer to JoinRoomViewController.m -(BOOL) groupCallUi:(uint32_t)gid video:(BOOL)video publish:(BOOL)publish { MesiboGroupCallController *vc = [[MesiboGroupCallController alloc] initWithGid:gid]; vc.modalPresentationStyle = UIModalPresentationFullScreen;
UIViewController *me = self;
[MesiboInstance runInThread:YES handler:^{
[me presentViewController:vc animated:YES completion:nil];
}];
return YES;
}
See GroupCallView.m
(void)startCall { /* create a group call instance and join the room */ mGc = [MesiboCallInstance groupCall:self groupid:mGid]; [mGc join:self];
/* publish streams */ MesiboParticipant *p = [mGc createPublisher:0]; [p setVideoSource:MESIBOCALL_VIDEOSOURCE_CAMERAFRONT index:0]; [mPublishers addObject:p]; [p call:YES video:YES listener:self];
}
In this app, GroupCallView.m implements GroupCallListener.
When someone joins the room and starts publishing, you will receive their Participant object through MesiboGroupCall_OnPublisher.
(void)MesiboGroupcall_OnPublisher:(MesiboParticipant * _Nonnull)p joined:(BOOL)joined {
/* we got a new publisher, subscribe to them*/ if (joined) { int pos = [self getParticipantPosition:mPublishers p:p]; if(pos >= 0) { [mPublishers removeObjectAtIndex:pos]; } [mPublishers addObject:p]; [p call:YES video:(YES) listener:self];;
} else { [self removeParticipant:p]; [self setStreams]; }
}
When you make a call using the
callmethod and you are connected, MesiboGroupcall_OnConnected will be called.Once you are connected, you will be notified when you receive the video stream through the listener MesiboGroupcall_OnVideo or the audio stream through MesiboGroupcall_OnAudio
When a publisher mutes audio or video, you will be notified through MesiboGroupcall_OnMute
When a publisher starts talking, MesiboGroupcall_OnTalking will be called (Talk Detection).
When a publisher leaves the conference, MesiboGroupcall_OnHangup will be called
When you receive the video stream from a participant MesiboGroupcall_OnVideo will be called. You can then use, setVideoView to display them.
Sorting Streams (Optional)
You can display the videos of participants in a grid or whatever fashion you like. Mesibo also provides a utility function to sort videos in a grid using the aspect ratio. To use this, you need to call the sort function with a list of streams and implement MesiboParticipantSortListener which will be called with the video coordinates. Note, this is an optional utility. You can always use your own method of sorting participants and displaying videos.
Here, each video is displayed in a ParticipantViewHolder containing a MesiboVideoView. So, in a grid, we will have a list of views. We will sort these views, based on the aspect ratio every time the grid is updated (when participant video added or removed, when video aspect ratio changes, etc). Refer to the source code here.
-(void) setStreams { …
NSArray *sorted = [mGc sortStreams:self views:mStreams width:mWidth height:mHeight start:0 size:mStreams.count params:nil];
… }
The position for each video in the grid is set in ParticipantSort_onSetCoordinates
(void)ParticipantSort_onSetCoordinates:(id _Nonnull)o position:(int)position x:(float)x y:(float)y width:(float)width height:(float)height {
ParticipantViewHolder *pv = (ParticipantViewHolder *)o; [pv setCoordinates:position x:x y:y width:width height:height]; }
MesiboGroupcall_OnMute is called when the publisher mutes audio or video. -(void) MesiboGroupcall_OnMute:(MesiboParticipant *)participant audio:(BOOL)audioMuted video:(BOOL)videoMuted {
if(remote){
// Remote participant has muted
}
// Check mute status
if(audioMuted){
// Audio Muted
}
if(videoMuted){
// Video Muted
}
}
You can toggle the audio using toggleAudioMute and toggle the video using toggleVideoMute
MesiboGroupcall_OnTalking is called when the participant starts or stops talking.
-(void) MesiboGroupcall_OnTalking:(MesiboParticipant *)participant talking:(BOOL)talking {
if(talking){
// If talking is true, participant started talking
// if it is false, participant stopped talking
// Handle talking. For example, Show a talking icon
}
}
You can use the utility function playInCallSound to play sound in the background in a group call.
NSURL *sound = [NSURL fileURLWithPath:@“file:///path/to/audiofile/”]; [GroupCallInstance playInCallSound:sound]
For implementing chat, you can use the Mesibo Messaging UI Helper.
For group chat, simply set the group profile and use launchMessageView to launch the chat UI for the group.
Similarly, for one-to-one chat, create a user profile and call launchMessageView.
For example,
- (IBAction)onLaunchMessagingUIModule:(id)sender { //requires pod mesibo-ui [MesiboUI launchMessageViewController:self profile:mProfile]; }
Refer to the documentation Launching Messaging UI in iOS learn more.
Whenever a publisher hangs up, MesiboGroupcall_OnHangup will be called.
To, stop viewing a participant you need to call hang up on their participant object.
[participant hangup];
-(void) onHangup:(id)sender { [mGc leave]; [mController dismiss]; }
In this app, we call leave when the local hangup button is pressed.
In the next part, we will explore the Javascript(Web) app.