Hi, I did a small script to get the multiple 1pixelout players in the same page and make just one playing while the other are stopped.

So if there is one of them playing and you want to play another one, the first one stops.

First you have to include this javascript somewhere (I added via drupal_add_js in my template):

  var ap_instances = new Array();

  function ap_stopAll(playerID) {
    var numero ;
    var indice ;
    var longitot ;
    for(var i = 0;i<ap_instances.length;i++) {
      indice = ap_instances[i].indexOf("swf") ;
      numero = ap_instances[i].substring(0, indice) ;
      longitot = ap_instances[i].length ;
      //alert(numero.toString()) ;
       try {
         if(numero != playerID) {
           document.getElementById(ap_instances[i].substring(indice, longitot)).SetVariable("closePlayer", 1);
         }
         else {
           document.getElementById(ap_instances[i].substring(indice, longitot)).SetVariable("closePlayer", 0);
         }
       } catch( errorObject ) {
         // stop any errors
       }
     }
  }

$(document).ready(function() {
     
  function ap_registerPlayers() {
    var objectID ;
    var objeto ;
    var cadena = "" ;

    var indice ;
    var indice2 ;
    var a, b, c ;
    var cadenatotal = "";
    var longitud = $("[id^=swf]").length ;
    
    var pid = "";
    for (var i=0; i < longitud; i++) {
      objectID = $("[id^=swf]:eq("+ i +")").attr("id");
      objeto = $("[id^=swf]:eq("+ i +") > param").filter("[name^=flashvars]") ;
      cadena = objeto.attr("value") ;

      indice = cadena.indexOf("playerID");
      indice2 = cadena.indexOf("&");
      a = cadena.substring(indice,indice2) ;
      pid = a.substring(9,a.length);
      ap_instances[i] = pid + objectID ;
    }
  }

    var ap_clearID = setInterval( ap_registerPlayers, 100 );
    //var ap_clearID = setTimeout( ap_registerPlayers, 100 );
});

And then, when you insert the player 1pixelout, be sure to add the following to flashvars:

'flashvars' => array('playerID' => $item->id)

Complete example:

print swf(path_to_mp3,
                 array(
                    'params' => array('width' => '400px', 'wmode' => 'transparent'),
                    'flashvars' => array('playerID' => $item->id),
                 )
            );

Where $item->id is a number representing the player id. (You have to choose it yourself)

Hope this helps, and feel free to edit the script for improving it.

Maybe would be great if the "playeriD" could be added automatically when you insert 1pixelout player.

Comments

Stuart Greenfield’s picture

The suggested code does seem to work, but it is only usable with SWF Object 2 substitution (but that's not too much of a problem at the moment).

I start to tweak the code a bit to simplify it - why not simply stored the player ID and object ID as two arrays, to save lots of string splitting...

var ap_objects = new Array();
var ap_players = new Array();

$(document).ready(function() {
  
	function ap_registerPlayers() {
	
	  // Get all elements with an id that starts swf
	  var elements = $("[id^=swf]").length ;
	 
	  // Iterate over the elements
	  for (var i=0; i < elements; i++) {
	    
		// Set objectID to the id attribute of the n'th id starting swf  
		objectID = $("[id^=swf]:eq("+ i +")").attr("id");
	    
		// Get the parameter called flashvars relating to this id
		objeto = $("[id^=swf]:eq("+ i +") > param").filter("[name^=flashvars]") ;
	    
		// Store the value of this parameter
		cadena = objeto.attr("value") ;
	
		// Find out where playerID appears in the value
	    indice = cadena.indexOf("playerID");
	    
	    // Find out where the first ampersand is in the value
	    indice2 = cadena.indexOf("&");
	    
	    // The playerID variable is this substring
	    a = cadena.substring(indice,indice2) ;
	    
	    // The playerID value is a substring of that string
	    pid = a.substring(9,a.length);
	
	    // When a player is stopped then the stop function is called with the PLAYER id, but we need to target the OBJECT id in response
	    
	    // Store the id of the object
	    ap_objects[i] = objectID;
	    
	    // Store the id of the player
	    ap_players[i] = pid;
	    
	  }
	
	}

  // For this code to work ap_registerPlayers needs to be called after SWF Object has made its substitutions
  var ap_clearID = setInterval(ap_registerPlayers, 100 );

});

function ap_stopAll(playerID) {
	
    // Iterate over the array of players
	for(var i = 0;i<ap_players.length;i++) {
	  
      try {
    
    	// If this player id is not the playerID that was clicked then close it
        if(ap_players[i] != playerID) {
          document.getElementById(ap_objects[i]).SetVariable("closePlayer", 1);
        }
        else {
    	  document.getElementById(ap_objects[i]).SetVariable("closePlayer", 0);
        }
      } catch( errorObject ) {
       // stop any errors
      }
    }
}
tms8707056’s picture

I have found that it is simple enough to use Views to generate the playerID. My method only works considering that each audio file to be added to a player has its own node. You can then create a view that groups the nodes accordingly and insert a PHP custom field to handle the player. You can then specify in the parameters to use $data->nid as the playerID. Since each player is on its own node this will attach a unique ID to the players. Example code for the customfield PHP field below.

BTW, I am using this on my band's website to group individual songs into albums. I don't know if this will work for you or not. The view is embedded into a node for the album.

What I was having problems with was the inclusion of the JS for 1pixelout in the pages. However, that should be solved when I figure out the syntax of drupal_add_js as mentioned by davebv. Is it possible to add this to the view header or does it have to be in the template?

Let me know if there are any disadvantages to my method.

<?php
 
  // Load file field containing audio file from node.
  $file = field_file_load($data->node_data_field_audio_preview_field_audio_preview_fid);

  print swf($file['filepath'], array(
    'params' => array('wmode' => 'transparent'),
    'flashvars' => array('playerID' => $data->nid,)
    )
  );

?>
tms8707056’s picture

So I tried adding the drupal_add_js function in a theme hook located in a custom module, but I can't get it to work. Code below. Why is this not adding the js file to my pages?

function theme_1pixelout_javascript() { 
  $data = drupal_get_path('module', 'custom_module') .'/js/1pixelout.js';
  drupal_add_js($data, 'module'); 
} 

EDIT: Got the js to insert into my pages but it isn't having any effect on the players that are on my pages. The all have a unique ID but player A will not stop if player B is started. Any ideas why not? I'm using the js from Stuart's post.

davebv’s picture

I forgot to say this does not work with player 1pixelout 2 beta, it is just for version 1. (As I adapted the script is included in the .zip of 1pixelout)

I will try stuart code as soon as I can. Thanks Stuart!! I am not an expert in programming (as you may see hehe) so thanks for simplify it!.

In my setup, I tried with direct embedding settings and the code I posted works too. (do not know with stuart's, but seems the same to me)

Stuart Greenfield’s picture

Status: Active » Needs review

I made a commit on branch DRUPAL-6--2 that builds in code to onepixelout to automatically assign a playerID, and it uses a modified js script to avoid using setInterval to repeatedly trigger the player id collection (basically it collects the data it needs the first time you click a player, so it does it once only).

It works under SWF Object 2 embedding, but fails under direct embedding since the "double embedding" method doesn't allow the same id to to be used twice.

But if you want this script to work you have to have JS enabled, so I don't see an issue in using the SWF Object mechanism.

Player ids are generated in a similar way to SWF Object (time + identifier) so they are always unique. This means you should be able to rely on this script in, say, a Views page where you could imagine many players!

Let me know if it works for you and if it's good it will be in the next release.

PS - yes - this script is for version 1 of the player. When version 2 is released there'll need to be a new module and/or script to support it.

tms8707056’s picture

I am using 1.2.3 of the player. Should Stuart's script work assuming that each player in a view has a unique ID and the script is included in the page? I seem to be missing something.

davebv’s picture

Tested the 2.x-dev version with the new script Stuart commited and works out of the box with input filter and php (swf method and with swfobject2 embedding method.

As Stuart said, did not work with direct embedding, but this is not a real problem.

Thanks!

Stuart Greenfield’s picture

@tms8707056 - the modified code will assign a unique player ID automatically, and then the script will process the players to make them stop. No customised code is needed at all, so in things like Views it should just be a case of letting SWF Tools put the players on the page.

tms8707056’s picture

Got it working with the dev version. Thanks! Now, is there a way to do this with the generic player (the little round play button)?

Stuart Greenfield’s picture

Now, is there a way to do this with the generic player

Simple answer - No!

Seriously - the interaction relies on the player being written to handle an external interface via JavaScript. The generic player is a very small lightweight thing, designed really to make SWF Tools work out of the box. It doesn't have any of the code necessary to do what OnePixelOut does.

Stuart Greenfield’s picture

Status: Needs review » Fixed

Released in SWF Tools 6.x-2.5.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

andrewsuth’s picture

I am trying to implement the javascript stop code from a page.tpl.php but I am stumped how to retreive the playerID.

I have the following:

print swf($node->field_audio_reading[0]['filepath'],
                 array(
                    'params' => array('width' => '400px', 'wmode' => 'transparent'),
                    'flashvars' => array('playerID' => $item->id),
                 )
            );

But I cannot work out how to call the equivalent of $item->id for access the swf object like I am.

Am I going about access the data from the swf object in the wrong way?

EDIT: moved to a new thread: http://drupal.org/node/522720