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