1###__PERLBIN__### 2# Copyright (C) 2002-2007 Adrian Ulrich <pab at blinkenlights.ch> 3# Part of the gnupod-tools collection 4# 5# URL: http://www.gnu.org/software/gnupod/ 6# 7# GNUpod is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 3 of the License, or 10# (at your option) any later version. 11# 12# GNUpod is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program. If not, see <http://www.gnu.org/licenses/>.# 19# 20# iTunes and iPod are trademarks of Apple 21# 22# This product is not supported/written/published by Apple! 23 24use strict; 25use GNUpod::XMLhelper; 26use GNUpod::FooBar; 27use GNUpod::iTunesDB; 28use Getopt::Long; 29 30use File::Glob ':glob'; 31 32use vars qw(%opts @keeper $plcref); 33 34 35$opts{mount} = $ENV{IPOD_MOUNTPOINT}; 36 37#Don't add xml and itunes opts.. we *NEED* the mount opt to be set.. 38GetOptions(\%opts, "top4secret"); 39GNUpod::FooBar::GetConfig(\%opts, {nosync=>'b', 'automktunes'=>'b', model=>'s'}, "otgsync"); 40#otgsync does just red nosync.. DONT add mount and such funny things! 41 42 43if($opts{top4secret} && !$opts{nosync}) { 44 go(); 45 exit(0); 46} 47elsif($opts{top4secret}) { #&& $opts{nosync} 48 print "> On-The-Go sync disabled by configuration, skipping work...\n"; 49 exit(0); 50} 51else { 52 usage("$0 isn't for humans :-)\nGNUpod::FooBar.pm has to execute me\n"); 53# exit(1); 54} 55 56#################################################### 57# Worker 58sub go { 59 60 $opts{_no_sync} = 1; # Do not run tunes2pod 61 $opts{_no_cstest} = 1; # Do not show case-sensitive warning 62 my $con = GNUpod::FooBar::connect(\%opts); 63 usage($con->{status}."\n") if $con->{status}; 64 65 if(GNUpod::FooBar::ItunesDBNeedsSync($con)) { 66 die "gnupod_otgsync.pl: Bug detected! You need to run tunes2pod.pl -> Sync broken!\n"; 67 } 68 69 ##Check if GNUtunesDB <-> iTunesDB is really in-sync 70 if(GNUpod::FooBar::OnTheGoDataIsInvalid($con)) { #Ok, On-The-Go data is ** BROKEN ** 71 warn "> On-The-Go data dropped, data belongs to an outdated iTunesDB\n"; 72 } 73 else { 74 #Read on The Go list written by the iPod 75 my @xotg = GNUpod::iTunesDB::readOTG($con->{onthego}); 76 #plcref is used by newfile() 77 #so we have to call this before doxml() 78 $plcref = GNUpod::iTunesDB::readPLC($con->{playcounts}); 79 #Add dummy entry, we start to count at 1, not at 0 80 if(int(@xotg) || $plcref) { #We have to modify 81 push(@keeper, -1); 82 #First, we parse the old xml document and create the keeper 83 GNUpod::XMLhelper::doxml($con->{xml}) or usage("Failed to parse $con->{xml}\n"); 84 mkotg(@xotg) if int(@xotg); 85 GNUpod::FooBar::SetEverythingAsInSync($con); # Needed for automktunes 86 GNUpod::XMLhelper::writexml($con, {automktunes=>$opts{automktunes}}); 87 } 88 } 89 90 # Everythig should be ok now.. 91 GNUpod::FooBar::SetEverythingAsInSync($con); 92} 93 94 95 96 97############################################# 98# Add onthego contents to XML 99sub mkotg { 100 my(@otgrefs) = @_; 101 102 #Get all old playlists and create a new name 103 my $otggen = 1; 104 foreach(GNUpod::XMLhelper::getpl_attribs()) { 105 my $plname = $_->{name}; 106 if($plname =~ /^On-The-Go (\d+)/) { 107 $otggen = ($1+1) if $otggen<=$1; 108 } 109 } 110 111 foreach (@otgrefs) { 112 my @xotg = @$_; #Change ref to array 113 next if int(@xotg) == 0; #Do not create empty OTG-Lists 114 GNUpod::XMLhelper::addpl("On-The-Go $otggen"); 115 foreach(@xotg) { 116 my $otgid = $_+1; 117 my $plfh = (); 118 $plfh->{add}->{id} = $keeper[$otgid]; 119 next unless $plfh->{add}->{id}; 120 GNUpod::XMLhelper::mkfile($plfh,{"plname"=>"On-The-Go $otggen"}); 121 } 122 $otggen++; 123 } 124 125} 126 127############################################# 128# Eventhandler for FILE items 129sub newfile { 130 my($el) = @_; 131 132 #This has to be 'in-sync' with the mktunes.pl method 133 # (GNUtunesDB_id <-> iTunesDB_id) 134 # in mktunes.pl, every <file.. will create a new 135 # id, like here :) 136 137 push(@keeper, int($el->{file}->{id})); 138 if($plcref) { #PlayCountref exists (=v2 ipod) -> adjust 139 #Adjust rating 140 my $playcount = $plcref->{playcount}{int(@keeper)-1}; 141 $el->{file}->{rating} = $plcref->{rating}{int(@keeper)-1}; 142 $el->{file}->{playcount} += $playcount; 143 $el->{file}->{skipcount} += $plcref->{skipcount}{int(@keeper)-1}; 144 $el->{file}->{bookmark} = $plcref->{bookmark}{int(@keeper)-1}; 145 $el->{file}->{played_flag} = 1 if ($el->{file}->{playcount} > 0 || $el->{file}->{skipcount} > 0 || $el->{file}->{bookmark} > 0); 146 147 if($plcref->{lastplay}{int(@keeper)-1}) { 148 $el->{file}->{lastplay} = $plcref->{lastplay}{int(@keeper)-1}; 149 } 150 if($plcref->{lastskip}{int(@keeper)-1}) { 151 $el->{file}->{lastskip} = $plcref->{lastskip}{int(@keeper)-1}; 152 } 153 } 154 #Add content 155 GNUpod::XMLhelper::mkfile($el); 156} 157 158############################################ 159# Eventhandler for PLAYLIST items 160sub newpl { 161 my($el,$name,$plt) = @_; 162 #Add playlist to output 163 GNUpod::XMLhelper::mkfile($el,{$plt."name"=>$name}); 164} 165 166############################################ 167# Die with status 168sub usage { 169 die "died: $_[0]\n"; 170} 171 172