Can't stop audio playback on iOS with Codename One - iphone

My Codename One app features audio playback in the background when the user taps the screen. The audio I use is an mp3. Here is how I use the Media playback :
public static void playSound(boolean stop) {
sound.reset(); // The input stream needs to go back to the beginning
Media myClip = MediaManager.createMedia(sound, "audio/mp3", () -> {
// If there is no order to stop playback, we keep playing when it has completed (looping)
playSound(false);
});
if (!stop) {
myClip.play();
} else {
myClip.cleanup();
}
}
So hen the user taps the screen components change and I pass true to playSound method. On Android the current playback stops not on iOS with an iPhone 4.
Please note that when the app gets minimized (center button pressed) the playback stops (even if I don't call cleanup() on the Media which I do on Android to stop the playback when the app is minimized).
How can I stop the playback on iPhone ?
Any help appreciated,

#Shai pointed me to the right direction so here is the code finally used :
Media myClip = null;
public static void playSound(boolean stop) {
sound.reset(); // The input stream needs to go back to the beginning
/**
* If the media is playing we don't create it
* otherwise we would have several media in the wild
* that could not be stopped
*/
if (myClip == null || !myClip.isPlaying()) {
myClip = MediaManager.createMedia(sound, "audio/mp3", () -> {
// If there is no order to stop playback, we keep playing when it has completed (looping)
playSound(false);
});
}
if (!stop) {
myClip.play();
} else {
myClip.cleanup();
}
}

Related

Web audio playback contains clicks

I am trying to build a midi player using web audio API. I used tonejs to parse midi file into JSON. I am using mp3 files to play notes. Following are the relevant parts of the code:
//create audio samples
static async setupSample(audioContext, filepath) {
const response = await fetch(filepath);
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await audioContext.decodeAudioData(arrayBuffer);
return audioBuffer;
}
//play a single sample
static playSample(audioContext, audioBuffer, time) {
const sampleSource = new AudioBufferSourceNode(audioContext, {
buffer: audioBuffer,
playbackRate: 1,
});
sampleSource.connect(audioContext.destination);
sampleSource.start(time);
return sampleSource;
}
Scheduling samples:
async start() {
this.startTime = this.audioCtx.currentTime;
this.play();
}
play() {
let nextNote = this.notes[this.noteIndex];
//schedule samples
while ((nextNote.time + this.startTime) - this.audioCtx.currentTime <= 0.250) {
let s = Audio.playSample(this.audioCtx, this.samples[nextNote.midi], this.startTime + nextNote.time);
s.stop(this.startTime + nextNote.time + nextNote.duration);
this.noteIndex++;
if (this.noteIndex == this.notes.length) {
break;
}
nextNote = this.notes[this.noteIndex];
}
if (this.noteIndex == this.notes.length) {
return;
}
requestAnimationFrame(() => {
this.play();
});
}
I am testing code with a midi file which contains C major scale. I have tested the midi file using timidity and it is fine.
The code does play the midi file correctly execpet a small problem: I hear some clicking sounds during playback. The clicking increases with increasing tempo but does not completely go away even with tempo as small as 50bpm. Any ideas what could be going wrong?
Full code can be viewed at : https://test.meedee.in/
Nothing is "wrong". You are observing a phenomenon intrinsic to the physics of audio.
Chopping audio samples arbitrarily like this creates clicks at the transitions. Any instantaneous change in level is heard as a click. To get rid of the clicks, apply an envelope to the sample, blend adjacent notes, or apply a low-pass filter.

Cant get video progress time in Flutter better player

I am building a video player app in flutter with better video player. All things are working fine with better player except that i cant get the video player progress(time of how much the video has been played) in better player and i also want to get the total time of the video too. Does anyone has any idea of how to get the video progress with it.. it will be helpfull with an example.
You can set the listener in BetterPlayerConfiguration, than you can get video duration and progress using event.parameters. Please, see the example below:
BetterPlayerConfiguration get _betterPlayerConfiguration => BetterPlayerConfiguration(
eventListener: _onPlayerEvent,
);
void _onPlayerEvent(BetterPlayerEvent event) {
if (_checkIfCanProcessPlayerEvent(event)) {
Duration progress = event.parameters!['progress'];
Duration duration = event.parameters!['duration'];
}
}
bool _checkIfCanProcessPlayerEvent(BetterPlayerEvent event) {
return
event.betterPlayerEventType == BetterPlayerEventType.progress &&
event.parameters != null &&
event.parameters!['progress'] != null &&
event.parameters!['duration'] != null;
}
you can get control of all events in better player after you create betterplayercontroller like this
_betterPlayerController!.addEventsListener((event) {
if (event.betterPlayerEventType == BetterPlayerEventType.finished) {
LessonRepo.completeVideo(lessonID: lessonID);
}
});
Duration myProgress;
_betterPlayerController.addEventsListener((event) => {
if (event.betterPlayerEventType == BetterPlayerEventType.progress) {
myProgress = event.parameters['progress']
},
}

Flutter - Stop audio playback from recorded video in the background

Essentially the app is like snapchat. I take pics and reset back to camera mode, the issue comes when I record video and reset, it goes back to camera mode but the audio form the video keeps playing in the background. The functions are somwhat exactly like the camera doc, with a few addition to reset the camera.
I added this:
_reset() {
if (mounted)
setState(() {
if (this._didCapture) {
this._didCapture = false;
this._isRecording = false;
this._isPosting = false;
this._file = File('');
this._fileType = null;
this._captions.clear();
this._textEditingControllers.clear();
this._videoController = null;
this._videoPlayerListener = null;
}
});
}
It works just fine but the audio in the background is still on. Also wondering if the video/picture is saved on the phone, which I don't want to...
i had been looking for a similar answer, but i didn´t find it. You could try to stop it adding this to your function:
this._controller.setVolume(0.0);
that´s what i did in my app

JavaFx set volume on MediaPlayer not working

This question has been asked before but to date there is no answer. I have just struck the same problem. I traced into the mediaplayer source and all is well until I get to gstSetVolume in GSTMediaPlayer for which I don't have the source.
At that point the volume value is still correct.
After setting the volume System.out.println(player.getVolume()); reports the correct value (0.0 - 1.0) BUT the volume has not changed. If the slider is set to 0, the audio is muted. Any other value is full volume.
Platform is Netbeans 8.1 on Windows 7 with JavaFX-8 and JDK-8 and the media source is a standard mp4 which works on all tested players (Windows, VLC etc).
Here is the code attached to a MediaView (which works well):
Runnable videoLoop;
PlayListViewController playListViewController;
// Videos are looped here
public void startVideoLoop() {
playerIndex = 0;
videoLoop = () -> {
// Previous player MUST be stopped otherwise it is left
// in the PLAYING state and the next video will not PLAY
if (player != null) {
player.stop();
}
// Point to the next player
if (++playerIndex == videoPlayersList.size()) {
playerIndex = 0;
}
playVideoSequence();
};
playVideoSequence();
}
public void playVideoSequence() {
// If the video options are shown we can update the listview
if (playListViewController != null) {
playListViewController.setListViewItem(playerIndex);
}
player = videoPlayersList.get(playerIndex);
mediaView.setMediaPlayer(player);
player.setOnEndOfMedia(videoLoop);
player.play();
}
A right mouse button press then invokes a 'settings' option. This is a View Controller which is attached to an FXML view. The controller receives a reference to the videoField when it is invoked. Here is the relevant snippet:
private void setHandlers() {
idVolumeSlider.valueProperty().addListener(new ChangeListener() {
#Override
public void changed(ObservableValue arg0, Object arg1, Object arg2) {
// videoField is a separate class
videoField.setVolume(idVolumeSlider.getValue());
}
});
I'm sorry I cannot supply a 'cut and paste' example, because that would mean a lot of pruning and simplifying of classes to achieve that with the risk of introducing additional problems.

html5 audio tag playing audio when it is load audio

i have html5 audio player like play, pause, stop buttons.
function onUpdate()
{
var isPlaying = (!getAudioElement().paused);
document.getElementById("playerplay").style.display = (isPlaying)?"none":"block";
document.getElementById("playerpause").style.display = (isPlaying)?"block":"none";
};
function getAudioElement()
{
return document.getElementById("id_audio_element");
}
function play() {
getAudioElement().play();
onUpdate();
}
function pause() {
getAudioElement().pause();
onUpdate();
}
function stop() {
getAudioElement().pause();
getAudioElement().currentTime=0;
onUpdate();
getAudioElement().load();
}
And audio tag:
<audio id="id_audio_element" onended="onUpdate();load();"><source src="105.ogg" type="audio/ogg"></audio>
it works all on browsers perfectly, exept iPhone and iPad's Safari and Chrome. When I call load() , audio starts playing, although I don't call play().
Anybody has a solution? Thanks!
If the source is not changing, there is no need to call load(). If it is changing, try calling pause() after it loads.