Ticket #11344: tmdb_parse-fanart.patch
| File tmdb_parse-fanart.patch, 17.2 KB (added by , 13 years ago) |
|---|
-
classes/Video.php
diff --git a/classes/Video.php b/classes/Video.php index 5c6f7e4..76a621e 100644
a b class Video { 39 39 SELECT dirname 40 40 FROM storagegroup 41 41 WHERE groupname="Coverart" 42 OR groupname="Fanart" 42 43 '); 43 44 44 45 $video = $db->query_assoc(' … … class Video { 62 63 $this->showlevel = $video['showlevel']; 63 64 $this->filename = $video['filename']; 64 65 $this->cover_file = $video['coverfile']; 66 $this->fanart_file = $video['fanart']; 65 67 $this->browse = $video['browse']; 66 68 // And the artwork URL 67 69 $this->cover_url = ''; 70 $fanart=false; 71 if (!$this->cover_file && $this->fanart_file) { 72 $foo = explode('/', $this->fanart_file); 73 $this->cover_file = $foo[count($foo) - 1]; 74 $fanart=true; 75 } 68 76 if ($this->cover_file && $this->cover_file != 'No Cover') { 69 77 $exists = false; 70 78 foreach ($video_dirs as $dir) { … … class Video { 75 83 } 76 84 } 77 85 if ($exists) { 78 $this->cover_url = 'pl/coverart/'.$this->cover_file; 86 if ($fanart) { 87 $this->cover_url = 'pl/fanart/'.$this->cover_file; 88 } else { 89 $this->cover_url = 'pl/coverart/'.$this->cover_file; 90 } 79 91 $this->cover_file = $path; 80 92 list($width, $height) = @getimagesize($this->cover_file); 81 93 if ($width > 0 && $height > 0) { -
new file modules/fanart/handler.pl
diff --git a/modules/fanart/handler.pl b/modules/fanart/handler.pl new file mode 100644 index 0000000..b149dea
- + 1 #!/usr/bin/perl 2 # 3 # MythWeb Coverart/Download module 4 # 5 # 6 7 # Necessary constants for sysopen 8 use Fcntl; 9 10 # Other includes 11 use Sys::Hostname; 12 use HTTP::Date; 13 14 # Attempt to use the perl bindings to prevent the backend from shutting down during streaming 15 eval 'use MythTV;'; 16 17 if (!$@) { 18 our $mythbackend = new MythTV(); 19 $mythbackend->backend_command('ANN Playback '.hostname); 20 } 21 22 # Which cover are we displaying 23 our $cover = url_param('cover'); 24 if ($Path[1]) { 25 $cover = $Path[1]; 26 } 27 28 # No match? 29 unless ($cover =~ /\w/) { 30 print header(), 31 "Unknown cover requested.\n"; 32 exit; 33 } 34 35 # Find the local file 36 our $filename; 37 $sh = $dbh->prepare('SELECT dirname FROM storagegroup WHERE groupname = "Fanart"'); 38 $sh->execute(); 39 while (my ($coverart_dir) = $sh->fetchrow_array()) { 40 next unless (-e "$coverart_dir/$cover"); 41 $filename = "$coverart_dir/$cover"; 42 last; 43 } 44 $sh->finish; 45 46 1; 47 48 unless ($filename) { 49 print header(), 50 "$cover does not exist in any recognized storage group directories for this host."; 51 exit; 52 } 53 54 # File size 55 my $size = -s $filename; 56 57 # Zero bytes? 58 if ($size < 1) { 59 print header(), 60 "$cover is an empty file."; 61 exit; 62 } 63 64 # File type 65 my $type = 'text/html'; 66 my $suffix = ''; 67 if ($cover =~ /\.jpg$/) { 68 $type = 'image/jpeg'; 69 $suffix = '.jpg'; 70 } 71 else { 72 print header(), 73 "Unknown image type requested: $cover\n"; 74 exit; 75 } 76 77 # Open the file for reading 78 unless (sysopen DATA, $filename, O_RDONLY) { 79 print header(), 80 "Can't read $cover: $!"; 81 exit; 82 } 83 84 # Binmode, in case someone is running this from Windows. 85 binmode DATA; 86 87 my $start = 0; 88 my $end = $size; 89 my $total_size = $size; 90 my $read_size = 1024; 91 my $mtime = (stat($filename))[9]; 92 93 # Handle cache hits/misses 94 if ( $ENV{'HTTP_IF_MODIFIED_SINCE'}) { 95 my $check_time = str2time($ENV{'HTTP_IF_MODIFIED_SINCE'}); 96 if ($mtime <= $check_time) { 97 print header(-Content_type => $type, 98 -status => "304 Not Modified" 99 ); 100 exit; 101 } 102 } 103 104 # Requested a range? 105 if ($ENV{'HTTP_RANGE'}) { 106 # Figure out the size of the requested chunk 107 ($start, $end) = $ENV{'HTTP_RANGE'} =~ /bytes\W+(\d*)-(\d*)\W*$/; 108 if ($end < 1 || $end > $size) { 109 $end = $size; 110 } 111 $size = $end - $start+1; 112 if ($read_size > $size) { 113 $read_size = $size; 114 } 115 print header(-status => "206 Partial Content", 116 -type => $type, 117 -Content_length => $size, 118 -Accept_Ranges => 'bytes', 119 -Content_Range => "bytes $start-$end/$total_size", 120 -Last_Modified => time2str($mtime), 121 -Content_disposition => " attachment; filename=\"$cover\"" 122 ); 123 } 124 else { 125 print header(-type => $type, 126 -Content_length => $size, 127 -Accept_Ranges => 'bytes', 128 -Last_Modified => time2str($mtime), 129 -Content_disposition => " attachment; filename=\"$cover\"" 130 ); 131 } 132 133 # Seek to the requested position 134 sysseek DATA, $start, 0; 135 136 # Print the content to the browser 137 my $buffer; 138 while (sysread DATA, $buffer, $read_size ) { 139 print $buffer; 140 $size -= $read_size; 141 if ($size == 0) { 142 last; 143 } 144 if ($size < $read_size) { 145 $read_size = $size; 146 } 147 } 148 close DATA; 149 150 # Escape a parameter for safe use in a commandline call 151 sub shell_escape { 152 $str = shift; 153 $str =~ s/'/'\\''/sg; 154 return "'$str'"; 155 } 156 157 # Return true 158 1; 159 -
new file modules/fanart/init.php
diff --git a/modules/fanart/init.php b/modules/fanart/init.php new file mode 100644 index 0000000..ce88ab4
- + 1 <?php 2 /** 3 * Initialization routines for the MythWeb Video Coverart module 4 * 5 * @license GPL 6 * 7 * @package MythWeb 8 * @subpackage Video Coverart 9 * 10 /**/ 11 ?> -
modules/video/handler.php
diff --git a/modules/video/handler.php b/modules/video/handler.php index 721f186..ff9e3fd 100644
a b 205 205 206 206 // Get the video categories on the system 207 207 $Category_String = array(); 208 $Category_Index = array(); 208 209 $sh = $db->query('SELECT * FROM videocategory ORDER BY category'); 209 while ($row = $sh->fetch_assoc()) 210 while ($row = $sh->fetch_assoc()) { 210 211 $Category_String[$row['intid']] = $row['category']; 212 $Category_Index[$row['category']] = $row['intid']; 213 } 211 214 $sh->finish(); 212 215 $Category_String[0] = t('Uncategorized'); 213 216 -
modules/video/imdb.php
diff --git a/modules/video/imdb.php b/modules/video/imdb.php index 1892e54..89ddab6 100644
a b 47 47 'ALLOCINE' => array( ' -M "%%TITLE%%"') 48 48 ); 49 49 50 $dupe = array();51 50 foreach ($options[$imdbwebtype] as $option) { 52 51 $cmd = $imdb.str_replace('%%TITLE%%', $title, $option); 53 52 exec($cmd, $output, $retval); 54 53 if ($retval == 255) 55 54 $return['warning'][] = "IMDB Command $cmd exited with return value $retval"; 55 if (!count($output)) { 56 $title_parts = explode(' ', $title); 57 $cmd = $imdb.str_replace('%%TITLE%%', $title_parts[0], $option); 58 exec($cmd, $output, $retval); 59 if ($retval == 255) 60 $return['warning'][] = "IMDB Command $cmd exited with return value $retval"; 61 } 56 62 if (!count($output)) 57 63 continue; 64 $single_output=''; 58 65 foreach ($output as $line) { 59 list($imdbid, $title) = explode(':', $line, 2); 60 if ($dupe[$imdbid]) 61 continue; 62 $dupe[$imdbid] = true; 63 $return['matches'][] = array('imdbid' => $imdbid, 64 'title' => $title); 66 $single_output=$single_output.$line; 67 } 68 $xml = simplexml_load_string($single_output); 69 70 foreach ($xml as $item) { 71 if (strlen($item->imdb) > 1) { 72 $imdbid = (string)$item->imdb; 73 $title = (string)$item->title; 74 $return['matches'][] = array('imdbid' => $imdbid, 'title' => $title); 75 } 65 76 } 66 77 } 67 78 } … … 70 81 { 71 82 global $db; 72 83 global $return; 84 85 // Get the video genres on the system 86 $Genre_String = array(); 87 $Genre_Index = array(); 88 $sh = $db->query('SELECT * FROM videogenre ORDER BY genre'); 89 while ($row = $sh->fetch_assoc()) { 90 $Genre_String[$row['intid']] = $row['genre']; 91 $Genre_Index[$row['genre']] = $row['intid']; 92 } 93 $sh->finish(); 94 $Genre_String[0] = t('No Genre'); 95 96 97 $Category_String = array(); 98 $Category_Index = array(); 99 $sh = $db->query('SELECT * FROM videocategory ORDER BY category'); 100 while ($row = $sh->fetch_assoc()) { 101 $Category_String[$row['intid']] = $row['category']; 102 $Category_Index[$row['category']] = $row['intid']; 103 } 104 $sh->finish(); 105 $Category_String[0] = t('Uncategorized'); 106 73 107 $return['action'] = 'grab'; 74 108 $imdb = setting('web_video_imdb_path', hostname); 75 109 $imdbwebtype = setting('web_video_imdb_type', hostname); … … 94 128 return; 95 129 } 96 130 $posterfile = "$artwork_dir/$imdbnum.jpg"; 131 132 # Figure out the fanart directory 133 $fanartwork_dirs = $db->query_list(' 134 SELECT dirname 135 FROM storagegroup 136 WHERE groupname="Fanart" 137 '); 138 if (empty($fanartwork_dirs)) { 139 $return['warning'][] = 'MythWeb now requires use of the Fanart Storage Group.'; 140 return; 141 } 142 foreach ($fanartwork_dirs as $dir) { 143 if (is_dir($dir) || is_link($dir)) { 144 $fanartwork_dir = $dir; 145 break; 146 } 147 } 148 if (empty($fanartwork_dir)) { 149 $return['warning'][] = 'Could not find a valid Fanart Storage Group directory'; 150 return; 151 } 152 $fanartfile = "$fanartwork_dir/$imdbnum.jpg"; 153 154 97 155 // Get the imdb data 98 156 $data = array(); 99 157 $cmd = "$imdb -D $imdbnum"; 100 exec($cmd, $ lines, $retval);158 exec($cmd, $output, $retval); 101 159 if ($retval == 255 || $DEBUG) { 102 160 $return['warning'][] = "IMDB Command $cmd exited with return value $retval"; 103 161 } 104 $valid = FALSE; 105 foreach ($lines as $line) { 106 list ($key, $value) = explode(':', $line, 2); 107 $data[strtolower($key)] = trim($value); 108 if (strlen($data[strtolower($key)]) > 0) { 109 $valid = TRUE; 162 $single_output=''; 163 foreach ($output as $line) { 164 $single_output=$single_output.$line; 165 } 166 $xml = simplexml_load_string($single_output); 167 168 foreach ($xml as $item) { 169 $data['title'] = (string)$item->title; 170 $data['plot'] = (string)$item->description; 171 $date = date_parse($item->releasedate); 172 $data['year'] = (string)$date['year']; 173 $data['userrating'] = (string)$item->userrating; 174 $data['runtime'] = (string)$item->runtime; 175 if ($item->certifications) { 176 foreach ($item->certifications->certification as $cert) { 177 if (strtoupper($cert->attributes()->locale) == "US" && !$data['movierating']) { 178 $data['movierating'] = (string)$cert->attributes()->name; 179 } 180 } 181 } 182 if ($item->people) { 183 foreach ($item->people->person as $person) { 184 if (strtoupper($person->attributes()->job) == "DIRECTOR" && !$data['director']) { 185 $data['director'] = (string)$person->attributes()->name; 186 } 187 } 188 } 189 $data['coverart']=''; 190 $data['fanart']=''; 191 foreach ($item->images->image as $image_data) { 192 if ($image_data->attributes()->type == 'coverart' && !$data['coverart']) { 193 $data['coverart'] = (string)$image_data->attributes()->url; 110 194 } 195 if ($image_data->attributes()->type == 'fanart' && !$data['fanart']) { 196 $data['fanart'] = (string)$image_data->attributes()->url; 197 } 198 } 111 199 } 112 if (!$valid) {113 $return['error'][] = t('Video: Error: IMDB');114 return;200 $data['genre'] = array(); 201 foreach ($item->categories->category as $cat) { 202 array_push($data['genre'], (string)$cat->attributes()->name); 115 203 } 116 204 // If the file already exists, use it, don't bother regrabbing 117 205 if (!file_exists($posterfile)) { 118 206 $posterurl = $data['coverart']; 119 if (!is_writable($artwork_dir)) 207 if (!is_writable($artwork_dir)) { 208 $return['warning'][] = t('Video: Warning: Artwork'); 209 } else { 210 if (!ini_get('allow_url_fopen')) { 211 $return['warning'][] = t('Video: Warning: fopen'); 212 } elseif(strlen($posterurl) > 0) { 213 $posterurl = preg_replace('/,.+$/', '', $posterurl); // For now, only bother to grab the first poster URL 214 $posterjpg = @file_get_contents($posterurl); 215 if ($posterjpg === FALSE) 216 $return['warning'][] = t('Video: Warning: Artwork: Download'); 217 else { 218 @file_put_contents( $posterfile, $posterjpg); 219 if (!file_exists($posterfile)) 220 $return['warning'][] = t('Video: Warning: Artwork'); 221 } 222 } 223 } 224 } 225 // rinse and repeat for fanart 226 // If the file already exists, use it, don't bother regrabbing 227 if (!file_exists($fanartfile)) { 228 $posterurl = $data['fanart']; 229 if (!is_writable($fanartwork_dir)) 120 230 $return['warning'][] = t('Video: Warning: Artwork'); 121 231 else { 122 232 if (!ini_get('allow_url_fopen')) … … 127 237 if ($posterjpg === FALSE) 128 238 $return['warning'][] = t('Video: Warning: Artwork: Download'); 129 239 else { 130 @file_put_contents( $ posterfile, $posterjpg);131 if (!file_exists($ posterfile))240 @file_put_contents( $fanartfile, $posterjpg); 241 if (!file_exists($fanartfile)) 132 242 $return['warning'][] = t('Video: Warning: Artwork'); 133 243 } 134 244 } 135 245 } 136 246 } 247 248 if (!$Category_Index[$data['genre'][0]]) { 249 $db->query('INSERT INTO videocategory SET category = ?', $data['genre'][0]); 250 } 251 137 252 // Update the database 138 253 $sh = $db->query('UPDATE videometadata 139 254 SET title = ?, 140 255 director = ?, 141 256 plot = ?, 142 257 rating = ?, 258 category = ?, 143 259 inetref = ?, 144 260 year = ?, 145 261 userrating = ?, 146 262 length = ?, 147 coverfile = ? 263 coverfile = ?, 264 fanart = ? 148 265 WHERE intid = ?', 149 266 $data['title'], 150 267 $data['director'], 151 268 $data['plot'], 152 269 $data['movierating'], 270 $Category_Index[$data['genre'][0]], 153 271 $imdbnum, 154 272 $data['year'], 155 273 $data['userrating'], 156 274 $data['runtime'], 157 275 ( @filesize($posterfile) > 0 ? "$imdbnum.jpg" : 'No Cover' ), 276 ( @filesize($fanartfile) > 0 ? "$imdbnum.jpg" : 'No Cover' ), 158 277 $id 159 278 ); 279 280 $db->query('DELETE FROM videometadatagenre 281 WHERE videometadatagenre.idvideo = ?', 282 $id 283 ); 284 285 if (count($data['genre']) > 0) 286 foreach ($data['genre'] as $genre) 287 $db->query('INSERT INTO videometadatagenre ( idvideo, idgenre ) 288 VALUES ( ?, ? )', 289 $id, 290 $Genre_Index[$genre] 291 ); 292 160 293 $return['update'][] = $id; 161 294 } 162 295
