Fix: return code is always 0.
[clive.git] / lib / clive / App.pm
blobcbe0067f9837ad50537db640b6524307243b4c24
1 # -*- coding: ascii -*-
2 ###########################################################################
3 # clive, command line video extraction utility.
4 # Copyright 2007, 2008, 2009 Toni Gundogdu.
6 # This file is part of clive.
8 # clive is free software: you can redistribute it and/or modify it under
9 # the terms of the GNU General Public License as published by the Free
10 # Software Foundation, either version 3 of the License, or (at your option)
11 # any later version.
13 # clive is distributed in the hope that it will be useful, but WITHOUT ANY
14 # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
15 # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
16 # details.
18 # You should have received a copy of the GNU General Public License along
19 # with this program. If not, see <http://www.gnu.org/licenses/>.
20 ###########################################################################
21 package clive::App;
23 use warnings;
24 use strict;
26 use base 'Class::Singleton';
28 use clive::Log;
29 use clive::Config;
30 use clive::Curl;
31 use clive::Cache;
32 use clive::Exec;
34 sub new {
35 my $class = shift;
36 return bless( {}, $class );
39 sub main {
40 my $self = shift;
42 clive::Config->instance->init;
43 clive::Curl->instance->init;
44 clive::Log->instance->init;
45 clive::Cache->instance->init;
46 clive::Exec->instance->init;
48 _parseInput();
50 exit(clive::Log->instance->errorOccurred);
53 sub _parseInput {
54 my $self = shift;
56 $self->{queue} = [];
58 my $config = clive::Config->instance->config;
60 # Read from recall file.
61 if ( $config->{recall} and -e $config->{recall_file} ) {
62 if ( open( my $fh, "<", $config->{recall_file} ) ) {
63 _parseLine( $self, $_ ) while (<$fh>);
64 close($fh);
66 else {
67 clive::Log->instance->errn("$config->{recall_file}: $!");
71 # From cache (grep).
72 if ( $config->{cache_grep} ) {
73 my $cache = clive::Cache->instance;
74 foreach ( @{ $cache->grepQueue } ) {
75 push( @{ $self->{queue} }, $_ );
79 # Use argv.
80 _parseLine( $self, $_ ) foreach (@ARGV);
82 # Default to STDIN.
83 if ( scalar( @{ $self->{queue} } ) == 0
84 && scalar( @ARGV == 0 ) )
86 _parseLine( $self, $_ ) while (<STDIN>);
89 my $cache = clive::Cache->instance;
90 my $curl = clive::Curl->instance;
91 my $log = clive::Log->instance;
93 require clive::HostFactory;
94 require clive::Video;
96 foreach ( @{ $self->{queue} } ) {
97 my $host = clive::HostFactory->new($_);
98 if ($host) {
99 my $props = clive::Video->new;
100 $props->page_link($_);
102 my $rc = 0;
104 # Read from cache.
105 if ( $cache->enabled() && $config->{cache_read} ) {
106 $rc = $cache->read( \$props );
107 if ( $rc == 1 && $props->video_format() ne $config->{format} )
110 # Cache: video format != requested format -> re-fetch.
111 $rc = 0;
115 # Cache failed or record did not exist. Fetch the video page.
116 if ( $rc == 0 ) {
117 my $content;
119 $rc = $curl->fetchToMem( $props->page_link, \$content );
121 if ( $rc == 0 ) {
123 $props->page_title( \$content );
124 $rc = $host->parsePage( \$content, \$props );
126 if ( $rc == 0 ) {
127 $rc = $curl->queryFileLength( \$props );
128 if ( $rc == 0 ) {
129 $props->video_format( $config->{format} );
130 $cache->write( \$props );
136 # Cache record found.
137 else {
138 $log->out("cache $_ ...done\n");
139 $rc = 0;
142 # If everything went OK so far, proceed to extract etc.
143 if ( $rc == 0 ) {
145 push( @{ $self->{passed_queue} }, $_ );
147 $props->formatOutputFilename;
149 if ( $props->nothing_todo ) {
150 $log->err(
151 "file is already fully retrieved; nothing to do");
152 clive::Exec->instance->queue( \$props );
153 next;
156 if ( $config->{no_extract} ) {
157 $props->printVideo;
159 elsif ( $config->{emit_csv} ) {
160 $props->emitCSV;
162 else {
163 if ( $curl->fetchToFile( \$props ) == 0 ) {
164 clive::Exec->instance->queue( \$self, \$props );
169 else {
170 $log->err("no support: $_");
174 clive::Exec->instance->runExec;
176 # Update recall file.
177 if ( !$log->errorOccurred() ) {
178 if ( open( my $fh, ">", $config->{recall_file} ) ) {
179 print( $fh "$_\n" ) foreach ( @{ $self->{passed_queue} } );
180 close($fh);
182 else {
183 $log->errn("$config->{recall_file}: $!");
188 sub _parseLine {
189 my ( $self, $ln ) = @_;
191 return if $ln =~ /^$/;
192 return if $ln =~ /^#/;
194 chomp $ln;
196 $ln = "http://$ln"
197 if $ln !~ m{^http://}i;
199 # Youtube: youtube-nocookie.com -> youtube.com.
200 $ln =~ s/-nocookie//;
202 # Translate host specific embedded link to video page link.
203 $ln =~ s!/v/!/watch?v=!i; # youtube
204 $ln =~ s!googleplayer.swf!videoplay!i; # googlevideo
205 $ln =~ s!/pl/!/videos/!i; # sevenload
206 $ln =~ s!/e/!/view?i=!i; # liveleak
208 # Lastfm demystifier.
209 if ( $ln =~ /last\.fm/ ) {
210 $ln =~ /\+1\-(.+)/;
211 if ( !$1 ) {
212 clive::Log->instance->errn("no support: $ln");
213 return;
215 $ln = "http://youtube.com/watch?v=$1";
218 push( @{ $self->{queue} }, $ln );
221 sub _printHosts {
222 require clive::HostFactory;
223 clive::HostFactory->dumpHosts();
224 exit(0);
229 # I am the man who walks alone.