/* * Copyright (c) 2010-2020 Belledonne Communications SARL. * * This file is part of linphone-iphone * * 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, see . */ #import "UILinphoneAudioPlayer.h" #import "Utils.h" @implementation UILinphoneAudioPlayer { @private LinphonePlayer *player; LinphonePlayerCbs *cbs; int duration; BOOL eofReached; } @synthesize file; #pragma mark - Factory + (id)audioPlayerWithFilePath:(NSString *)filePath { return [[self alloc] initWithFilePath:filePath]; } #pragma mark - Life cycle - (instancetype)initWithFilePath:(NSString *)filePath { if (self = [super initWithNibName:NSStringFromClass(self.class) bundle:[NSBundle mainBundle]]) { player = linphone_core_create_local_player(LC, NULL, NULL, NULL); cbs = linphone_player_get_callbacks(player); linphone_player_set_user_data(player, (__bridge void *)self); linphone_player_cbs_set_eof_reached(cbs, on_eof_reached); file = filePath; eofReached = NO; _refreshTimer = nil; } return self; } - (void)dealloc { [self close]; } - (void)close { if (player) { [_refreshTimer invalidate]; _refreshTimer = nil; linphone_player_close(player); linphone_player_unref(player); player = NULL; } [self.view removeFromSuperview]; } - (void)viewDidAppear:(BOOL)animated { [_playButton setTitle:@"" forState:UIControlStateNormal]; if (player && linphone_player_get_state(player) == LinphonePlayerPlaying) [_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPause:[UIColor blackColor]] forState:UIControlStateNormal]; else [_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal]; [_stopButton setTitle:@"" forState:UIControlStateNormal]; [_stopButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemRefresh:[UIColor blackColor]] forState:UIControlStateNormal]; } - (void)viewWillDisappear:(BOOL)animated { [self close]; } - (void)open { linphone_player_open(player, file.UTF8String); duration = linphone_player_get_duration(player); [self updateTimeLabel:0]; _timeProgress.progress = 0; eofReached = NO; [_playButton setTitle:@"" forState:UIControlStateNormal]; [_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal]; [_stopButton setTitle:@"" forState:UIControlStateNormal]; [_stopButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemRefresh:[UIColor blackColor]] forState:UIControlStateNormal]; } - (BOOL)isOpened { return player && linphone_player_get_state(player) != LinphonePlayerClosed; } - (BOOL)isCreated { return player!=nil; } - (void)setFile:(NSString *)fileName { if (player) linphone_player_close(player); file = fileName; } #pragma mark - Callbacks void on_eof_reached(LinphonePlayer *pl) { NSLog(@"EOF reached"); UILinphoneAudioPlayer *player = (__bridge UILinphoneAudioPlayer *)linphone_player_get_user_data(pl); dispatch_async(dispatch_get_main_queue(), ^{ [player.playButton setTitle:@"" forState:UIControlStateNormal]; [player.playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal]; }); player->eofReached = YES; } #pragma mark - ViewController methods - (void)viewDidLoad { [super viewDidLoad]; } - (void)didReceiveMemoryWarning { [super didReceiveMemoryWarning]; } #pragma mark - Utils + (NSString *)timeToString:(int)time { time /= 1000; int hours = time / 3600; time %= 3600; int minutes = time / 60; int seconds = time % 60; NSNumberFormatter *formatter = [NSNumberFormatter new]; formatter.maximumIntegerDigits = 2; formatter.minimumIntegerDigits = 2; NSString *ret = [NSString stringWithFormat:@"%@:%@", [formatter stringFromNumber:[NSNumber numberWithInt:minutes]], [formatter stringFromNumber:[NSNumber numberWithInt:seconds]]]; ret = (hours == 0)?ret:[[NSString stringWithFormat:@"%d:", hours] stringByAppendingString:ret]; return ret; } #pragma mark - Updating - (void)updateTimeLabel:(int)currentTime { _timeLabel.text = [NSString stringWithFormat:@"%@ / %@", [self.class timeToString:currentTime], [self.class timeToString:duration]]; } - (void)displayProgress{ int pos = linphone_player_get_current_position(player); _timeProgress.progress = (float)pos / (float)duration; [self updateTimeLabel:pos]; } - (void)update { if (!_refreshTimer) _refreshTimer = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(displayProgress) userInfo:nil repeats:YES]; } - (void)pause { if ([self isOpened]) { linphone_player_pause(player); [_playButton setTitle:@"" forState:UIControlStateNormal]; [_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal]; } } #pragma mark - Event handlers - (IBAction)onPlay:(id)sender { if (eofReached) { linphone_player_seek(player, 0); eofReached = NO; } LinphonePlayerState state = linphone_player_get_state(player); switch (state) { case LinphonePlayerClosed: break; case LinphonePlayerPaused: NSLog(@"Play"); [_playButton setTitle:@"" forState:UIControlStateNormal]; [_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPause:[UIColor blackColor]] forState:UIControlStateNormal]; linphone_player_start(player); break; case LinphonePlayerPlaying: NSLog(@"Pause"); [_playButton setTitle:@"" forState:UIControlStateNormal]; [_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal]; linphone_player_pause(player); break; } [self update]; } - (IBAction)onStop:(id)sender { NSLog(@"Stop"); linphone_player_pause(player); linphone_player_seek(player, 0); eofReached = NO; [_playButton setTitle:@"" forState:UIControlStateNormal]; [_playButton setImage:[UIImage imageFromSystemBarButton:UIBarButtonSystemItemPlay:[UIColor blackColor]] forState:UIControlStateNormal]; _timeProgress.progress = 0; [self updateTimeLabel:0]; } - (IBAction)onTapTimeBar:(UITapGestureRecognizer *)sender { if (sender.state != UIGestureRecognizerStateEnded) return; CGPoint loc = [sender locationInView:self.view]; CGPoint timeLoc = _timeProgress.frame.origin; CGSize timeSize = _timeProgress.frame.size; if (loc.x >= timeLoc.x && loc.x <= timeLoc.x + timeSize.width && loc.y >= timeLoc.y - 10 && loc.y <= timeLoc.y + timeSize.height + 10) { float progress = (loc.x - timeLoc.x) / timeSize.width; _timeProgress.progress = progress; [self updateTimeLabel:(int)(progress * duration)]; linphone_player_seek(player, (int)(progress * duration)); } } @end