I'm using MobileVLCKit in form of MobileVLCKit-prod version 2.7.9 from CocoaPods.
I am initializing VLCMediaPlayer this way
VLCMediaPlyer *player;
....
player=[[VLCMediaPlayer alloc] init];
player.delegate=self;
VLCMedia * media;
media=[VLCMedia mediaWithURL:#"UrlOfRemoteAudiFile"]
I don't setup player.drawable because I only need audio and remote file doesn't contain video stream anyway.
Audio file plays correctly. Pause/resume works.
but I cannot change sound volume: player.audio.volume returns 0, attempts to assign player.audio.volume value in interval 0..200 are ignored with no change in volume.
I currently test on iOS9.
Only solution I found so far which works is changing system volume.
only way I find to do that (partially based on code from ttps://stackoverflow.com/questions/33168497/ios-9-how-to-change-volume-programmatically-without-showing-system-sound-bar-po ) is just change system volume.
code like this.
- (void) fakeSystemVolumeSetup:(float)newValue {
MPVolumeView* volumeView = [[MPVolumeView alloc] init];
// Get the Volume Slider
UISlider* volumeViewSlider = nil;
for (UIView *view in [volumeView subviews]){
if ([view.class.description isEqualToString:#"MPVolumeSlider"]){
volumeViewSlider = (UISlider*)view;
break;
}
}
// Fake the volume setting
[volumeViewSlider setValue:newValue animated:YES];
[volumeViewSlider sendActionsForControlEvents:UIControlEventTouchUpInside];
}
It works and it turned out that having system indicators active is even better for this project.
Related
I am using AVPlayer to play music in my code. I know I can use MPVolumeView from MediaPlayer to route between speakers, but I am looking for something different(Because I am developing the application in Ionic and I am not able to find some plugin that can perform such thing, plugin which I use is cordova-plugin-media).
I have searched about how to create it and found some answers like I can switch using AVAudioSession.
I am not able to find some code related to it so if anyone can help it would be great.
Another thing is that if I change this forcefully how will it behave with Control Center.
You can still use MPVolumeView with IONIC as plugin, you just need to control UITouchUpInside through code.
Check this if helps.
- (void) currentOutputs:(CDVInvokedUrlCommand*)command {
if(!mpVolumeView){
mpVolumeView = [[MPVolumeView alloc] initWithFrame:CGRectZero];
mpVolumeView.showsVolumeSlider = FALSE;
[self.webView.superview addSubview:mpVolumeView];
[mpVolumeView setAlpha:0.01];
}
UIButton* btn = nil;
for (UIView *view in [mpVolumeView subviews]){
if ([view.class.description isEqualToString:#"MPButton"]){
btn = (UIButton*)view;
break;
}
}
if(btn){
[btn sendActionsForControlEvents:UIControlEventTouchUpInside];
}
}
Working plugin
https://github.com/jaymehtasa/cordova-plugin-audioroute
Have you tried this?
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSessionPortBluetoothA2DP)
} catch _ {
}
This maybe helpful.
I am trying to use this Library to play youtube video in my ios app, it works for when I load the page for the first time, when I go back to the previous view controller and go into the viewcontroller again which have the youtube video, the video player doesn't show up any more, unless I kill the app and restart again. Not sure Why it is like.
I have a view controller, in the view controller I am using this library to play youtube videos. when I get into this view controller for the first time it all works fine, but when i get to this view controller for the second time, the player not showing up unless I kill the app.
- (void)viewDidLoad
{
[super viewDidLoad];
[self.player loadPlayerWithVideoId:#"M7lc1UVf-VE"];
}
-(YTPlayerView*)player
{
if(!_player)
{
_player = [[YTPlayerView alloc] initWithFrame:CGRectMake(0, 50, self.view.bounds.size.width, 220)];
_player.delegate = self;
_player.autoplay = NO;
_player.modestbranding = YES;
_player.allowLandscapeMode = YES;
_player.forceBackToPortraitMode = YES;
_player.allowAutoResizingPlayerFrame = YES;
_player.playsinline = NO;
_player.fullscreen = YES;
_player.playsinline = YES;
}
return _player;
}
I have used this library to load youtube video and it's working fine for me in the situation you described....
You should declare YTPlayerView as property in .h file like this.
#property(nonatomic, strong) IBOutlet YTPlayerView *playerView;
It is working well for me.
I used the following code to initial the text to speech synthesis using a button. But sometimes users may want to stop the voice in the middle of the speech. May i know is there any code i can do that.
Thanks
Here is my code
#interface RMDemoStepViewController ()
#end
#implementation RMDemoStepViewController
- (void)viewDidLoad
{
[super viewDidLoad];
//Add Border to TextBox
//Instantiate the object that will allow us to use text to speech
self.speechSynthesizer = [[AVSpeechSynthesizer alloc] init];
[self.speechSynthesizer setDelegate:self];
}
- (IBAction)speakButtonWasPressed:(id)sender{
[self speakText:[self.textView text]];
}
- (void)speakText:(NSString *)toBeSpoken{
AVSpeechUtterance *utt = [AVSpeechUtterance speechUtteranceWithString:toBeSpoken];
utt.rate = [self.speedSlider value];
[self.speechSynthesizer speakUtterance:utt];
}
- (IBAction)speechSpeedShouldChange:(id)sender
{
UISlider *slider = (UISlider *)sender;
NSInteger val = lround(slider.value);
NSLog(#"%#",[NSString stringWithFormat:#"%ld",(long)val]);
}
#end
But sometimes users may want to stop the voice in the middle of the speech.
To stop speech, send the speech synthesizer a -stopSpeakingAtBoundary: message:
[self.speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
Use AVSpeechBoundaryWord instead of AVSpeechBoundaryImmediate if you want the speech to continue to the end of the current word rather than stopping instantly.
You can also pause speech instead of stopping it altogether.
This will completely stop the SpeechSynthesizer: -stopSpeakingAtBoundary and if you want more code after the SS, then put : at the end of that. So basically, -stopSpeakingAtBoundary: For the full code to fit in with yours, here: [self.speechSynthesizer stopSpeakingAtBoundary:AVSpeechBoundaryImmediate];
I've migrated my VoIP application to iOS7 recently, and there's an open bug still remaining which I can't understand.
When in VoIP call, in iOS6 you can push the physical volume button to lower the volume, down to Zero.
Now, in iOS7, I can lower the sound only down to the last step before zero, which means the volume cannot be muted.
I suspect this is something that's on iOS7 side, since I don't have the problem with the same IPA on an iOS6 device.
Anybody knows what's up?
A bit old question, but I also needed a solution for Gui13's question/comment:
We're not using any sort of control in our app, all volume interaction is based on volume buttons.. So I could maybe implement this but I'd need a way to tie it to the volume buttons. Is this possible?
Apple recommends using MPVolumeView, so I came up with this:
MPVolumeView *volumeView = [MPVolumeView new];
[self.view addSubview:volumeView];
and then:
__block UISlider *volumeSlider = nil;
[[volumeView subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[UISlider class]]) {
volumeSlider = obj;
*stop = YES;
}
}];
[volumeSlider addTarget:self action:#selector(handleVolumeChanged:) forControlEvents:UIControlEventValueChanged];
with:
- (void)handleVolumeChanged:(id)sender
{
NSLog(#"%s - %f", __PRETTY_FUNCTION__, ((UISlider *)sender).value);
}
The [MPVolumeView new] code above inits MPVolumeView with no frame so, it's not visible in our self.view where it has been added as a subview, but it is important that it has to be added!
You can also init the MPVolumeView with the code:
MPVolumeView *volumeView = [[MPVolumeView alloc] initWithFrame:self.view.frame];
volumeView.showsRouteButton = NO;
volumeView.showsVolumeSlider = NO;
[self.view addSubview:volumeView];
which will also init the empty MPVolumeView (i.e. without RouteButton and VolumeSlider).
What's interesting is that UISlider subview (actually MPVolumeSlider, the subclass of UISlider) will still be found in the enumerateObjectsUsingBlock above.
This approach is also interesting because you can save the reference to volumeSlider and use it later to set volume from code, or your custom control:
Init and add to your view:
MPVolumeView *volumeView = [MPVolumeView new];
volumeView.showsRouteButton = NO;
volumeView.showsVolumeSlider = NO;
[self.view addSubview:volumeView];
Find and save reference to UISlider:
__weak __typeof(self)weakSelf = self;
[[volumeView subviews] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if ([obj isKindOfClass:[UISlider class]]) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
strongSelf.volumeSlider = obj;
*stop = YES;
}
}];
Add target action for UIControlEventValueChanged:
[self.volumeSlider addTarget:self action:#selector(handleVolumeChanged:) forControlEvents:UIControlEventValueChanged];
And then update your custom control when the volume has been changed (i.e. by the hardware volume controls):
- (void)handleVolumeChanged:(id)sender
{
NSLog(#"%s - %f", __PRETTY_FUNCTION__, self.volumeSlider.value);
self.myCustomVolumeSliderView.value = self.volumeSlider.value;
}
and also:
- (IBAction)myCustomVolumeSliderViewValueChanged:(id)sender {
NSLog(#"set volume to: %f", self.myCustomVolumeSliderView.value);
self.volumeSlider.value = self.myCustomVolumeSliderView.value;
}
Hope this helps someone (and that Apple doesn't remove MPVolumeSlider from MPVolumeView).
Same problem with my VoIP app...
My Solution:
After everything is set up, set the category to Playback,
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
Then set it back to PlayAndRecord,
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayAndRecord error:nil];
This works for me, hope this helps someone who comes across the same problem.
You have to use applicationMusicPlayer instead of iPodMusicPlayer to set the system volume:
#import <MediaPlayer/MediaPlayer.h>
musicPlayer = [MPMusicPlayerController applicationMusicPlayer];
musicPlayer.volume = 1; // max volume
musicPlayer.volume = 0; // min volume (mute)
musicPlayer.volume = 0.0625; // 1 bar on the overlay volume display
Apple is assuming that they know each and every way in which a volume will need to be administered.
There are, in fact, occasions when we want to change how the volume is controlled without forcing the user to have a volume slider on the screen, (alarm clocks and media players come to mind immediately).
Yuou can take reference
https://developer.apple.com/library/ios/documentation/mediaplayer/reference/MPVolumeView_Class/Reference/Reference.html
http://ios-blog.co.uk/tutorials/controlling-system-output-volume-with-the-mpvolumeview-class-part-one/
Using the code at the bottom of this post I can successfully display a movie. However I need to now use moviePlayer as a property rather than a local variable. So by adding the following in the header file:
#property (retain, nonatomic) MPMoviePlayerController *mPlayer;
...and synthesizing it as:
#synthesize mPlayer = _mPlayer
Here's the original code. This works fine. All I change is the initialisation line where instead of using a local variable I use the property. A
MPMoviePlayerController * mPlayer = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL] autorelease];
mPlayer.shouldAutoplay=YES;
[self.welcomeImage setUserInteractionEnabled:YES];
[mPlayer.view setFrame: self.welcomeImage.bounds]; // player's frame must match parent's
[self.welcomeImage addSubview:mPlayer.view];
mPlayer.scalingMode = MPMovieScalingModeAspectFit;
mPlayer.controlStyle = MPMovieControlStyleEmbedded;
[mPlayer prepareToPlay];
[mPlayer play];
I just get a black box, no controls or video. What am I doing wrong?
Your not using your synthesized property. Change mPlayer to _mPlayer.
_mPlayer = [[[MPMoviePlayerController alloc] initWithContentURL:videoURL] autorelease];
_mPlayer.shouldAutoplay=YES;
[self.welcomeImage setUserInteractionEnabled:YES];
[_mPlayer.view setFrame: self.welcomeImage.bounds]; // player's frame must match parent's
[self.welcomeImage addSubview:_mPlayer.view];
_mPlayer.scalingMode = MPMovieScalingModeAspectFit;
_mPlayer.controlStyle = MPMovieControlStyleEmbedded;
[_mPlayer prepareToPlay];
[mPlayer play];
This should work as long your videoURL is valid.