1: <?php
  2: 
  3:   4:   5:   6:   7:   8:   9:  10:  11:  12:  13: 
 14: 
 15: 
 16: $plugin_is_filter = 990 | CLASS_PLUGIN;
 17: $plugin_description = gettext('The Zenphoto <em>audio-video</em> handler.');
 18: $plugin_notice = gettext('This plugin must always be enabled to use multimedia content. Note that you should also enable a multimedia player. See the info of the player you use to see how it is configured.');
 19: $plugin_author = "Stephen Billard (sbillard)";
 20: 
 21: Gallery::addImageHandler('3gp', 'Video');
 22: Gallery::addImageHandler('mov', 'Video');
 23: $option_interface = 'VideoObject_Options';
 24: 
 25: define('GETID3_INCLUDEPATH', SERVERPATH . '/' . ZENFOLDER . '/' . PLUGIN_FOLDER . '/class-video/getid3/');
 26: require_once(dirname(__FILE__) . '/class-video/getid3/getid3.php');
 27: 
 28:  29:  30:  31: 
 32: class VideoObject_Options {
 33: 
 34:     function __construct() {
 35:         setOptionDefault('class-video_mov_w', 520);
 36:         setOptionDefault('class-video_mov_h', 390);
 37:         setOptionDefault('class-video_3gp_w', 520);
 38:         setOptionDefault('class-video_3gp_h', 390);
 39:         setOptionDefault('class-video_videoalt', 'ogg, avi, wmv');
 40:     }
 41: 
 42:      43:  44:  45:  46: 
 47:     function getOptionsSupported() {
 48:         return array(gettext('Watermark default images')     => array('key'      => 'video_watermark_default_images', 'type'     => OPTION_TYPE_CHECKBOX,
 49:                                         'order'  => 0,
 50:                                         'desc'   => gettext('Check to place watermark image on default thumbnail images.')),
 51:                         gettext('Quicktime video width')         => array('key'      => 'class-video_mov_w', 'type'  => OPTION_TYPE_TEXTBOX,
 52:                                         'order'  => 2,
 53:                                         'desc'   => ''),
 54:                         gettext('Quicktime video height')        => array('key'      => 'class-video_mov_h', 'type'  => OPTION_TYPE_TEXTBOX,
 55:                                         'order'  => 2,
 56:                                         'desc'   => ''),
 57:                         gettext('3gp video width')                   => array('key'      => 'class-video_3gp_w', 'type'  => OPTION_TYPE_TEXTBOX,
 58:                                         'order'  => 2,
 59:                                         'desc'   => ''),
 60:                         gettext('3gp video height')                  => array('key'      => 'class-video_3gp_h', 'type'  => OPTION_TYPE_TEXTBOX,
 61:                                         'order'  => 2,
 62:                                         'desc'   => ''),
 63:                         gettext('High quality alternate')        => array('key'      => 'class-video_videoalt', 'type'   => OPTION_TYPE_TEXTBOX,
 64:                                         'order'  => 1,
 65:                                         'desc'   => gettext('<code>getFullImageURL()</code> returns a URL to a file with one of these high quality video alternate suffixes if present.'))
 66:         );
 67:     }
 68: 
 69: }
 70: 
 71: class Video extends Image {
 72: 
 73:     var $videoalt = array();
 74: 
 75:      76:  77:  78:  79:  80:  81: 
 82:     function __construct($album, $filename, $quiet = false) {
 83:         global $_zp_supported_images;
 84:         $msg = false;
 85:         if (!is_object($album) || !$album->exists) {
 86:             $msg = gettext('Invalid video instantiation: Album does not exist');
 87:         } else if (!$this->classSetup($album, $filename) || !file_exists($this->localpath) || is_dir($this->localpath)) {
 88:             $msg = gettext('Invalid video instantiation: file does not exist.');
 89:         }
 90:         if ($msg) {
 91:             $this->exists = false;
 92:             if (!$quiet) {
 93:                 trigger_error($msg, E_USER_ERROR);
 94:             }
 95:             return;
 96:         }
 97:         $alts = explode(',', extensionEnabled('class-video_videoalt'));
 98:         foreach ($alts as $alt) {
 99:             $this->videoalt[] = trim(strtolower($alt));
100:         }
101:         $this->sidecars = $_zp_supported_images;
102:         $this->video = true;
103:         $this->objectsThumb = checkObjectsThumb($this->localpath);
104: 
105:         
106:         $album_name = $album->name;
107:         $this->updateDimensions();
108: 
109:         $new = $this->instantiate('images', array('filename' => $filename, 'albumid' => $this->album->getID()), 'filename', true, empty($album_name));
110:         if ($new || $this->filemtime != $this->get('mtime')) {
111:             if ($new)
112:                 $this->setTitle($this->displayname);
113:             $this->updateMetaData();
114:             $this->set('mtime', $this->filemtime);
115:             $this->save();
116:             if ($new)
117:                 zp_apply_filter('new_image', $this);
118:         }
119:     }
120: 
121:     122: 123: 124: 
125:     function updateDimensions() {
126:         global $_zp_multimedia_extension;
127:         $ext = getSuffix($this->filename);
128:         switch ($ext) {
129:             case '3gp':
130:                 $h = extensionEnabled('class-video_3gp_h');
131:                 $w = extensionEnabled('class-video_3gp_w');
132:                 break;
133:             case 'mov':
134:                 $h = extensionEnabled('class-video_mov_h');
135:                 $w = extensionEnabled('class-video_mov_w');
136:                 break;
137:             default:
138:                 $h = $_zp_multimedia_extension->getHeight($this);
139:                 $w = $_zp_multimedia_extension->getWidth($this);
140:         }
141:         $this->set('width', $w);
142:         $this->set('height', $h);
143:     }
144: 
145:     146: 147: 148: 149: 150: 151: 
152:     function getThumbImageFile($path = NULL) {
153:         global $_zp_gallery;
154:         if (is_null($path))
155:             $path = SERVERPATH;
156:         if (is_null($this->objectsThumb)) {
157:             $suffix = getSuffix($this->filename);
158:             switch ($suffix) {
159:                 case "mp3":
160:                     $img = '/mp3Default.png';
161:                     break;
162:                 case "mp4": 
163:                     $img = '/mp4Default.png';
164:                     break;
165:                 case "m4v": 
166:                     $img = '/m4vDefault.png';
167:                     break;
168:                 case "m4a": 
169:                     $img = '/m4aDefault.png';
170:                     break;
171:                 case "flv": 
172:                     $img = '/flvDefault.png';
173:                     break;
174:                 case "fla": 
175:                     $img = '/flaDefault.png';
176:                     break;
177:                 case "mov":
178:                     $img = '/movDefault.png';
179:                     break;
180:                 case "3gp":
181:                     $img = '/3gpDefault.png';
182:                     break;
183:                 default: 
184:                     $img = '/multimediaDefault.png';
185:                     break;
186:             }
187:             $imgfile = $path . '/' . THEMEFOLDER . '/' . internalToFilesystem($_zp_gallery->getCurrentTheme()) . '/images' . $img;
188:             if (!file_exists($imgfile)) { 
189:                 $imgfile = $path . '/' . THEMEFOLDER . '/' . internalToFilesystem($_zp_gallery->getCurrentTheme()) . '/images/multimediaDefault.png';
190:                 if (!file_exists($imgfile)) { 
191:                     $imgfile = $path . "/" . ZENFOLDER . '/' . PLUGIN_FOLDER . '/' . substr(basename(__FILE__), 0, -4) . $img;
192:                 }
193:             }
194:         } else {
195:             $imgfile = ALBUM_FOLDER_SERVERPATH . internalToFilesystem($this->imagefolder) . '/' . $this->objectsThumb;
196:         }
197:         return $imgfile;
198:     }
199: 
200:     201: 202: 203: 204: 
205:     function getThumb($type = 'image') {
206:         $ts = getOption('thumb_size');
207:         $sw = getOption('thumb_crop_width');
208:         $sh = getOption('thumb_crop_height');
209:         list($custom, $cw, $ch, $cx, $cy) = $this->getThumbCropping($ts, $sw, $sh);
210:         $wmt = getOption('Video_watermark');
211:         if (empty($wmt)) {
212:             $wmt = getWatermarkParam($this, WATERMARK_THUMB);
213:         }
214:         if ($this->objectsThumb == NULL) {
215:             $mtime = $cx = $cy = NULL;
216:             $filename = makeSpecialImageName($this->getThumbImageFile());
217:             if (!getOption('video_watermark_default_images')) {
218:                 $wmt = '!';
219:             }
220:         } else {
221:             $filename = filesystemToInternal($this->objectsThumb);
222:             $mtime = filemtime(ALBUM_FOLDER_SERVERPATH . '/' . internalToFilesystem($this->imagefolder) . '/' . $this->objectsThumb);
223:         }
224:         $args = getImageParameters(array($ts, $sw, $sh, $cw, $ch, $cx, $cy, NULL, true, true, true, $wmt, NULL, NULL), $this->album->name);
225:         return getImageURI($args, $this->album->name, $filename, $mtime);
226:     }
227: 
228:     229: 230: 231: 232: 233: 234: 235: 236: 237: 238: 239: 240: 241: 242: 243: 244: 
245:     function getCustomImage($size, $width, $height, $cropw, $croph, $cropx, $cropy, $thumbStandin = false, $effects = NULL) {
246:         if ($thumbStandin) {
247:             $wmt = getOption('Video_watermark');
248:             if (empty($wmt)) {
249:                 $wmt = getWatermarkParam($this, WATERMARK_THUMB);
250:             }
251:         } else {
252:             $wmt = NULL;
253:         }
254:         if ($thumbStandin & 1) {
255:             $args = array($size, $width, $height, $cropw, $croph, $cropx, $cropy, NULL, $thumbStandin, NULL, $thumbStandin, NULL, NULL, NULL);
256:             if ($this->objectsThumb == NULL) {
257:                 $filename = makeSpecialImageName($this->getThumbImageFile());
258:                 if (!getOption('video_watermark_default_images')) {
259:                     $args[11] = '!';
260:                 }
261:                 $mtime = NULL;
262:             } else {
263:                 $filename = filesystemToInternal($this->objectsThumb);
264:                 $mtime = filemtime(ALBUM_FOLDER_SERVERPATH . '/' . internalToFilesystem($this->imagefolder) . '/' . $this->objectsThumb);
265:             }
266:             return getImageURI($args, $this->album->name, $filename, $this->filemtime);
267:         } else {
268:             $args = getImageParameters(array($size, $width, $height, $cropw, $croph, $cropx, $cropy, NULL, $thumbStandin, NULL, $thumbStandin, $wmt, NULL, $effects), $this->album->name);
269:             $filename = $this->filename;
270:             return getImageURI($args, $this->album->name, $filename, $this->filemtime);
271:         }
272:     }
273: 
274:     275: 276: 277: 
278:     function getSizedImage($size) {
279:         $width = $this->getWidth();
280:         $height = $this->getHeight();
281:         if ($width > $height) { 
282:             $height = $height * $size / $width;
283:         } else {
284:             $width = $width * $size / $height;
285:         }
286:         return $this->getContent($width, $height);
287:     }
288: 
289:     290: 291: 292: 293: 294: 
295:     function getFullImageURL() {
296:         
297:         if ($vid = parent::getFullImageURL()) {
298:             $folder = ALBUM_FOLDER_SERVERPATH . internalToFilesystem($this->album->getFileName());
299:             $video = stripSuffix($this->filename);
300:             $curdir = getcwd();
301:             chdir($folder);
302:             $candidates = safe_glob($video . '.*');
303:             chdir($curdir);
304:             foreach ($candidates as $target) {
305:                 $ext = getSuffix($target);
306:                 if (in_array($ext, $this->videoalt)) {
307:                     $vid = stripSuffix($vid) . '.' . substr(strrchr($target, "."), 1);
308:                 }
309:             }
310:         }
311:         return $vid;
312:     }
313: 
314:     function getBody($w = NULL, $h = NULL) {
315:         Video_deprecated_functions::getBody();
316:         $this->getContent($w, $h);
317:     }
318: 
319:     320: 321: 322: 323: 324: 325: 
326:     function getContent($w = NULL, $h = NULL) {
327:         global $_zp_multimedia_extension;
328:         if (is_null($w))
329:             $w = $this->getWidth();
330:         if (is_null($h))
331:             $h = $this->getHeight();
332:         $ext = getSuffix($this->getFullImage());
333:         switch ($ext) {
334:             default:
335:                 return $_zp_multimedia_extension->getPlayerConfig($this, NULL, NULL, $w, $h);
336:                 break;
337:             case '3gp':
338:             case 'mov':
339:                 return '</a>
340:                     <object classid="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" width="' . $w . '" height="' . $h . '" codebase="http://www.apple.com/qtactivex/qtplugin.cab">
341:                     <param name="src" value="' . pathurlencode($this->getFullImage()) . '"/>
342:                     <param name="autoplay" value="false" />
343:                     <param name="type" value="video/quicktime" />
344:                     <param name="controller" value="true" />
345:                     <embed src="' . pathurlencode($this->getFullImage()) . '" width="' . $w . '" height="' . $h . '" scale="aspect" autoplay="false" controller"true" type="video/quicktime"
346:                         pluginspage="http://www.apple.com/quicktime/download/" cache="true"></embed>
347:                     </object><a>';
348:                 break;
349:         }
350:     }
351: 
352:     353: 354: 355: 
356:     private function getMetaDataID3() {
357:         $suffix = getSuffix($this->localpath);
358:         if (in_array($suffix, array('m4a', 'm4v', 'mp3', 'mp4', 'flv', 'fla', 'mov', '3gp'))) {
359:             $getID3 = new getID3;
360:             @set_time_limit(30);
361:             $ThisFileInfo = $getID3->analyze($this->localpath);
362:             getid3_lib::CopyTagsToComments($ThisFileInfo);
363:             
364:             if (is_array($ThisFileInfo)) {
365:                 return $ThisFileInfo;
366:             }
367:         }
368:         return NULL; 
369:     }
370: 
371:     372: 373: 374: 375: 
376:     function updateMetaData() {
377:         global $_zp_exifvars;
378:         parent::updateMetaData();
379:         if (!SAFE_MODE) {
380:             
381:             $process = array();
382:             foreach ($_zp_exifvars as $field => $exifvar) {
383:                 if ($exifvar[5] && $exifvar[0] == 'VIDEO') {
384:                     $process[$field] = $exifvar;
385:                 }
386:             }
387:             if (!empty($process)) {
388:                 $ThisFileInfo = $this->getMetaDataID3();
389:                 if (is_array($ThisFileInfo)) {
390:                     foreach ($ThisFileInfo as $key => $info) {
391:                         if (is_array($info)) {
392:                             switch ($key) {
393:                                 case 'comments':
394:                                     foreach ($info as $key1 => $data) {
395:                                         $ThisFileInfo[$key1] = array_shift($data);
396:                                     }
397:                                     break;
398:                                 case 'audio':
399:                                 case 'video':
400:                                     foreach ($info as $key1 => $data) {
401:                                         $ThisFileInfo[$key1] = $data;
402:                                     }
403:                                     break;
404:                                 case 'error':
405:                                     $msg = sprintf(gettext('getid3 exceptions for %1$s::%2$s'), $this->album->name, $this->filename);
406:                                     foreach ($info as $data) {
407:                                         $msg .= "\n" . $data;
408:                                     }
409:                                     debugLog($msg);
410:                                     break;
411:                                 default:
412:                                     
413:                                     break;
414:                             }
415:                             unset($ThisFileInfo[$key]);
416:                         }
417:                     }
418:                     foreach ($process as $field => $exifvar) {
419:                         if (isset($ThisFileInfo[$exifvar[1]])) {
420:                             $data = $ThisFileInfo[$exifvar[1]];
421:                             if (!empty($data)) {
422:                                 $this->set($field, $data);
423:                                 $this->set('hasMetadata', 1);
424:                             }
425:                         }
426:                     }
427:                     $title = $this->get('VideoTitle');
428:                     if (!empty($title)) {
429:                         $this->setTitle($title);
430:                     }
431:                 }
432:             }
433:         }
434:     }
435: 
436: }
437: 
438: class pseudoPlayer {
439: 
440:     public $name = '';
441:     private $width = 480;
442:     private $height = 360;
443: 
444:     function getWidth($dummy) {
445:         return $this->width;
446:     }
447: 
448:     function getHeight($dummy) {
449:         return $this->height;
450:     }
451: 
452:     function getPlayerConfig($moviepath, $imagefilename) {
453:         return '<img src="' . WEBPATH . '/' . ZENFOLDER . '/images/err-noflashplayer.png" alt="' . gettext('No multimeida extension installed.') . '" />';
454:     }
455: 
456: }
457: 
458: $_zp_multimedia_extension = new pseudoPlayer();
459: ?>
460: