Hi arthurf

Just raising to your attention swftools. I'm trying to provide broad api support for flash embedding and replacement and thus reduce the redundancy throughout contrib. Not just for swfobject, but for flash players and flash image rotators as well.

I notice that you initially approached rz on this thread. My goal is to make swftools a comprehensive and flexible api so if you are still interested in collaborating on this then I'd like to talk!

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

arthurf’s picture

Hi Sime-

I'd totally be into collaborating on this- i'd be happy to merge this module into swftools if that makes sense to you. Let me know and we can make it happen

sime’s picture

Great great.

I actually feel a little silly for missing your project when I started. I was focussing on a Flash Player API and the Flash Replacement API just seemed like an obvious add-on.

Are you normally in IRC? Or shall I email you when I'm ready to discuss details?

sime’s picture

Hi arthurf

I've just released
http://drupal.org/node/149048

Looking through your issues queue, I think I've covered most of the problems your users have raised.

sun’s picture

Title: swftools for comprehensive api » SWF Tools for comprehensive api
Component: Miscellaneous » Documentation

What's the status of this issue?

Sorry in advance, but I needed to add both modules to the new Duplicated Modules Hall of Shame list for Flash embedding/replacement. :P

I used SWFObject API without any issues on several sites before, but SWF Tools seems to be more flexible, maybe not.

Is it possible that you guys could join forces?

arthurf’s picture

Sun- you're seriously in trouble :) In the future, it'd be nice if you contact authors before you do this, not after.

There are a few modules out there that depend on swfobject_api so depreciating swfobject_api is objectionable to me. While I agree that swftools is doing many different kinds of flash replacement, swfobject_api fulfills a specific need and doesn't include the additional weight that swftools includes.

That being said, if we can create a compatibility layer for swfobject_api in swftools, I'm completely fine to have swfobject_api absorbed into swftools.

arthurf’s picture

In looking at swftools swfobject2.module, it looks like a wrapper function could be made for swfobject2_swftools_embed() out of theme_swfobject_api(). This could be included in swftools swfobject2.module which would allow for a fairly seamless transition.

Perhaps something like:

<?php

function theme_swfobject_api($url, $params = array(), $flash_vars = array(), $id = null, $attributes = array()) {
  $return_vars = new stdClass();

  // merge the id into $params
  $params['id'] = $id;

  // merge the url of the swf into $params
  $params['src'] = $url;

  // add the params to the vars 
  $return_vars ->params = $params;
  
  // add the flashars to the the vars
  $return_vars->flashvars = $flashvars;

  return swfobject2_swftools_embed(false, SWFTOOLS_EMBED_METHOD, $return_vars, $params['no_flash'], $attributes)
}

?>

I'm not quite sure about the first two params on swfobject2_swftools_embed(); Sime- if you could weight in here...

Secondly, it would be nice if swfobject2_swftools_embed() added an $attributes var which can set the attributes of the container div-

<?php
function swfobject2_swftools_embed($action = 'add_js', $methods = FALSE, $vars = FALSE, $html_alt = '', $attributes = array()) {
  ...
  $attributes['class'] .= ' swftools swfobject2';
  $attributes['id'] = $id;
  ...

  $html  = '<div '. drupal_attributes($attributes) .'>' . "\n";
  ...
}

?>

Any thoughts?

Stuart Greenfield’s picture

Hello! Stuart here- maintainer of SWF Tools. Just to acknowledge that I've seen this thread, and the transition layer looks fairly straightforward. Adding the capability to assign attributes makes sense, and is actually needed for some of the features that might derive from flowplayer3 where you need to know the id of the embedded content as you can't rely on the (essentially random) SWF Tools generated one.

I must admit I've never used SWFObject API as a module, but I'll grab a copy and see what I can do.

With respect to "weight" - I don't actually think the core of SWF Tools is that heavy - the whole package is big because of the player modules, but just SWF Tools 'core' and the SWFObject2 embedding code it's reasonable. You only have to enable as much (or as little!) of SWF Tools as you need. In any case, I am currently thinking about ways to slim the code further by making other elements "optional".

In the extreme what you'd end up with is a lightweight SWF Tools core that would probably look a lot like how I imagine the SWF Object API looks. That would be for those users who know how to call the theme function via PHP. Then on top of the core you add the filters, players and playlist functions. It might just take a while to work out the best way to do it. With Drupal 7 coming it seems a good time to address this though.

Out of curiosity, SWF Tools currently supports a range of JS replacement methods. How many of these are actually needed? I'll need to start thinking about SWF Tools 7 at some point, and while the embedding modules are relatively simple do we really need so many choices??!!

arthurf’s picture

Status: Active » Needs review
FileSize
7.79 KB

So I took some of the aspects of SWFObject API and merged these into swfobject2.module. This includes writing the JS to the footer using the cache option on drupal_add_js, as well as doing some reorganization of how the actual build process works. I also added a JS file that does the actual embedding process via jquery. There is also a compatibility layer for SWFObject API. This is included in the patch- hopefully this is not too much of a departure from the original. Also, this is only for D5. If this concept is acceptable, I'll do a patch for D6 as well.

sun’s picture

Component: Documentation » Code
Category: support » task

@Stuart: Arthur has taken the necessary and unselfish steps to announce the module merger publicly and even worked on a patch. Now it's your turn: Can you grant him CVS access to SWF Tools?

Obviously, there are still many things to rule out and discuss. But I'm sure you will be able to do so. One thing that may help you is to settle on common standards for development, maintenance, and collaboration - the Best practices for co-maintaining projects are here to assist you.

arthurf’s picture

Stuart is on vacation for the next week, and we've talk about getting the modules to work together- we're both on board for it, we just need to work out the code logistics at this point. FYI, there is now also http://drupal.org/project/swfembed . Roger Lopez contacted me about dealing with the swfobject module. So I'm going to look at how that might be supported in swftools- it maybe the case that swfembed could handle it.

sun’s picture

So Stuart agreed already? Shall I grant you CVS access to SWF Tools?

arthurf’s picture

Let's wait until he's back from vacation- I'd like to do this with him to make sure that we have an agreement about coding styles, etc. Since I've already made the announcement and posted the patch, anybody who is looking to use swfobject api should see it.

mbutcher’s picture

I'm one of the co-maintainers of SWF Embed (http://drupal.org/project/swfembed), which is designed to be a very lightweight module for adding generic Flash support. It differs from SWFObject API in one major way: It uses a jQuery plugin instead of the SWFObject JavaScript toolkit (and the reason for this is that we experienced cross-browser conflicts regarding jQuery's ready event and swfobject's sorta-ready event.)

We'd certainly be interested in any moves to provide a common abstraction layer over various backend libraries. Ours is a pretty low-level implementation (with a very simple API). We're not interested in growing this into something like SWF tools. We just needed an alternative to the SWFObject JavaScript library.

(For the history on SWF Embed, see #407030: Why another module for SWF?.)

Stuart Greenfield’s picture

Hi all - I'm still away enjoying some sunshine, so I'll read all this properly and get things going when I get back. However, despite being away I have been able to do some Drupal stuff in the evenings (sad I know, but it is addictive...)

First, in terms of SWF Embed, I did some work in parallel. The more I thought about it the more I thought why go to the trouble of writing a conversion layer for SWF Object API? SWF Tools calls a "wrapper" function so I can very easily meld that in to the API format. I did that first, and it works great, but some changes are needed to the API to support things like cached content from filters. I have all that running, but no way at the moment to post the code back.

Anyhow, the next thing I've already done is get the API module in place in SWF Tools. That's now working fine - no conversion layer needed for existing API users, and the module activates without needing the main SWF Tools module. I have rewritten a chunk of SWF Tools so it now has what I'm calling "core" parameters that are shared across SWF Tools AND the API, so if you use either you put all your settings in one place.

This should all give a fairly seamless transition for all concerned. SWF Tools users simply install the new SWF Tools and off they go. SWF Object API users would disable their existing API module, enable the SWF Tools API, and off they go. It should also allay any concerns about SWF Tools being "bloated". I don't actually think the module is. Each part is quite small, but if you enable the whole it is a bit bigger, but then it does an awful lot for you!!!!

In terms of other methods, I am thinking about D7 - SWF Tools supports a lot of what are probably legacy embedding methods. It would make sense to me to focus on one or two "preferred" methods. That said, getting SWF Tools to interface to any method is actually very easy.

Stuart Greenfield’s picture

The sunshine is good for thinking (and so was a glass or two of beer). I was thinking about the whole concept of a flash API, and captured it in this (fairly long!) post I wrote while I was away and am finally back on-line and able to share!

Rather than having lots of different implementations for inserting SWF, using different functions and different layouts, why not have a true "API" in the sense of the forms API.

At the moment different methods use different functions, so if you settle on one, and then realise you need another, it is difficult to reconfigure your code to accommodate the change.

If all the SWF data is wrapped up in a single array, and that is then passed to theme functions that then interpret the array things get easy. The "API Array" becomes a standard way of expressing data, and it is also extensible. If a module wants to support additional elements these can be added to the API, while other modules that don't understand that element will simply ignore them.

It would make sense to structure the API like the forms API, and prefix element descriptors with #, to make clear what they are.

Other modules that want to use flash could then construct an API array, and embedding methods implement the ability to interpret the array of data, so any module can then interface to any embedding method.

Users could call theme functions directly, simply passing the array of data, or you could imagine having a "wrapper" function, and the user can choose from available methods, like SWF Tools already offers. Having a "wrapper" might make sense since things like determining defaults could be done once in a wrapper. It would probably simply be a theme that goes on to call another theme?

It could simplify things like audio and video modules since they could simply respond by returning an array of data in the API format. The person writing the module, or template, can then implement any embedding method that suits their needs, including writing their own method.

This is where a wrapper API function makes sense. A generic video module would call the wrapper, and it wouldn't need to know what the user is going to use for the final embedding. All it needs to know is that it can pass an SWF array, and it will get back some mark up that will work. The user chooses their own configuration on a separate settings page somewhere.

It would free writers of modules that implement things like audio or video players from having to write embedding code. That could be very useful for users who need to use a particular embedding library because it gives them some specific feature, and it would mean if you need a JavaScript library you can install it once, in one place.

Suggested API format

#file / #movie / #swf
The file to play, either as a path or a full url. Not sure what the right name is for this element. File is simple, movie is consistent with Adobe, swf would be analogous to img for an image tag. Not sure what the answer is!

#height
The height of the file - distinct from params since it appears in different places in different embedding strategies. Should probably default to 100% if not supplied. Modules would need to accept heights in % or absolute terms.

#width
The width of the file - distinct from params since it appears in different places in different embedding strategies. Should probably default to 100% if not supplied. Modules would need to accept widths in % or absolute terms.

#parameters
An array of parameters (flash parameters) to apply to the embedded flash. Check with the Adobe knowledgebase to verify what goes in here, but it would be all those things that logically appear as parameters, such as allowFullscreen, play, loop and base. Not sure if themes should generate defaults if nothing is provided. This is where a wrapper with a set of defaults might help since it would provide predictable behavior, and the theme then goes on to call other themes.

#flashvars
An array of flash variables to apply to the embedded flash

#cacheable / #inline
Not sure what this should be called. But it is is needed to ensure that returned JavaScript is placed inline for those modules that use a JS embedding technique. Basically indicates to the module rendering the flash that whatever it does needs to be done in way that can be cached. That would normally mean returning code inline with the markup as this can be captured by the filters for subsequent caching. Not sure what the default should be.

#express
The path to an express install implementation, for code that supports it. If not provided it would default to FALSE - no express install.

#alt
Just borrow from regular HTML - the alternate text to show if the flash embedding fails. If not provided not sure it should necessarily generate a default, but that would be up to the embededing module. Could just insert a comment to show something is missing?

#id
The id for the swf. If this isn't supplied the rendering function will need to do something sensible. Do we need a way of returning what the div was, in case another function wants to use it? Could imagine having sequential swf id's using a function to track some counter variable, or we stick with the current format of time() + counter. See also form.inc form_clean_id().

#attributes
Same as form API. Array of attributes to tag on to the container div? Or a wrapper div?) using drupal_attributes() to generate the string. E.g. ['#attributes']['class'] = 'myclass'. Look at form.inc theme_fieldset().

#theme
If we work on the basis that there is a "wrapper" api that handles things like assigning ids in a logical manner, determining default parameters, and perhaps even letting the user choose an embedding approach, then #theme would tell the wrapper what theme function to go on and call. Using #theme is consistent with the form API.

#type
Is this needed? Do we assume everything is #type => 'swf'? Could always be included as even if not used now it could be an assumed default, but reserved for potential future use?

#weight
Not sure this can be used? The themes to generate swf will be being called by other functions, so it is probably up to them to implement an appropriate weighting.?

#???
Any others that are necessary from the outset?

Implementing modules / themes that use JavaScript would need to implement a hook_init() to put their script library on a given page.

So the code would look something like

print theme('some_swf_implementation', $swf_array);

That would be for a direct call to a theme function that can process an SWF API array. It returns a string of markup.

If there were a wrapper function it would be something like

print theme('swf_api', $swf_array);

On its own, without a #theme, it would direct the array to the current default method. Alternatively the $swf_array could include '#theme' => 'some_swf_implementation' to specify a requirement to use a given method.

Again, this returns a string of markup.

This now looks very neat, since the user only has to write code, or use a module, that outputs an SWF array. It is up to them whether they then go on and pass that array to a direct emedding method, a JavaScript method, or whatever they want. Because everything goes via a single $swf_array they don't need to rewrite their code if a new/better/more appropriate embedding method is needed. They simply rewrite their code to call the different theme. Or if there is an API wrapper layer, they simply reconfigure that to direct rendering to their chosen method. That would allow people to choose the method that best suits their needs.

The other advantage of using themes is that all the code associated with generating the mark up for swf content is now themable, so it can be overidden if the end user wants.

This actually also suggests that SWF Tools "splits" in to two logical components. An API layer that really does nothing more than implement embedding methods, and then the "Tools" component that provides all the file handling and playlist capabilities. If you're writing a website and you know how to use flash, you can take advantage of the lightweight API layer to put your content on the page. If you want a fully functional solution to handle your media, you enable the full SWF Tools suite.

SWF Tools becomes a standard technique, and if the code base for the core embedding layers can be made very stable then other flash based modules could be encouraged to adopt the API layer, simplifying their code, the need to install multiple JavaScript libraries etc. If needed custom Drupal embedding libraries become possible / practical.

Maybe SWF Tools needs to divide in two - a "core" or "API" layer that enables the basic embedding functions and themes, and a "Tools" layer that adds support for file handling etc via the swf function.

Strangely, that thought had crossed my mind as a "neat" solution just for SWF Tools, but I couldn't see a strong driver to do it. The model above actually says this is the right way to go!

A "power" user would simply enable the API layer of SWF Tools, along with their preferred embedding strategy. They can call theme('swf_api') or theme('some_swf_implementation') directly from their template, module etc

A "regular" user would enable the API layer, and then extend that with the Tools layer to get access to the CCK filter, the input filter, the ability to render mp3 and video in a media player, and so on.

That should answer the concern that SWF Tools is "too big" - the API layer would be pretty light since it wouldn't do much at all as it assumes you know how to call the themes.

To simpify transition it becomes quite easy to write a "conversion" layer that takes existing function calls and turns them in to calls to the new API layer.

I've done some crude development locally and have a prototype that proves the concept. It does nothing more that implement theme('swapi') (a wrapper that does some basic validation and assigns ids) and theme('swfapi_direct') (that takes an API array and turns in to directly embedded content).

Does this sound like something work exploring? It means a bit of a step change for existing content, but with Drupal 7 coming it might be a good time to establish this??

Stuart Greenfield’s picture

I've been working on this on and off for a few days, and it's actually looking quite good.

After a few false starts I'm now working on a model that creates a new component module within SWF Tools that I'm calling "SWF Tools API". This is basically a "wrapper" module with a few helper functions in it, but the key thing is it implements a theme called 'swf'. This is essentially a wrapper that accepts an "SWF API" array and then passes it on to other themes for rendering. The key concept is that other modules only need to know about theme('swf') since that theme will pass the data on for you.

The "API module" does a few things like ensure the ID is unique, sets the minimum required parameters for flash, but not much else. I'm trying to make it do enough to be "helpful", but light enough so as to be quick. It then passes the content on to other small modules that implement themes that actually turn the array in to content. These "rendering" modules implement simple themes that turn the API array in to markup / javascript.

At the moment I have it working for direct embedding, SWF Object 2 (SWF Tools style) and SWF Object (SWF Object API style).

The API is pretty much using the format I outlined above.

The next logical step is to build in the "method gathering" feature of SWF Tools to the API, so it becomes easy to install and choose your embedding method.

I think this has real potential - if an (unspecified) module wants to generate flash it can simply output the API array, and call theme('swf', $swf). It doesn't need to know anything about how the swf will be rendered, and it would mean that instead of every module that uses flash having its own embedding library there is a "standard" means of talking to ANY library.

My plan is, as a minimum, to rewrite SWF Tools itself to work via this API since it exposes the flash capabilities to everyone without having to install the main SWF Tools module.

At the moment the files are parcelled up on my local machine, on a non-CVS copy of SWF Tools, but if people are really interested I'm happy to zip it, or otherwise I'm hoping it will move to HEAD when it's looking reasonably stable.

No-one commented to the earlier post so am I going down a blind alley here??!!

Stuart Greenfield’s picture

This coming together really well (I think).

After some more work I've overhauled things even more, and am now working with the concept that 'swf' is made a new element type, and then we can simply call drupal_render($swf) to output the content. Things like id clean up can be handled by assigning a pre-render function, and it now means that embedding methods are simply registered by defining them as a theme, and setting the #theme property of the swf API array.

So the default is #theme = 'swf', and that's built in to the API module. SWF Object, for example, is registered as theme_swf_swfobject, and to use it you simply set #theme = 'swf_swfobject'.

Using drupal_render means that things like #prefix and #suffix are handled automatically.

So for the user there is now no change to implement a different embedding strategy since the flash definition is now all in the API. All they have to do is set a new theme (and my plan is to make that selectable much as it is for SWF Tools, in the event a specific theme isn't requested).

I'm just working out a few last bits and then I'll post here, probably as a zip, since I don't want to mess up the SWF Tools CVS at the moment. My next step is going to be to change my local copy of SWF Tools to talk to the API, but I now don't see that being very difficult at all.

By way of example, here's the PHP code from a node I'm using to test the onepixel out player rendered via the API:

$swf = array(
  '#type' => 'swf',
  '#movie' => '/new/sites/all/modules/swftools/shared/1pixelout/player.swf',
  '#height' => 50,
  '#width' => 200,
  '#flashvars' => array(
    'soundFile' => 'http://localhost/head/sites/default/files/Limbo.mp3',
  ),
);

print drupal_render($swf);

The API intelligently assigns an id as one wasn't given, and you get a player.

But if you want to get clever you can use something like

$swf = array(
  '#type' => 'swf',
  '#movie' => '/new/sites/all/modules/swftools/shared/1pixelout/player.swf',
  '#id' => 'myContent',
  '#height' => 50,
  '#width' => 200,
  '#alt' => 'Sorry it didn\'t work out.',
  '#parameters' => array(
    'Play' => 1,
  ),
  '#attributes' => array(
    'class' => 'myclass',
  ),
  '#version' => '10.0.0',
  '#cacheable_script' => FALSE,
  '#prefix' => '<div id="myDiv">',
  '#suffix' => '</div>',
  '#flashvars' => array(
    'soundFile' => 'http://localhost/head/sites/default/files/Limbo.mp3',
  ),
  '#theme' => 'swf_swfobject',
);

print drupal_render($swf);

and that passes a whole load more information, and in this case switches the output to swfobject.

Well, I'm having fun trying this out...!!! Does anyone else have any input on this?

Stuart Greenfield’s picture

Last post for tonight...

Of course, what I just realised is that by implementing it this way you can now add flash content directly to a node, simply by putting an swf API array in it.

To simulate this I added

// Test function to try adding swf to a node via the API...
function swftools_api_nodeapi(&$node, $op) {
  
  switch ($op) {

    case 'view':

      $node->content['swf'] = array(
        '#type' => 'swf',
        '#movie' => '/new/sites/all/modules/swftools/shared/1pixelout/player.swf',
        '#height' => 50,
        '#width' => 200,
        '#flashvars' => array(
          'soundFile' => 'http://localhost/head/sites/default/files/Limbo.mp3',
        ),
        '#prefix' => '<p>This is being rendered from the node directly!</p>',
        '#weight' => 50,
      );

  }

}

to my api module, and I now get a onepixel out player on all my nodes, and I haven't had to call any functions. Thinking ahead, would this means that any modules that embed flash could take advantage of the API simply by adding their output to a node in this way??

Stuart Greenfield’s picture

I'm going to try and parcel the code up over the weekend and post it so others can have a look.

It's working well, and as a proof of concept I now have it interfacing to swfEmbed (in this case you install swfEmbed, but then you also install a small SWF Tools API module that acts as the interface).

So what I can do now is add swf content to my test site using the API array, and switch at will between direct embedding, 'SWF Tools style' SWF Object 2, SWF Object API (which, for some, I hacked to make a local implement rather than an interface), and SWF Embed via an interface module.

The content arrays never change, and I don't need to know anything about how the embedding works (as an end user). If no theme is set then the API uses whatever I have as default, while if I set a specific theme it uses that.

--edit
I meant to say I've also tested a quickly modified SWF Tools that is now generating output via the API. That worked first time, and the code within SWF Tools looks much simpler as a result. It is immediately clear how the flash is built, and there's a simple call to drupal_render to get the markup!
--/edit

Stuart Greenfield’s picture

FileSize
12.37 KB

I've attached a zip with the basic API in it. This has the API module itself, which includes direct embedding, the admin settings, a module to interface to swfembed, and a sample swf which is shown on the admin page. If you examine the admin form you can see that the swf element is generated simply by declaring an element of type swf on the form, so in itself that pretty much demonstrates the API.

The package in here is in a folder called 'swftools_api' so it is installed separately, and independently of SWF Tools. Locally I have modules working with SWF Object 2, but for the purposes of demonstration I didn't attach those. This means that the attached version doesn't need any additional JavaScript to be downloaded.

I've documented the code very liberally, partly as I'm trying to get to grips with Doxygen, but mainly as I found that trying to put down in the file what the code is supposed to do helped me decide if it was doing the right thing. That means you should be able to read the module and understand where I'm coming from.

I've never tried anything quite like this with Drupal before, so I'd welcome any comments!

I'm also trying to decide whether this module, if it has value, should be part of the whole SWF Tools suite, or whether it should be separated out and is actually a separate, but related module. As an aside, I did think of calling it SWFT API (as in SWF Tools API, and pronounced Swift API), but only because it sounded kind of neat!

arthurf’s picture

I really like the direction this is going. Thanks for your hard work and thinking!

A few things:

#file/#movie/#swf
I would vote for #path here. The reasons for this are as follows: 1) could be local or remote. 2) might not be a swf (potentially support QT with this?) 3) while flash objects are often called "movies" I think it's a bad name space- for someone doing audio, it is odd to have to set #movie

Params
A full list of params is here: http://kb.adobe.com/selfservice/viewContent.do?externalId=tn_12701 I agree that this should just be an array.

Cachable
I think this should be boolean, default to true. Because we can handle this both by drupal_add_js and a filter that implements this API should be able to handle this in the cases where things can't be cached.

Express
It strikes me that this could be a global setting that can be overridden, but is set via admin interface... not sure though

Alt & Attributes
Thumbs up on using drupal_attributes(). Can't we handle the alt tag in attributes as well?

Type
Well... if we wanted to handle QT as well.... then we might want to consider making this definable, or at least ignoring it unless there is something there.

Weight
I'm not sure that this is necessary- I feel like things should be displayed in FIFO, but maybe I don't know the use case you're thinking about

Anyway, great work on this. It is starting to feel more like an "embed api" rather than just flash, but perhaps I should shush and help you code it!

arthurf’s picture

Looking at the quicktime spec: http://www.apple.com/quicktime/tutorials/embed2.html it seems like we could handle basically everything the same way with one exception that I found dontflattenwhensaving is not a $key=>$value so I'm not sure how we'd handle it- perhaps it would be a special case? I don't even know how often that particular item is used anyway....

Stuart Greenfield’s picture

Hi! I wasn't sure if this thread had died - I seemed to be happily filling it up with my long rambling posts and no-one was replying.

First, "It is starting to feel more like an "embed api" rather than just flash" - I had exactly the same thought, but I'm focussing on flash first. If it becomes a more generic API then the set of properties becomes a little vague since properties are different for different embed types. I'll work it up as an swf API for now, and then see how it looks. In a way the type doesn't matter - the way the API works at the moment is that it is actually the theme that controls how the content is rendered. Assigning #type = swf simply means that if the theme isn't set it will default to theme_swf().

I like the idea of using #path instead of #movie. #path is more generic, so if we expand the API further then we're in place to grow.

I like the idea of #cacheable in place of #cacheable_script - again, much more generic, plus less typing.

I did wonder about building #alt in the attributes. That does make sense, since for an image the alt tag goes in with the tag. But for a lot of embedded content we might want to put the alt content elsewhere. I'll investigate the drupal_render() code, but one option might be to use alt as a generic place to store the alternate content, and then let themes pull it out or move it around?? Not sure - will need to think about this.

If I remember rightly then #weight is a generic item, and is normally set on the element for renderer to know where to place the content. So #weight will be a valid property, but the api doesn't need to do anything.

As this project looks like it might going in the right way I am contemplating committing it on CVS to enable collaboration, but I won't create any project pages. The reason I have held off until now is that I really don't know what to call the project!

At the moment everything is "swftools_api_", then I had the idea of "swft_"... I'd like to get the code available and start to take advantage of patches etc (plus it means I have a backup!) so I should probably quit thinking too hard about it. But I think having a sensible name from the outset will save a lot of refactoring later. My current favourite is swft_, largely because it is less typing in the code, particularly when defining swftools_api_swftools_api_info()! Do you have any thoughts or suggestions on this??!!

Thanks for the positive feedback! I'm about to do another couple of hours on it, so I'll build in your suggestions now!!

Stuart Greenfield’s picture

I was thinking some more about planning ahead for a "generic" API. Maybe a way to do this would be to define the #type as embed. Then use a secondary property of #embed or #embed_type #subtype which could be swf, quicktime. Basically any type of embed that a theme can support.

Thinking out loud, if we set #type to embed then drupal_render() would call embed_elements(). From the new property of #subtype we could we piggy back out to a new custom hook to get the defaults for that embed type, so now we have our defaults for a specific embed going back. In those defaults we include an appropriate #pre_render if one is needed to get the content ready for theming. In this way the embed api would expand quickly and easily. Thought some more - could simply adopt a convention of #type = embed_{subtype}. Now we let drupal_render do everything for us. No fancy code - that I like a lot. Now we don't need #subtype and piggy backed hooks!!

So how would this handle things like audio? #type = embed, #subtype = audio. SWF Tools can embed audio, but it does it as flash. So how would SWF Tools interact with an embed_type of audio? Would SWF Tools just declare a theme that it has theme capable of embedding audio? In theory, in the case of SWF Tools, yes. All SWF Tools wants to get is a filepath - it can work everything else out from that (so a good reason to use #path, not #movie!) In theory this sounds hugely powerful. In practice... is it a nightmare waiting to happen??!! I'm thinking there would be some additional data in hook_embed_info() that declares the type of embed the theme offers, then we'd need some settings page to produce selectors to choose how we want that content embedding. I can really see some attractions in this...

Thinking some more, I don't think we have to decide now. We have themes that are capable of handling type #swf. If we extend the API later we still have themes, all they do now is handle #type = embed, #subtype = swf.

I still like the idea, but it might be too much too soon as we're just starting down this track. I think I'll stick with the single swf for now and get that working really nicely (although I don't think it's far off already!).

Any thoughts?

Stuart Greenfield’s picture

FileSize
18.87 KB

Last one for tonight - I've attached a revised zip with the "proof of concept" API in it. This one includes the module to support SWF Object 2 (put the swf object 2 files in libraries/swfobject).

This uses the properties #path and #cacheable as suggested. While not essential to the functioning of the module it also has what I think is a rather cool settings page (borrowed somewhat from the theme settings page)!

Seeing as I'm starting from scratch I decided to set out and document thoroughly per Doxygen, so there's a lot in there.

arthurf’s picture

Ok, lots to go through here! Somewhat in chronological order:

type
If I'm reading the standard correctly, #type ought to be a mimetype. At least, if you look at: http://www.w3schools.com/TAGS/tag_object.asp. Well, looking at this list, the #attributes value should handle the object type. Possible values are: align, archive, borader, classid, codebase, codetype, data, declare, height, hspace, name, standby, type, usemap, vspace, width. These can all be covered with #attributes, so perhaps never mind.

I've been going back and forth for the last half hour on this #type thing. What I don't like about it is that, in general, file "types" are yucky to me- meaning that when we call something a SWF, we're not really describing the file, but the file format. I don't want to use the file format to describe how to display it (although there may be no choice on this one). So an example would be a flash based audio player vs. a flash based image slide show. I think the question really comes down to how to define what exactly the #type and #subtype mean.... It feels like they are an attempt to auto define what theme function should ultimately be used- which is a great idea, I just am unclear how we would develop that criteria.

just a filepath
In #24 you're pondering about just getting a file path for swf tools.... I'd argue against this one- or at least, in the theoretical sense beacuse I still want to embed objects with JS, but some objects do not have a path, they have param src=$filepath Of course, I'm pushing for the broader use cases, but I'd rather have the API as abstract as possible... that may mean that swfobject.js doesn't get to play all the time, but.....

alt
The thing that gets me on this is that it really makes sense as "alternative display" but it means something quite different in the context of the no flash display vs. the alt tag of a link. At least, in my mind it does. It is not a legal tag for an object, so maybe we can hijack it? That doesn't make me exactly feel good, however, we're basically doing what the characteristic intends, so maybe it's fine, and if it's not.... we'll burn that bridge when we get there.

weight
Sure, not required works for me, that way if some theme operation wants it, it is there for code that has defined it

the name
Well.... I'd argue for something more generic- especially if this can support QT content out of the box.... how about "embed_api" ? Are there kinds of embeddable objects that this won't support? Looking at the specs for objects, I think we'd be completely safe with calling it something general like embed or object api- though "object" would get the name space messy quickly.

Thanks again for all your work on this. I'll check it a bit tomorrow and hopefully have more meaningful feedback.

a.

Stuart Greenfield’s picture

mimetype - genius.

I was thinking about this a bit - we make the #type = embed, then we have a new property #mime / #mimetype / #mime_type (take your pick - not sure which is "better"), and then we put all the object data as an array under the #value property of the element. I think under there I'd stick with the convention of # in front of the property names, although that could be dropped since we are now "hidden" from drupal_render(). Personally I find the # helps in the code as it makes it clear where I'm referring to properties to do with the flash element, versus those that are arrays internal to the operation of the module.

The beauty of this approach is that now we can define content to be embedded using an existing and established protocol, and it doesn't matter what the content is CALLED, just what it IS.

Secondly, we only add one "new" property to an element - the mimetype, and we can tuck an arbitrary number of object properties under #value without polluting the main element properties.

The hook_api_info() gets extended a little bit so it reports back the mime types it can handle, and the themes it is offering in support of them.

I *really* like the sound of this.

What would it mean in practice? I was thinking about audio since as I've been thinking about flash too much! A conceptual audio module would have two parts. The first would output an element of #type=embed #mimetype=audio/mpeg #value={some_data}. That is then exposed in the Drupal node waiting to be rendered. The audio module also provides a theme for putting the content in a player that it provides. It exposes that player to the API through hook_embed_info(). But other modules might provide alternative players. They are also exposed through hook_embed_info().

On my conceptual settings page I have a tab for audio/mpeg. On there I choose the player that I like. If everything worked in this way I could combine any Drupal module for providing audio content with any audio player - I am not tied down in to "I like the way module A lets me upload files, but I'd rather have the player in module B".

When drupal_render() comes along it sends the audio element to the embed API, and the API sends it to my player of choice for rendering. This sounds hugely powerful. I can write a module that is really good at managing audio files, but I don't have to write a player - I leave that to people who write really good players.

The only thing everyone would need to know is what is the specification of the object in the API - in the case of audio would that be as simple as just the path to the file I want to play? The audio players provide their own customisation internal to themselves - the API doesn't care?!

As an aside, I get decide about the #alt versus #attributes['alt']. On balance I think I like the #alt format as it would be easier to write in code, and alt won't have meaning for all types of embedded object. #alt uses a tag that people are familiar with, but leaves it up to the theme functions how that want to implement it - it might be as a tag for images, it might be inline markup for flash?

sun’s picture

dontflattenwhensaving is the same as dontflattenwhensaving="dontflattenwhensaving" in XHTML (and required to note this way in HTML Strict).

Please use [#attributes]['alt'] - keep it standard. People do not want to learn custom element #properties. Most of what goes into HTML attributes should be defined via #attributes.

arthurf’s picture

#alt
I agree with sun here- if this was supported for <object> it would go under #attributes, however it's not, so let's bag it. I propose: #no_support which means the HTML display when the <object> #type is not supported. Also, we could make this a function call back so that we can fire a specific #no_support behavior. For example

<?php
  $objects['my_video'] = array(
    '#no_support' => array('my_no_support_function => array($arg1, $arg2 ....
?>

And then on the build side we just check to see if #no_support is a string or function. We could handle the flash express install this way. Also we should send the full $objects['my_video'] to the function call so the #no_support property can decide how it wants to interact with the <object>

#type aka mime
This is going to be a bit tricky for auto detection that is not local. The code author can set the value, but my preference is that it will be auto detected. With the soon to come php stream wrappers (see http://drupal.org/node/227232) I think we will be able to handle remote files, but it is a cautionary note. Secondly, I think this needs to be handled under #attributes to keep things consistent with how the HTML is actually built

#path
I'm realizing this should be an attribute... this lets the author deal with if it is a src, movie, etc.

#params
I've been thinking about how to handle the data structure of params vs properties. So for example, we have an object:

<?php
  $objects['my_video'] = array(
    '#attributes' => array('class' => ... 
    '#no_support' => t('Sorry, this is not supported on your browser, please upgrade'),
    '#params' => array(
      'height' => 300,
      'width' => 200,
      'quality' => 'high',
      'flashvars' => array(
        'foo' => 'bar'
      ),
   ),
   '#theme' => 'my_theme_function',

?>

While I recognize that this is slightly more code to write, I think it is more consistent with how the

is actually built. I know that I'm pushing for the more abstracted version of the concept, but I think ultimately trying to mimic the structure of <object> will make it easier to write code for it, as well as extend it. Feel free to argue, these are just early morning thoughts. Here's how I envision the object being built:
<?php

  <#no_support>
    <object #attributes >
       <#params> 
    </object>
  </#no_support>
?>
Stuart Greenfield’s picture

I've done some more work tonight, refactoring the code a lot again...

  • I think we're all (does two people constitute all!) agreed that we should plan to make this generic, so I am changing the code as of now to embed_api before it gets too complicated.
  • To settle on a structure I proposed that we define a single new type, where #type = object. That adds a property of #object We also add a property called #parameters to handler object parameters, and we use #attributes to define the object, where the keys are the names of standard attributes, see http://www.w3schools.com/tags/tag_object.asp. So, the path is defined in data, the type is defined in type and is the mime type, and so on. We now have a completely unambiguous format that just follows standards that already exist. We can also immediately prepare an object definition by calling drupal_attributes() to squash the attributes in to a string.
  • I'm still not sure about the whole alt thing. alt is not an attribute of an object so putting it in attributes "feels" wrong. How about we use the existing element property #value. If the object fails we could revert to #type = markup, and the alternate markup is in #value? Other modules can grab the content of #value if they want to display it themselves. That sounds good - we aren't doing anything "unexpected"

Like I said, I refactored this tonight, and I now have a "generic" routine in theme_object() that takes an object element and outputs standard markup and parameters. It works beautifully for a test flash under Firefox which handles object properly. Let's stick with flash for now...

What about SWF Object, SWF Embed? If we change hook_embed_api_info() to return an arrays of arrays. The primary keys are mimetypes, the secondary arrays define themes. I did a quick and dirty change to the original settings page so it now produces the same table, but for mimetype application/x-shockwave-flash. If no theme is assigned then we use the generic object theme, but if I select an alternative I use that. It's working here. (and actually, doesn't this sound remarkably like CCK field formatting?!)

The next step would be a generic settings system that collects all the data from hook_embed_api_info() and presents a separate page for each mime type for which there's a handler. If no specific handler exists then the module falls back on generic embedding and we hope for the best.

What do you think?

Stuart Greenfield’s picture

FileSize
252.19 KB

I've attached a new zip with what is becoming "embed API". I adopted the approach above of using #attributes for the object data, #parameters for the object parameters, and the generic element of #type = object.

There is a default theme that does nothing more than render the object using <object>...</object>, so it's good for testing on more compliant browsers like FireFox. That is working great and I've been embedding flash, quicktime mov, mp4, mp3 on pages.

I refactored the hook_embed_api_info() to use the format

$info = array(
  'mime-type' => array(
    'theme_1' => array(
      'data' => 'about_the_theme',
    ),
  ),
);

This means that the api can enquire about themes that want to handle, say, application/x-shockwave-flash. At the moment the main use of this is to make a nicely formatted settings page where the user can set the default.

Using this approach I now have the module taking flash and outputting it via direct markup (ie the default mode), direct 'IE compatible' markup, SWF Object and SWF Embed, all configurable from the settings. Not everything is in yet (express install and version not done).

E.g. to add flash you create an element, and render it, using:


$object = array(
  'type' => 'application/x-shockwave-flash',
  'data' => '/new/sites/default/files/FlashVarsTest.swf',
  'height' => 200,
  'width' => 200,
);

$params = array(
  'flashvars' => array(
    'first' => 'This',
    'second' => 'is',
    'third' => 'flash!',
  ),
);

$element = array(
  '#type' => 'object',
  '#attributes' => $object,
  '#parameters' => $params,
);

print drupal_render($element);

The neat thing is that you can just as easily define this on a form, and that's what the settings page does at the moment. It all becomes very transparent.

I've attached a zip if anyone wants to take a look. The comments in the code are out of date as this code evolved from the swfAPI source.

My next thoughts are...

  • Get some feedback to see if this module looks like it has a place in Drupal!
  • Refactor SWF Tools to use the API for its flash embedding (should be quick - it already talked to swfAPI) Done in a rough and ready way - SWF Tools no longer uses its internal rendering - it creates object elements and lets embed API handle it.
  • See if I can make an existing SWF Tools audio player available generically by assigning it as a handler to audio/mp3 Done quick and dirty code to prove this - SWF Tools players are exposed as audio/mp3 handlers - a generic audio object can now find its way to SWF Tools
  • Think more about the multiple object case - what would be incredibly cool is to be able to pass not just one object but a collection of objects, and have some handlers recognise this and do something neat, like make an audio playlist. In effect an object version of a CCK formatter with a multiple variables option

Just to recap why I think this module has potential - if we can expose audio players and video players through a common interface we potentially simplify the whole media handling thing. Modules express their content as objects, and players collect objects and render them. We can mix and match all of them, and it makes Drupal even more flexible. At least, that's what I *think* it does!

arthurf’s picture

Ok- trying to respond to a few of your last points here.

As per:

To settle on a structure I proposed that we define a single new type, where #type = object. That adds a property of #object, and that is an array where the keys are the names of standard attributes, see http://www.w3schools.com/tags/tag_object.asp. So, the path is defined in data, the type is defined in type and is the mime type, and so on. We now have a completely unambiguous format that just follows standards that already exist.

I'm actually arguing for a #attributes and #params to handle the attributes to the specific object (#type could still be object by default, leaves room for "embed" or some unknown thing). The reason for this is a few things: 1) we have attributes like #theme which don't make sense in relationship to the object itself. My proposal above for #no_support falls into this as well. 2) the amount of coding incurred by #params => array ('foo' => 'bar' as compared to #foo => bar is not that large, and it allows us to keep the separation between data that describes the object vs the object's data quite separate. It is not the end of the world if you don't agree with me, but I think it follows the structure of the object better.

I'm still not sure about the whole alt thing. alt is not an attribute of an object so putting it in attributes "feels" wrong. How about we use the existing element property #value. If the object fails we could revert to #type = markup, and the alternate markup is in #value? Other modules can grab the content of #value if they want to display it themselves. That sounds good - we aren't doing anything "unexpected"

I think #alt is a no go. I think we should use #no_support because it describes what we want better- only display this if the kind of object is not supported. Above, I also mention that this can be a function which can make for dynamic non-supported content- swap a flash file for a h264 for the iphone, etc.

doesn't this sound remarkably like CCK field formatting?!

Yes, it paves the way for widget based object rendering... could be really cool.

I'm going to try to think through some of the other aspects of your post here. I think I'm really focused on the data creation side, and am not really thinking that much about the actual render side.... I'll try to get up to speed....

arthurf’s picture

HA! I submitted mine right after yours. Please ignore mine and let me catch up (again).

arthurf’s picture

There is a bunch to respond to, but this point

Modules express their content as objects, and players collect objects and render them.

Is really interesting. I wrote XSPF Playlist to do some aspects of this- it does the collection. Players are responsible for getting the playlist (flvmediaplayer does this), but XSPF finds and formats all the content... I'm not sure if it is the right model to use, but something to think about anyway.

sun’s picture

Sorry, I'm just quickly scanning the follow-ups and trying to throw in my thoughts. Actually, I have little experience with this entire topic - but I surely can assist in other areas. ;)

- On multiple objects and CCK fields/widgets: Attention, you're "risking" another module duplication with http://drupal.org/project/emfield and very potentially also http://drupal.org/project/filefield. While I like the idea in general very much (everything should [also] be a field), this direction should be fleshed out thoroughly.

- On the example in #31: Looks quite a bit more complex than the good ol' theme_swfobject_api()... but it makes sense. However, based on that snippet, I have no immediate idea of how to explicitly tell the rendering to use SWFObject as embedding method.

Stuart Greenfield’s picture

Just sneakily reading this while at work...

With this new method you still use a theme to use swf object.

$object = array(
  'type' => 'application/x-shockwave-flash',
  'data' => '/new/sites/default/files/FlashVarsTest.swf',
  'height' => 200,
  'width' => 200,
);

$params = array(
  'flashvars' => array(
    'first' => 'This',
    'second' => 'is',
    'third' => 'flash!',
  ),
);

$element = array(
  '#type' => 'object',
  '#attributes' => $object,
  '#parameters' => $params,
  '#theme' => 'swfobject',
);

print drupal_render($element);

The only difference is that in the new structure we use #attributes and #parameters, which are well defined for objects in the standards.

I am giving thought to if there is duplication here as this idea has expanded somewhat from the original 'swf API'. In terms of filefield, I actually see the embed API potentially extended that very nicely. You upload a file, which has a mime-type, you pick the object formatter, and the upload pops in to embed API to be rendered - you wouldn't need an audio formatter, a flash formatter, a quick time formatter - you just hand it to the API to work out. And you extend the API with additional handlers.

But yes, prevention of duplication is important!!!

Stuart Greenfield’s picture

@arthurf

I think I'm really focused on the data creation side, and am not really thinking that much about the actual render side.... I'll try to get up to speed....

I think that's a good thing - the render part is, in some ways, the easy bit. But getting the data structure right to avoid being stuck is probably the harder part!

Stuart Greenfield’s picture

I had a quick look at emfield on my lunch break, and I don't think there's duplication here. In fact, it's a good example of why this approach might be a good idea. Inside the google.inc file of emfield is a function called theme_embed_google_flash(). What does it do? It puts some flash on a page using its own version of direct embedding. If the Embed API were live then what it *could* do instead is prepare an object element, send it to the API, and the API would put it on the page using my currently preferred handler for application/x-shockwave-flash.

Now the author of google.inc doesn't have to worry about the best way to put flash on a page since they have access to the API, and I'm not forced to use direct embedding. If I prefer to use SWF Embed for my flash I can.

The way I imagine this working is that things like emfield are object providers, and the embed API provides object handlers.

Where there is danger of duplication is in things like audio players, but here the concept I have in mind is that some modules are audio object providers, and embed handlers are audio object outputters. I can mix and match the two to suit my needs. Because I look after SWF Tools this is very topical for me - do the SWF Tools audio player modules stay in SWF Tools, or do they become abstracted in to the API. I am trying to get my head round that bit and understand what the "object flow" would look like. In the short term it doesn't matter - SWF Tools turns audio in to a flash object. But in the longer term does the API take audio/mp3 objects itself?

What I have realised is that I don't think SWF Tools is an embed API handler. SWF Tools is a helper that lets me turn a loosely defined piece of flash content in to a properly prepared object element ready for the handler. That is entirely consistent with its title of "SWF Tools". With this model then if someone wants to add a new embedding method then they write it for the API, and its available to everyone who handles flash. At the moment you'd write it for SWF Tools, which is great, as long as you use SWF Tools to embed your flash.

I apologise for my many rambling posts in this thread, but I find writing these thoughts down is helping me to shape how this module should develop (and also IF it should develop!)

Stuart Greenfield’s picture

Posting more as a note to self - should the new element include a property #meta or #metadata to store meta data that receiving handlers might like to know about. Eg audio objects might be accompanied by ID3 metadata. It is up to the receiving handler whether it does anything with it upon receipt. It is data that can be ignored, but can enhance handling for capable modules.

sun’s picture

On that note you might be interested in reading this (not too closely tied, but related) approach: #256195: Enhance image_import by allowing submitter to provide captions (plus a general-case solution)

Stuart Greenfield’s picture

I haven't posted in at least an hour, so it must be time for another one :-)

Things are looking quite good as a concept, so this post is to try and say clearly where things are.

  1. The embed API can now embed any arbitrary object using the element #type = object, where #attributes and #parameters define it.
  2. I have a modified SWF Tools that no longers uses its built in flash rendering modules, but it now uses the embed API configured settings. All I had to do to enable this is output existing data in the new object format.
  3. To create the markup you can either just place the object element in the node/form array, or you can call drupal_render($element) to fetch it.
  4. I have extended the existing SWF Tools module so that it now presents as a handler for content types of audio/mp3. So if I add an audio object to my page with the default handler I just get <object>...</object> (which turns in to QuickTime!). But if I set it to SWF Tools handler I can get my audio in any supported SWF Tools player. This seems to prove the concept of placing content in to any player.
  5. I have got the code working for object elements that contain an array of child objects. This is still proof of concept, but it looks like it will be relatively easy to set it up so you either get each object rendered individually, or you can collect them and process them as a group. This is directly analagous to CCK. I don't have this "selectable" yet, but I am creating audio playlists in players via SWF Tools.

Things I'm still thinking about / haven't implemented yet:

  1. Not built in the code for handling alternate content. I like the idea of potential call back function, but I'd like to make it easy to have text if everything else fails. I am still wondering about the use of #value since this is where plain markup would be stored for a markup element. We could have #no_support as the callback.
  2. I've not reinstated the #cachable property yet. This is necessary to cope with JavaScript embedding where everything has to be returned in the theme function to make it work with filters.
  3. I like the idea of #meta to share metadata between providers and handlers. I think that's important to make modules work nicely together, for example, allowing them to construct meaningful playlists etc.
  4. I'd like to hack a couple of existing modules (something easy though!) to see if we can make them talk to the API. A good example might be the google.inc file in emfield - that implements direct embedding. I'd also like to try and hack audio.module to see if it could send its output to SWF Tools. That would be a superb test since the two modules don't currently interact.
  5. Umm, think that's it for now.

The only thing that occurs to me is that I think I am ending up almost rewriting SWF Tools. At least, the flash handling part. But it looks like there are some things that get stripped, but the rest of SWF Tools stays to help end users put the flash stuff in. As an aside, the SWF Tools input filter lets you add audio / audio playlists. In the existing world of SWF Tools those playlists get sent to SWF Tools players. In the "new world" of embed API those playlists would emerge as an object element, so they are exposed to the API as well, ready to go wherever the user sends them (which might be back to SWF Tools!). It sounds a bit convoluted but I guess that's the price of flexibility!

What do you think?

By way of illustration, here's how the code looks to produce a playlist in the new format:


$attributes = array();

$attributes[] = array(
  'type' => 'audio/mp3',
  'data' => 'http://server/someAudio.mp3',
);

$attributes[] = array(
  'type' => 'audio/mp3',
  'data' => 'http://server/moreAudio.mp3',
);

$element = array(
    '#type' => 'object',

  '0' => array(
    '#attributes' => $attributes[0],
  ),

  '1' => array(
    '#attributes' => $attributes[1],
  ),

);

print drupal_render($element);

To me this now looks beautifully simple. I have simply made an array of object elements that are expressed in a completely standard way. I don't do anything "special" to work with a player, I just enable it. If someone writes a great new player module and uses the API I simply install it, set it as my handler, and it works. I don't change any code. That sounds very attractive! It opens up the whole array of media creator modules to the whole array of media players (if people were to adopt it...)

sun’s picture

Glad that sime is here to hand over http://drupal.org/project/embed (the name I originally wanted to use for Inline API ;)

But, of course, you could also register http://drupal.org/project/object to make the #type match the module's namespace. Or maybe also http://drupal.org/project/objectfield...

OTOH, if #type = 'object' does not necessarily result in an <object>, then #type = 'embed' would sound more sane to me.

After all, SWF Tools can live on as toolbox for players and bonus stuff (as the name implies). However, this new embed/object API sounds like it deserves a new module and namespace. That will increase the possibility for other modules to add a (optional) dependency on that module, e.g. Emfield for certain content types.

sime’s picture

Wow I'm awestruck by this thread. That's quite a scroll in my iPhone!

Embed namespace is handed over, I was sadly way too green and got way too busy. If you decide not to use it, at least you control it. :)

I'll have a good read soon and see if you're covering .mov embedding. I certainly would like to see a jQuery default replacement script that lives in this module. Making swfobject optional. The only jQuery option I had back then was external and too flaky.

Stuart Greenfield’s picture

Thanks sime!

To save you reading (and to help on an iPhone). This module will already embed mov - just set #attributes['type'] = video/quicktime. Job done.
jQuery replacement is in place at the moment using SWF Embed.

Stuart Greenfield’s picture

OK - we now have the embed project, which is excellent as this is a nice simple name. I'll refactor the code (again) to reflect this.

#type = 'object' does not necessarily result in an <object>, then #type = 'embed' would sound more sane to me.

Not sure I agree with that. Semantically the element is describing an object, and it has properties that describe an object. The module then renders that object in some way. On that basis I'd propose we stick with the element 'object' since it describes that data that it contains, and it expresses nothing about what we will do with that object in future.

I think the combination of 'embed' as the project namespace, and 'object' as its datatype is nice.

Thinking some more about the element over the last day - I'm proprosing another property for the object, a name for which I can't quite decide, so I'll describe its purpose first!

This comes about from reworking SWF Tools. My local SWF Tools can now "consume" a collection of objects and turn them in to a playlist - that's fine. Now, SWF Tools also has an input filter to let users add audio. The input format lets you pass parameters to control what the player then does.

In our new scheme what that function should ACTUALLY do is create an object element and hand in back for the API to decide where it goes. But what if I know I'm targetting FlowPlayer3 and I want to send it some parameters. The API wouldn't allow that.

So what I suggest is a property of something like #module_data which contains arrays of data, keyed on the name of the module that provided it. So now if SWF Tools wants to send some parameters it can store this "additional" data under [#module_data][swftools]. In my example this would enhance SWF Tools modules if they are the target element, but if the user chose another handler from the API they would get the content in their alternative player, all that happens is they may lose a tiny bit of functionality. In a way this is a bit like the form_state array in Forms API. We can also "reserve" [#module_data][embed] for our own purposes to communicate additional data. If nothing else we could store the API handlers that have processed the object to help with debugging!

We could actually use this to allow players to help target alternatives. A common setting for a media player is "autoplay". A "smart" audio preparation module could, in theory, output data to a range of #module_data keys to help targetted players it knows about.

Any thoughts? Either on this concept, but particularly on the property name! I'll go with #module_data for now.

Stuart Greenfield’s picture

Status update - working very well locally - it is now rendering fully using the theme system via drupal_render, and it's handling single objects and multiple objects, with conversion of single objects to either single elements, or passing as a collection of elements. E.g. if an array of audio object are passed I have them rendering as either a series of audio players, or a single player with a playlist. All aspects such as #prefix and #suffix are fully support since the module renders using the existing Drupal mechanism. The objects are maintained as objects until the very last minute.

There's a bit more work to refactor the handler assignment as I realised it would better organised with the primary key as the theme name, not as the object type since we may want to interrogate the capabilities of a specific theme more often than needing a collection of handlers. I'm waiting on confirmation that the embed project has been transferred. I'll then make a commit in to CVS to open the code up, but I'm pretty (ok, very) pleased with progress so far.

sun’s picture

@Stuart: sime granted you CVS access to http://drupal.org/project/embed. If you want to completely take over the project (and sime agrees), then just let me know and I'll change the owner.

Stuart Greenfield’s picture

I've been thinking some more about the #no_support as a callback. Seeing as we render the element entirely via drupal_render() we already have that in the #post_render property. The problem is that in our case the #post_render function depends on the handling theme, i.e. they are assigned dynamically and they are not an inherent property of the element.

To get round this I'd like to propose that in hook_embed_epi_info() we add another key called element_info elements (to correlate with the hook called by drupal for a regular element). That will be an array of element properties that the handler wants to use. It's primary purpose would be to blend a #post_render function if required.

Why do it that way? We now don't write any new code - drupal already understands the concept of #post_render. We also get a chance for the handling theme to manipulate the object before it is rendered by dynamically adding #pre_render functions (although we need to chain those from our own #pre_render).

How would that work in practice? If the theme function has a problem it's only way of communicating is via the markup it returns. I think it could return non-markup as its result, that gets sent to the #post_render and that could transfer $content back to sensible markup ready for output. I'm going to test this locally and report back.

If we go this way then we make object elements as powerful as any other Drupal element.

That still leaves us with what to call / where to store some basic alternate markup though. I'm still pushing for #value to store it, since that is an existing property, and the 'markup' element uses #value for this, so it is consistent (http://api.drupal.org/api/file/developer/topics/forms_api_reference.html...)

Stuart Greenfield’s picture

@sun - sime has given me ownership of the embed project and transferred it already.

So now we're all good to go. I am about 90% of the way through fixing code to the new project name, then I'll commit on CVS.

Stuart Greenfield’s picture

I have committed a version of the new embed module to CVS under the embed project and the entire code now runs in the "embed" namespace.

I've not committed everything I have locally yet as I'm ironing out some wrinkles, but the commit includes the core module, the admin page, and handlers for direct emedding of flash and interfacing to SWF Embed.

With respect to existing SWF Object and SWF Embed projects is the way forward to keep them as stand alone projects and let Embed interface to them, or would they make more sense having implementations brought under the embed banner? The existing modules need some tweaking to fully support the embed model (particularly around support for cacheable content).

Also, as an aside, post #432188: Multiple 1pixelout players in single page and stop the others. on SWF Tools describes a work around to place multiple one pixel out players on a page and have one stop if another starts. In our new model that looks like it would be a good use of the #post_render callback since the code needs to know the element id. Maybe bits and pieces like this could be tracked on the embed issue queue as a holding area for code aspects to implement or test?

Anyhow, feel free to grab the code from CVS and pull it to pieces :-)

Stuart Greenfield’s picture

I've started posting some tasks/notes under the issue queue for the embed project as this thread is becoming very long and it's difficult to track the thought processes. I've tried to break out the current discussions under separate headings. Please chip in at http://drupal.org/project/issues/embed.

sime’s picture

Title: SWF Tools for comprehensive api » Embed API strategy discussion (was SWF Tools for comprehensive api)
Project: SWFObject API » Embed
Version: 5.x-1.x-dev »

Moved to the Embed queue.

Stuart Greenfield’s picture

Status: Needs review » Active
aaron’s picture

I would like to integrate the Styles module with some of this work, which is basically ready and working now (I'm planning to publish its first alpha this weekend). Subscribing, so I remember to look at this thread.

cparrish817’s picture

subscribe

sun’s picture

oh dear :) I hope Embed doesn't duplicate Styles now (or vice-versa) ;)

Didn't look at Embed's code yet, but all of this sounds very promising.

sun’s picture

@Stuart Greenfield: Any updates on this? The project page doesn't show a dev release yet, so I was wondering what state the current code in the repo is in?

Dave Reid’s picture

Issue summary: View changes
Status: Active » Closed (fixed)