You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@cordova.apache.org by "Bob Flavin (JIRA)" <ji...@apache.org> on 2012/10/06 19:43:03 UTC

[jira] [Created] (CB-1599) successCallback not called after stopRecording, duplicate AudioRecorder objects created

Bob Flavin created CB-1599:
------------------------------

             Summary: successCallback not called after stopRecording, duplicate AudioRecorder objects created
                 Key: CB-1599
                 URL: https://issues.apache.org/jira/browse/CB-1599
             Project: Apache Cordova
          Issue Type: Bug
          Components: CordovaJS
    Affects Versions: 2.1.0
         Environment: Android 2.3? 
            Reporter: Bob Flavin
            Assignee: Filip Maj
             Fix For: 2.1.0


A successCallback is not called sometimes after stopRecording() is called.

The problem is that javascript cordova calls to 'new Media()' and 'mediaObj.startRecord() are dispatched by androidExec (prompt) to new threads on the java side and are not synchronized.  Thus org.apache.cordova.AudioHandler.execute for action='create', calls new AudioPlayer().   Asynchronously, ...AudioHandler.execute for action='startAudioRecording' calls AudioHandler.startAudioRecording(), which gets a null from this.players.get(id) which causes the if statement to call new AudioRecorder which creates a second instance of AudioRecorder for that id.

    public void startRecordingAudio(String id, String file) {
        AudioPlayer audio = this.players.get(id);
        if ( audio == null) {
            audio = new AudioPlayer(this, id, file);
            this.players.put(id, audio);
        }
        audio.startRecording(file);
    }

One instance of AudioPlayer goes into STATE MEDIA_RUNNING the other remains in MEDIA_NONE.  

When the javascript calls mediaObj.stopRecord() (and mediaObj.release()) it may get the instance of AudioPlayer that is in MEDIA_NONE.  This prevents AudioPlayer.stopRecording() from calling this.recorder.stop() and this.setState(STATE.MEDIA_STOPPED) because that AudioPlayer instance is in STATE MEDIA_NONE.  Thus AudioPlayer.setState doesn't call the handler.sendJavascript to call the javascript Media.onStatus method that would call the statusCallback and the successCallback.

I think that the AudioHandler should have a synchronized block that prevents 'create' and 'startRecordingAudio from running at the same time and that 'create' should use the same code that startRecodingAudio does:
        AudioPlayer audio = this.players.get(id);
        if ( audio == null) {
            audio = new AudioPlayer(this, id, file);
            this.players.put(id, audio);
        }
to prevent creating a second AudioPlayer instance if the startRecordingAudio thread executes before the 'create' thread.

There may be other actions in AudioHandler.execute that need this synchronization as well.

One effect of this problem is that the javascript successCallback is never called (after stopRecord)

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Updated] (CB-1599) successCallback not called after stopRecording, duplicate AudioPlayer objects created

Posted by "Shazron Abdullah (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/CB-1599?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Shazron Abdullah updated CB-1599:
---------------------------------

    Fix Version/s:     (was: 2.1.0)
                   2.3.0
    
> successCallback not called after stopRecording, duplicate AudioPlayer objects created
> -------------------------------------------------------------------------------------
>
>                 Key: CB-1599
>                 URL: https://issues.apache.org/jira/browse/CB-1599
>             Project: Apache Cordova
>          Issue Type: Bug
>          Components: CordovaJS
>    Affects Versions: 2.1.0
>         Environment: Android 2.3? 
>            Reporter: Bob Flavin
>            Assignee: Simon MacDonald
>             Fix For: 2.3.0
>
>         Attachments: AudioHandler.java
>
>
> A successCallback is not called sometimes after stopRecording() is called.
> The problem is that javascript cordova calls to 'new Media()' and 'mediaObj.startRecord() are dispatched by androidExec (prompt) to new threads on the java side and are not synchronized.  Thus org.apache.cordova.AudioHandler.execute for action='create', calls new AudioPlayer().   Asynchronously, ...AudioHandler.execute for action='startAudioRecording' calls AudioHandler.startAudioRecording(), which gets a null from this.players.get(id) which causes the if statement to call new AudioRecorder which creates a second instance of AudioRecorder for that id.
>     public void startRecordingAudio(String id, String file) {
>         AudioPlayer audio = this.players.get(id);
>         if ( audio == null) {
>             audio = new AudioPlayer(this, id, file);
>             this.players.put(id, audio);
>         }
>         audio.startRecording(file);
>     }
> One instance of AudioPlayer goes into STATE MEDIA_RUNNING the other remains in MEDIA_NONE.  
> When the javascript calls mediaObj.stopRecord() (and mediaObj.release()) it may get the instance of AudioPlayer that is in MEDIA_NONE.  This prevents AudioPlayer.stopRecording() from calling this.recorder.stop() and this.setState(STATE.MEDIA_STOPPED) because that AudioPlayer instance is in STATE MEDIA_NONE.  Thus AudioPlayer.setState doesn't call the handler.sendJavascript to call the javascript Media.onStatus method that would call the statusCallback and the successCallback.
> I think that the AudioHandler should have a synchronized block that prevents 'create' and 'startRecordingAudio from running at the same time and that 'create' should use the same code that startRecodingAudio does:
>         AudioPlayer audio = this.players.get(id);
>         if ( audio == null) {
>             audio = new AudioPlayer(this, id, file);
>             this.players.put(id, audio);
>         }
> to prevent creating a second AudioPlayer instance if the startRecordingAudio thread executes before the 'create' thread.
> There may be other actions in AudioHandler.execute that need this synchronization as well.
> One effect of this problem is that the javascript successCallback is never called (after stopRecord)

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Updated] (CB-1599) successCallback not called after stopRecording, duplicate AudioPlayer objects created

Posted by "Bob Flavin (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/CB-1599?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Bob Flavin updated CB-1599:
---------------------------

    Attachment: AudioHandler.java

Proposed solution
                
> successCallback not called after stopRecording, duplicate AudioPlayer objects created
> -------------------------------------------------------------------------------------
>
>                 Key: CB-1599
>                 URL: https://issues.apache.org/jira/browse/CB-1599
>             Project: Apache Cordova
>          Issue Type: Bug
>          Components: CordovaJS
>    Affects Versions: 2.1.0
>         Environment: Android 2.3? 
>            Reporter: Bob Flavin
>            Assignee: Filip Maj
>             Fix For: 2.1.0
>
>         Attachments: AudioHandler.java
>
>
> A successCallback is not called sometimes after stopRecording() is called.
> The problem is that javascript cordova calls to 'new Media()' and 'mediaObj.startRecord() are dispatched by androidExec (prompt) to new threads on the java side and are not synchronized.  Thus org.apache.cordova.AudioHandler.execute for action='create', calls new AudioPlayer().   Asynchronously, ...AudioHandler.execute for action='startAudioRecording' calls AudioHandler.startAudioRecording(), which gets a null from this.players.get(id) which causes the if statement to call new AudioRecorder which creates a second instance of AudioRecorder for that id.
>     public void startRecordingAudio(String id, String file) {
>         AudioPlayer audio = this.players.get(id);
>         if ( audio == null) {
>             audio = new AudioPlayer(this, id, file);
>             this.players.put(id, audio);
>         }
>         audio.startRecording(file);
>     }
> One instance of AudioPlayer goes into STATE MEDIA_RUNNING the other remains in MEDIA_NONE.  
> When the javascript calls mediaObj.stopRecord() (and mediaObj.release()) it may get the instance of AudioPlayer that is in MEDIA_NONE.  This prevents AudioPlayer.stopRecording() from calling this.recorder.stop() and this.setState(STATE.MEDIA_STOPPED) because that AudioPlayer instance is in STATE MEDIA_NONE.  Thus AudioPlayer.setState doesn't call the handler.sendJavascript to call the javascript Media.onStatus method that would call the statusCallback and the successCallback.
> I think that the AudioHandler should have a synchronized block that prevents 'create' and 'startRecordingAudio from running at the same time and that 'create' should use the same code that startRecodingAudio does:
>         AudioPlayer audio = this.players.get(id);
>         if ( audio == null) {
>             audio = new AudioPlayer(this, id, file);
>             this.players.put(id, audio);
>         }
> to prevent creating a second AudioPlayer instance if the startRecordingAudio thread executes before the 'create' thread.
> There may be other actions in AudioHandler.execute that need this synchronization as well.
> One effect of this problem is that the javascript successCallback is never called (after stopRecord)

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Updated] (CB-1599) successCallback not called after stopRecording, duplicate AudioPlayer objects created

Posted by "Bob Flavin (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/CB-1599?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Bob Flavin updated CB-1599:
---------------------------

    Summary: successCallback not called after stopRecording, duplicate AudioPlayer objects created  (was: successCallback not called after stopRecording, duplicate AudioRecorder objects created)
    
> successCallback not called after stopRecording, duplicate AudioPlayer objects created
> -------------------------------------------------------------------------------------
>
>                 Key: CB-1599
>                 URL: https://issues.apache.org/jira/browse/CB-1599
>             Project: Apache Cordova
>          Issue Type: Bug
>          Components: CordovaJS
>    Affects Versions: 2.1.0
>         Environment: Android 2.3? 
>            Reporter: Bob Flavin
>            Assignee: Filip Maj
>             Fix For: 2.1.0
>
>
> A successCallback is not called sometimes after stopRecording() is called.
> The problem is that javascript cordova calls to 'new Media()' and 'mediaObj.startRecord() are dispatched by androidExec (prompt) to new threads on the java side and are not synchronized.  Thus org.apache.cordova.AudioHandler.execute for action='create', calls new AudioPlayer().   Asynchronously, ...AudioHandler.execute for action='startAudioRecording' calls AudioHandler.startAudioRecording(), which gets a null from this.players.get(id) which causes the if statement to call new AudioRecorder which creates a second instance of AudioRecorder for that id.
>     public void startRecordingAudio(String id, String file) {
>         AudioPlayer audio = this.players.get(id);
>         if ( audio == null) {
>             audio = new AudioPlayer(this, id, file);
>             this.players.put(id, audio);
>         }
>         audio.startRecording(file);
>     }
> One instance of AudioPlayer goes into STATE MEDIA_RUNNING the other remains in MEDIA_NONE.  
> When the javascript calls mediaObj.stopRecord() (and mediaObj.release()) it may get the instance of AudioPlayer that is in MEDIA_NONE.  This prevents AudioPlayer.stopRecording() from calling this.recorder.stop() and this.setState(STATE.MEDIA_STOPPED) because that AudioPlayer instance is in STATE MEDIA_NONE.  Thus AudioPlayer.setState doesn't call the handler.sendJavascript to call the javascript Media.onStatus method that would call the statusCallback and the successCallback.
> I think that the AudioHandler should have a synchronized block that prevents 'create' and 'startRecordingAudio from running at the same time and that 'create' should use the same code that startRecodingAudio does:
>         AudioPlayer audio = this.players.get(id);
>         if ( audio == null) {
>             audio = new AudioPlayer(this, id, file);
>             this.players.put(id, audio);
>         }
> to prevent creating a second AudioPlayer instance if the startRecordingAudio thread executes before the 'create' thread.
> There may be other actions in AudioHandler.execute that need this synchronization as well.
> One effect of this problem is that the javascript successCallback is never called (after stopRecord)

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira

[jira] [Assigned] (CB-1599) successCallback not called after stopRecording, duplicate AudioPlayer objects created

Posted by "Simon MacDonald (JIRA)" <ji...@apache.org>.
     [ https://issues.apache.org/jira/browse/CB-1599?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel ]

Simon MacDonald reassigned CB-1599:
-----------------------------------

    Assignee: Simon MacDonald  (was: Filip Maj)
    
> successCallback not called after stopRecording, duplicate AudioPlayer objects created
> -------------------------------------------------------------------------------------
>
>                 Key: CB-1599
>                 URL: https://issues.apache.org/jira/browse/CB-1599
>             Project: Apache Cordova
>          Issue Type: Bug
>          Components: CordovaJS
>    Affects Versions: 2.1.0
>         Environment: Android 2.3? 
>            Reporter: Bob Flavin
>            Assignee: Simon MacDonald
>             Fix For: 2.1.0
>
>         Attachments: AudioHandler.java
>
>
> A successCallback is not called sometimes after stopRecording() is called.
> The problem is that javascript cordova calls to 'new Media()' and 'mediaObj.startRecord() are dispatched by androidExec (prompt) to new threads on the java side and are not synchronized.  Thus org.apache.cordova.AudioHandler.execute for action='create', calls new AudioPlayer().   Asynchronously, ...AudioHandler.execute for action='startAudioRecording' calls AudioHandler.startAudioRecording(), which gets a null from this.players.get(id) which causes the if statement to call new AudioRecorder which creates a second instance of AudioRecorder for that id.
>     public void startRecordingAudio(String id, String file) {
>         AudioPlayer audio = this.players.get(id);
>         if ( audio == null) {
>             audio = new AudioPlayer(this, id, file);
>             this.players.put(id, audio);
>         }
>         audio.startRecording(file);
>     }
> One instance of AudioPlayer goes into STATE MEDIA_RUNNING the other remains in MEDIA_NONE.  
> When the javascript calls mediaObj.stopRecord() (and mediaObj.release()) it may get the instance of AudioPlayer that is in MEDIA_NONE.  This prevents AudioPlayer.stopRecording() from calling this.recorder.stop() and this.setState(STATE.MEDIA_STOPPED) because that AudioPlayer instance is in STATE MEDIA_NONE.  Thus AudioPlayer.setState doesn't call the handler.sendJavascript to call the javascript Media.onStatus method that would call the statusCallback and the successCallback.
> I think that the AudioHandler should have a synchronized block that prevents 'create' and 'startRecordingAudio from running at the same time and that 'create' should use the same code that startRecodingAudio does:
>         AudioPlayer audio = this.players.get(id);
>         if ( audio == null) {
>             audio = new AudioPlayer(this, id, file);
>             this.players.put(id, audio);
>         }
> to prevent creating a second AudioPlayer instance if the startRecordingAudio thread executes before the 'create' thread.
> There may be other actions in AudioHandler.execute that need this synchronization as well.
> One effect of this problem is that the javascript successCallback is never called (after stopRecord)

--
This message is automatically generated by JIRA.
If you think it was sent incorrectly, please contact your JIRA administrators
For more information on JIRA, see: http://www.atlassian.com/software/jira