Page 1 of 1

player.js: I can't access the Player object in player_add.js

Posted: Wed Oct 14, 2020 12:20 pm
by drakinite
I'm trying to write an extension that modifies the volume bar's behavior, but I can't access the Player object that is defined at player.js lines 630-1070. If I change player.js to do "console.log(this)", I get an object named "Player":
https://i.imgur.com/3YUwlIG.png

Code: Select all

{
  "container": {
    "initInProgress": true,
    "ListenObjectID": 1795
  },
  "disabledCounter": 0,
  "_disabled": false,
  "_tabIndex": -1,
  "_hasSplitters": false,
  "_dockable": false,
  "_isDock": false,
  "_controlTitle": "player",
  "_localPromises": [],
  "_dataSourceListenFuncts": [],
  "disableStateStoring": false,
  "_statusParams": {},
  "uniqueID": "uniqueID_38",
  "canBeUsedAsSource": true,
  "_cleanFuncs": [
    null
  ],
  "dragging": false,
  "dndEventsRegistered": true,
  "currTime": 0,
  "currState": "stop",
  "songLength": 0,
  "timeStep": 250,
  "ctrl": {},
  "ctrlsForTimeUpdate": [],
  "ctrlsForValueUpdate": [],
  "isSeeking": false,
  "isVolumeChanging": false
}
however, the global "player" / "window.player" object is different:
https://i.imgur.com/dBdF3Qj.png
and I cannot find a way to access that object.

Additionally, I attempted to get around this by directly querying the document to get the volume slider control... but its controlClass is undefined somehow.

Code: Select all

try {
	console.log(this);
	var volumeDiv = window.q('div[data-id=player-volumebar]');
	var slider = volumeDiv.controlClass;
	
	//HTML element as expected
	console.log(volumeDiv);
	//undefined
	console.log(slider);
}
catch (err) {
	console.error(err);
}

Also, unrelated, but it seems like the asJSON method for that global player object causes a crash. (log ID EF9B1F35)

Re: player.js: I can't access the Player object in player_add.js

Posted: Thu Oct 15, 2020 2:03 am
by MiPi
For the idea how to modify Player control look at sample script "pulsingPause" in SampleScripts folder (unzip mmip), which modifies behavior of pause button. This can be typically done by using override on Player class prototypes, where "$super" functions calls original function, window.playerControlsHandlers (defined in player.js too) contains functions for handling individual player controls (volume bar is under window.playerControlsHandlers.volume). Querying document will not work correctly, as it can contain more elements with controlClass "Player"(some in separate window, like for control for fullscreen video playback).
Global window.player contains app.player object, it is used for calling internal player functions in the main application (handling of play/stop/pause, skipping tracks, nowplaying list handling, etc.), and you are right, it does not support asJSON, it cannot be transformed to JSON, it would lose its functionality, it is not in Javascript. But it should probably return empty object, instead of crash :), I will look at it.

Re: player.js: I can't access the Player object in player_add.js

Posted: Mon Oct 19, 2020 9:11 am
by drakinite
Thanks for the help!

Strangely, it seems like the Player.handle_mousewheel function is never called. I think that's one of the reasons why I was confused. But I managed to get my code working after looking at the pulsingPause script :grinning:

Re: player.js: I can't access the Player object in player_add.js

Posted: Mon Oct 19, 2020 10:10 am
by MiPi
Strange, for me, Player.handle_mousewheel is called while hovering player control and rotating mouse wheel as expected and changes volume.

Re: player.js: I can't access the Player object in player_add.js

Posted: Mon Oct 19, 2020 2:40 pm
by drakinite
Oh, my bad. It looks like handle_mousewheel is only called when you're NOT hovered over the volume bar or seek bar; and the volume/seek bars have their own handlers.

I actually didn't have to override any event handlers in my code, fortunately. All I had to do was modify volCtrl.controlClass.stepSize; and the slider class takes the modified stepSize without a hitch. :grinning:

My goal was to implement this feature request in an extension, and it works seamlessly! :grinning:

Code: Select all

"use strict";

/**
@module UI
*/

// inside a try-catch block just in case
try {
	
	var defaultStepSize = 5;
	var fineStepSize = 1;
	var fineControlKey = 16; // Key code for shift
	var showToastMessage = false;
	var volCtrl;
	
	// Have to override Player.prototype in order to get access to the volume slider controlClass
	Player.prototype.override({
		initialize: function ($super, elem, params) {
			$super(elem, params);
			var volCtrlElem = this.ctrl['volume'];
			volCtrl = volCtrlElem.controlClass;
		},
	});
	
	app.listen(window, 'keydown', function(e) {
		// only enable fine control when it matches the right key code
		if (e.keyCode == fineControlKey) {
			enableFineControl(e);
		}
	})
	app.listen(window, 'keyup', function(e) {
		// only disable fine control when it matches the right key code
		if (e.keyCode == fineControlKey) {
			disableFineControl(e);
		}
	});
	// When window loses focus, we have to disable fine control just in case they let go of shift outside of the MM5 window
	app.listen(window, 'blur', disableFineControl)
	
	function enableFineControl() {
		if (showToastMessage) {
			uitools.toastMessage.show(' ' + _('Fine control: Enabled') + ' ', {
				disableUndo: true,
				disableClose: true,
				delay: 3000
			});
		}
		if (volCtrl && volCtrl.wheelStep) {
			// Change the control step size to the fine size
			volCtrl.wheelStep = fineStepSize;
		}
	}
	
	function disableFineControl() {
		if (showToastMessage) {
			uitools.toastMessage.show(' ' + _('Fine control: Disabled') + ' ', {
				disableUndo: true,
				disableClose: true,
				delay: 3000
			});
		}
		if (volCtrl && volCtrl.wheelStep) {
			//Change the control step size to the default
			volCtrl.wheelStep = defaultStepSize;
		}
	}
}
catch (err) {
	console.error(err);
}
Gotta be honest, developing extensions for MM5 is a lot of fun when it works.

Re: player.js: I can't access the Player object in player_add.js

Posted: Tue Oct 20, 2020 9:41 am
by MiPi
Yes, Player.handle_mousewheel only redirect wheel event to volume control, above some slider it is called directly on Slider.
Nice sample. Even though I will add something like this directly to slider control, will be in the next release.

Re: player.js: I can't access the Player object in player_add.js

Posted: Tue Oct 20, 2020 10:10 am
by drakinite
Thanks :slight_smile:

And cool, it'll be nice to have that in the official release! I guess I'll delete my addon submission that I uploaded to the site. :stuck_out_tongue_closed_eyes: