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

To discuss development of addons / skins / customization of MediaMonkey.

Moderators: jiri, drakinite

drakinite
Posts: 253
Joined: Tue May 12, 2020 10:06 am
Contact:

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

Post 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)
Image
Student electrical-computer engineer, web programmer, part-time MediaMonkey developer, full-time MediaMonkey enthusiast
MiPi
Posts: 673
Joined: Tue Aug 18, 2009 2:56 pm
Location: Czech Republic
Contact:

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

Post 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.
drakinite
Posts: 253
Joined: Tue May 12, 2020 10:06 am
Contact:

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

Post 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:
Image
Student electrical-computer engineer, web programmer, part-time MediaMonkey developer, full-time MediaMonkey enthusiast
MiPi
Posts: 673
Joined: Tue Aug 18, 2009 2:56 pm
Location: Czech Republic
Contact:

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

Post by MiPi »

Strange, for me, Player.handle_mousewheel is called while hovering player control and rotating mouse wheel as expected and changes volume.
drakinite
Posts: 253
Joined: Tue May 12, 2020 10:06 am
Contact:

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

Post 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.
Image
Student electrical-computer engineer, web programmer, part-time MediaMonkey developer, full-time MediaMonkey enthusiast
MiPi
Posts: 673
Joined: Tue Aug 18, 2009 2:56 pm
Location: Czech Republic
Contact:

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

Post 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.
drakinite
Posts: 253
Joined: Tue May 12, 2020 10:06 am
Contact:

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

Post 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:
Image
Student electrical-computer engineer, web programmer, part-time MediaMonkey developer, full-time MediaMonkey enthusiast
Post Reply