first import

This commit is contained in:
Bachir Soussi Chiadmi
2015-04-08 11:40:19 +02:00
commit 1bc61b12ad
8435 changed files with 1582817 additions and 0 deletions

View File

@@ -0,0 +1,4 @@
CHANGELOG for Media: Archive
by aaron: Add provider file for archive.org videos.

View File

@@ -0,0 +1,274 @@
GNU GENERAL PUBLIC LICENSE
Version 2, June 1991
Copyright (C) 1989, 1991 Free Software Foundation, Inc. 675 Mass Ave,
Cambridge, MA 02139, USA. Everyone is permitted to copy and distribute
verbatim copies of this license document, but changing it is not allowed.
Preamble
The licenses for most software are designed to take away your freedom to
share and change it. By contrast, the GNU General Public License is
intended to guarantee your freedom to share and change free software--to
make sure the software is free for all its users. This General Public License
applies to most of the Free Software Foundation's software and to any other
program whose authors commit to using it. (Some other Free Software
Foundation software is covered by the GNU Library General Public License
instead.) You can apply it to your programs, too.
When we speak of free software, we are referring to freedom, not price. Our
General Public Licenses are designed to make sure that you have the
freedom to distribute copies of free software (and charge for this service if
you wish), that you receive source code or can get it if you want it, that you
can change the software or use pieces of it in new free programs; and that
you know you can do these things.
To protect your rights, we need to make restrictions that forbid anyone to
deny you these rights or to ask you to surrender the rights. These restrictions
translate to certain responsibilities for you if you distribute copies of the
software, or if you modify it.
For example, if you distribute copies of such a program, whether gratis or for
a fee, you must give the recipients all the rights that you have. You must make
sure that they, too, receive or can get the source code. And you must show
them these terms so they know their rights.
We protect your rights with two steps: (1) copyright the software, and (2)
offer you this license which gives you legal permission to copy, distribute
and/or modify the software.
Also, for each author's protection and ours, we want to make certain that
everyone understands that there is no warranty for this free software. If the
software is modified by someone else and passed on, we want its recipients
to know that what they have is not the original, so that any problems
introduced by others will not reflect on the original authors' reputations.
Finally, any free program is threatened constantly by software patents. We
wish to avoid the danger that redistributors of a free program will individually
obtain patent licenses, in effect making the program proprietary. To prevent
this, we have made it clear that any patent must be licensed for everyone's
free use or not licensed at all.
The precise terms and conditions for copying, distribution and modification
follow.
GNU GENERAL PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND
MODIFICATION
0. This License applies to any program or other work which contains a notice
placed by the copyright holder saying it may be distributed under the terms
of this General Public License. The "Program", below, refers to any such
program or work, and a "work based on the Program" means either the
Program or any derivative work under copyright law: that is to say, a work
containing the Program or a portion of it, either verbatim or with
modifications and/or translated into another language. (Hereinafter, translation
is included without limitation in the term "modification".) Each licensee is
addressed as "you".
Activities other than copying, distribution and modification are not covered
by this License; they are outside its scope. The act of running the Program is
not restricted, and the output from the Program is covered only if its contents
constitute a work based on the Program (independent of having been made
by running the Program). Whether that is true depends on what the Program
does.
1. You may copy and distribute verbatim copies of the Program's source
code as you receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice and
disclaimer of warranty; keep intact all the notices that refer to this License
and to the absence of any warranty; and give any other recipients of the
Program a copy of this License along with the Program.
You may charge a fee for the physical act of transferring a copy, and you
may at your option offer warranty protection in exchange for a fee.
2. You may modify your copy or copies of the Program or any portion of it,
thus forming a work based on the Program, and copy and distribute such
modifications or work under the terms of Section 1 above, provided that you
also meet all of these conditions:
a) You must cause the modified files to carry prominent notices stating that
you changed the files and the date of any change.
b) You must cause any work that you distribute or publish, that in whole or in
part contains or is derived from the Program or any part thereof, to be
licensed as a whole at no charge to all third parties under the terms of this
License.
c) If the modified program normally reads commands interactively when run,
you must cause it, when started running for such interactive use in the most
ordinary way, to print or display an announcement including an appropriate
copyright notice and a notice that there is no warranty (or else, saying that
you provide a warranty) and that users may redistribute the program under
these conditions, and telling the user how to view a copy of this License.
(Exception: if the Program itself is interactive but does not normally print such
an announcement, your work based on the Program is not required to print
an announcement.)
These requirements apply to the modified work as a whole. If identifiable
sections of that work are not derived from the Program, and can be
reasonably considered independent and separate works in themselves, then
this License, and its terms, do not apply to those sections when you distribute
them as separate works. But when you distribute the same sections as part
of a whole which is a work based on the Program, the distribution of the
whole must be on the terms of this License, whose permissions for other
licensees extend to the entire whole, and thus to each and every part
regardless of who wrote it.
Thus, it is not the intent of this section to claim rights or contest your rights to
work written entirely by you; rather, the intent is to exercise the right to
control the distribution of derivative or collective works based on the
Program.
In addition, mere aggregation of another work not based on the Program
with the Program (or with a work based on the Program) on a volume of a
storage or distribution medium does not bring the other work under the scope
of this License.
3. You may copy and distribute the Program (or a work based on it, under
Section 2) in object code or executable form under the terms of Sections 1
and 2 above provided that you also do one of the following:
a) Accompany it with the complete corresponding machine-readable source
code, which must be distributed under the terms of Sections 1 and 2 above
on a medium customarily used for software interchange; or,
b) Accompany it with a written offer, valid for at least three years, to give
any third party, for a charge no more than your cost of physically performing
source distribution, a complete machine-readable copy of the corresponding
source code, to be distributed under the terms of Sections 1 and 2 above on
a medium customarily used for software interchange; or,
c) Accompany it with the information you received as to the offer to distribute
corresponding source code. (This alternative is allowed only for
noncommercial distribution and only if you received the program in object
code or executable form with such an offer, in accord with Subsection b
above.)
The source code for a work means the preferred form of the work for
making modifications to it. For an executable work, complete source code
means all the source code for all modules it contains, plus any associated
interface definition files, plus the scripts used to control compilation and
installation of the executable. However, as a special exception, the source
code distributed need not include anything that is normally distributed (in
either source or binary form) with the major components (compiler, kernel,
and so on) of the operating system on which the executable runs, unless that
component itself accompanies the executable.
If distribution of executable or object code is made by offering access to
copy from a designated place, then offering equivalent access to copy the
source code from the same place counts as distribution of the source code,
even though third parties are not compelled to copy the source along with the
object code.
4. You may not copy, modify, sublicense, or distribute the Program except as
expressly provided under this License. Any attempt otherwise to copy,
modify, sublicense or distribute the Program is void, and will automatically
terminate your rights under this License. However, parties who have received
copies, or rights, from you under this License will not have their licenses
terminated so long as such parties remain in full compliance.
5. You are not required to accept this License, since you have not signed it.
However, nothing else grants you permission to modify or distribute the
Program or its derivative works. These actions are prohibited by law if you
do not accept this License. Therefore, by modifying or distributing the
Program (or any work based on the Program), you indicate your acceptance
of this License to do so, and all its terms and conditions for copying,
distributing or modifying the Program or works based on it.
6. Each time you redistribute the Program (or any work based on the
Program), the recipient automatically receives a license from the original
licensor to copy, distribute or modify the Program subject to these terms and
conditions. You may not impose any further restrictions on the recipients'
exercise of the rights granted herein. You are not responsible for enforcing
compliance by third parties to this License.
7. If, as a consequence of a court judgment or allegation of patent
infringement or for any other reason (not limited to patent issues), conditions
are imposed on you (whether by court order, agreement or otherwise) that
contradict the conditions of this License, they do not excuse you from the
conditions of this License. If you cannot distribute so as to satisfy
simultaneously your obligations under this License and any other pertinent
obligations, then as a consequence you may not distribute the Program at all.
For example, if a patent license would not permit royalty-free redistribution
of the Program by all those who receive copies directly or indirectly through
you, then the only way you could satisfy both it and this License would be to
refrain entirely from distribution of the Program.
If any portion of this section is held invalid or unenforceable under any
particular circumstance, the balance of the section is intended to apply and
the section as a whole is intended to apply in other circumstances.
It is not the purpose of this section to induce you to infringe any patents or
other property right claims or to contest validity of any such claims; this
section has the sole purpose of protecting the integrity of the free software
distribution system, which is implemented by public license practices. Many
people have made generous contributions to the wide range of software
distributed through that system in reliance on consistent application of that
system; it is up to the author/donor to decide if he or she is willing to
distribute software through any other system and a licensee cannot impose
that choice.
This section is intended to make thoroughly clear what is believed to be a
consequence of the rest of this License.
8. If the distribution and/or use of the Program is restricted in certain
countries either by patents or by copyrighted interfaces, the original copyright
holder who places the Program under this License may add an explicit
geographical distribution limitation excluding those countries, so that
distribution is permitted only in or among countries not thus excluded. In such
case, this License incorporates the limitation as if written in the body of this
License.
9. The Free Software Foundation may publish revised and/or new versions
of the General Public License from time to time. Such new versions will be
similar in spirit to the present version, but may differ in detail to address new
problems or concerns.
Each version is given a distinguishing version number. If the Program specifies
a version number of this License which applies to it and "any later version",
you have the option of following the terms and conditions either of that
version or of any later version published by the Free Software Foundation. If
the Program does not specify a version number of this License, you may
choose any version ever published by the Free Software Foundation.
10. If you wish to incorporate parts of the Program into other free programs
whose distribution conditions are different, write to the author to ask for
permission. For software which is copyrighted by the Free Software
Foundation, write to the Free Software Foundation; we sometimes make
exceptions for this. Our decision will be guided by the two goals of
preserving the free status of all derivatives of our free software and of
promoting the sharing and reuse of software generally.
NO WARRANTY
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE,
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT
PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE
STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT
WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED,
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND
PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL
NECESSARY SERVICING, REPAIR OR CORRECTION.
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR
AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR
ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE
LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL,
SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES
ARISING OUT OF THE USE OR INABILITY TO USE THE
PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA
OR DATA BEING RENDERED INACCURATE OR LOSSES
SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE
PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN
IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF
THE POSSIBILITY OF SUCH DAMAGES.
END OF TERMS AND CONDITIONS

View File

@@ -0,0 +1,39 @@
<?php
/**
* @file
* Create a Archive Stream Wrapper class for the Media/Resource module.
*/
/**
* Create an instance like this:
* $archive = new ResourceArchiveStreamWrapper('archive://?v=[video-code]');
*/
class MediaArchiveStreamWrapper extends MediaReadOnlyStreamWrapper {
protected $base_url = 'http://archive.org/file';
function getTarget($f) {
return FALSE;
}
static function getMimeType($uri, $mapping = NULL) {
return 'video/archive';
}
function getOriginalThumbnailPath() {
$parts = $this->get_parameters();
return 'http://www.archive.org/download/'. check_plain($parts['v']) .'/' . check_plain($parts['v']) .'.thumbs/' . check_plain($parts['org']) .'_000001.jpg';
}
function getLocalThumbnailPath() {
$parts = $this->get_parameters();
$local_path = 'public://media-archive/' . check_plain($parts['v']) . '.jpg';
if (!file_exists($local_path)) {
$dirname = drupal_dirname($local_path);
file_prepare_directory($dirname, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS);
@copy($this->getOriginalThumbnailPath(), $local_path);
}
return $local_path;
}
}

View File

@@ -0,0 +1,5 @@
Media: Archive
Creates a Archive PHP Stream Wrapper for Resource and implements the various
formatter and file listing hooks in the Media module.

View File

@@ -0,0 +1,21 @@
.media-archive-preview-wrapper {
max-width: 100%;
min-height: 50px;
position: relative;
}
.media-archive-preview-wrapper object,
.media-archive-preview-wrapper iframe {
max-width: 100%;
position: relative;
}
.media-archive-preview-wrapper .js-fallback {
left: 0;
margin-top: -0.5em;
position: absolute;
right: 0;
text-align: center;
top: 50%;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -0,0 +1,166 @@
<?php
/**
* @file media_archive/includes/media_archive.styles.inc
* Styles definitions for Media: Archive.
*/
/**
* Implementation of Styles module hook_styles_default_containers().
*/
function media_archive_styles_default_containers() {
// We append Archive to the file containers.
return array(
'file' => array(
'containers' => array(
'media_archive' => array(
'class' => 'MediaArchiveStyles',
'name' => 'media_archive',
'label' => t('Archive'),
'preview' => 'media_archive_preview_style',
),
),
),
);
}
/**
* Implementation of Styles module hook_styles_default_presets().
*/
function media_archive_styles_default_presets() {
return array(
'file' => array(
'containers' => array(
'media_archive' => array(
'default preset' => 'linked_thumbnail',
'styles' => array(
'original' => array(
'default preset' => 'video',
),
'thumbnail' => array(
'default preset' => 'linked_thumbnail',
),
'square_thumbnail' => array(
'default preset' => 'linked_square_thumbnail',
),
'medium' => array(
'default preset' => 'linked_medium',
),
'large' => array(
'default preset' => 'large_video',
),
),
'presets' => array(
'unlinked_thumbnail' => array(
array(
'name' => 'thumbnail',
'settings' => array(),
),
),
'linked_thumbnail' => array(
array(
'name' => 'link_to_media',
'settings' => array(),
),
array(
'name' => 'thumbnail',
'settings' => array(),
),
),
'linked_square_thumbnail' => array(
array(
'name' => 'link_to_media',
'settings' => array(),
),
array(
'name' => 'image_style',
'settings' => array(
'image_style' => 'square_thumbnail',
),
),
array(
'name' => 'thumbnail',
'settings' => array(),
),
),
'linked_medium' => array(
array(
'name' => 'link_to_media',
'settings' => array(),
),
array(
'name' => 'image_style',
'settings' => array(
'image_style' => 'medium',
),
),
array(
'name' => 'thumbnail',
'settings' => array(),
),
),
'video' => array(
array(
'name' => 'video',
'settings' => array(),
),
),
'large_video' => array(
array(
'name' => 'resize',
'settings' => array(
'width' => 480,
'height' => 360,
),
),
array(
'name' => 'video',
'settings' => array(),
),
),
),
),
),
),
);
}
class MediaArchiveStyles extends FileStyles {
public $autoplay;
public $fullscreen;
function get_autoplay() {
return $this->get('autoplay');
}
function set_autoplay($value) {
return $this->set('autoplay', $value);
}
function get_fullscreen() {
return $this->get('fullscreen');
}
function set_fullscreen($value) {
return $this->set('fullscreen', $value);
}
function get_image_uri() {
if ($image_uri = $this->get('image_uri')) {
return $image_uri;
}
$object = $this->get_object();
if ($object->uri) {
$wrapper = file_stream_wrapper_get_instance_by_uri($object->uri);
return $wrapper->getLocalThumbnailPath();
}
}
function video($effect) {
$variables = array(
'uri' => $this->get_uri(),
'width' => $this->get_width(),
'height' => $this->get_height(),
'autoplay' => $this->get_autoplay(),
'fullscreen' => $this->get_fullscreen(),
);
$this->set_output(theme('media_archive_video', $variables));
}
}

View File

@@ -0,0 +1,132 @@
<?php
/**
* @file media_archive/includes/media_archive.variables.inc
* Variable defaults for Media: Archive.
*/
/**
* Define our constants.
*/
/**
* This is the variable namespace, automatically prepended to module variables.
*/
define('MEDIA_ARCHIVE_NAMESPACE', 'media_archive__');
/**
* Wrapper for variable_get() using the Media: Archive variable registry.
*
* @param string $name
* The variable name to retrieve. Note that it will be namespaced by
* pre-pending MEDIA_ARCHIVE_NAMESPACE, as to avoid variable collisions
* with other modules.
* @param unknown $default
* An optional default variable to return if the variable hasn't been set
* yet. Note that within this module, all variables should already be set
* in the media_archive_variable_default() function.
* @return unknown
* Returns the stored variable or its default.
*
* @see media_archive_variable_set()
* @see media_archive_variable_del()
* @see media_archive_variable_default()
*/
function media_archive_variable_get($name, $default = NULL) {
// Allow for an override of the default.
// Useful when a variable is required (like $path), but namespacing is still
// desired.
if (!isset($default)) {
$default = media_archive_variable_default($name);
}
// Namespace all variables.
$variable_name = MEDIA_ARCHIVE_NAMESPACE . $name;
return variable_get($variable_name, $default);
}
/**
* Wrapper for variable_set() using the Media: Archive variable registry.
*
* @param string $name
* The variable name to set. Note that it will be namespaced by
* pre-pending MEDIA_ARCHIVE_NAMESPACE, as to avoid variable collisions with
* other modules.
* @param unknown $value
* The value for which to set the variable.
* @return unknown
* Returns the stored variable after setting.
*
* @see media_archive_variable_get()
* @see media_archive_variable_del()
* @see media_archive_variable_default()
*/
function media_archive_variable_set($name, $value) {
$variable_name = MEDIA_ARCHIVE_NAMESPACE . $name;
return variable_set($variable_name, $value);
}
/**
* Wrapper for variable_del() using the Media: Archive variable registry.
*
* @param string $name
* The variable name to delete. Note that it will be namespaced by
* pre-pending MEDIA_ARCHIVE_NAMESPACE, as to avoid variable collisions with
* other modules.
*
* @see media_archive_variable_get()
* @see media_archive_variable_set()
* @see media_archive_variable_default()
*/
function media_archive_variable_del($name) {
$variable_name = MEDIA_ARCHIVE_NAMESPACE . $name;
variable_del($variable_name);
}
/**
* The default variables within the Media: Archive namespace.
*
* @param string $name
* Optional variable name to retrieve the default. Note that it has not yet
* been pre-pended with the MEDIA_ARCHIVE_NAMESPACE namespace at this time.
* @return unknown
* The default value of this variable, if it's been set, or NULL, unless
* $name is NULL, in which case we return an array of all default values.
*
* @see media_archive_variable_get()
* @see media_archive_variable_set()
* @see media_archive_variable_del()
*/
function media_archive_variable_default($name = NULL) {
static $defaults;
if (!isset($defaults)) {
$defaults = array(
'width' => 560,
'height' =>340,
'autoplay' => FALSE,
'fullscreen' => TRUE,
'preview_uri' => 'archive://v/-jubiv7QUco',
);
}
if (!isset($name)) {
return $defaults;
}
if (isset($defaults[$name])) {
return $defaults[$name];
}
}
/**
* Return the fully namespace variable name.
*
* @param string $name
* The variable name to retrieve the namespaced name.
* @return string
* The fully namespace variable name, prepended with
* MEDIA_ARCHIVE_NAMESPACE.
*/
function media_archive_variable_name($name) {
return MEDIA_ARCHIVE_NAMESPACE . $name;
}

View File

@@ -0,0 +1,24 @@
<?php
/**
* @file media_archive/includes/themes/media-archive-video.tpl.php
*
* Template file for theme('media_archive_video').
*
* Variables available:
* $uri - The uri to the Archive video, such as archive://v/xsy7x8c9.
* $video_id - The unique identifier of the Archive video.
* $width - The width to render.
* $height - The height to render.
* $autoplay - If TRUE, then start the player automatically when displaying.
* $fullscreen - Whether to allow fullscreen playback.
*
* Note that we set the width & height of the outer wrapper manually so that
* the JS will respect that when resizing later.
*/
?>
<div class="media-archive-outer-wrapper" id="media-archive-<?php print $id; ?>" style="width: <?php print $width; ?>px; height: <?php print $height; ?>px;">
<div class="media-archive-preview-wrapper" id="<?php print $wrapper_id; ?>">
<?php print $output; ?>
</div>
</div>

View File

@@ -0,0 +1,222 @@
<?php
/**
* @file media_archive/includes/themes/media_archive.theme.inc
*
* Theme and preprocess functions for Media: Archive.
*/
/**
* Preprocess function for theme('media_archive_video').
*/
function media_archive_preprocess_media_archive_video(&$variables) {
// Build the URL for display.
$uri = $variables['uri'];
$wrapper = file_stream_wrapper_get_instance_by_uri($uri);
$parts = $wrapper->get_parameters();
$variables['video_id'] = check_plain($parts['v']);
//convert episode id from filepath to embed code
$variables['embed_code'] = media_archive_embedcode_lookup($variables['video_id']);
$variables['width'] = isset($variables['width']) ? $variables['width'] : media_archive_variable_get('width');
$variables['height'] = isset($variables['height']) ? $variables['height'] : media_archive_variable_get('height');
$variables['autoplay'] = isset($variables['autoplay']) ? $variables['autoplay'] : media_archive_variable_get('autoplay');
$variables['fullscreen'] = isset($variables['fullscreen']) ? $variables['fullscreen'] : media_archive_variable_get('fullscreen');
$variables['autoplay'] = $variables['autoplay'] ? 1 : 1;
$variables['fullscreen'] = $variables['fullscreen'] ? 'true' : 'false';
$variables['wrapper_id'] = 'media_archive_' . $variables['video_id'] . '_' . $variables['id'];
$mp4URL = 'http://www.archive.org/download/' . $variables['video_id'] . '/' . $variables['embed_code'] . '_512kb.mp4';
$ogvURL = 'http://www.archive.org/download/' . $variables['video_id'] . '/' . $variables['embed_code'] . '.ogv';
//Fix for IE!!
//<object width="640" height="506" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"><param value="true" name="allowfullscreen"/><param value="always" name="allowscriptaccess"/><param value="high" name="quality"/><param value="true" name="cachebusting"/><param value="#000000" name="bgcolor"/><param name="movie" value="http://www.archive.org/flow/flowplayer.commercial-3.2.1.swf" /><param value="config={'key':'#$aa4baff94a9bdcafce8','playlist':['format=Thumbnail?.jpg',{'autoPlay':false,'url':'Domino_Theory_512kb.mp4'}],'clip':{'autoPlay':true,'baseUrl':'http://www.archive.org/download/bavc-77620-dominotheory/','scaling':'fit','provider':'h264streaming'},'canvas':{'backgroundColor':'#000000','backgroundGradient':'none'},'plugins':{'controls':{'playlist':false,'fullscreen':true,'height':26,'backgroundColor':'#000000','autoHide':{'fullscreenOnly':true}},'h264streaming':{'url':'http://www.archive.org/flow/flowplayer.pseudostreaming-3.2.1.swf'}},'contextMenu':[{},'-','Flowplayer v3.2.1']}" name="flashvars"/><embed src="http://www.archive.org/flow/flowplayer.commercial-3.2.1.swf" type="application/x-shockwave-flash" width="640" height="506" allowfullscreen="true" allowscriptaccess="always" cachebusting="true" bgcolor="#000000" quality="high" flashvars="config={'key':'#$aa4baff94a9bdcafce8','playlist':['format=Thumbnail?.jpg',{'autoPlay':false,'url':'Domino_Theory_512kb.mp4'}],'clip':{'autoPlay':true,'baseUrl':'http://www.archive.org/download/bavc-77620-dominotheory/','scaling':'fit','provider':'h264streaming'},'canvas':{'backgroundColor':'#000000','backgroundGradient':'none'},'plugins':{'controls':{'playlist':false,'fullscreen':true,'height':26,'backgroundColor':'#000000','autoHide':{'fullscreenOnly':true}},'h264streaming':{'url':'http://www.archive.org/flow/flowplayer.pseudostreaming-3.2.1.swf'}},'contextMenu':[{},'-','Flowplayer v3.2.1']}"> </embed></object>
$variables['output'] = '<video width="' . $variables['width'] .'" height="' . $variables['height'] .'" controls>
<source src="' . $mp4URL . '" type=\'video/mp4; codecs="avc1.42E01E, mp4a.40.2"\'>
<source src="' . $ogvURL . '" type=\'video/ogg; codecs="theora, vorbis"\'>
</video>';
// For users with JavaScript, these object and embed tags will be replaced
// by an iframe, so that we can support users without Flash.
/*
$variables['output'] = '<object width="' . $variables['width'] . '" height="' . $variables['height'] . '">';
$variables['output'] .= '<param value="true" name="allowfullscreen"/><param value="always" name="allowscriptaccess"/><param value="high" name="quality"/><param value="true" name="cachebusting"/><param value="#000000" name="bgcolor"/>';
$variables['output'] .= '<param name="movie" value="http://www.archive.org/flow/flowplayer.commercial-3.2.1.swf"></param>';
$variables['output'] .= '<param name="allowFullScreen" value="' . $variables['fullscreen'] . '"></param>';
$variables['output'] .= '<param name="wmode" value="transparent" />';
$variables['output'] .= "<param value=\"config={'key':'#$aa4baff94a9bdcafce8','playlist':['format=Thumbnail?.jpg',{'autoPlay':false,'url':'" . $variables['embed_code'] . "_512kb.mp4'}],'clip':{'autoPlay':true,'baseUrl':'http://www.archive.org/download/bavc-77620-dominotheory/','scaling':'fit','provider':'h264streaming'},'canvas':{'backgroundColor':'#000000','backgroundGradient':'none'},'plugins':{'controls':{'playlist':false,'fullscreen':true,'height':26,'backgroundColor':'#000000','autoHide':{'fullscreenOnly':true}},'h264streaming':{'url':'http://www.archive.org/flow/flowplayer.pseudostreaming-3.2.1.swf'}},'contextMenu':[{},'-','Flowplayer v3.2.1']}\" name=\"flashvars\"/>";
$config = "'key':\'#$aa4baff94a9bdcafce8','playlist':['format=Thumbnail?.jpg',{'autoPlay':false,'url':'" . $variables['embed_code'] . "_512kb.mp4'}],'clip':{'autoPlay':true,'baseUrl':'http://www.archive.org/download/" . $variables['video_id'] . "/','scaling':'fit','provider':'h264streaming'},'canvas':{'backgroundColor':'#000000','backgroundGradient':'none'},'plugins':{'controls':{'playlist':false,'fullscreen':true,'height':26,'backgroundColor':'#000000','autoHide':{'fullscreenOnly':true}},'h264streaming':{'url':'http://www.archive.org/flow/flowplayer.pseudostreaming-3.2.1.swf'}},'contextMenu':[{},'-','Flowplayer v3.2.1']";
$variables['output'] .= '<embed src="http://www.archive.org/flow/flowplayer.commercial-3.2.1.swf" type="application/x-shockwave-flash" width="' . $variables['width'] . '" height="' . $variables['height'] . '" allowfullscreen="' . $variables['fullscreen'] . 'allowfullscreen="true" allowscriptaccess="always" cachebusting="true" bgcolor="#000000" quality="high" flashvars="config={' . $config . '}"></embed>';
$variables['output'] .= '</object>';
*/
/*
$variables['output'] = <<<OUTPUT
<object width="{$variables['width']}" height="{$variables['height']}">
<param name="movie" value="http://www.archive.org/play/{$variables['embed_code']}"></param>
<param name="allowFullScreen" value="{$variables['fullscreen']}"></param>
<param name="wmode" value="transparent" />
<embed src="http://www.archive.org/play/{$variables['embed_code']}" type="application/x-shockwave-flash" width="{$variables['width']}" height="{$variables['height']}" allowfullscreen="{$variables['fullscreen']}"></embed>
</object>
OUTPUT;
*/
// @todo Replace this inline JavaScript with at least calls to
// drupal_add_js()/drupal_get_js(), and ideally, with a behavior. Keep
// in mind that the solution needs to work when inside a colorbox or
// otherwise in an AJAX response, but that should now be possible in D7.
/*
$iframe_id = drupal_json_encode($variables['wrapper_id'] .'_iframe');
$wrapper_id = drupal_json_encode($variables['wrapper_id']);
$JSObject = 'Drupal.settings.media_archive[' . $wrapper_id . ']';
$variables['output'] .= <<<OUTPUT
<script type="text/javascript">
if (Drupal.settings && Drupal.media_archive) {
Drupal.settings.media_archive = Drupal.settings.media_archive || {};
$JSObject = {};
$JSObject.width = {$variables['width']};
$JSObject.height = {$variables['height']};
$JSObject.video_id = "{$variables['video_id']}";
$JSObject.fullscreen = {$variables['fullscreen']};
$JSObject.id = $iframe_id;
Drupal.media_archive.insertEmbed($wrapper_id);
}
</script>
OUTPUT;
*/
//drupal_add_js(drupal_get_path('module', 'media_archive') . '/js/media_archive.js');
drupal_add_css(drupal_get_path('module', 'media_archive') . '/css/media_archive.css');
drupal_add_js(drupal_get_path('module', 'media_archive') . '/js/flash_detect_min.js');
}
function theme_media_archive_field_formatter_styles($variables) {
$element = $variables['element'];
$style = $variables['style'];
$variables['file'] = $element['#item'];
$variables['uri'] = $variables['file']['uri'];
$variables['style_name'] = $style['name'];
return theme('media_archive_embed', $variables);
}
/**
* Preview for Styles UI.
*/
function theme_media_archive_preview_style($variables) {
$variables['uri'] = media_archive_variable_get('preview_uri');
$variables['field_type'] = 'file';
$variables['object'] = file_uri_to_object($variables['uri']);
return theme('styles', $variables);
}
/**
* NOTE: Deprecated with Styles version 2.
*/
function theme_media_archive_styles($variables) {
$style = $variables['style'];
$variables['file'] = $variables['object'];
$variables['uri'] = $variables['object']->uri;
$variables['style_name'] = $style['name'];
return theme('media_archive_embed', $variables);
}
/**
* @todo: get this working
*
* This code is for embedding videos in WYSIYWG areas, not currently working.
* NOTE: Deprecated with Styles version 2.
*/
function theme_media_archive_embed($variables) {
$preset_name = $variables['preset_name'];
$preset = styles_containers_available_styles('file', 'media_archive', $preset_name);
$output = '';
if (!empty($preset)) {
// Build the URL for display.
$uri = $variables['uri'];
$wrapper = file_stream_wrapper_get_instance_by_uri($uri);
$parts = $wrapper->get_parameters();
$fullscreen_value = $autoplay = 'false';
$in_browser = $thumbnail = FALSE;
foreach ($preset['effects'] as $effect) {
switch ($effect['name']) {
case 'autoplay':
$autoplay = $effect['data']['autoplay'] ? 'true' : 'false';
break;
case 'resize':
$width = $effect['data']['width'];
$height = $effect['data']['height'];
break;
case 'fullscreen':
$fullscreen_value = $effect['data']['fullscreen'] ? 'true' : 'false';
break;
case 'thumbnail':
$thumbnail = $effect['data']['thumbnail'];
}
}
if (isset($variables['object']->override)) {
$override = $variables['object']->override;
if (isset($override['width'])) {
$width = $override['width'];
}
if (isset($override['height'])) {
$height = $override['height'];
}
if (isset($override['wysiwyg'])) {
$thumbnail = TRUE;
}
if (isset($override['browser']) && $override['browser']) {
$in_browser = TRUE;
$thumbnail = TRUE;
}
}
$width = isset($width) ? $width : media_archive_variable_get('width');
$height = isset($height) ? $height : media_archive_variable_get('height');
$video_id = check_plain($parts['v']);
if ($thumbnail) {
// @todo Clean this up.
$image_variables = array(
'path' => $wrapper->getOriginalThumbnailPath(),
'alt' => $variables['alt'],
'title' => $variables['title'],
'getsize' => FALSE,
);
if (isset($preset['image_style'])) {
$image_variables['path'] = $wrapper->getLocalThumbnailPath();
$image_variables['style_name'] = $preset['image_style'];
$output = theme('image_style', $image_variables);
}
else {
// We need to add this style attribute here so that it doesn't get lost
// If you resize a video in a node, save it, edit it, but don't adjust
// the sizing of the video while editing, the size will revert to the
// default. Adding the specific size here retains the original resizing
$WYSIWYG = isset($variables['object']->override['style']) ? $variables['object']->override['style'] : '';
$image_variables['attributes'] = array('width' => $width, 'height' => $height, 'style' => $WYSIWYG);
$output = theme('image', $image_variables);
}
if ($in_browser) {
// Add an overlay that says 'Archive' to media library browser thumbnails.
$output .= '<span />';
}
}
else {
$output = theme('media_archive_video', array('uri' => $uri, 'width' => $width, 'height' => $height, 'autoplay' => ($autoplay == 'true' ? TRUE : NULL), 'fullscreen' => ($fullscreen_value == 'true' ? TRUE : NULL)));
}
}
return $output;
}

View File

@@ -0,0 +1,5 @@
//http://www.featureblend.com/license.txt
var FlashDetect=new function(){var self=this;self.installed=false;self.raw="";self.major=-1;self.minor=-1;self.revision=-1;self.revisionStr="";var activeXDetectRules=[{"name":"ShockwaveFlash.ShockwaveFlash.7","version":function(obj){return getActiveXVersion(obj);}},{"name":"ShockwaveFlash.ShockwaveFlash.6","version":function(obj){var version="6,0,21";try{obj.AllowScriptAccess="always";version=getActiveXVersion(obj);}catch(err){}
return version;}},{"name":"ShockwaveFlash.ShockwaveFlash","version":function(obj){return getActiveXVersion(obj);}}];var getActiveXVersion=function(activeXObj){var version=-1;try{version=activeXObj.GetVariable("$version");}catch(err){}
return version;};var getActiveXObject=function(name){var obj=-1;try{obj=new ActiveXObject(name);}catch(err){obj={activeXError:true};}
return obj;};var parseActiveXVersion=function(str){var versionArray=str.split(",");return{"raw":str,"major":parseInt(versionArray[0].split(" ")[1],10),"minor":parseInt(versionArray[1],10),"revision":parseInt(versionArray[2],10),"revisionStr":versionArray[2]};};var parseStandardVersion=function(str){var descParts=str.split(/ +/);var majorMinor=descParts[2].split(/\./);var revisionStr=descParts[3];return{"raw":str,"major":parseInt(majorMinor[0],10),"minor":parseInt(majorMinor[1],10),"revisionStr":revisionStr,"revision":parseRevisionStrToInt(revisionStr)};};var parseRevisionStrToInt=function(str){return parseInt(str.replace(/[a-zA-Z]/g,""),10)||self.revision;};self.majorAtLeast=function(version){return self.major>=version;};self.minorAtLeast=function(version){return self.minor>=version;};self.revisionAtLeast=function(version){return self.revision>=version;};self.versionAtLeast=function(major){var properties=[self.major,self.minor,self.revision];var len=Math.min(properties.length,arguments.length);for(i=0;i<len;i++){if(properties[i]>=arguments[i]){if(i+1<len&&properties[i]==arguments[i]){continue;}else{return true;}}else{return false;}}};self.FlashDetect=function(){if(navigator.plugins&&navigator.plugins.length>0){var type='application/x-shockwave-flash';var mimeTypes=navigator.mimeTypes;if(mimeTypes&&mimeTypes[type]&&mimeTypes[type].enabledPlugin&&mimeTypes[type].enabledPlugin.description){var version=mimeTypes[type].enabledPlugin.description;var versionObj=parseStandardVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revisionStr=versionObj.revisionStr;self.revision=versionObj.revision;self.installed=true;}}else if(navigator.appVersion.indexOf("Mac")==-1&&window.execScript){var version=-1;for(var i=0;i<activeXDetectRules.length&&version==-1;i++){var obj=getActiveXObject(activeXDetectRules[i].name);if(!obj.activeXError){self.installed=true;version=activeXDetectRules[i].version(obj);if(version!=-1){var versionObj=parseActiveXVersion(version);self.raw=versionObj.raw;self.major=versionObj.major;self.minor=versionObj.minor;self.revision=versionObj.revision;self.revisionStr=versionObj.revisionStr;}}}}}();};FlashDetect.JS_RELEASE="1.0.4";

View File

@@ -0,0 +1,127 @@
/**
* @file
* Create the 'Archive' tab for the WYSIWYG plugins.
*/
// (function ($) {
// namespace('Drupal.media.browser.plugin');
//
// Drupal.media.browser.plugin.media_archive = function(mediaBrowser, options) {
// return {
// init: function() {
// tabset = mediaBrowser.getTabset();
// tabset.tabs('add', '#media_archive', 'Archive');
// mediaBrowser.listen('tabs.show', function (e, id) {
// if (id == 'media_archive') {
// // We only need to set this once.
// // We probably could set it upon load.
// if (mediaBrowser.getActivePanel().html() == '') {
// mediaBrowser.getActivePanel().html(options.media_archive);
// }
// }
// });
// }
// }
// };
//
// // For now, I guess self registration makes sense.
// // Really though, we should be doing it via drupal_add_js and some settings
// // from the drupal variable.
// //@todo: needs a review.
// Drupal.media.browser.register('media_archive', Drupal.media.browser.plugin.media_archive, {});
// })(jQuery);
(function ($) {
namespace('media.browser.plugin');
Drupal.media.browser.plugin.archive_library = function(mediaBrowser, options) {
return {
mediaFiles: [],
init: function() {
tabset = mediaBrowser.getTabset();
tabset.tabs('add', '#archive_library', 'Archive');
var that = this;
mediaBrowser.listen('tabs.show', function (e, id) {
if (id == 'archive_library') {
// This is kinda rough, I'm not sure who should delegate what here.
mediaBrowser.getActivePanel().addClass('throbber');
mediaBrowser.getActivePanel().html('');
//mediaBrowser.getActivePanel().addClass('throbber');
// Assumes we have to refresh everytime.
// Remove any existing content
mediaBrowser.getActivePanel().append('<ul></ul>');
that.browser = $('ul', mediaBrowser.getActivePanel());
that.browser.addClass('clearfix');
that.getMedia();
}
});
},
getStreams: function () {
return ['archive://'];
},
getConditions: function () {
return {};
//return this.settings.conditions;
},
getMedia: function() {
var that = this;
var callback = mediaBrowser.getCallbackUrl('getMedia');
var params = {
conditions: JSON.stringify(this.getConditions()),
streams: JSON.stringify(this.getStreams())
};
jQuery.get(
callback,
params,
function(data, status) {
that.mediaFiles = data.media;
that.emptyMessage = data.empty;
that.pager = data.pager;
that.render();
},
'json'
);
},
render: function() {
var that = this;
mediaBrowser.getActivePanel().removeClass('throbber');
if (this.mediaFiles.length < 1) {
jQuery('<div id="media-empty-message" class="media-empty-message"></div>').appendTo(this.browser)
.html(this.emptyMessage);
return;
}
for (var m in this.mediaFiles) {
mediaFile = this.mediaFiles[m];
var listItem = jQuery('<li></li>').appendTo(this.browser)
.attr('id', 'media-file-' + mediaFile.fid)
.addClass('media-file');
var imgLink = jQuery('<a href="#"></a>').appendTo(listItem)
.html(mediaFile.preview)
.bind('click', mediaFile, function(e) {
// Notify the main browser
//this.selectedMedia = mediaFile;
$('div.media-thumbnail img').removeClass('selected');
$('div.media-thumbnail img', $(this)).addClass('selected');
mediaBrowser.notify('mediaSelected', {mediaFiles: [e.data]});
//that.settings.onSelect(mediaFile);
return false;
});
}
jQuery('<div id="media-pager" class="media-pager"></div>').appendTo(this.browser)
.html(this.pager);
}
};
};
Drupal.media.browser.register('archive_library', Drupal.media.browser.plugin.archive_library);
})(jQuery);

View File

@@ -0,0 +1,99 @@
/**
* @file media_archive/js/media_archive.js
*/
(function ($) {
Drupal.media_archive = {};
Drupal.behaviors.media_archive = {
attach: function (context, settings) {
// Check the browser to see if it supports html5 video.
var video = document.createElement('video');
var html5 = video.canPlayType ? true : false;
// If it has video, does it support the correct codecs?
if (html5) {
html5 = false;
if (video.canPlayType( 'video/webm; codecs="vp8, vorbis"' ) || video.canPlayType('video/mp4; codecs="avc1.42E01E, mp4a.40.2"')) {
html5 = true;
}
}
// Put a prompt in the video wrappers to let users know they need flash
if (!FlashDetect.installed && !html5){
$('.media-archive-preview-wrapper').each(Drupal.media_archive.needFlash);
}
}
};
Drupal.media_archive.needFlash = function () {
var id = $(this).attr('id');
var wrapper = $('.media-archive-preview-wrapper');
var hw = Drupal.settings.media_archive[id].height / Drupal.settings.media_archive[id].width;
wrapper.html('<div class="js-fallback">' + Drupal.t('You need Flash to watch this video. <a href="@flash">Get Flash</a>', {'@flash':'http://get.adobe.com/flashplayer'}) + '</div>');
wrapper.height(wrapper.width() * hw);
};
Drupal.media_archive.insertEmbed = function (embed_id) {
var videoWrapper = $('#' + embed_id + '.media-archive-preview-wrapper');
var settings = Drupal.settings.media_archive[embed_id];
// Calculate the ratio of the dimensions of the embed.
settings.hw = settings.height / settings.width;
// Replace the object embed with Archive's iframe. This isn't done by the
// theme function because Archive doesn't have a no-JS or no-Flash fallback.
var video = $('<iframe class="archive-player" type="text/html" frameborder="0"></iframe>');
var src = 'http://www.archive.org/file/' + settings.video_id;
// Allow other modules to modify the video settings.
settings.options = {wmode : 'opaque'};
$(window).trigger('media_archive_load', settings);
// Merge Archive options (such as autoplay) into the source URL.
var query = $.param(settings.options);
if (query) {
src += '?' + query;
}
// Set up the iframe with its contents and add it to the page.
video
.attr('id', settings.id)
.attr('width', settings.width)
.attr('height', settings.height)
.attr('src', src);
videoWrapper.html(video);
// Bind a resize event to handle fluid layouts.
$(window).bind('resize', Drupal.media_archive.resizeEmbeds);
// For some reason Chrome does not properly size the container around the
// embed and it will just render the embed at full size unless we set this
// timeout.
if (!$('.lightbox-stack').length) {
setTimeout(Drupal.media_archive.resizeEmbeds, 1);
}
};
Drupal.media_archive.resizeEmbeds = function () {
$('.media-archive-preview-wrapper').each(Drupal.media_archive.resizeEmbed);
};
Drupal.media_archive.resizeEmbed = function () {
var context = $(this).parent();
var video = $(this).children(':first-child');
var hw = Drupal.settings.media_archive[$(this).attr('id')].hw;
// Change the height of the wrapper that was given a fixed height by the
// Archive theming function.
$(this)
.height(context.width() * hw)
.width(context.width());
// Change the attributes on the embed to match the new size.
video
.height(context.width() * hw)
.width(context.width());
};
})(jQuery);

View File

@@ -0,0 +1,113 @@
<?php
/**
* @file
* Administrative page callbacks for Media: Archive.
*/
/**
* Callback for /media/add/media_archive and
* /admin/content/media/add/media_archive.
*/
function media_archive_add($form, &$form_state = array(), $redirect = NULL) {
global $user;
$form = array();
$form['archive'] = array(
'#type' => 'vertical_tabs',
);
$form['archive']['all'] = array(
'#type' => 'fieldset',
'#title' => t('All Archive videos'),
);
// Get all archive files for this user
$results = db_query("SELECT fid FROM {file_managed} WHERE uid = :uid AND uri LIKE :uri", array(
':uid' => $user->uid,
':uri' => 'archive%%'
))->fetchAll();
foreach ($results as $result) {
$file = file_load($result->fid);
$output = theme('image', array(
'path' => 'http://img.archive.org/vi/' . pathinfo($file->uri, PATHINFO_FILENAME) . '/0.jpg',
'title' => 'title',
'alt' => 'alt',
'attributes' => array('width' => 150),
'getsize' => FALSE,
));
$form['archive']['all'][$file->fid] = array(
'#markup' => $output,
);
}
/* $form['archive']['all']['test'] = array(
'#type' => 'checkbox',
'#title' => 'test',
);*/
$form['archive']['add_from_url'] = array(
'#type' => 'fieldset',
'#title' => t('Add from URL'),
);
$form['archive']['add_from_url']['url'] = array(
'#type' => 'textfield',
'#title' => 'URL',
'#description' => 'Input the URL of the desired Archive video page.',
);
$form['redirect'] = array(
'#type' => 'value',
'#value' => $redirect,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => 'Submit',
);
return $form;
}
/**
* Validation for media_archive_add().
*/
function media_archive_add_validate($form, &$form_state) {
if (!preg_match('@blip\.tv/file/([^"\& ]+)@i', $form_state['values']['url'], $matches)) {
form_set_error('url', t('Please submit a valid Archive video URL.'));
}
}
/**
* Submission for media_archive_add().
*
* This will create a file object for the Archive video.
*/
function media_archive_add_submit($form, &$form_state) {
$defaults = array (
'display' => TRUE,
);
$uri = media_archive_media_parse($form_state['values']['url']);
// Check to see if this a duplicate of an existing file
$files = file_load_multiple(NULL, array('uri' => $uri));
if ($files) {
// This is ugly.
$file = array_shift($files);
}
else {
// @TODO: This won't work for Archive and many other streams.
// copy($url, $destination);
$file = file_uri_to_object($uri);
file_save($file);
}
// field_attach_insert('media', $file);
if ($file) {
$form_state['redirect'] = 'media/' . $file->fid . '/edit';
field_attach_submit('media', $file, $form, $form_state);
field_attach_insert('media', $file);
}
else {
drupal_set_message(t('An error occurred and no file was saved.'), 'error');
}
$form_state['redirect'] = !empty($form_state['values']['redirect']) ? $form_state['values']['redirect'] : 'media/' . $file->fid . '/edit';
}

View File

@@ -0,0 +1,17 @@
name = Media: Archive
description = Provides Archive support to the Media module.
package = "Media"
core = 7.x
files[] = media_archive.module
files[] = MediaArchiveStreamWrapper.inc
files[] = media_archive.admin.inc
files[] = includes/media_archive.styles.inc
dependencies[] = media_internet
; Information added by drupal.org packaging script on 2011-05-31
version = "7.x-1.0-beta1"
core = "7.x"
project = "media_archive"
datestamp = "1306873316"

View File

@@ -0,0 +1,24 @@
<?php
/**
* @file
* Install, update and uninstall functions for the Media: Archive module.
*/
/**
* Implement hook_install().
*/
function media_archive_install() {
return array();
}
/**
* Implement hook_uninstall().
*/
function media_archive_uninstall() {
foreach (media_archive_variable_default() as $variable => $value) {
media_archive_variable_del($variable);
}
return array(array('success' => TRUE, 'query' => "Deleted all variables in the Media: Archive namespace."));
}

View File

@@ -0,0 +1,352 @@
<?php
/**
* @file media_archive/media_archive.module
*
* Media: Archive provides a stream wrapper and formatters for videos provided
* by Archive, available at http://archive.org/.
*
* @TODO:
* Tie in Archive API.
* Allow editors to search for videos to display on the browser.
* Allow editors to put in a archive username to display on the browser.
* Allow editors to log in w/ their credentials.
* Allow editors to upload videos to Archive.
*/
// A registry of variable_get defaults.
include_once('includes/media_archive.variables.inc');
/**
* Create stream wrapper for Archive videos.
*/
function media_archive_stream_wrappers() {
return array(
'archive' => array(
'name' => t('Archive videos'),
'class' => 'MediaArchiveStreamWrapper',
'description' => t('Videos provided by Archive.'),
'type' => STREAM_WRAPPERS_READ_VISIBLE,
),
);
}
function media_archive_media_format_form_prepare_alter(&$form, &$form_state, $media) {
$settings = array('autosubmit' => ($media->type == "video"));
drupal_add_js(array('media_format_form' => $settings), 'setting');
}
/**
* Implements hook_theme().
*/
function media_archive_theme($existing, $type, $theme, $path) {
return array(
'media_archive_preview_style' => array(
'variables' => array('style_name' => NULL),
'file' => 'media_archive.theme.inc',
'path' => $path . '/includes/themes',
),
'media_archive_field_formatter_styles' => array(
'variables' => array('element' => NULL, 'style' => NULL),
'file' => 'media_archive.theme.inc',
'path' => $path . '/includes/themes',
),
'media_archive_video' => array(
'variables' => array('uri' => NULL, 'width' => NULL, 'height' => NULL, 'autoplay' => NULL, 'fullscreen' => NULL),
'file' => 'media_archive.theme.inc',
'path' => $path . '/includes/themes',
'template' => 'media-archive-video',
),
'media_archive_embed' => array(
'variables' => array('style_name' => NULL, 'uri' => NULL, 'alt' => NULL, 'title' => NULL),
'file' => 'media_archive.theme.inc',
'path' => $path . '/includes/themes',
),
'media_archive_styles' => array(
'variables' => array('element' => NULL, 'style' => NULL),
'file' => 'media_archive.theme.inc',
'path' => $path . '/includes/themes',
),
);
}
/**
* Implementation of Styles module hook_styles_register().
*/
function media_archive_styles_register() {
return array(
'MediaArchiveStyles' => array(
'field_types' => 'file',
'name' => t('MediaArchive'),
'description' => t('Media Archive styles.'),
'path' => drupal_get_path('module', 'media_archive') .'/includes',
'file' => 'media_archive.styles.inc',
),
);
}
/**
* Implements hook_styles_containers(). (Deprecated in version 2)
*/
function media_archive_styles_containers() {
return array(
'file' => array(
'containers' => array(
'media_archive' => array(
'label' => t('Archive Styles'),
'data' => array(
'streams' => array(
'archive',
),
'mimetypes' => array(
'video/archive',
),
),
'weight' => 0,
'filter callback' => 'media_archive_formatter_filter',
'themes' => array(
'field_formatter_styles' => 'media_archive_field_formatter_styles',
'styles' => 'media_archive_styles',
'preview' => 'media_archive_preview_style',
),
'description' => t('Archive Styles will display embedded Archive videos and thumbnails to your choosing, such as by resizing, setting colors, and autoplay. You can !manage.', array('!manage' => l(t('manage your Archive styles here'), 'admin/config/media/media-archive-styles'))),
),
),
),
);
}
function media_archive_formatter_filter($variables) {
if (isset($variables['object'])) {
$object = $variables['object'];
return (file_uri_scheme($object->uri) == 'archive') && ($object->filemime == 'video/archive');
}
}
/**
* Implementation of the File Styles module's hook_file_styles_filter().
*/
function media_archive_file_styles_filter($object) {
if ((file_uri_scheme($object->uri) == 'archive') && ($object->filemime == 'video/archive')) {
return 'media_archive';
}
}
/**
* Implements hook_styles_styles().
*/
function media_archive_styles_styles() {
$styles = array(
'file' => array(
'containers' => array(
'media_archive' => array(
'styles' => array(
'archive_thumbnail' => array(
'name' => 'archive_thumbnail',
'effects' => array(
array('label' => t('Thumbnail'), 'name' => 'thumbnail', 'data' => array('thumbnail' => 1)),
array('label' => t('Resize'), 'name' => 'resize', 'data' => array('width' => 100, 'height' => 75)),
),
),
'archive_preview' => array(
'name' => 'archive_preview',
'effects' => array(
array('label' => t('Autoplay'), 'name' => 'autoplay', 'data' => array('autoplay' => 1)),
array('label' => t('Resize'), 'name' => 'resize', 'data' => array('width' => 220, 'height' => 165)),
),
),
'archive_full' => array(
'name' => 'archive_full',
'effects' => array(
array('label' => t('Autoplay'), 'name' => 'autoplay', 'data' => array('autoplay' => 0)),
array('label' => t('Resize'), 'name' => 'resize', 'data' => array('width' => 640, 'height' => 480)),
array('label' => t('Full screen'), 'name' => 'fullscreen', 'data' => array('fullscreen' => 1)),
),
),
),
),
),
),
);
// Allow any image style to be applied to the thumbnail.
foreach (image_styles() as $style_name => $image_style) {
$styles['file']['containers']['media_archive']['styles']['archive_thumbnail_' . $style_name] = array(
'name' => 'archive_thumbnail_' . $style_name,
'image_style' => $style_name,
'effects' => array(
array('label' => t('Thumbnail'), 'name' => 'thumbnail', 'data' => array('thumbnail' => 1)),
),
);
}
return $styles;
}
/**
* Implements hook_styles_presets().
*/
function media_archive_styles_presets() {
$presets = array(
'file' => array(
'square_thumbnail' => array(
'media_archive' => array(
'archive_thumbnail_square_thumbnail',
),
),
'thumbnail' => array(
'media_archive' => array(
'archive_thumbnail',
),
),
'small' => array(
'media_archive' => array(
'archive_preview',
),
),
'large' => array(
'media_archive' => array(
'archive_full',
),
),
'original' => array(
'media_archive' => array(
'archive_full',
),
),
),
);
return $presets;
}
/**
* Implements hook_media_parse().
*
* @todo: this might be deprecated now that we have media_internet,
* but the hook is still being called in a couple places in media.
*/
function media_archive_media_parse($url, $options = array()) {
$scheme = 'archive://';
preg_match('@archive\.org/details/([^"\& ]+)@i', $url, $matches);
if (isset($matches[1])) {
$org = media_archive_embedcode_lookup($matches[1]);
return file_stream_wrapper_uri_normalize($scheme . 'v/' . $matches[1] . '/org/' . $org);
}
// @TODO: Validate for malformed archive urls.
}
/**
* Implements hook_media_internet_providers();
*/
function media_archive_media_internet_providers() {
$path = drupal_get_path('module', 'media_archive');
return array(
'MediaInternetArchiveHandler' => array(
'title' => 'archive',
'image' => $path . '/images/stream-archive.png'
),
);
}
class MediaInternetArchiveHandler extends MediaInternetBaseHandler {
public function claim($embedCode) {
if (media_archive_media_parse($embedCode)) {
return TRUE;
}
}
public function validate() {
// @todo Media module currently fails when two files try to have the same
// URI, so catch that in the validation step. Some day, it would be nice
// to allow it, however. See http://drupal.org/node/952422.
$uri = media_archive_media_parse($this->embedCode);
$existing_files = file_load_multiple(array(), array('uri' => $uri));
if (count($existing_files)) {
throw new MediaInternetValidationException(t('You have entered a URL for a video that is already in your library.'));
}
}
public function save() {
$file = $this->getFileObject();
file_save($file);
return $file;
}
public function getFileObject() {
$uri = media_archive_media_parse($this->embedCode);
//@todo: this is terribly broken in some ways because the function is really
// made for local files which are 'real'
return file_uri_to_object($uri);
}
/**
* Returns information about the media. See http://video.search.yahoo.com/mrss.
*
* @return
* If ATOM+MRSS information is available, a SimpleXML element containing
* ATOM and MRSS elements, as per those respective specifications.
*
* @todo Would be better for the return value to be an array rather than a
* SimpleXML element, but media_retrieve_xml() needs to be upgraded to
* handle namespaces first.
*/
//http://archive.org/file/4035623?skin=rss
public function getMRSS() {
$uri = media_archive_media_parse($this->embedCode);
$video_id = arg(1, file_uri_target($uri));
$rss_url = url('http://gdata.archive.org/feeds/api/videos/' . $video_id, array('query' => array('v' => '2')));
// @todo Use media_retrieve_xml() once it's upgraded to include elements
// from all namespaces, not just the document default namespace.
$entry = simplexml_load_file($rss_url);
return $entry;
}
/**
* Returns information about the media. See http://www.oembed.com/.
*
* @return
* If oEmbed information is available, an array containing 'title', 'type',
* 'url', and other information as specified by the oEmbed standard.
* Otherwise, NULL.
*/
//http://archive.org/oembed/?url=http://archive.org/file/12345
public function getOEmbed() {
$uri = media_archive_media_parse($this->embedCode);
$external_url = drupal_realpath($uri);
$oembed_url = url('http://archive.org/oembed', array('query' => array('url' => $external_url, 'format' => 'json')));
$response = drupal_http_request($oembed_url);
if (!isset($response->error)) {
return drupal_json_decode($response->data);
}
}
}
function media_archive_embedcode_lookup($video_id) {
//http://www.archive.org/download/bavc-77620-dominotheory/bavc-77620-dominotheory_files.xml
//<original>Domino_Theory.mpeg</original>
// I hate this, but after reading http://data.agaric.com/node/2378 I'm
// begining to think there isn't an easier way
// if there isn't a better way, this needs to be done once and stored
$url = 'http://www.archive.org/download/' . $video_id . '/' . $video_id;
$rss_source = $url . '_files.xml';
$rss = file_get_contents($rss_source);
preg_match('/<original>(.+)<\/original>/', $rss, $matches);
if (isset($matches[1])) {
$info = pathinfo($matches[1]);
$file_name = basename($matches[1],'.'.$info['extension']);
return $file_name;
}
}

View File

@@ -0,0 +1,30 @@
/**
* @file
* Overlay for Archive thumbnails in the media library browser.
*/
#media-browser .styles-container-media_archive {
/* Relative wrapper for the overlay. */
position: relative;
}
#media-browser .styles-container-media_archive span {
/* Here's the overlay image. */
background: url(images/stream-archive.png) no-repeat;
/* Absolute positioning in the relative wrapper creates the overlay. */
position: absolute;
/* Size of the overlay */
width: 69px;
height: 22px;
/* Position of the overlay */
left: 33px;
top: 80px;
}
#media-browser .styles-container-media_archive span:hover {
/* The */
background-position: 0px -22px;
}
#media-browser .styles-container-media_archive img {
}

View File

@@ -0,0 +1,359 @@
<?php
/**
* @file
* This include processes archive.org audio files for use with Embedded Media Field.
*/
/**
* This is the main URL for your provider.
*/
define('EMAUDIO_ARCHIVE_MAIN_URL', 'http://www.archive.org/');
/**
* This is the URL to the API of your provider, if this exists.
*/
define('EMAUDIO_ARCHIVE_API_URL', 'http://www.google.com/search?q=archive.org+api');
/**
* This defines the version of the content data array that we serialize
* in emaudio_archive_data(). If we change the expected keys of that array,
* we must increment this value, which will allow older content to be updated
* to the new version automatically.
*/
define('EMAUDIO_ARCHIVE_DATA_VERSION', 2);
/**
* hook emaudio_PROVIDER_info
* This returns information relevant to a specific 3rd party audio provider.
*
* @return
* A keyed array of strings requested by various admin and other forms.
* 'provider' => The machine name of the provider. This must be the same as
* the base name of this filename, before the .inc extension.
* 'name' => The translated name of the provider.
* 'url' => The url to the main page for the provider.
* 'settings_description' => A description of the provider that will be
* posted in the admin settings form.
* 'supported_features' => An array of rows describing the state of certain
* supported features by the provider. These will be rendered in a table,
* with the columns being 'Feature', 'Supported', 'Notes'. In general,
* the 'Feature' column will give the name of the feature, 'Supported'
* will be Yes or No, and 'Notes' will give an optional description or
* caveats to the feature.
*/
function emaudio_archive_audio_info() {
$features = array(
array(t('Thumbnails'), t('No'), ''),
array(t('Autoplay'), t('Yes'), ''),
array(t('RSS attachment'), t('No'), ''),
);
return array(
'provider' => 'archive_audio',
'name' => t('Archive'),
'url' => EMAUDIO_ARCHIVE_MAIN_URL,
'settings_description' => t('These settings specifically affect audio played from !archive. You can also read more about its !api.', array('!archive' => l(t('Archive.com'), EMAUDIO_ARCHIVE_MAIN_URL), '!api' => l(t("developer's API"), EMAUDIO_ARCHIVE_API_URL))),
'supported_features' => $features,
);
}
/**
* hook emaudio_PROVIDER_settings
* This should return a subform to be added to the emaudio_settings() admin
* settings page.
*
* Note that a form field set will already be provided at $form['archive'],
* so if you want specific provider settings within that field set, you should
* add the elements to that form array element.
*/
function emaudio_archive_audio_settings() {
/* No Settings for this provider */
}
/**
* hook emaudio_PROVIDER_extract
*
* This is called to extract the audio code from a pasted URL or embed code.
*
* We'll be passed a URL or the embed code from a audio when an editor pastes
* that in the field's textfield. We'll need to either pass back an array of
* regex expressions to match, or do the matching ourselves and return the
* resulting audio code.
*
* @param $parse
* An optional string with the pasted URL or embed code.
* @return
* Either an array of regex expressions to be tested, or a string with the
* audio code to be used. If the hook tests the code itself, it should
* return either the string of the audio code (if matched), or an empty
* array. Otherwise, the calling function will handle testing the embed code
* against each regex string in the returned array.
*/
function emaudio_archive_audio_extract($parse = '') {
// Here we assume that a URL will be passed in the form of
// http://www.archive.org/details/text-audio-title
// or embed code in the form of
//<embed ... "playlist":[{"url":"http://www.archive.org/download/text-audio-title/...
// We'll simply return an array of regular expressions for Embedded Media
// Field to handle for us.
return array(
//In the URL the archive.org item id will appear after "details/" in the URL
'@archive\.org\/details\/([^\"\&]+)@i',
// Now we test for embedded audio code, which is similar in this case to
// the above expression, except the item id will appear after "download/"
'@archive\.org/download/([^/]+)@i',
);
}
/**
* Implement hook emaudio_PROVIDER_data_version().
*/
function emaudio_archive_audio_data_version() {
return EMAUDIO_ARCHIVE_DATA_VERSION;
}
/**
* hook emaudio_PROVIDER_data
*
* Provides an array to be serialised and made available with $item elsewhere.
*
* This data can be used to store any extraneous information available
* specifically to the archive provider.
*/
function emaudio_archive_audio_data($field, $item, $error_field = '') {
// Initialize the data array.
$data = array();
// Create some version control. Thus if we make changes to the data array
// down the road, we can respect older content. If allowed by Embedded Media
// Field, any older content will automatically update this array as needed.
// In any case, you should account for the version if you increment it.
$data['emaudio_archive_version'] = EMAUDIO_ARCHIVE_DATA_VERSION;
// Construct a base item url
$item_url = "http://www.archive.org/details/". $item['value'];
// We will leverage the JSON archive.org api to get details about this item
// See http://www.archive.org/help/json.php
$xml_meta_url = $item_url .'&output=json';
$xml_meta = media_archive_request_xml('archive', $xml_meta_url, array(), TRUE, TRUE, $item['value'] .'_meta', FALSE, TRUE);
if ($xml_meta['stat'] == 'error' || empty($xml_meta)) {
drupal_set_message('This item\'s details cannot be retrieved. The audio can not be displayed.');
return $data;
}
else {
$data['details'] = $xml_meta;
$server_url = $data['details']['server'] . $data['details']['dir'];
}
$item_files = $data['details']['files'];
if (!$item_files) {
form_set_error($error_field, 'The list of files for the item at archive.org could not be retrieved. The audio can not be displayed.');
return $data;
}
//Putting the $key (which is actually the file name) as an element of the
//array too for convenience later.
foreach ($item_files as $key => $value) {
$item_files[$key]['name'] = $key;
}
//Get playlist files only (.m3u files)
$files_playlists = array_filter($item_files, "_archive_audio_isplaylist");
//If there is no playlist then fail
if (is_null($files_playlists)) {
form_set_error($error_field, 'This archive.org item does not appear to have a playlist.');
return $data;
}
//We'll custom sort the array so we'll get first VBR playlists, then other
//playlists sorted by highest bitrate. Goal is to present the highest
//bitrate playlist offered for this item.
$data['playlists'] = $files_playlists;
$worked = uasort($files_playlists, "_archive_audio_playlistsort");
$candidate_playlist = array_shift($files_playlists);
$data['playlist_file_used'] = $candidate_playlist;
//Retrieve the playlist
$result = drupal_http_request('http://' . $server_url . $candidate_playlist['name']);
if (!empty($result->error)) {
form_set_error($error_field, 'The playlist for the item at archive.org could not be retrieved. The audio can not be displayed.');
return $data;
}
$playlist = $result->data;
//We'll store it in the data element as it is used in our theme function to
//output the player later.
$data['playlist'] = explode("\n", trim($playlist));
return $data;
}
/**
* Sort playlist files
*/
function _archive_audio_playlistsort($file1, $file2) {
$components1 = explode(" ", $file1['format']);
$components2 = explode(" ", $file2['format']);
if ($components1[0] == $components2[0]) {
return 0;
}
//We'll prefer the Variable Bitrate (VBR)
elseif ($components1[0] == "VBR") {
return -1;
}
elseif ($components2[0] == "VBR") {
return 1;
}
//Otherwise we'll look for the highest bitrate playlist
$br1 = (int)$components1[0];
$br2 = (int)$components2[0];
if ($br1 > $br2) {
return -1;
}
else {
return 1;
}
}
/**
* Is this file a playlist (.m3u) file?
*/
function _archive_audio_isplaylist($file) {
if (substr($file['format'], -3, 3) == "M3U") {
return TRUE;
}
else {
return FALSE;
}
}
/**
* hook emfield_PROVIDER_rss
*/
function emaudio_archive_audio_rss($item, $teaser = NULL) {
// Get size and mime type of first playlist file
$url = $item['data']['playlist'][0];
$response = emfield_request_header('archive_audio', $url, $cached = FALSE);
if ($response->code == 200) {
$data['size'] = $response->headers['Content-Length'];
$data['mime'] = $response->headers['Content-Type'];
}
if ($data['size']) {
$file = array();
$file['filepath'] = $url;
$file['filesize'] = $data['size'];
$file['filemime'] = $data['mime'];
}
return $file;
}
/**
* hook emaudio_PROVIDER_embedded_link($audio_code)
* returns a link to view the audio at the provider's site.
* @param $audio_code
* The string containing the audio item.
* @return
* A string containing the URL the audio item at the original provider's site.
*/
function emaudio_archive_audio_embedded_link($audio_code) {
return 'http://www.archive.org/details/'. $audio_code;
}
/**
* Implementation of hook emaudio_archive_audio_audio().
*
* This actually displays the full/normal-sized audio we want, usually on the default page view.
*
* @param $embed
* The audio code for the audio to embed.
* @param $width
* The width to display the audio.
* @param $height
* The height to display the audio.
* @param $field
* The field info from the requesting node.
* @param $item
* The actual content from the field.
* @return
* The html of the embedded audio.
*/
function emaudio_archive_audio_audio($embed = NULL, $width = 0, $height = 0, $field = NULL, $item, $node, $autoplay) {
$output = theme('emaudio_archive_audio_flash', $embed, $width, $height, $field, $item, $node, $autoplay);
return $output;
}
/**
* The embedded flash displaying the archive audio.
*/
function theme_emaudio_archive_audio_flash($embed, $width, $height, $field, $item, $node, $autoplay) {
$output = '';
if ($item) {
$flowplayerplaylist = _media_archive_flowplayer_playlist($item['data']['playlist']);
$controlplaylist = (count($item['data']['playlist'])>1) ? "true" : "false";
$clipautoplay = $autoplay ? 'true' : 'false';
$output = <<<EOD
<embed type="application/x-shockwave-flash" width="$width" height="$height" allowfullscreen="true"
allowscriptaccess="always" src="http://www.archive.org/flow/flowplayer.commercial-3.0.5.swf" w3c="true"
flashvars='config={
"key":"#\$b6eb72a0f2f1e29f3d4",
"playlist":[
{$flowplayerplaylist}
],
"clip":{
"autoPlay":{$clipautoplay}
},
"canvas":{
"backgroundColor":"0x000000",
"backgroundGradient":"none"
},
"plugins":{
"audio":{
"url":"http://www.archive.org/flow/flowplayer.audio-3.0.3-dev.swf"
},
"controls":{
"playlist":{$controlplaylist},
"fullscreen":false,
"gloss":"high",
"backgroundColor":"0x000000",
"backgroundGradient":"medium",
"sliderColor":"0x777777",
"progressColor":"0x777777",
"timeColor":"0xeeeeee",
"durationColor":"0x01DAFF",
"buttonColor":"0x333333",
"buttonOverColor":"0x505050"
}
},
"contextMenu":[
{
"Item {$item['value']} at archive.org":"function()"
},
"-",
"Flowplayer 3.0.5"
]
}'>
</embed>
EOD;
}
return $output;
}
/**
* Implementation of hook_emfield_subtheme().
*/
function emaudio_archive_audio_emfield_subtheme() {
return array(
'emaudio_archive_audio_flash' => array(
'arguments' => array('embed' => NULL, 'width' => NULL, 'height' => NULL, 'field' => NULL, 'data' => NULL, 'node' => NULL, 'autoplay' => NULL),
'file' => 'providers/emaudio/archive_audio.inc',
'path' => drupal_get_path('module', 'media_archive'),
)
);
}

View File

@@ -0,0 +1,407 @@
<?php
/**
* @file
* This is an archive.org provider include file for Embedded Media Video.
*/
/**
* This is the main URL for your provider.
*/
define('EMVIDEO_ARCHIVE_MAIN_URL', 'http://www.archive.org/');
/**
* This is the URL to the API of your provider, if this exists.
*/
define('EMVIDEO_ARCHIVE_API_URL', 'http://www.google.com/search?q=archive.org+api');
/**
* This defines the version of the content data array that we serialize
* in emvideo_archive_data(). If we change the expected keys of that array,
* we must increment this value, which will allow older content to be updated
* to the new version automatically.
*/
define('EMVIDEO_ARCHIVE_DATA_VERSION', 2);
/**
* hook emvideo_PROVIDER_info
* This returns information relevant to a specific 3rd party video provider.
*
* @return
* A keyed array of strings requested by various admin and other forms.
* 'provider' => The machine name of the provider. This must be the same as
* the base name of this filename, before the .inc extension.
* 'name' => The translated name of the provider.
* 'url' => The url to the main page for the provider.
* 'settings_description' => A description of the provider that will be
* posted in the admin settings form.
* 'supported_features' => An array of rows describing the state of certain
* supported features by the provider. These will be rendered in a table,
* with the columns being 'Feature', 'Supported', 'Notes'. In general,
* the 'Feature' column will give the name of the feature, 'Supported'
* will be Yes or No, and 'Notes' will give an optional description or
* caveats to the feature.
*/
function emvideo_archive_info() {
$features = array(
array(t('Autoplay'), t('Yes'), ''),
array(t('RSS Attachment'), t('Yes'), ''),
array(t('Thumbnails'), t('Yes'), t('')),
array(t('Full screen mode'), t('Yes'), t('You may customize the player to enable or disable full screen playback. Full screen mode is enabled by default.')),
);
return array(
'provider' => 'archive',
'name' => t('archive.org'),
'url' => EMVIDEO_ARCHIVE_MAIN_URL,
'settings_description' => t('These settings specifically affect videos displayed from !archive. You can also read more about its !api.', array('!archive' => l(t('Archive.com'), EMVIDEO_ARCHIVE_MAIN_URL), '!api' => l(t("developer's API"), EMVIDEO_ARCHIVE_API_URL))),
'supported_features' => $features,
);
}
/**
* hook emvideo_PROVIDER_settings
* This should return a subform to be added to the emvideo_settings() admin
* settings page.
*
* Note that a form field set will already be provided at $form['archive'],
* so if you want specific provider settings within that field set, you should
* add the elements to that form array element.
*/
function emvideo_archive_settings() {
// We'll add a field set of player options here. You may add other options
// to this element, or remove the field set entirely if there are no
// user-configurable options allowed by the archive provider.
/* $form['archive']['player_options'] = array(
'#type' => 'fieldset',
'#title' => t('Embedded video player options'),
'#collapsible' => TRUE,
'#collapsed' => TRUE,
);
// This is an option to set the video to full screen. You should remove this
// option if it is not provided by the archive provider.
$form['archive']['player_options']['emvideo_archive_full_screen'] = array(
'#type' => 'checkbox',
'#title' => t('Allow fullscreen'),
'#default_value' => variable_get('emvideo_archive_full_screen', 1),
'#description' => t('Allow users to view video using the entire computer screen.'),
);
return $form;*/
}
/**
* hook emvideo_PROVIDER_extract
*
* This is called to extract the video code from a pasted URL or embed code.
*
* We'll be passed a URL or the embed code from a video when an editor pastes
* that in the field's textfield. We'll need to either pass back an array of
* regex expressions to match, or do the matching ourselves and return the
* resulting video code.
*
* @param $parse
* An optional string with the pasted URL or embed code.
* @return
* Either an array of regex expressions to be tested, or a string with the
* video code to be used. If the hook tests the code itself, it should
* return either the string of the video code (if matched), or an empty
* array. Otherwise, the calling function will handle testing the embed code
* against each regex string in the returned array.
*/
function emvideo_archive_extract($parse = '') {
// Here we assume that a URL will be passed in the form of
// http://www.archive.org/video/text-video-title
// or embed code in the form of <object value="http://www.archive.org/embed...".
// We'll simply return an array of regular expressions for Embedded Media
// Field to handle for us.
return array(
//In the URL the archive.org item id will appear after "details/" in the URL
'@archive\.org\/details\/([^\"\&]+)@i',
// Now we test for embedded video code, which is similar in this case to
// the above expression, except the item id will appear after "download/"
'@archive\.org/download/([^/]+)@i',
);
}
/**
* Implement hook emvideo_PROVIDER_data_version().
*/
function emvideo_archive_data_version() {
return EMVIDEO_ARCHIVE_DATA_VERSION;
}
/**
* hook emvideo_PROVIDER_data
*
* Provides an array to be serialised and made available with $item elsewhere.
*
* This data can be used to store any extraneous information available
* specifically to the archive provider.
*/
function emvideo_archive_data($field, $item, $error_field = '') {
// Initialize the data array.
$data = array();
// Create some version control. Thus if we make changes to the data array
// down the road, we can respect older content. If allowed by Embedded Media
// Field, any older content will automatically update this array as needed.
// In any case, you should account for the version if you increment it.
$data['emvideo_archive_version'] = $data['emvideo_data_version'] = EMVIDEO_ARCHIVE_DATA_VERSION;
// Construct a base item url
$item_url = "http://www.archive.org/details/". $item['value'];
$download_url = "http://www.archive.org/download/". $item['value'];
// We will leverage the JSON archive.org api to get details about this item
// See http://www.archive.org/help/json.php
$xml_meta_url = $item_url .'&output=json';
$xml_meta = media_archive_request_xml('archive', $xml_meta_url, array(), TRUE, TRUE, $item['value'] .'_meta', FALSE, TRUE);
if ($xml_meta['stat'] == 'error' || empty($xml_meta)) {
drupal_set_message('This item\'s details cannot be retrieved. The video can not be displayed.');
return $data;
}
else {
$data['details'] = $xml_meta;
$server_url = $data['details']['server'] . $data['details']['dir'];
}
$item_files = $data['details']['files'];
if (!$item_files) {
form_set_error($error_field, 'The list of files for the item at archive.org could not be retrieved. The video can not be displayed.');
return $data;
}
//Putting the $key (which is actually the file name) as an element of the
//array too for convenience later.
foreach ($item_files as $key => $value) {
$item_files[$key]['name'] = $key;
}
//Get only .mp4 files
$files_play = array_filter($item_files, "_archive_video_toplay");
//If there is no playlist then fail
if (is_null($files_play)) {
form_set_error($error_field, 'This archive.org item does not appear to have files to play.');
return $data;
}
//Create a playlist suitable for feeding to player
foreach ($files_play as $file => $file_data) {
$data['playlist'][] = $download_url . $file;
}
// Add the thumbnail data.
$data['thumbnail'] = 'http://www.archive.org/download/'. $item['value'] .'/format=Thumbnail?.jpg';
return $data;
}
/**
* Is this a 512Kb MPEG4 file?
*/
function _archive_video_toplay($file) {
if ($file['format'] == "512Kb MPEG4") {
return TRUE;
}
else {
return FALSE;
}
}
/**
* hook emvideo_PROVIDER_duration($item)
* Returns the duration of the video in seconds.
* @param $item
* The video item itself, which needs the $data array.
* @return
* The duration of the video in seconds.
*/
function emvideo_archive_duration($item) {
if (!isset($item['data']['emvideo_archive_version'])) {
$item['data'] = emvideo_archive_data(NULL, $item);
}
return isset($item['data']['metadata']['RUNTIME'][0]) ? emvideo_convert_to_seconds($item['data']['metadata']['RUNTIME'][0]) : 0;
}
/**
* hook emvideo_PROVIDER_rss
*
* This attaches a file to an RSS feed.
*/
function emvideo_archive_rss($item, $teaser = NULL) {
if ($item['value']) {
$file['thumbnail']['filepath'] = $item['data']['thumbnail'];
return $file;
}
}
/**
* hook emvideo_PROVIDER_embedded_link($video_code)
* returns a link to view the video at the provider's site.
* @param $video_code
* The string containing the video to watch.
* @return
* A string containing the URL to view the video at the original provider's site.
*/
function emvideo_archive_embedded_link($video_code) {
return 'http://www.archive.org/details/'. $video_code;
}
/**
* The embedded flash displaying the archive video.
*/
function theme_emvideo_archive_flash($item, $width, $height, $autoplay) {
$output = '';
if ($item['embed']) {
$flowplayerplaylist = _media_archive_flowplayer_playlist($item['data']['playlist']);
$controlplaylist = (count($item['data']['playlist'])>1) ? "true" : "false";
$clipautoplay = $autoplay ? 'true' : 'false';
$output = <<<EOD
<embed type="application/x-shockwave-flash" width="$width" height="$height" allowfullscreen="true"
allowscriptaccess="always" src="http://www.archive.org/flow/flowplayer.commercial-3.0.5.swf"
w3c="true" flashvars='config={
"key":"#\$b6eb72a0f2f1e29f3d4",
"playlist":[
{
"url":"{$item['data']['thumbnail']}",
"autoPlay":true,
"scaling":"fit"
},
{$flowplayerplaylist}
],
"clip":{
"autoPlay":false,
"accelerated":true,
"scaling":"fit"
},
"canvas":{
"backgroundColor":"0x000000",
"backgroundGradient":"none"
},
"plugins":{
"audio":{
"url":"http://www.archive.org/flow/flowplayer.audio-3.0.3-dev.swf"
},
"controls":{
"playlist":{$controlplaylist},
"fullscreen":true,
"gloss":"high",
"backgroundColor":"0x000000",
"backgroundGradient":"medium",
"sliderColor":"0x777777",
"progressColor":"0x777777",
"timeColor":"0xeeeeee",
"durationColor":"0x01DAFF",
"buttonColor":"0x333333",
"buttonOverColor":"0x505050"
}
},
"contextMenu":[
{
"{$item['value']}":"function()"
},
"-",
"Flowplayer 3.0.5"
]
}'> </embed>
EOD;
}
return $output;
}
/**
* hook emvideo_PROVIDER_thumbnail
* Returns the external url for a thumbnail of a specific video.
* @param $field
* The field of the requesting node.
* @param $item
* The actual content of the field from the requesting node.
* @return
* A URL pointing to the thumbnail.
*/
function emvideo_archive_thumbnail($field, $item, $formatter, $node, $width, $height) {
// In this demonstration, we previously retrieved a thumbnail using oEmbed
// during the data hook.
return $item['data']['thumbnail'];
}
/**
* hook emvideo_PROVIDER_video
* This actually displays the full/normal-sized video we want, usually on the
* default page view.
* @param $embed
* The video code for the video to embed.
* @param $width
* The width to display the video.
* @param $height
* The height to display the video.
* @param $field
* The field info from the requesting node.
* @param $item
* The actual content from the field.
* @return
* The html of the embedded video.
*/
function emvideo_archive_video($embed, $width, $height, $field, $item, $node, $autoplay) {
$output = theme('emvideo_archive_flash', $item, $width, $height, $autoplay);
return $output;
}
/**
* hook emvideo_PROVIDER_video
*
* This actually displays the preview-sized video we want, commonly for the
* teaser.
* @param $embed
* The video code for the video to embed.
* @param $width
* The width to display the video.
* @param $height
* The height to display the video.
* @param $field
* The field info from the requesting node.
* @param $item
* The actual content from the field.
* @return
* The html of the embedded video.
*/
function emvideo_archive_preview($embed, $width, $height, $field, $item, $node, $autoplay) {
$output = theme('emvideo_archive_flash', $item, $width, $height, $autoplay);
return $output;
}
/**
* Implementation of hook_emfield_subtheme().
* This returns any theme functions defined by this provider.
*/
function emvideo_archive_emfield_subtheme() {
$themes = array(
'emvideo_archive_flash' => array(
'arguments' => array('item' => NULL, 'width' => NULL, 'height' => NULL, 'autoplay' => NULL),
'file' => 'providers/archive.inc',
// If you don't provide a 'path' value, then it will default to
// the emvideo.module path. Obviously, replace 'emarchive' with
// the actual name of your custom module.
//'path' => drupal_get_path('module', 'emarchive'),
)
);
return $themes;
}
/**
* Implement hook_emvideo_PROVIDER_content_generate().
*/
function emvideo_archive_content_generate() {
return array(
'http://www.archive.org/details/DrupalconDc2009-DrupalMultimedia',
'http://www.archive.org/details/DrupalconBoston2008-DrupalMultimedia',
'http://www.archive.org/details/drupal_song_dcamp_pune_09',
'http://www.archive.org/details/Drupal.Peru_DrupalSong20090718',
);
}