Skip to content

Commit

Permalink
Merge pull request #16964 from dominickuo/bug-973156-new-2
Browse files Browse the repository at this point in the history
Bug 973156 - [Music] Send mozinterruptbegin and mozinterruptend to system for show/hide the media playback widget, r=jimporter
  • Loading branch information
dominickuo committed Mar 11, 2014
2 parents b31771c + 65f2d24 commit b83a799
Show file tree
Hide file tree
Showing 8 changed files with 102 additions and 7 deletions.
18 changes: 18 additions & 0 deletions apps/music/js/Player.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ var PLAYSTATUS_PAUSED = 'PAUSED';
var PLAYSTATUS_FWD_SEEK = 'FWD_SEEK';
var PLAYSTATUS_REV_SEEK = 'REV_SEEK';
var PLAYSTATUS_ERROR = 'ERROR';
// Interrupt begin and end are the statuses for audio channel,
// they will be used when music app is interrupt by some other channels.
var INTERRUPT_BEGIN = 'mozinterruptbegin';
var INTERRUPT_END = 'mozinterruptend';

// We get headphoneschange event when the headphones is plugged or unplugged
// A related Bug 809106 in Bugzilla
Expand Down Expand Up @@ -140,6 +144,10 @@ var PlayerView = {
this.audio.addEventListener('durationchange', this);
this.audio.addEventListener('timeupdate', this);
this.audio.addEventListener('ended', this);
// Listen to mozinterruptbegin and mozinterruptend for notifying the system
// media playback widget to reflect the playing status.
this.audio.addEventListener('mozinterruptbegin', this);
this.audio.addEventListener('mozinterruptend', this);

// A timer we use to work around
// https://bugzilla.mozilla.org/show_bug.cgi?id=783512
Expand Down Expand Up @@ -1023,6 +1031,16 @@ var PlayerView = {
this.next(true);
break;

case 'mozinterruptbegin':
this.playStatus = INTERRUPT_BEGIN;
this.updateRemotePlayStatus();
break;

case 'mozinterruptend':
this.playStatus = INTERRUPT_END;
this.updateRemotePlayStatus();
break;

default:
return;
}
Expand Down
22 changes: 18 additions & 4 deletions apps/system/js/media_playback.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,19 @@ function MediaPlaybackWidget(container, options) {
// about doing something similar, step away from your keyboard immediately.
window.addEventListener('appterminated', function(event) {
if (event.detail.origin === this.origin)
this.container.hidden = true;
this.hidden = true;
}.bind(this));
}

MediaPlaybackWidget.prototype = {
get hidden() {
return this.container.hidden;
},

set hidden(value) {
return this.container.hidden = value;
},

handleMessage: function mpw_handleMessage(event) {
var message = event.detail;
switch (message.type) {
Expand Down Expand Up @@ -93,15 +101,21 @@ MediaPlaybackWidget.prototype = {
updatePlaybackStatus: function mp_updatePlaybackStatus(status) {
switch (status.playStatus) {
case 'PLAYING':
this.container.hidden = false;
this.hidden = false;
this.playPauseButton.classList.remove('is-paused');
break;
case 'PAUSED':
this.container.hidden = false;
this.hidden = false;
this.playPauseButton.classList.add('is-paused');
break;
case 'STOPPED':
this.container.hidden = true;
this.hidden = true;
break;
case 'mozinterruptbegin':
this.hidden = true;
break;
case 'mozinterruptend':
this.hidden = false;
break;
}
},
Expand Down
5 changes: 3 additions & 2 deletions apps/system/style/media_playback/media_playback.css
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
left: 0;
right: 0;
bottom: calc(10rem + 1px);
height: 12rem;
height: auto;
background: rgba(0, 0, 0, 0.75);
border-top: 1px solid #9c9a9c;
border-bottom: 1px solid black;
Expand All @@ -28,7 +28,7 @@

.media-playback-nowplaying {
height: 4rem;
margin: 1rem 1rem 0rem 1rem;
margin: 1rem;
}

.media-playback-nowplaying > .icon {
Expand Down Expand Up @@ -76,6 +76,7 @@

.media-playback-controls {
height: 4.5rem;
margin-top: -1rem;
overflow: hidden;
text-align: center;
font-size: 0; /* ensure there's no space between the buttons */
Expand Down
1 change: 1 addition & 0 deletions apps/system/test/marionette/fakemusic/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
<button id="stop">Stop</button>
<button id="next">Next</button>
</div>
<button id="interrupt">Toggle interrupt</button>
</body>

</html>
20 changes: 20 additions & 0 deletions apps/system/test/marionette/fakemusic/js/fakemusic.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ var albumOne = [

var FakeMusic = {
_mode: 'stopped',
_interrupted: false,
_queue: null,
_queueIndex: null,

Expand All @@ -29,12 +30,16 @@ var FakeMusic = {
},

play: function() {
if (this._interrupted)
return;
this._mode = 'playing';
document.getElementById('play-pause').classList.remove('is-paused');
FakeMusicComms.notifyStatusChanged({playStatus: 'PLAYING'});
},

pause: function() {
if (this._interrupted)
return;
this._mode = 'paused';
document.getElementById('play-pause').classList.add('is-paused');
FakeMusicComms.notifyStatusChanged({playStatus: 'PAUSED'});
Expand All @@ -48,23 +53,35 @@ var FakeMusic = {
},

stop: function() {
if (this._interrupted)
return;
this._mode = 'stopped';
document.getElementById('play-pause').classList.remove('is-paused');
FakeMusicComms.notifyStatusChanged({playStatus: 'STOPPED'});
},

previous: function() {
if (this._interrupted)
return;
if (this._queueIndex > 0)
FakeMusicComms.notifyTrackChanged(this._queue[--this._queueIndex]);
},

next: function() {
if (this._interrupted)
return;
if (this._queueIndex < this._queue.length - 1)
FakeMusicComms.notifyTrackChanged(this._queue[++this._queueIndex]);
else
this.stop();
},

toggleInterrupt: function() {
this._interrupted = !this._interrupted;
var status = this._interrupted ? 'mozinterruptbegin' : 'mozinterruptend';
FakeMusicComms.notifyStatusChanged({playStatus: status});
},

get isPlaying() {
return this._mode === 'playing';
},
Expand All @@ -86,6 +103,9 @@ var FakeMusic = {
case 'album-one':
this.startQueue(albumOne);
break;
case 'interrupt':
this.toggleInterrupt();
break;
}
}
};
Expand Down
8 changes: 7 additions & 1 deletion apps/system/test/marionette/lib/fake_music.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,9 @@ FakeMusic.Selector = Object.freeze({
playPauseElement: '#play-pause',
stopElement: '#stop',
previousTrackElement: '#previous',
nextTrackElement: '#next'
nextTrackElement: '#next',

interruptElement: '#interrupt'
});

FakeMusic.prototype = {
Expand All @@ -39,6 +41,10 @@ FakeMusic.prototype = {
return this.client.findElement(FakeMusic.Selector.nextTrackElement);
},

get interruptElement() {
return this.client.findElement(FakeMusic.Selector.interruptElement);
},

get isPlaying() {
var className = this.playPauseElement.getAttribute('class');
return !(/\bis-paused\b/.test(className));
Expand Down
30 changes: 30 additions & 0 deletions apps/system/test/marionette/media_playback_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,36 @@ marionette('media playback tests', function() {
});
});

test('should hide controls when interrupted', function() {
music.runInApp(function() {
music.albumOneElement.click();
});

playback[suiteInfo.opener](function(container) {
container.waitForContainerShown(true);
assert.equal(container.isPlaying, true);
});

music.runInApp(function() {
// XXX: It would be better if we had the audio channel code do the
// interrupt for us instead of just synthesizing the event, but this
// still tests the system app side of things adequately.
music.interruptElement.click();
});

playback[suiteInfo.opener](function(container) {
container.waitForContainerShown(false);
});

music.runInApp(function() {
music.interruptElement.click();
});

playback[suiteInfo.opener](function(container) {
container.waitForContainerShown(true);
});
});

test.skip('should play/pause from now playing widget', function() {
music.runInApp(function() {
music.albumOneElement.click();
Expand Down
5 changes: 5 additions & 0 deletions shared/js/media/remote_controls.js
Original file line number Diff line number Diff line change
Expand Up @@ -365,6 +365,11 @@ MediaRemoteControls.prototype.notifyMetadataChanged = function(metadata) {
MediaRemoteControls.prototype.notifyStatusChanged = function(status) {
// Send the new status via bluetooth.
if (this.defaultAdapter) {
// Don't send the interrupted statuses to the remote client because
// they are not the AVRCP statuses.
if (status === 'mozinterruptbegin' || status === 'mozinterruptend')
return;

var request = this.defaultAdapter.sendMediaPlayStatus(status);

request.onerror = function() {
Expand Down

0 comments on commit b83a799

Please sign in to comment.