1 # -*- coding: ascii -*-
2 ###########################################################################
3 # clive, command line video extraction utility.
5 # Copyright 2009 Toni Gundogdu.
7 # This file is part of clive.
9 # clive is free software: you can redistribute it and/or modify it under
10 # the terms of the GNU General Public License as published by the Free
11 # Software Foundation, either version 3 of the License, or (at your option)
14 # clive is distributed in the hope that it will be useful, but WITHOUT ANY
15 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
16 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
19 # You should have received a copy of the GNU General Public License along
20 # with this program. If not, see <http://www.gnu.org/licenses/>.
21 ###########################################################################
27 use base
'Class::Singleton';
43 return bless( {}, $class );
49 clive
::Config
->instance->init;
50 clive
::Curl
->instance->init;
51 clive
::Log
->instance->init;
52 clive
::Cache
->instance->init;
53 clive
::Exec
->instance->init;
57 exit( clive
::Log
->instance->returnCode );
65 my $config = clive
::Config
->instance->config;
67 # Read from recall file.
68 if ( $config->{recall
} and -e
$config->{recall_file
} ) {
69 if ( open( my $fh, "<", $config->{recall_file
} ) ) {
70 _parseLine
( $self, $_ ) while (<$fh>);
74 clive
::Log
->instance->errn( CLIVE_READ
,
75 "$config->{recall_file}: $!" );
80 if ( $config->{cache_grep
} ) {
81 my $cache = clive
::Cache
->instance;
82 foreach ( @
{ $cache->grepQueue } ) {
83 push( @
{ $self->{queue
} }, $_ );
88 _parseLine
( $self, $_ ) foreach (@ARGV);
91 if ( scalar( @
{ $self->{queue
} } ) == 0
92 && scalar( @ARGV == 0 ) )
94 _parseLine
( $self, $_ ) while (<STDIN
>);
97 my $cache = clive
::Cache
->instance;
98 my $curl = clive
::Curl
->instance;
99 my $log = clive
::Log
->instance;
101 require clive
::HostFactory
;
102 require clive
::Video
;
104 foreach ( @
{ $self->{queue
} } ) {
105 my $host = clive
::HostFactory
->new($_);
107 my $props = clive
::Video
->new;
108 $props->page_link($_);
113 if ( $cache->enabled() && $config->{cache_read
} ) {
114 $rc = $cache->read( \
$props );
115 if ( $rc == 1 && $props->video_format() ne $config->{format
} )
118 # Cache: video format != requested format -> re-fetch.
123 # Cache failed or record did not exist. Fetch the video page.
127 $rc = $curl->fetchToMem( $props->page_link, \
$content );
131 $props->page_title( \
$content );
132 $rc = $host->parsePage( \
$content, \
$props );
135 $rc = $curl->queryFileLength( \
$props );
137 $props->video_format( $config->{format
} );
138 $cache->write( \
$props );
144 # Cache record found.
146 $log->out("cache $_ ...done\n");
150 # If everything went OK so far, proceed to extract etc.
153 push( @
{ $self->{passed_queue
} }, $_ );
155 $props->formatOutputFilename;
157 if ( $props->nothing_todo ) {
158 $log->err( CLIVE_NOTHINGTODO
,
159 "file already retrieved; nothing todo" );
160 clive
::Exec
->instance->queue( \
$props );
164 if ( $config->{no_extract
} ) {
167 elsif ( $config->{emit_csv
} ) {
170 elsif ( $config->{stream_pass
} ) {
171 clive
::Exec
->instance->passStream( \
$props );
174 if ( $config->{print_fname
} ) {
177 if ( $curl->fetchToFile( \
$props ) == 0 ) {
178 clive
::Exec
->instance->queue( \
$props );
182 elsif ( $rc == 0xff ) {
184 # Purpose: dump (cctv) video segment links to terminal.
185 # a.k.a. "One link leads to many video segment links."
186 # a.k.a. "Something we never had even thought of."
187 # We skip quite a few steps with this chunk of joy.
191 $log->err( CLIVE_NOSUPPORT
, "no support: $_" );
195 clive
::Exec
->instance->runExec;
197 # Update recall file.
198 if ( $log->returnCode == CLIVE_OK
) {
199 if ( open( my $fh, ">", $config->{recall_file
} ) ) {
200 print( $fh "$_\n" ) foreach ( @
{ $self->{passed_queue
} } );
204 $log->errn( CLIVE_READ
, "$config->{recall_file}: $!" );
210 my ( $self, $ln ) = @_;
212 return if $ln =~ /^$/;
213 return if $ln =~ /^#/;
218 if $ln !~ m{^http://}i;
220 # Youtube: youtube-nocookie.com -> youtube.com.
221 $ln =~ s/-nocookie//;
223 # Translate host specific embedded link to video page link.
224 $ln =~ s!/v/!/watch?v=!i; # youtube
225 $ln =~ s!googleplayer.swf!videoplay!i; # googlevideo
226 $ln =~ s!/pl/!/videos/!i; # sevenload
227 $ln =~ s!/e/!/view?i=!i; # liveleak
229 if ($ln =~ /\/swf\
//) { # dailymotion
231 $ln =~ s!/swf/!/video/!;
234 # Lastfm demystifier.
235 if ( $ln =~ /last\.fm/ ) {
238 clive
::Log
->instance->err( CLIVE_NOSUPPORT
, "no support: $ln" );
241 $ln = "http://youtube.com/watch?v=$1";
244 push( @
{ $self->{queue
} }, $ln );
248 require clive
::HostFactory
;
249 clive
::HostFactory
->dumpHosts();
255 # There must be some kinda way out of here.