summaryrefslogtreecommitdiff
path: root/lib/gcstar/GCImport
diff options
context:
space:
mode:
Diffstat (limited to 'lib/gcstar/GCImport')
-rw-r--r--lib/gcstar/GCImport/GCImportAMC.pm234
-rw-r--r--lib/gcstar/GCImport/GCImportAlexandria.pm205
-rw-r--r--lib/gcstar/GCImport/GCImportBase.pm217
-rw-r--r--lib/gcstar/GCImport/GCImportCSV.pm313
-rw-r--r--lib/gcstar/GCImport/GCImportDVDProfiler.pm192
-rw-r--r--lib/gcstar/GCImport/GCImportFolder.pm510
-rw-r--r--lib/gcstar/GCImport/GCImportGCfilms.pm190
-rw-r--r--lib/gcstar/GCImport/GCImportGCstar.pm106
-rw-r--r--lib/gcstar/GCImport/GCImportList.pm202
-rw-r--r--lib/gcstar/GCImport/GCImportMyMovies.pm211
-rw-r--r--lib/gcstar/GCImport/GCImportScanner.pm394
-rw-r--r--lib/gcstar/GCImport/GCImportTarGz.pm152
-rw-r--r--lib/gcstar/GCImport/GCImportTellico.pm496
13 files changed, 3422 insertions, 0 deletions
diff --git a/lib/gcstar/GCImport/GCImportAMC.pm b/lib/gcstar/GCImport/GCImportAMC.pm
new file mode 100644
index 0000000..c5d38c9
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportAMC.pm
@@ -0,0 +1,234 @@
+package GCImport::GCImportAMC;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use GCImport::GCImportBase;
+
+{
+ package GCImport::GCImporterAMC;
+ use base qw(GCImport::GCImportBaseClass);
+
+ use File::Basename;
+ use File::Copy;
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+ $self->{fileId} = " AMC_X.Y Ant Movie Catalog 3.5.x www.buypin.com www.antp.be ";
+
+ bless ($self, $class);
+ return $self;
+ }
+
+ sub getName
+ {
+ return "Ant Movie Catalog (.amc)";
+ }
+
+ sub getFilePatterns
+ {
+ return (['Ant Movie Catalog (.amc)', '*.amc']);
+ }
+
+ #Return supported models name
+ sub getModels
+ {
+ return ['GCfilms'];
+ }
+
+ #Return current model name
+ sub getModelName
+ {
+ return 'GCfilms';
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+ my @options;
+ return \@options;
+ }
+
+ # Ignored for the moment
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+ sub getEndInfo
+ {
+ return "";
+ }
+
+ sub readBool
+ {
+ my $self = shift;
+
+ my $value;
+ read $self->{file}, $value, 1;
+ return unpack('C',$value);
+ }
+
+ sub readInt
+ {
+ my $self = shift;
+
+ my $value;
+ read $self->{file}, $value, 4;
+ $value = unpack('L',$value);
+ return undef if $value == 4294967295;
+ return $value;
+ }
+
+ sub readString
+ {
+ my $self = shift;
+ my $binary = shift;
+
+ my $length = $self->readInt;
+ my $string;
+
+ return '' if $length == 0;
+ read $self->{file}, $string, $length;
+
+ #$string =~ s/\n/<br\/>/gm if !$binary;
+ $string =~ s/\|/,/gm if !$binary;
+
+ return $string;
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $file) = @_;
+ my @result;
+
+ open ITEMS, $file;
+ binmode ITEMS;
+ $self->{file} = \*ITEMS;
+
+ my $identifier;
+ read ITEMS, $identifier, length($self->{fileId});
+ ($self->{AMCVersion} = $identifier) =~ s/.*?AMC_(\d+)\.(\d+).*/$1.$2/;
+ my @versions = split m/\./, $self->{AMCVersion};
+ $self->{AMCMajorVersion} = $versions[0];
+ $self->{AMCMinorVersion} = $versions[1];
+
+ $self->readString; # name
+ $self->readString; # mail
+ if (($self->{AMCMinorVersion} <= 3) && ($self->{AMCMinorVersion} < 5))
+ {
+ $self->readString; # icq
+ }
+ $self->readString; # site
+ $self->readString; # description
+
+ my $baseDir = dirname($file);
+
+ my $i = 0;
+
+ while (! eof ITEMS)
+ {
+ $result[$i]->{identifier} = $self->readInt; #Id
+ $self->readInt; #Add date
+ $result[$i]->{rating} = $self->readInt;
+
+ if (($self->{AMCMinorVersion} >= 3) && ($self->{AMCMinorVersion} >= 5))
+ {
+ use integer;
+ $result[$i]->{rating} /= 10;
+ }
+
+ $result[$i]->{date} = $self->readInt;
+ $result[$i]->{time} = $self->readInt;
+ my $ vb = $self->readInt; #Video bitrate
+ my $ab = $self->readInt; #Audio bitrate
+ $result[$i]->{number} = $self->readInt;
+
+ $self->readBool; #Checked
+
+ $result[$i]->{place} = $self->readString; #Media label
+ $result[$i]->{format} = $self->readString;
+ $self->readString; #Source
+ $result[$i]->{borrower} = $self->readString;
+ $result[$i]->{borrower} = 'none' if ! $result[$i]->{borrower};
+ $result[$i]->{original} = $self->readString;
+ $result[$i]->{title} = $self->readString;
+ $result[$i]->{title} = $result[$i]->{original} if !$result[$i]->{title};
+
+ $result[$i]->{director} = $self->readString;
+ $self->readString; #Producer
+ $result[$i]->{country} = $self->readString;
+ $result[$i]->{genre} = [[$self->readString]];
+ $result[$i]->{actors} = $self->readString;
+ $result[$i]->{webPage} = $self->readString;
+ $result[$i]->{synopsis} = $self->readString;
+ $result[$i]->{comment} = $self->readString;
+ $result[$i]->{video} = $self->readString;
+ my $encodings = $self->readString; #Audio format
+ my $res = $self->readString; #Resolution
+ $self->readString; #Framerate
+ $result[$i]->{audio} = $self->readString;
+ if ($result[$i]->{audio})
+ {
+ my @encodings = split /,/,$encodings;
+ $result[$i]->{audio} =~ s/(^|,)([^;]*?)(,|$)/$1$2;$_$3/ foreach (@encodings);
+ $result[$i]->{audio} =~ s/, +/,/g;
+ $result[$i]->{audio} =~ s/; +/;/g;
+ }
+ $result[$i]->{subt} = [[$self->readString]];
+ $self->readString; #File size
+ $result[$i]->{image} = $self->readString;
+
+ my $picture = $self->readString(1);
+
+ if ($result[$i]->{image} =~ /^\..{3}/)
+ {
+ my $pictureName = $self->{options}->{parent}->getUniqueImageFileName($result[$i]->{image},
+ $result[$i]->{title});
+ open PIC, "> $pictureName";
+ binmode PIC;
+ print PIC $picture;
+ close PIC;
+ $result[$i]->{image} = $self->{options}->{parent}->transformPicturePath($pictureName);
+ }
+ else
+ {
+ if (! File::Spec->file_name_is_absolute($result[$i]->{image}))
+ {
+ $result[$i]->{image} = $baseDir . $result[$i]->{image};
+ }
+ #copy $result[$i]->{image}, $pictureName;
+ }
+
+ $i++;
+ }
+
+ close ITEMS;
+
+ return \@result;
+ }
+}
+
+1;
diff --git a/lib/gcstar/GCImport/GCImportAlexandria.pm b/lib/gcstar/GCImport/GCImportAlexandria.pm
new file mode 100644
index 0000000..6233ed7
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportAlexandria.pm
@@ -0,0 +1,205 @@
+package GCImport::GCImportAlexandria;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use GCImport::GCImportBase;
+
+{
+ package GCImport::GCImporterAlexandria;
+
+ use base qw(GCImport::GCImportBaseClass);
+ use File::Copy;
+ use Encode;
+ use GCUtils 'glob';
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+ bless ($self, $class);
+ $self->{errors} = '';
+
+ return $self;
+ }
+
+ sub getName
+ {
+ return "Alexandria";
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+ return [
+ {
+ name => 'where',
+ type => 'options',
+ label => 'Where',
+ default => 'Default',
+ valuesList => 'Default,Specified'
+ }
+ ];
+ }
+
+ sub getFilePatterns
+ {
+ my $self = shift;
+
+ return ();
+ }
+
+ #Return supported models name
+ sub getModels
+ {
+ return ['GCbooks'];
+ }
+
+ sub getModelName
+ {
+ my $self = shift;
+
+ return 'GCbooks';
+ }
+
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+
+ sub wantsFileSelection
+ {
+ return 0;
+ }
+
+ sub wantsDirectorySelection
+ {
+ return 1;
+ }
+
+ sub getEndInfo
+ {
+ my $self = shift;
+
+ return '';
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $directory) = @_;
+
+ my @result = ();
+
+ my @files;
+ $directory = $ENV{HOME}.'/.alexandria'
+ if $self->{options}->{where} eq 'Default';
+
+ foreach (glob "$directory/*")
+ {
+ if (-d $_)
+ {
+ my @array = glob "$_/*";
+ foreach my $file(glob "$_/*")
+ {
+ push @files, $file if $file =~ /yaml$/;
+ }
+ }
+ push @files, $_ if /yaml$/;
+ }
+
+ foreach (@files)
+ {
+ push @result, $self->getBook($_);
+ }
+
+ return \@result;
+ }
+
+ sub transformValue
+ {
+ my ($self, $value) = @_;
+
+ $value =~ s/^"(.*)"$/$1/;
+ $value =~ s/\\x([0-9a-fA-F]{2})/pack("H2",$1)/ge;
+ $value = decode('UTF-8', $value);
+
+ return $value;
+ }
+
+ sub getBook
+ {
+ my ($self, $file) = @_;
+
+ my %book;
+ open BOOK, "<$file";
+ binmode(BOOK, ':utf8');
+ # 1st line contain ruby information
+ my $line = <BOOK>;
+ my $current = '';
+ my $value = '';
+ foreach (<BOOK>)
+ {
+ next if /^#/;
+ if (/^([a-z_]*): (.*)$/)
+ {
+ $current = $1;
+ next if $current eq 'saved_ident';
+ # Tag conversion
+ $current = 'lendDate' if $current eq 'loaned_since';
+ $current = 'borrower' if $current eq 'loaned_to';
+ $book{$current} = $self->transformValue($2);
+ }
+ elsif (/^\s*- (.*)$/)
+ {
+ $book{$current} ||= [];
+ push @{$book{$current}}, [$self->transformValue($1)];
+ }
+ }
+ close BOOK;
+ #Some adjustments
+ $book{rating} *= 2;
+ $book{lendDate} =~ s|^([0-9]{4})-([0-9]{2})-([0-9]{2}).*$|$3/$2/$1|;
+ if ($book{loaned} eq 'false')
+ {
+ $book{borrower} = 'none';
+ $book{lendDate} = '';
+ }
+ delete $book{loaned};
+ #cover
+ $file =~ s/yaml$/cover/;
+ if (-e $file)
+ {
+ my $pic = $self->{options}->{parent}->getUniqueImageFileName('jpg', $book{title});
+ copy $file, $pic;
+ $book{cover} = $pic;
+ }
+ return \%book;
+ }
+
+}
+
+
+
+
+1; \ No newline at end of file
diff --git a/lib/gcstar/GCImport/GCImportBase.pm b/lib/gcstar/GCImport/GCImportBase.pm
new file mode 100644
index 0000000..026be19
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportBase.pm
@@ -0,0 +1,217 @@
+package GCImport::GCImportBase;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use GCExportImport;
+
+{
+ package GCImport::GCImportBaseClass;
+
+ use base 'GCExportImportBase';
+ use File::Basename;
+ use File::Copy;
+
+ #Methods to be overriden in specific classes
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new;
+
+ $self->{parsingError} = '';
+ $self->{modelAlreadySet} = 0;
+
+ bless ($self, $class);
+ return $self;
+ }
+
+ sub getFilePatterns
+ {
+ return (['*.*', '*.*']);
+ }
+
+ sub getSuffix
+ {
+ my $self = shift;
+ return '' if ! ($self->getFilePatterns)[0];
+ (my $pattern = ($self->getFilePatterns)[0]->[1]) =~ s/.*?([[:alnum:]]+)/$1/;
+ return $pattern;
+ }
+
+ #Return supported models name
+ sub getModels
+ {
+ return [];
+ }
+
+ #Return current model name
+ sub getModelName
+ {
+ return 'GCfilms';
+ }
+
+ sub getOptions
+ {
+ }
+
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+
+ sub wantsIgnoreField
+ {
+ return 0;
+ }
+
+ sub wantsImagesSelection
+ {
+ return 0;
+ }
+
+ sub wantsFileSelection
+ {
+ return 1;
+ }
+
+ sub wantsDirectorySelection
+ {
+ return 0;
+ }
+
+ # Returns true if the module should be hidden from
+ # the menu when a collection of an incompatible kind is open.
+ sub shouldBeHidden
+ {
+ return 0;
+ }
+
+ sub generateId
+ {
+ return 1;
+ }
+
+ sub getEndInfo
+ {
+ }
+
+ sub getItemsArray
+ {
+ }
+
+ #End of methods to be overriden
+
+ # If you need really specific processing, you can instead override the process method
+
+ sub process
+ {
+ my ($self, $options) = @_;
+ $self->{options} = $options;
+
+ $options->{parent}->{items}->updateSelectedItemInfoFromPanel;
+ my $alreadySaved = 0;
+ if ($options->{newList})
+ {
+ return if !$options->{parent}->checkAndSave;
+ $alreadySaved = 1;
+ $options->{parent}->setFile('');
+ }
+ $self->{options}->{parent}->setWaitCursor($self->{options}->{lang}->{ImportListTitle}.' ('.$options->{file}.')');
+ my @tmpArray = @{$self->getItemsArray($options->{file})};
+
+ if ($self->{parsingError})
+ {
+ $self->{options}->{parent}->restoreCursor;
+ return $self->getEndInfo;
+ }
+
+ my $realModel = $self->getModelName;
+
+ # Here we really know the model so we force a new list if needed
+ if (($options->{newList})
+ || ($options->{parent}->{model}->getName ne $realModel))
+ {
+ $options->{parent}->newList($realModel, $self->{modelAlreadySet}, $alreadySaved);
+ }
+
+ my $generateId = $self->generateId;
+ foreach (@tmpArray)
+ {
+ $options->{parent}->{items}->addItem($_, !$generateId, 1);
+ }
+ $options->{parent}->{items}->unselect;
+ $self->{options}->{parent}->restoreCursor;
+
+ $options->{parent}->checkPanelVisibility;
+ $options->{parent}->selectFirst;
+ $options->{parent}->markAsUpdated;
+ $options->{parent}->viewAllItems;
+ return $self->getEndInfo;
+ }
+
+ # This method could only be use if $self->{model} has been initialized
+ sub copyPictures
+ {
+ my ($self, $itemsArray, $file) = @_;
+ return if !$self->{model};
+ foreach my $item(@$itemsArray)
+ {
+ my $title = $item->{$self->{model}->{commonFields}->{title}};
+ foreach my $field(@{$self->{model}->{fieldsImage}})
+ {
+ (my $suffix = $item->{$field}) =~ s/.*?(\.[^.]*)$/$1/;
+ my $imageFile = $self->{options}->{parent}->getUniqueImageFileName($suffix, $title);
+ copy(GCUtils::getDisplayedImage($item->{$field}, '', $file),
+ $imageFile)
+ if $item->{$field};
+ $item->{$field} = $imageFile;
+ }
+ }
+ }
+
+ # 3 methods below are created to implement interface
+ # from GCFrame plugins could need to simulate if using
+ # some backends
+ sub preloadModel
+ {
+ my ($self, $model) = @_;
+ # Preload the model into the factory cache
+ $self->{modelsFactory}->getModel($model);
+ }
+
+ sub setCurrentModel
+ {
+ my ($self, $model) = @_;
+ $self->{model} = $self->{modelsFactory}->getModel($model);
+ }
+
+ sub setCurrentModelFromInline
+ {
+ my ($self, $container) = @_;
+ $self->{model} = GCModelLoader->newFromInline($self, $container);
+ }
+}
+
+1;
diff --git a/lib/gcstar/GCImport/GCImportCSV.pm b/lib/gcstar/GCImport/GCImportCSV.pm
new file mode 100644
index 0000000..efb3e5d
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportCSV.pm
@@ -0,0 +1,313 @@
+package GCImport::GCImportCSV;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use utf8;
+
+use GCImport::GCImportBase;
+
+{
+ package GCImport::GCImporterCSV;
+
+ use base qw(GCImport::GCImportBaseClass);
+ use Encode;
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+
+ bless ($self, $class);
+ return $self;
+ }
+
+ sub wantsFieldsSelection
+ {
+ return 1;
+ }
+
+ sub wantsIgnoreField
+ {
+ return 1;
+ }
+
+ sub wantsFileSelection
+ {
+ return 1;
+ }
+
+ sub getName
+ {
+ my $self = shift;
+
+ return "CSV";
+ }
+
+ sub getFilePatterns
+ {
+ return (['CSV (*.csv)', '*.csv']);
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+
+ my $charsets = '';
+ my @charsetList = Encode->encodings(':all');
+ foreach (@charsetList)
+ {
+ $charsets .= $_.',';
+ }
+
+ my $pluginsList = $self->{model}->{parent}->{lang}->{PluginDisabled}.',';
+ foreach (@{$self->{model}->getPluginsNames})
+ {
+ my $plugin = $GCPlugins::pluginsMap{$self->{model}->getName}->{$_};
+ $pluginsList .= $plugin->getName . ',';
+ }
+
+ my $searchFieldsList;
+ foreach (@{$self->{model}->getSearchFields})
+ {
+ $searchFieldsList->{$_} = $self->{model}->getDisplayedText($self->{model}->{fieldsInfo}->{$_}->{label});
+ }
+
+ return [
+ {
+ name => 'sep',
+ type => 'short text',
+ label => 'Separator',
+ default => ';'
+ },
+
+ {
+ name => 'charset',
+ type => 'options',
+ label => 'Charset',
+ valuesList => $charsets,
+ default => 'utf8',
+ },
+
+ {
+ name => 'withHeader',
+ type => 'yesno',
+ label => 'Header',
+ default => '1'
+ },
+
+ {
+ name => 'plugin',
+ type => 'options',
+ label => 'Plugin',
+ valuesList => $pluginsList
+ },
+
+ {
+ name => 'searchfield',
+ type => 'options',
+ label => 'SearchField',
+ valuesList => $searchFieldsList,
+ default => $self->{model}->{commonFields}->{title}
+ },
+
+ {
+ name => 'first',
+ type => 'yesno',
+ label => 'UseFirst',
+ default => '1'
+ },
+
+ ];
+ }
+
+ sub getModelName
+ {
+ my $self = shift;
+ return $self->{model}->getName;
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $file) = @_;
+ my @result;
+
+ # First we try to get the correct plugin
+ my $plugin;
+ my $titleField;
+ my $pluginEnabled;
+ $pluginEnabled = 1 if $self->{options}->{plugin}
+ && ($self->{options}->{plugin} ne $self->{options}->{lang}->{PluginDisabled});
+ if ($pluginEnabled)
+ {
+ $plugin = $GCPlugins::pluginsMap{$self->{model}->getName}->{$self->{options}->{plugin}};
+ $titleField = $self->{options}->{searchfield};
+
+ # Force values of search field if it's incompatible with current plugin
+ my $compatible = 1;
+ $compatible = grep /^$titleField$/, @{$plugin->getSearchFieldsArray}
+ if $titleField;
+ if (!$compatible)
+ {
+ # If it is not, we use the 1st compatible one
+ $titleField = $plugin->getSearchFieldsArray->[0];
+ }
+
+ }
+
+ open ITEMS, $file;
+ binmode(ITEMS, ':utf8')
+ if $self->{options}->{charset} eq 'utf8';;
+
+ my $sep = $self->{options}->{sep};
+ my $ignoreFirstLine = $self->{options}->{withHeader};
+
+ my $resultsDialog;
+ if ((!$self->{options}->{first}) && ($pluginEnabled))
+ {
+ $resultsDialog = $self->{options}->{parent}->getDialog('Results');
+ $resultsDialog->setModel($self->{model}, $self->{model}->{fieldsInfo});
+ $resultsDialog->setMultipleSelection(0);
+ }
+
+ my $i = 0;
+
+ while (<ITEMS>)
+ {
+ if ($ignoreFirstLine)
+ {
+ $ignoreFirstLine = 0;
+ next;
+ }
+
+ chomp;
+ # Special characters are escaped
+ my @values = split m/\Q$sep\E/;
+
+ $result[$i] = {} if (!$pluginEnabled);
+
+ my $j = 0;
+ my $searchTitle = '';
+ foreach (@{$self->{options}->{fields}})
+ {
+ $values[$j] = decode($self->{options}->{charset}, $values[$j])
+ if $self->{options}->{charset} ne 'utf8';
+ $result[$i]->{$_} = $values[$j] if (!$pluginEnabled);
+ $searchTitle = $values[$j] if (($_ eq $titleField) && ($pluginEnabled));
+ $j++;
+ }
+
+ if (($pluginEnabled) && ($searchTitle ne ''))
+ {
+ $plugin->{title} = $searchTitle;
+ $plugin->{type} = 'load';
+ $plugin->{urlField} = $self->{model}->{commonFields}->{url};
+ $plugin->{searchField} = $titleField;
+
+ #Initialize what will be pushed in the array
+ my $info = {$titleField => $searchTitle};
+
+ $self->{options}->{parent}->setWaitCursor($self->{options}->{lang}->{StatusSearch}.' ('.$_.')');
+ $plugin->load;
+
+ my $itemNumber = $plugin->getItemsNumber;
+
+ if ($itemNumber != 0)
+ {
+ $plugin->{type} = 'info';
+ if (($itemNumber == 1) || ($self->{options}->{first}))
+ {
+ $plugin->{wantedIdx} = 0;
+ }
+ else
+ {
+ my $withNext = 0;
+ my @items = $plugin->getItems;
+ $resultsDialog->setWithNext(0);
+ $resultsDialog->setSearchPlugin($plugin);
+ $resultsDialog->setList($_, @items);
+ $resultsDialog->show;
+ if ($resultsDialog->{validated})
+ {
+ $plugin->{wantedIdx} = $resultsDialog->getItemsIndexes->[0];
+ }
+ }
+ $info = $plugin->getItemInfo;
+ my $title = $info->{$titleField};
+ $self->{options}->{parent}->{defaultPictureSuffix} = $plugin->getDefaultPictureSuffix;
+ foreach my $field(@{$self->{model}->{managedImages}})
+ {
+ $info->{$field} = '' if $info->{$field} eq 'empty';
+ next if !$info->{$field};
+ ($info->{$field}) = $self->{options}->{parent}->downloadPicture($info->{$field}, $title);
+ }
+ $info->{comment} = $self->getLang->{CommentAuto}
+ . "\n"
+ . $self->getLang->{CommentSite}
+ . $plugin->getName()
+ . "\n"
+ . $self->getLang->{CommentTitle}
+ . $_
+ . "\n";
+
+ # Add the default value
+ my $defaultInfo = $self->{model}->getDefaultValues;
+ foreach my $field(keys %$defaultInfo)
+ {
+ next if exists $info->{$field};
+ $info->{$field} = $defaultInfo->{$field};
+ }
+ my $j = 0;
+ foreach (@{$self->{options}->{fields}})
+ {
+ $values[$j] = decode($self->{options}->{charset}, $values[$j])
+ if $self->{options}->{charset} ne 'utf8';
+ $info->{$_} = $values[$j];
+ $j++;
+ }
+ }
+
+ push @result, $info;
+ $self->{options}->{parent}->restoreCursor;
+ }
+
+ $i++;
+ }
+ close ITEMS;
+
+
+ return \@result;
+ }
+
+
+ sub getEndInfo
+ {
+ my $self = shift;
+ my $message;
+
+ return $message;
+ }
+}
+
+1;
diff --git a/lib/gcstar/GCImport/GCImportDVDProfiler.pm b/lib/gcstar/GCImport/GCImportDVDProfiler.pm
new file mode 100644
index 0000000..6f47d7b
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportDVDProfiler.pm
@@ -0,0 +1,192 @@
+package GCImport::GCImportDVDProfiler;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use GCImport::GCImportBase;
+
+{
+ package GCImport::GCImporterDVDProfiler;
+
+ use base qw(GCImport::GCImportBaseClass);
+
+ use XML::Simple;
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+ bless ($self, $class);
+
+ return $self;
+ }
+
+ sub getName
+ {
+ return "DVDProfiler (.xml)";
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+ my @options;
+ return \@options;
+ }
+
+ sub getFilePatterns
+ {
+ return (['DVDProfiler (.xml)', '*.xml']);
+ }
+
+ #Return supported models name
+ sub getModels
+ {
+ return ['GCfilms'];
+ }
+
+ # Ignored for the moment
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+ sub getEndInfo
+ {
+ return "";
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $file) = @_;
+ my $xml;
+ my $data;
+ # creer un objet
+ $xml = XML::Simple->new; # sans keyAttr les dvd seront dans une liste ou chaque dvd sera identifie par l'emplacement qu'il a dans cette liste
+ $data = $xml->XMLin ("$file");
+
+
+ my @result;
+ my $film;
+
+ foreach $film(@{$data->{DVD}}){
+ my $item;
+
+ $item->{title} = $film->{Title};
+ $item->{date} = $film->{ProductionYear};
+ $item->{time} = $film->{RunningTime}.' mn';
+ $item->{synopsis} = $film->{Overview};
+ ####### DIRECTOR #########
+ my $director;
+
+ if (ref ($film->{Credits}->{Credit}) eq "ARRAY") {
+ foreach $director(@{$film->{Credits}->{Credit}}){
+ if (($director->{CreditType}) eq 'Direction') {
+ $item->{director} .= $director->{FirstName}.' '.$director->{LastName}.', ';
+
+ }
+ }
+ }
+ else {
+ if (($film->{Credits}->{Credit}->{CreditType}) eq 'Direction') {
+ $item->{director} .= $film->{Credits}->{Credit}->{FirstName}.' '.$film->{Credits}->{Credit}->{LastName};
+ }
+ }
+ ###### END DIRECTOR ######
+
+ ####### ACTORS #########
+ my $actor;
+ if (ref ($film->{Actors}->{Actor}) eq "ARRAY") {
+ foreach $actor(@{$film->{Actors}->{Actor}}){
+ $item->{actors} .= $actor->{FirstName}.' '.$actor->{LastName}.' '.'('.$actor->{Role}.')'.', ';
+
+ }
+ }
+ else {
+ $item->{actors} .= $film->{Actors}->{Actor}->{'FirstName'}.' '.$film->{Actors}->{Actor}->{LastName}.' '.'('.$film->{Actors}->{Actor}->{Role}.')';
+ }
+ ###### END ACTORS ######
+
+ ####### AUDIO #########
+ my $audio;
+ if (ref ($film->{Audio}->{AudioFormat}) eq "ARRAY"){
+ foreach $audio(@{$film->{Audio}->{AudioFormat}}){
+ $item->{audio} .= $audio->{AudioLanguage}.', ';
+
+ }
+ }
+ else {
+ $item->{audio} .= $film->{Audio}->{AudioFormat}->{'AudioLanguage'};
+ }
+ ###### END AUDIO ######
+ ####### SUBT #########
+ my $subt;
+ if (ref ($film->{Subtitles}->{Subtitle}) eq "ARRAY"){
+ foreach $subt(@{$film->{Subtitles}->{Subtitle}}){
+ $item->{subt} .= $subt.', ';
+
+ }
+ }
+ else {
+ $item->{subt} = $film->{Subtitles}->{Subtitle};
+ }
+ ####### END SUBT #########
+ ####### TYPE #########
+ my $type;
+ if (ref ($film->{Genres}->{Genre}) eq "ARRAY"){
+ foreach $type(@{$film->{Genres}->{Genre}}){
+ $item->{type} .= $type.',';
+
+ }
+ }
+ else {
+ $item->{type} = $film->{Genres}->{Genre};
+ }
+ ####### END TYPE #########
+
+ #$item->{original} = $film->{Title};
+ #$item->{subt} = $film->{Subtitles}->{Subtitle};
+ #$item->{borrower} = $film->{Title};
+ #$item->{lendDate} = $film->{Title};
+ #$item->{history} = $film->{Title};
+ #$item->{seen} = $film->{Title};# non par defaut ?
+ #$item->{comment} = $film->{Title};
+ #$item->{image} = $film->{Title};
+ #$item->{country} = $film->{Title};
+ #$item->{number} = $film->{CollectionNumber};
+ #$item->{rating} = $film->{Title};# note par defaut
+ #$item->{format} = $film->{Title};#DVD par d�faut ?
+ #$item->{webPage} = $film->{Title};
+ #$item->{place} = $film->{Title};
+ $item->{director} =~ s/, $//;
+ $item->{actors} =~ s/, $//;
+ $item->{audio} =~ s/, $//;
+ $item->{subt} =~ s/, $//;
+ $item->{type} =~ s/, $//;
+ push @result, $item;
+ }
+ return \@result;
+
+ }
+}
+
+1; \ No newline at end of file
diff --git a/lib/gcstar/GCImport/GCImportFolder.pm b/lib/gcstar/GCImport/GCImportFolder.pm
new file mode 100644
index 0000000..10d9fd1
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportFolder.pm
@@ -0,0 +1,510 @@
+package GCImport::GCImportFolder;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+
+use GCImport::GCImportBase;
+
+{
+ package GCImport::GCImporterFolder;
+
+ use File::Find;
+ use File::Basename;
+ use base qw(GCImport::GCImportBaseClass);
+
+ use GCPlugins;
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+
+ bless ($self, $class);
+ return $self;
+ }
+
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+
+ sub wantsFileSelection
+ {
+ return 1;
+ }
+
+ sub wantsDirectorySelection
+ {
+ return 1;
+ }
+
+ sub shouldBeHidden
+ {
+ return 1;
+ }
+
+ sub getFilePatterns
+ {
+ return ();
+ }
+
+ #Return supported models name
+ sub getModels
+ {
+ return ['GCfilms', 'GCMusics'];
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+
+ my $pluginsList;
+ foreach (@{$self->{model}->getPluginsNames})
+ {
+ my $plugin = $GCPlugins::pluginsMap{$self->{model}->getName}->{$_};
+ push @$pluginsList,$plugin->getName;
+ }
+
+
+ return [
+ {
+ name => 'plugin',
+ type => 'options',
+ label => 'Plugin',
+ valuesList => $pluginsList
+ },
+ {
+ name => 'multipleResult',
+ type => 'options',
+ label => 'MultipleResult',
+ tooltip => 'MultipleResultTooltip',
+ valuesList => 'Ask,AskEnd,AddWithoutInfo,DontAdd,TakeFirst',
+ default => 'Ask',
+ },
+ {
+ name => 'noResult',
+ type => 'options',
+ label => 'NoResult',
+ tooltip => 'NoResultTooltip',
+ valuesList => 'AddWithoutInfo,DontAdd', # TODO AskNewName AskNewPlugin at End
+ default => 'AddEmpty',
+ },
+ {
+ name => 'recursive',
+ type => 'yesno',
+ label => 'Recursive',
+ default => '1'
+ },
+
+ {
+ name => 'suffixes',
+ type => 'short text',
+ label => 'Suffixes',
+ tooltip => 'SuffixesTooltip',
+ default => '',
+ },
+
+ {
+ name => 'remove',
+ type => 'short text',
+ label => 'Remove',
+ tooltip => 'RemoveTooltip',
+ default => '',
+ },
+ {
+ name => 'removeWholeWord',
+ type => 'yesno',
+ label => 'RemoveWholeWord',
+ tooltip => 'RemoveTooltipWholeWord',
+ default => '1',
+ },
+ {
+ name => 'removeRegularExpr',
+ type => 'yesno',
+ label => 'RemoveRegularExpr',
+ tooltip => 'RemoveTooltipRegularExpr',
+ changedCallback => sub {
+ my ($self,$widget) =@_;
+ $widget->[0]->{options}->{removeWholeWord}->lock($self->getValue);
+ },
+ default => '0',
+ },
+ {
+ name => 'skipFileAlreadyInCollection',
+ type => 'options',
+ label => 'SkipFileAlreadyInCollection',
+ tooltip => 'SkipFileAlreadyInCollectionTooltip',
+ valuesList => 'SkipFileNo,SkipFileFullPath,SkipFileFileName,SkipFileFileNameAndUpdate',
+ default => 'SkipFileNo',
+ },
+ {
+ name => 'infoFromFileNameRegExp',
+ type => 'history text',
+ label => 'InfoFromFileNameRegExp',
+ tooltip => 'InfoFromFileNameRegExpTooltip',
+ initValues => ['',
+ '^$A\s*([[\(]part $x( of $y)?[)\]])?\s*([[\(]$Y[)\]])?\s*$',
+ '^$N\s+[^\w ]\s+S$SE$E\s+[^\w ]\s+$T\s+([[(]part $x( of $y)?[)\]])?\s*$',
+ ],
+ default => '',
+ },
+ ];
+
+
+ }
+
+ sub getModelName
+ {
+ my $self = shift;
+ return $self->{model}->getName;
+ }
+
+ # Required by extracter to make this class acts as a panel
+ sub AUTOLOAD
+ {
+ return [];
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $directory) = @_;
+ my @result;
+ my @filesList;
+
+ #First we try to get the correct plugin
+ my $plugin = $GCPlugins::pluginsMap{$self->{model}->getName}->{$self->{options}->{plugin}};
+ $plugin->{bigPics} = $self->{options}->{parent}->{options}->bigPics;
+ my $titleField = $self->{model}->{commonFields}->{title};
+ my $fileField = $self->{model}->{commonFields}->{play};
+
+ # Required by extracter
+ $self->{lang} = $self->{options}->{lang};
+
+ (my $suffixes = $self->{options}->{suffixes}) =~ s/[,; ]/\|/g;
+ $suffixes =~ s/\*\.//g;
+ # Create list of files
+ if ($self->{options}->{recursive})
+ {
+ find(sub {
+ return if -d $File::Find::name;
+ return if ! /$suffixes$/;
+ my $name=Encode::decode_utf8($File::Find::name);
+ push @filesList, $name;
+ }, $directory);
+ }
+ else
+ {
+ foreach (glob "$directory/*")
+ {
+ next if -d $_;
+ next if ! /$suffixes$/;
+ push @filesList, $_;
+ }
+ }
+ my $resultsDialog;
+ # initialize choose good result dialog if needed
+ if (($self->{options}->{multipleResult} ne 'Ask') || ($self->{options}->{multipleResult} ne 'AskEnd'))
+ {
+ $resultsDialog = $self->{options}->{parent}->getDialog('Results');
+ $resultsDialog->setModel($self->{model}, $self->{model}->{fieldsInfo});
+ $resultsDialog->setMultipleSelection(0);
+ }
+ #Initialize stuff to retrieve info from name with regexp
+ my $infoFromName;
+ if ($self->{options}->{infoFromFileNameRegExp} ne '')
+ {
+ my %knownParam=($titleField=>'T',alphabTitle=>'A',year=>'Y',season=>'S',episode=>'E',alphabSeries=>'N',number=>'x',totNumber=>'y');
+ my $orderStr= $self->{options}->{infoFromFileNameRegExp};
+ $orderStr=~ s/(?<!\$).//g;
+ # Search the order of $A $T ... in the user regexp
+ my %places;
+ foreach my $key (keys %knownParam) {
+ my $i=1+index $orderStr,$knownParam{$key};
+ $places{$i} = $key;
+ }
+ my $myRegExp=$self->{options}->{infoFromFileNameRegExp};
+ # avoid capturing something else than $T,$A ... make already present () not capturing
+ $myRegExp =~ s/(?<!\\)\(/(?:/g;
+ my $articles='(?:'.join('|',@{$self->{model}->{parent}->{articles}}).')\'?\b';
+ our $myRegExpArt=qr/^(.*?)(?:, ?($articles))?$/i;
+
+ $myRegExp =~ s/\$A/(.*?(?:, ?$articles)?)/g;
+ $myRegExp =~ s/\$N/(.*?(?:, ?$articles)?)/g;
+ $myRegExp =~ s/\$T/(.*?)/;
+ $myRegExp =~ s/\$Y/(\\d{2}|\\d{4}?)/;
+ $myRegExp =~ s/\$x/(\\d{1,2})/;
+ $myRegExp =~ s/\$y/(\\d{1,2})/;
+ $myRegExp =~ s/\$E/(\\d{1,4}?)/;
+ $myRegExp =~ s/\$S/(\\d{1,2}?)/;
+ sub deAlpha{
+ my $s;
+ $_[0] =~ $myRegExpArt;
+ $s=$1;
+ my $a=$2.' ' if $2 && (substr($2,-1) ne '\'');
+ $s=$a.$s if $a;
+ return $s;
+ }
+ # Check if regexp is good
+ my $pattern = shift;
+ my $test = eval { $myRegExp=qr/$myRegExp/i };
+ #print $myRegExp;
+ #
+ if ($@)
+ {
+ $myRegExp= qr/./ ;print $@;
+ }
+ my $i=2;
+ $infoFromName=sub {
+ my $n=$_[0] ;
+ $n=~ $myRegExp;
+ my %info; # TODO Can be more readable in Perl 5.10 by using named capturing
+ $info{$places{1}}=$1 if $1;$info{$places{2}}=$2 if $2;$info{$places{3}}=$3 if $3;$info{$places{4}}=$4 if $4;$info{$places{5}}=$5 if $5;
+ $info{$places{6}}=$6 if $6;$info{$places{7}}=$7 if $7;$info{$places{8}}=$8 if $8;$info{$places{9}}=$9 if $9;$info{$places{10}}=$10 if $10;
+ $info{$places{11}}=$11 if $11;$info{$places{12}}=$12 if $12;$info{$places{13}}=$13 if $13;$info{$places{14}}=$14 if $14;$info{$places{15}}=$15 if $15;
+ $info{$places{16}}=$16 if $16;$info{$places{17}}=$17 if $17;$info{$places{18}}=$18 if $18;$info{$places{19}}=$19 if $19;$info{$places{20}}=$20 if $20;
+
+ $info{$titleField}=deAlpha($info{alphabTitle}) if($info{alphabTitle});
+ $info{series}=deAlpha($info{alphabSeries}) if($info{alphabSeries});
+ return \%info;
+ }
+ }
+ # initialize regexp word to remove
+ my $removed =$self->{options}->{remove};
+ if(!$self->{options}->{removeRegularExpr})
+ {
+ $removed =~ s/[,; ]/\|/g;
+ if($self->{options}->{removeWholeWord})
+ {
+ $removed=~s/\|/\\b\|\\b/g ;
+ $removed='\b'.$removed.'\b';
+ }
+ }
+ # if we want to ignore files already in the list
+ # we initialize a hash with filenames to be fast !
+ my %fileNameKnown;
+ if($self->{options}->{skipFileAlreadyInCollection} ne 'SkipFileNo')
+ {
+ if($self->{options}->{skipFileAlreadyInCollection} eq 'SkipFileFullPath')
+ {
+ foreach my $originalFilm(@{$self->{options}->{originalList}->{itemArray}})
+ {
+ $fileNameKnown{$originalFilm->{$fileField}}=$originalFilm;
+ }
+ }
+ else
+ {
+ foreach my $originalFilm(@{$self->{options}->{originalList}->{itemArray}})
+ {
+ $fileNameKnown{basename($originalFilm->{$fileField})}=$originalFilm;
+ }
+ }
+ }
+ my $hasFileWaiting=0;my $inWaitingQueue=0;
+ # Main loop on files entries
+ file: foreach my $file(@filesList)
+ {
+ if($file eq 'WaitingList')
+ {
+ $inWaitingQueue=1;
+ next file;
+ }
+ # Skip file already in the collection
+ next file if(($self->{options}->{skipFileAlreadyInCollection} eq 'SkipFileFullPath') && (exists $fileNameKnown{$file}));
+ next file if(($self->{options}->{skipFileAlreadyInCollection} eq 'SkipFileFileName') && (exists $fileNameKnown{basename($file)}));
+ if(($self->{options}->{skipFileAlreadyInCollection} eq 'SkipFileFileNameAndUpdate') && (exists $fileNameKnown{basename($file)}))
+ {
+ # if filename already in collection, and collection full path invalid : correct it
+ if (!(-e $fileNameKnown{basename($file)}->{$fileField}))
+ {
+ print "Path updated : ",$fileNameKnown{basename($file)}->{$fileField},"\n";
+ print " --> ",$file,"\n";
+ $fileNameKnown{basename($file)}->{$fileField}=$file;
+ }
+ next file;
+ }
+
+ # Get info from the file (avi, mp3, ...)
+ my $extracter = $self->{model}->getExtracter($self, $file, $self, $self->{model});
+ my $extracted = $extracter->getInfo;
+ # Add info from file
+ my $infoFromFile={$fileField => $file};
+ foreach my $field(keys %$extracted)
+ {
+ $infoFromFile->{$field} = $extracted->{$field}->{value};
+ }
+
+ # Test if subtitle is present
+ if ($self->{model}->getName eq 'GCfilms')
+ {
+ my @subtitlesExt=qw(sub srt);
+ my @subtitlesFiles;
+ my $startFileName=$file;
+ $startFileName=~s/\.[^.]*$//;
+ for my $ext(@subtitlesExt)
+ {
+ my $fileSubsName=$startFileName.'.'.$ext;
+ if(-e $fileSubsName)
+ {
+ #TODO Try to guess the language see cpan
+ my $lang=["Yes"];
+ push @subtitlesFiles,$lang;
+ }
+ }
+ $infoFromFile->{subt}=\@subtitlesFiles if (@subtitlesFiles);
+ }
+ my $infoFromFileName;
+ my $name = basename($file);
+ # Filter the name
+ # Remove suffix
+ $name =~ s/\.[^.]*$//;
+ # Try to apply regexp on filename
+ if ($self->{options}->{infoFromFileNameRegExp} ne '')
+ {
+ $infoFromFileName=&$infoFromName($name);
+ $name = $infoFromFileName->{$titleField} if ($infoFromFileName->{$titleField} ne '');
+ #TODO: Use this known info to search with plugin
+ }
+ # Remove everything between () {} []
+ $name =~ s/[\(\[\{].*?[\)\]\}]/ /g;
+ # Remove special characters
+ $name =~ s/[-\._,#@"']/ /g;
+ #'"
+ # Remove info from extracter for movies
+ if ($self->{model}->getName eq 'GCfilms')
+ {
+ my $info = $extracted->{video}->{value}.'|'.$extracted->{audio}->{value}->[0]->[1];
+ $info =~ s/ (.*?)//g;
+ $name =~ s/$info//g;
+ }
+ $name =~ s/$removed//gi;
+
+ # $name contains the title to search
+ $plugin->{title} = $name;
+ $plugin->{type} = 'load';
+ $plugin->{urlField} = $self->{model}->{commonFields}->{url};
+ $plugin->{searchField} = $titleField;
+
+ #Initialize what will be pushed in the array
+ my $infoPlugin = {$titleField => $name};
+
+ $self->{options}->{parent}->setWaitCursor($self->{options}->{lang}->{StatusSearch}.' ('.$name.')');
+ $plugin->load;
+
+ my $itemNumber = $plugin->getItemsNumber;
+
+ if ($itemNumber == 0)
+ {
+ goto endPluginGetItemInfo if (($self->{options}->{noResult} eq 'AddEmpty'));
+ next file if (($self->{options}->{noResult} eq 'DontAdd'));
+ }
+ else
+ {
+ $plugin->{type} = 'info';
+ if (($itemNumber == 1) || ($self->{options}->{multipleResult} eq 'TakeFirst'))
+ {
+ $plugin->{wantedIdx} = 0;
+ }
+ elsif($self->{options}->{multipleResult} eq 'AddWithoutInfo' )
+ {
+ goto endPluginGetItemInfo;
+ }
+ elsif($self->{options}->{multipleResult} eq 'DontAdd' )
+ {
+ next file;
+ }
+ elsif($self->{options}->{multipleResult} eq 'AskEnd' && !$inWaitingQueue)
+ {
+ # re push the filename at the end of the list, to be proceded
+ push @filesList,'WaitingList' if !$hasFileWaiting;
+ push @filesList,$file;
+ $hasFileWaiting=1;
+ next file;
+ }
+ else
+ {
+ # Ask the user to choose
+ my $withNext = 0;
+ my @items = $plugin->getItems;
+ $resultsDialog->setWithNext(0);
+ $resultsDialog->setSearchPlugin($plugin);
+ $resultsDialog->setList($name, @items);
+ $resultsDialog->show;
+ if ($resultsDialog->{validated})
+ {
+ $plugin->{wantedIdx} = $resultsDialog->getItemsIndexes->[0];
+ }
+ }
+ $infoPlugin = $plugin->getItemInfo;
+ my $title = $infoPlugin->{$titleField};
+ $self->{options}->{parent}->{defaultPictureSuffix} = $plugin->getDefaultPictureSuffix;
+ foreach my $field(@{$self->{model}->{managedImages}})
+ {
+ $infoPlugin->{$field} = '' if $infoPlugin->{$field} eq 'empty';
+ next if !$infoPlugin->{$field};
+ ($infoPlugin->{$field}) = $self->{options}->{parent}->downloadPicture($infoPlugin->{$field}, $title);
+ }
+ $infoPlugin->{plugin} =$plugin->getName();
+ $infoPlugin->{comment} = $self->getLang->{CommentAuto}
+ . "\n"
+ . $self->getLang->{CommentSite}
+ . $plugin->getName()
+ . "\n"
+ . $self->getLang->{CommentTitle}
+ . $name
+ . "\n"
+ . $extracted->{comment}->{displayed};
+ }
+ endPluginGetItemInfo:
+
+ # Add the default value
+ my $defaultInfo = $self->{model}->getDefaultValues;
+
+ my $info;
+ # TODO : ask the user for order, or even for order on each fields
+ my @order=($defaultInfo,$infoFromFile,$infoFromFileName,$infoPlugin);
+ for my $infoSource(@order)
+ {
+ foreach my $field(keys %$infoSource)
+ {
+ $info->{$field} =$infoSource->{$field} if $infoSource->{$field};
+ }
+ }
+ push @result, $info;
+ $self->{options}->{parent}->restoreCursor;
+ }
+ return \@result;
+ }
+
+
+ sub getEndInfo
+ {
+ my $self = shift;
+ my $message;
+
+ return $message;
+ }
+}
+
+1;
diff --git a/lib/gcstar/GCImport/GCImportGCfilms.pm b/lib/gcstar/GCImport/GCImportGCfilms.pm
new file mode 100644
index 0000000..285e17d
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportGCfilms.pm
@@ -0,0 +1,190 @@
+package GCImport::GCImportGCfilms;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use GCImport::GCImportBase;
+
+{
+ package GCImport::GCImporterGCfilms;
+ use base qw(GCImport::GCImportBaseClass);
+ use File::Basename;
+ use File::Copy;
+ use GCUtils;
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+
+ bless ($self, $class);
+ $self->{errors} = '';
+
+ #The fields as they were in GCfilms 6.1
+ # If name has changed in GCstar, the comment contains the original one
+ $self->{fields} = [
+ 'id',
+ 'title',
+ 'date',
+ 'time',
+ 'director',
+ 'country', # nat
+ 'genre', # type
+ 'image',
+ 'actors',
+ 'original', # orig
+ 'synopsis',
+ 'webPage', # url
+ 'seen',
+ 'format',
+ 'number',
+ 'place',
+ 'rating',
+ 'comment',
+ 'audio',
+ 'subt',
+ 'borrower',
+ 'lendDate',
+ 'borrowings', # history
+ 'age',
+ 'video',
+ 'serie', # collection
+ 'rank',
+ 'trailer',
+ ];
+
+ return $self;
+ }
+
+ sub getName
+ {
+ return "GCfilms (.gcf)";
+ }
+
+ sub getFilePatterns
+ {
+ return (['GCfilms (.gcf)', '*.gcf']);
+ }
+
+ #Return supported models name
+ sub getModels
+ {
+ return ['GCfilms'];
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+ return [
+ {
+ name => 'generate',
+ type => 'yesno',
+ label => 'ImportGenerateId',
+ default => '1'
+ },
+ ];
+ }
+
+ # Ignored for the moment
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+ sub generateId
+ {
+ my $self = shift;
+ return $self->{options}->{generate};
+ }
+ sub getEndInfo
+ {
+ return "";
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $file) = @_;
+ my @result;
+
+ open MOVIES, "<$file";
+ my $gotFirstLine = 0;
+ my $i = 0;
+ while (<MOVIES>)
+ {
+ chomp;
+ my @values = split m/\|/;
+
+ if (!$gotFirstLine)
+ {
+ $gotFirstLine = 1;
+ if ($values[0] eq 'GCfilms')
+ {
+ binmode( MOVIES, ':utf8' ) if $values[2] eq 'UTF8';
+ next;
+ }
+ }
+ my $idx = 0;
+ for my $field (@{$self->{fields}})
+ {
+ my $value = $values[$idx];
+ if ($field eq 'image')
+ {
+ my $origPath = GCUtils::getDisplayedImage($value, '', $file);
+ my $origFile = basename($origPath);
+ $origFile = $origPath = '' if ! -f $origPath;
+ # We copy the image only if it was a generated one and if we use the default path
+ if ($origFile =~ /^gcfilms_/)
+ {
+ # We don't change the filename as gcstar has a different pattern for automatic files
+ my $destPath = $self->{options}->{parent}->getImagesDir;
+ copy($origPath, $destPath) if $origPath ne $destPath;
+ $result[$i]->{image} = $destPath.$origFile;
+ }
+ else
+ {
+ # We use the full path
+ $result[$i]->{image} = $origPath;
+ }
+ }
+ else
+ {
+ $value =~ s|:|;|gm if $field eq 'borrowings';
+ $value =~ s|<br>|\n|gm;
+ $value =~ s|<.*?>||gm;
+ if (!$value)
+ {
+ $value = 0 if $field eq 'age';
+ $value = 'none' if $field eq 'borrower';
+ }
+ $result[$i]->{$field} = $value;
+ }
+ $idx++;
+ }
+ $i++;
+ }
+ return \@result;
+
+ }
+}
+
+1;
diff --git a/lib/gcstar/GCImport/GCImportGCstar.pm b/lib/gcstar/GCImport/GCImportGCstar.pm
new file mode 100644
index 0000000..1bff9c2
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportGCstar.pm
@@ -0,0 +1,106 @@
+package GCImport::GCImportGCstar;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use GCImport::GCImportBase;
+
+{
+ package GCImport::GCImporterGCstar;
+ use base qw(GCImport::GCImportBaseClass);
+
+ use GCBackend::GCBackendXmlParser;
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+ bless ($self, $class);
+ return $self;
+ }
+
+ sub getName
+ {
+ return "GCstar (.gcs)";
+ }
+
+ sub getFilePatterns
+ {
+ return (['GCstar (.gcs)', '*.gcs']);
+ }
+
+ sub getModelName
+ {
+ my $self = shift;
+ return $self->{model}->getName;
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+ return [
+ {
+ name => 'copyPics',
+ type => 'yesno',
+ label => 'CopyPictures',
+ default => '1'
+ }];
+ }
+
+ # Ignored for the moment
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+ sub getEndInfo
+ {
+ return "";
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $file) = @_;
+
+ my $parent = $self->{options}->{parent};
+ $self->{modelsFactory} = $parent->{modelsFactory};
+ $self->{modelAlreadySet} = 0;
+
+ my $copyPics = 1;
+ $copyPics = $self->{options}->{copyPics}
+ if exists $self->{options}->{copyPics};
+
+ my $backend = new GCBackend::GCBeXmlParser($self);
+ $backend->setParameters(file => $file);
+ my $loaded = $backend->load(0);
+ my $itemsArray = $loaded->{data};
+ if ($copyPics)
+ {
+ $self->copyPictures($itemsArray, $file);
+ }
+ return $itemsArray;
+
+ }
+}
+
+1;
diff --git a/lib/gcstar/GCImport/GCImportList.pm b/lib/gcstar/GCImport/GCImportList.pm
new file mode 100644
index 0000000..a2b2ec2
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportList.pm
@@ -0,0 +1,202 @@
+package GCImport::GCImportList;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+
+use GCImport::GCImportBase;
+
+{
+ package GCImport::GCImporterList;
+
+ use base qw(GCImport::GCImportBaseClass);
+
+ use GCPlugins;
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+
+ bless ($self, $class);
+ return $self;
+ }
+
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+
+ sub wantsFileSelection
+ {
+ return 1;
+ }
+
+ sub getFilePatterns
+ {
+ return ();
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+
+ my $pluginsList = '';
+ foreach (@{$self->{model}->getPluginsNames})
+ {
+ my $plugin = $GCPlugins::pluginsMap{$self->{model}->getName}->{$_};
+ $pluginsList .= $plugin->getName . ',';
+ }
+
+
+ return [
+ {
+ name => 'plugin',
+ type => 'options',
+ label => 'Plugin',
+ valuesList => $pluginsList
+ },
+
+ {
+ name => 'first',
+ type => 'yesno',
+ label => 'UseFirst',
+ default => '1'
+ },
+ ];
+
+
+ }
+
+ sub getModelName
+ {
+ my $self = shift;
+ return $self->{model}->getName;
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $file) = @_;
+ my @result;
+
+ #First we try to get the correct plugin
+ my $plugin = $GCPlugins::pluginsMap{$self->{model}->getName}->{$self->{options}->{plugin}};
+ $plugin->{bigPics} = $self->{options}->{parent}->{options}->bigPics;
+
+ my $titleField = $self->{model}->{commonFields}->{title};
+
+ open ITEMS, $file;
+ binmode(ITEMS, ':utf8');
+
+ my $i = 0;
+
+ my $resultsDialog;
+ if (!$self->{options}->{first})
+ {
+ $resultsDialog = $self->{options}->{parent}->getDialog('Results');
+ $resultsDialog->setModel($self->{model}, $self->{model}->{fieldsInfo});
+ $resultsDialog->setMultipleSelection(0);
+ }
+ while (<ITEMS>)
+ {
+ chomp;
+ next if ! $_;
+ # $_ contains the title to search
+ $plugin->{title} = $_;
+ $plugin->{type} = 'load';
+ $plugin->{urlField} = $self->{model}->{commonFields}->{url};
+ $plugin->{searchField} = $titleField;
+ #Initialize what will be pushed in the array
+ my $info = {$titleField => $_};
+
+ $self->{options}->{parent}->setWaitCursor($self->{options}->{lang}->{StatusSearch}.' ('.$_.')');
+ $plugin->load;
+
+ my $itemNumber = $plugin->getItemsNumber;
+
+ if ($itemNumber != 0)
+ {
+ $plugin->{type} = 'info';
+ if (($itemNumber == 1) || ($self->{options}->{first}))
+ {
+ $plugin->{wantedIdx} = 0;
+ }
+ else
+ {
+ my $withNext = 0;
+ my @items = $plugin->getItems;
+ $resultsDialog->setWithNext(0);
+ $resultsDialog->setSearchPlugin($plugin);
+ $resultsDialog->setList($_, @items);
+ $resultsDialog->show;
+ if ($resultsDialog->{validated})
+ {
+ $plugin->{wantedIdx} = $resultsDialog->getItemsIndexes->[0];
+ }
+ }
+ $info = $plugin->getItemInfo;
+ my $title = $info->{$titleField};
+ $self->{options}->{parent}->{defaultPictureSuffix} = $plugin->getDefaultPictureSuffix;
+ foreach my $field(@{$self->{model}->{managedImages}})
+ {
+ $info->{$field} = '' if $info->{$field} eq 'empty';
+ next if !$info->{$field};
+ ($info->{$field}) = $self->{options}->{parent}->downloadPicture($info->{$field}, $title);
+ }
+ $info->{comment} = $self->getLang->{CommentAuto}
+ . "\n"
+ . $self->getLang->{CommentSite}
+ . $plugin->getName()
+ . "\n"
+ . $self->getLang->{CommentTitle}
+ . $_
+ . "\n";
+
+ # Add the default value
+ my $defaultInfo = $self->{model}->getDefaultValues;
+ foreach my $field(keys %$defaultInfo)
+ {
+ next if exists $info->{$field};
+ $info->{$field} = $defaultInfo->{$field};
+ }
+ }
+
+ push @result, $info;
+ $self->{options}->{parent}->restoreCursor;
+ }
+ close ITEMS;
+ return \@result;
+ }
+
+
+ sub getEndInfo
+ {
+ my $self = shift;
+ my $message;
+
+ return $message;
+ }
+}
+
+1;
diff --git a/lib/gcstar/GCImport/GCImportMyMovies.pm b/lib/gcstar/GCImport/GCImportMyMovies.pm
new file mode 100644
index 0000000..a51b1c4
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportMyMovies.pm
@@ -0,0 +1,211 @@
+package GCImport::GCImportMyMovies;
+
+#################################################################################
+#
+# Created by Rob Maas rob@progob.nl | http://www.robmaas.eu (2008)
+#
+#
+# This file is strongly based op the already existing DVDProfiler
+# import class. It is also my first perl script :-)
+#
+# Since MyMovies has some different fields then GCStar, there are some work
+# arounds to get as much of the original data.
+#
+# If the field ExtraFeatures is filled, it will appear in the General tab in
+# the synopsis.
+#
+# The rating system will be calculated back to the Dutch rating system.
+#
+# If data was imported from IMDB, the webpage button will link to the specific
+# movie site on IMDB.
+#
+# Cause GCstar hasn´t (yet?) a real EAN field, the EAN code is placed on the
+# details tab under comments.
+#
+# Special thanks goes to Tian who helped me with some array trouble :-P and
+# for creating this software.
+#
+#################################################################################
+
+use strict;
+use GCImport::GCImportBase;
+
+{
+ package GCImport::GCImporterMyMovies;
+
+ use base qw(GCImport::GCImportBaseClass);
+
+ use XML::Simple;
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+ bless ($self, $class);
+
+ return $self;
+ }
+
+ sub getName
+ {
+ return "MyMovies (.xml)";
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+ my @options;
+ return \@options;
+ }
+
+ sub getFilePatterns
+ {
+ return (['MyMovies (.xml)', '*.xml']);
+ }
+
+ #Return supported models name
+ sub getModels
+ {
+ return ['GCfilms'];
+ }
+
+ # Ignored for the moment
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+ sub getEndInfo
+ {
+ return "";
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $file) = @_;
+ my $xml;
+ my $data;
+ # Creates an object / Skip empty ellements
+ $xml = new XML::Simple(suppressempty => 1);
+ $data = $xml->XMLin ("$file");
+
+ my @result;
+ my $film;
+
+ # For each "Title" in the XML file
+ foreach $film(@{$data->{Title}}){
+ my $item;
+
+ #General fields
+ $item->{title} = $film->{LocalTitle};
+ $item->{original} = $film->{OriginalTitle};
+ $item->{date} = $film->{ProductionYear};
+ $item->{time} = $film->{RunningTime}.' min';
+ $item->{synopsis} = $film->{Description};
+
+ #Extra's on the disc
+ if ($film->{ExtraFeatures}->{content}){
+ $item->{synopsis} .= "\n\nEXTRA\n";
+ $item->{synopsis} .= $film->{ExtraFeatures}->{content};
+ }
+
+ #Based on the Dutch ratings!
+
+ $item->{age} =
+ ($film->{ParentalRating}->{Value} == 1) ? 1
+ : ($film->{ParentalRating}->{Value} == 2) ? 2
+ : ($film->{ParentalRating}->{Value} == 3) ? 5
+ : ($film->{ParentalRating}->{Value} == 4) ? 12
+ : 16;
+
+ if ($film->{DataProvider} eq 'IMDB.com'){
+ $item->{webPage} = 'http://www.imdb.com/title/'.$film->{DataProviderId};
+ }
+ $item->{country} = $film->{Country};
+
+ ###### GENRE #########
+ my $type;
+ if (ref ($film->{Genres}->{Genre}) eq "ARRAY"){
+ foreach $type(@{$film->{Genres}->{Genre}}){
+ $item->{genre} .= $type.',';
+ }
+ }
+ else{
+ $item->{genre} = $film->{Genres}->{Genre};
+ }
+ ###### END GENRE #########
+ ####### DIRECTOR AND ACTORS #########
+ my $actor;
+ if (ref ($film->{Persons}->{Person}) eq "ARRAY") {
+ foreach $actor(@{$film->{Persons}->{Person}}){
+ if ($actor->{Type} eq 'Director'){
+ $item->{director} = $actor->{Name};
+ }
+ else{
+ $item->{actors}.= $actor->{Name}.' ('.$actor->{Role}.'), ';
+ }
+ }
+ }
+ else{
+ $item->{actors}.= $film->{Persons}->{Person}->{Name}.' ('.$film->{Persons}->{Person}->{Role}.')';
+ }
+ ###### END DIRECTOR AND ACTORS ######
+
+ ##DETAIL
+ $item->{format} = $film->{Type};
+ $item->{video} = $film->{VideoStandard};
+ $item->{added} = $film->{Added};
+ $item->{identifier} = $film->{CollectionNumber};
+
+ #Temporately cause a real barcode field is missing
+ if (length($film->{Barcode}) gt 0){
+ $item->{comment} = 'EAN: '.$film->{Barcode};
+ }
+
+ ###### AUDIO #########
+ my $audio;
+ my @audioTracks;
+ if (ref ($film->{AudioTracks}->{AudioTrack}) eq "ARRAY"){
+ foreach $audio(@{$film->{AudioTracks}->{AudioTrack}}){
+ push @audioTracks, [$audio->{Language}, $audio->{Type}.' '.$audio->{Channels}];
+ }
+ $item->{audio} = \@audioTracks;
+ }
+ else{
+ $item->{audio} = [[$audio->{Language}, $audio->{Type}]];
+ }
+ ###### END AUDIO #########
+ ###### SUBTITLES #########
+ my $subt;
+ if (ref ($film->{Subtitles}->{Subtitle}) eq "ARRAY"){
+ foreach $subt(@{$film->{Subtitles}->{Subtitle}}){
+ $item->{subt} .= $subt->{Language}.',';
+ }
+ }
+ else{
+ $item->{subt} = $subt->{Language};
+ }
+ ###### END SUBTITLES #########
+
+ #$item->{borrower} = $film->{Title};
+ #$item->{lendDate} = $film->{Title};
+ #$item->{history} = $film->{Title};
+ #$item->{seen} = $film->{Title};# non par defaut ?
+ #$item->{image} = $film->{Title};
+ #$item->{number} = $film->{CollectionNumber};
+ #$item->{rating} = $film->{Title};# note par defaut
+ #$item->{place} = $film->{Title};
+
+ $item->{director} =~ s/, $//;
+ $item->{actors} =~ s/, $//;
+ $item->{audio} =~ s/, $//;
+ $item->{subt} =~ s/, $//;
+ $item->{genre} =~ s/, $//;
+ push @result, $item;
+ }
+ return \@result;
+
+ }
+}
+
+1;
diff --git a/lib/gcstar/GCImport/GCImportScanner.pm b/lib/gcstar/GCImport/GCImportScanner.pm
new file mode 100644
index 0000000..92c5bba
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportScanner.pm
@@ -0,0 +1,394 @@
+package GCImport::GCImportList;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+
+use GCImport::GCImportBase;
+
+{
+ package GCScannerDialog;
+ use base 'GCModalDialog';
+ use XML::Simple;
+
+ sub new
+ {
+ my ($proto, $parent, $lang, $model, $serverSocket) = @_;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new($parent,
+ $lang->{Waiting});
+ bless($self, $class);
+
+ $self->{lang} = $lang;
+ $self->{model} = $model;
+ $self->{accepted} = 0;
+ if ($serverSocket)
+ {
+ $self->{network} = 1;
+ $self->{serverSocket} = $serverSocket;
+ }
+ my $table = new Gtk2::Table(2, 2);
+ $table->set_row_spacings($GCUtils::halfMargin);
+ $table->set_col_spacings($GCUtils::margin);
+ $table->set_border_width($GCUtils::margin);
+ $self->{previousLabel} = new GCLabel('');
+ $self->{promptLabel} = new GCLabel($lang->{ScanPrompt});
+ $table->attach($self->{previousLabel}, 0, 1, 0, 1, 'fill', 'fill', 0, 0);
+ $table->attach($self->{promptLabel}, 0, 1, 1, 2, 'fill', 'fill', 0, 0);
+ my $eanLabel = new GCLabel($lang->{EAN});
+ $self->{ean} = new GCShortText;
+ $self->{ean}->signal_connect('activate' => sub {$self->response('ok')} );
+ if (!$self->{network})
+ {
+ $table->attach($eanLabel, 0, 1, 2, 3, 'fill', 'fill', 0, 0);
+ $table->attach($self->{ean}, 1, 2, 2, 3, ['fill', 'expand'], 'fill', 0, 0);
+ }
+ $self->vbox->pack_start($table, 1, 1, 0);
+ $table->show_all;
+ $self->setCancelLabel($lang->{Terminate});
+ $self->action_area->remove(($self->action_area->get_children)[$self->{okPosition}]);
+ return $self;
+ }
+
+ sub setPrevious
+ {
+ my ($self, $previous) = @_;
+ if (!$self->{first})
+ {
+ $self->{first} = 1;
+ return;
+ }
+ my $label;
+ if ($previous)
+ {
+ ($label = $self->{lang}->{Previous}) =~ s|%s|<b>$previous</b>|;
+ }
+ else
+ {
+ my $previous = $self->{previousCode};
+ ($label = $self->{lang}->{NothingFound}) =~ s|%s|<b>$previous</b>|;
+ }
+ $self->{previousLabel}->set_markup($label);
+ $self->{promptLabel}->set_label($self->{lang}->{ScanOtherPrompt});
+ }
+
+ sub readSocket
+ {
+ my ($self) = @_;
+ Glib::Source->remove($self->{socketWatch});
+ my $socket = $self->{socket};
+ my $line = <$socket>;
+ $self->response('cancel') if !$line;
+ my $xs = XML::Simple->new;
+ my $scan = $xs->XMLin($line);
+ my $code = $scan->{scan}->{content};
+ $code = $self->eanToIsbn($code)
+ if $self->{model} eq 'GCbooks';
+ $self->{ean}->setValue($code);
+ $self->{previousCode} = $code;
+ $self->response('ok');
+ }
+
+ sub waitForCode
+ {
+ my $self = shift;
+ $self->{socketWatch} = Glib::IO->add_watch($self->{socket}->fileno,
+ 'in',
+ sub {
+ $self->readSocket;
+ });
+ }
+
+ sub eanToIsbn
+ {
+ my ($self, $code) = @_;
+ return $code if $code !~ /978(\d{9})/;
+ my $sub = $1;
+ my $multiplier = 1;
+ my $checkSum = 0;
+ foreach (split(//, $sub))
+ {
+ $checkSum += $_ * $multiplier++;
+ }
+ $checkSum %= 11;
+ $checkSum = 'X' if $checkSum == 10;
+ return $sub.$checkSum;
+ }
+
+ sub show
+ {
+ my $self = shift;
+ $self->SUPER::show();
+ $self->show_all;
+ $self->showMe;
+ if ($self->{network})
+ {
+ if (!$self->{accepted})
+ {
+ $self->{serverWatch} = Glib::IO->add_watch($self->{serverSocket}->fileno,
+ 'in',
+ sub {
+ $self->{socket} = $self->{serverSocket}->accept;
+ $self->{accepted} = 1;
+ $self->waitForCode;
+ });
+ }
+ else
+ {
+ $self->waitForCode;
+ }
+ }
+ else
+ {
+ $self->{ean}->setValue('');
+ $self->{ean}->grab_focus;
+ }
+ my $code = $self->run;
+ $self->hide;
+ return $self->{ean}->getValue if $code eq 'ok';
+ $self->{socket}->close;
+ return undef;
+ }
+}
+
+{
+ package GCImport::GCImporterScanner;
+
+ use base qw(GCImport::GCImportBaseClass);
+
+ use IO::Socket;
+ use GCPlugins;
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+
+ bless ($self, $class);
+ return $self;
+ }
+
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+
+ sub wantsFileSelection
+ {
+ return 0;
+ }
+
+ sub hideFileSelection
+ {
+ return 1;
+ }
+
+ sub getFilePatterns
+ {
+ return ();
+ }
+
+ sub checkPortField
+ {
+ my ($self, $data) = @_;
+ my ($parent, $list) = @{$data};
+ my $model = $list->getValue ;
+ $parent->{options}->{port}->set_sensitive($model eq 'Network');
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+
+ my $pluginsList = '';
+ foreach (@{$self->{model}->getPluginsNames})
+ {
+ my $plugin = $GCPlugins::pluginsMap{$self->{model}->getName}->{$_};
+ $pluginsList .= $plugin->getName . ','
+ if $plugin->getEanField;
+ }
+
+
+ return [
+ {
+ name => 'type',
+ type => 'options',
+ label => 'Type',
+ valuesList => 'Local,Network',
+ default => 'Local',
+ changedCallback => sub {shift; $self->checkPortField(@_)},
+ },
+
+ {
+ name => 'port',
+ type => 'number',
+ label => 'Port',
+ default => 50007,
+ min => 1024,
+ max => 65536,
+ },
+
+ {
+ name => 'plugin',
+ type => 'options',
+ label => 'Plugin',
+ valuesList => $pluginsList
+ },
+
+ {
+ name => 'first',
+ type => 'yesno',
+ label => 'UseFirst',
+ default => '1'
+ },
+ ];
+ }
+
+ sub getModelName
+ {
+ my $self = shift;
+ return $self->{model}->getName;
+ }
+
+ sub getBarCode
+ {
+ my ($self, $previous) = @_;
+ #my $dialog = new
+ $self->{dialog}->setPrevious($previous);
+ return $self->{dialog}->show;
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $file) = @_;
+ my @result;
+
+ #First we try to get the correct plugin
+ my $plugin = $GCPlugins::pluginsMap{$self->{model}->getName}->{$self->{options}->{plugin}};
+ $plugin->{bigPics} = $self->{options}->{parent}->{options}->bigPics;
+
+ my $titleField = $self->{model}->{commonFields}->{title};
+ my $searchField = $plugin->getEanField;
+
+ my $i = 0;
+
+ my $resultsDialog;
+ if (!$self->{options}->{first})
+ {
+ $resultsDialog = $self->{options}->{parent}->getDialog('Results');
+ $resultsDialog->setModel($self->{model}, $self->{model}->{fieldsInfo});
+ $resultsDialog->setMultipleSelection(0);
+ }
+ my $search;
+
+ my $socket;
+ if ($self->{options}->{type} eq 'Network')
+ {
+ $socket = new IO::Socket::INET(
+ LocalPort => $self->{options}->{port},
+ Proto => 'tcp',
+ Listen => 1,
+ Reuse => 1
+ );
+ }
+
+ $self->{dialog} = new GCScannerDialog($self->{options}->{parent},
+ $self->getLang,
+ $self->{model}->getName,
+ $socket);
+ my $previous = '';
+ while ($search = $self->getBarCode($previous))
+ {
+ chomp $search;
+ next if ! $search;
+ # $_ contains the title to search
+ $plugin->{title} = $search;
+ $plugin->{type} = 'load';
+ $plugin->{urlField} = $self->{model}->{commonFields}->{url};
+ $plugin->{searchField} = $searchField;
+ #Initialize what will be pushed in the array
+ my $info = {$searchField => $search};
+
+ $self->{options}->{parent}->setWaitCursor($self->{options}->{lang}->{StatusSearch}.' ('.$search.')');
+ $plugin->load;
+
+ my $itemNumber = $plugin->getItemsNumber;
+
+ if ($itemNumber != 0)
+ {
+ $plugin->{type} = 'info';
+ if (($itemNumber == 1) || ($self->{options}->{first}))
+ {
+ $plugin->{wantedIdx} = 0;
+ }
+ else
+ {
+ my $withNext = 0;
+ my @items = $plugin->getItems;
+ $resultsDialog->setWithNext(0);
+ $resultsDialog->setSearchPlugin($plugin);
+ $resultsDialog->setList($search);
+ $resultsDialog->show;
+ if ($resultsDialog->{validated})
+ {
+ $plugin->{wantedIdx} = $resultsDialog->getItemsIndexes->[0];
+ }
+ }
+ $info = $plugin->getItemInfo;
+ my $title = $info->{$titleField};
+ $self->{options}->{parent}->{defaultPictureSuffix} = $plugin->getDefaultPictureSuffix;
+ foreach my $field(@{$self->{model}->{managedImages}})
+ {
+ $info->{$field} = '' if $info->{$field} eq 'empty';
+ next if !$info->{$field};
+ ($info->{$field}) = $self->{options}->{parent}->downloadPicture($info->{$field}, $title);
+ }
+
+ # Add the default value
+ my $defaultInfo = $self->{model}->getDefaultValues;
+ foreach my $field(keys %$defaultInfo)
+ {
+ next if exists $info->{$field};
+ $info->{$field} = $defaultInfo->{$field};
+ }
+ }
+ $previous = $info->{$titleField};
+ push @result, $info;
+ $self->{options}->{parent}->restoreCursor;
+ }
+ $socket->close if $socket;
+ return \@result;
+ }
+
+
+ sub getEndInfo
+ {
+ my $self = shift;
+ my $message;
+ return $message;
+ }
+}
+
+
+1;
diff --git a/lib/gcstar/GCImport/GCImportTarGz.pm b/lib/gcstar/GCImport/GCImportTarGz.pm
new file mode 100644
index 0000000..b995b82
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportTarGz.pm
@@ -0,0 +1,152 @@
+package GCImport::GCImportTarGz;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use GCImport::GCImportBase;
+
+{
+ package GCImport::GCImporterTarGz;
+
+ use base qw(GCImport::GCImportBaseClass);
+
+ use GCBackend::GCBackendXmlParser;
+
+ use File::Spec;
+ use File::Temp qw/ tempfile tempdir /;
+ use Cwd;
+ use File::Copy;
+
+ #use GCData;
+
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+ bless ($self, $class);
+
+ $self->checkModule('Compress::Zlib');
+ $self->checkModule('Archive::Tar');
+ $self->checkModule('File::Path');
+
+ return $self;
+ }
+
+ sub getName
+ {
+ return ".tar.gz";
+ }
+
+ sub getFilePatterns
+ {
+ return (['Tar gzip (.tar.gz)', '*.tar.gz']);
+ }
+
+ sub getModelName
+ {
+ my $self = shift;
+
+ return $self->{model}->getName;
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+ my @options;
+ return \@options;
+ }
+
+ # Ignored for the moment
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+ sub getEndInfo
+ {
+ my $self = shift;
+ return ($self->{parsingError}, 'error');
+ }
+
+ sub addFieldsToDefaultModel
+ {
+ my ($self, $inlineModel) = @_;
+ my $model = GCModelLoader->newFromInline($self, {inlineModel => $inlineModel, defaultModifier => 1});
+ $self->{model}->addFields($model);
+ $self->{options}->{parent}->setCurrentModel($self->{model});
+ $self->{modelAlreadySet} = 1;
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $file) = @_;
+
+ my ($tarFh, $tarFilename) = tempfile();
+ my $gz = Compress::Zlib::gzopen($file, "rb");
+ my $buffer;
+ print $tarFh $buffer while $gz->gzread($buffer) > 0 ;
+ close $tarFh;
+ $gz->gzclose;
+
+ my $tmpDir = tempdir();
+ my $oldCwd = getcwd;
+ chdir $tmpDir;
+ my $tar = Archive::Tar->new($tarFilename);
+ $tar->extract;
+ my $listFile = './collection.gcs';
+
+ my $parent = $self->{options}->{parent};
+ $self->{modelsFactory} = $parent->{modelsFactory};
+ $self->{modelAlreadySet} = 0;
+
+ my $backend = new GCBackend::GCBeXmlParser($self);
+ $backend->setParameters(file => $listFile);
+ my $loaded = $backend->load(0);
+ my $itemsArray = [];
+ if ($loaded->{error})
+ {
+ $self->{parsingError} = GCUtils::formatOpenSaveError(
+ $parent->{lang},
+ $file,
+ $loaded->{error}
+ );
+ }
+ else
+ {
+ $itemsArray = $loaded->{data};
+
+ #Copying pictures
+ $self->copyPictures($itemsArray, $file);
+ }
+
+ #Cleaning
+ chdir $oldCwd;
+ File::Path::rmtree($tmpDir);
+ unlink $tarFilename;
+
+ return $itemsArray;
+ }
+}
+
+1;
diff --git a/lib/gcstar/GCImport/GCImportTellico.pm b/lib/gcstar/GCImport/GCImportTellico.pm
new file mode 100644
index 0000000..033b474
--- /dev/null
+++ b/lib/gcstar/GCImport/GCImportTellico.pm
@@ -0,0 +1,496 @@
+package GCImport::GCImportTellico;
+
+###################################################
+#
+# Copyright 2005-2010 Christian Jodar
+#
+# This file is part of GCstar.
+#
+# GCstar is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 2 of the License, or
+# (at your option) any later version.
+#
+# GCstar is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GCstar; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+#
+###################################################
+
+use strict;
+use GCImport::GCImportBase;
+
+{
+ package GCImport::GCImporterTellico;
+
+ use base qw(GCImport::GCImportBaseClass);
+ use File::Spec;
+
+ sub new
+ {
+ my $proto = shift;
+ my $class = ref($proto) || $proto;
+ my $self = $class->SUPER::new();
+ bless ($self, $class);
+
+ $self->checkModule('Archive::Zip');
+ $self->checkModule('MIME::Base64');
+
+ # Associate a Tellico type to a GCstar model
+ $self->{models} = {
+ 2 => 'GCbooks',
+ 3 => 'GCfilms',
+ 4 => 'GCmusics',
+ 8 => 'GCcoins',
+ 11 => 'GCgames'
+ };
+
+ return $self;
+ }
+
+ sub getName
+ {
+ return "Tellico (.tc)";
+ }
+
+ sub getOptions
+ {
+ my $self = shift;
+ my @options;
+ return \@options;
+ }
+
+ sub getFilePatterns
+ {
+ my $self = shift;
+
+ return (['Tellico Format (.tc)', '*.tc'], ['Tellico XML (.xml)', '*.xml']);
+ }
+
+ #Return supported models name
+ sub getModels
+ {
+ my $self = shift;
+ my @models = values %{$self->{models}};
+ return \@models;
+ }
+
+ sub getModelName
+ {
+ my $self = shift;
+
+ return $self->{extractedModel};
+ }
+
+ sub wantsFieldsSelection
+ {
+ return 0;
+ }
+
+ sub getEndInfo
+ {
+ my $self = shift;
+
+ return $self->{parsingError};
+ }
+
+ sub getItemsArray
+ {
+ my ($self, $file) = @_;
+
+ my @result = ();
+
+ my $xml;
+
+ # File type is based on suffix
+ # T is for Tellico (zipped file)
+ # X is for XML
+ $self->{type} = ($file =~ m/tc$/) ? 'T' : 'X';
+ #Then we test to be sure
+ eval
+ {
+ $self->{zip} = Archive::Zip->new($file);
+ };
+ #First we uncompress file
+ if (($self->{type} eq 'T') && ($self->{zip}))
+ {
+ $xml = $self->{zip}->contents('tellico.xml');
+ }
+ else
+ {
+ $self->{type} = 'X';
+ open XML, $file;
+ $xml = do {local $/; <XML>};
+ close XML;
+ }
+
+ #Then we parse XML data
+ my $xs = XML::Simple->new;
+ my $tellico = $xs->XMLin($xml,
+ SuppressEmpty => '',
+ ForceArray => 1);
+ my $collection = $tellico->{collection}->[0];
+
+ $self->{extractedModel} = $self->{models}->{$collection->{type}};
+ #We check we know this model
+ if (! $self->{extractedModel})
+ {
+ $self->{parsingError} = $self->getLang->{NotSupported};
+ return \@result;
+ }
+
+ my %tmpMap;
+ # If there are no ids, we have an array in $collection
+ if (ref ($collection->{entry}) eq 'ARRAY')
+ {
+ my $i = 0;
+ #Then we prepare a map
+ foreach (@{$collection->{entry}})
+ {
+ $tmpMap{$i} = $_;
+ $i++;
+ }
+ }
+ else
+ {
+ %tmpMap = %{$collection->{entry}};
+ }
+ #Loop on entries
+ my $i = 0;
+
+ my $methodName = 'get'.$self->{extractedModel}.'Item';
+
+ while (my ($id, $entry) = each (%tmpMap))
+ {
+ $result[$i] = $self->$methodName($entry, $collection);
+ $i++;
+ }
+ return \@result;
+
+ }
+
+ sub getGCfilmsItem
+ {
+ my ($self, $entry, $collection) = @_;
+
+ my %result;
+
+ $result{title} = $entry->{title}->[0];
+ $result{format} = $entry->{medium}->[0];
+ $result{date} = $entry->{year}->[0];
+ my $certification = $entry->{certification}->[0];
+ if ($certification eq 'U (USA)')
+ {
+ $result{age} = 1;
+ }
+ elsif ($certification eq 'G (USA)')
+ {
+ $result{age} = 2;
+ }
+ elsif ($certification eq 'PG (USA)')
+ {
+ $result{age} = 5;
+ }
+ elsif ($certification eq 'PG-13 (USA)')
+ {
+ $result{age} = 13;
+ }
+ elsif ($certification eq 'R (USA)')
+ {
+ $result{age} = 17;
+ }
+ $result{genre} = [];
+ if ($entry->{genres}->[0])
+ {
+ for my $genre(@{$entry->{genres}->[0]->{genre}})
+ {
+ push @{$result{genre}}, [$genre];
+ }
+ }
+ if ($entry->{nationalitys}->[0])
+ {
+ for my $country(@{$entry->{nationalitys}->[0]->{nationality}})
+ {
+ $result{country} .= $country.', ';
+ }
+ }
+ $result{country} =~ s/, $//;
+
+ $result{video} = $entry->{format}->[0];
+ if ($entry->{casts}->[0])
+ {
+ for my $cast(@{$entry->{casts}->[0]->{cast}})
+ {
+ $result{actors} .= $cast->{column}->[0];
+ $result{actors} .= ' ('.$cast->{column}->[1].')' if $cast->{column}->[1];
+ $result{actors} .= ', ';
+ }
+ }
+ $result{actors} =~ s/, $//;
+
+ if ($entry->{directors}->[0])
+ {
+ for my $director(@{$entry->{directors}->[0]->{director}})
+ {
+ $result{director} .= $director.', ';
+ }
+ }
+ $result{director} =~ s/, $//;
+
+ $result{audio} = [];
+ if ($entry->{languages}->[0])
+ {
+ for my $language(@{$entry->{languages}->[0]->{language}})
+ {
+ push @{$result{audio}}, [$language];
+ }
+ }
+ $result{subt} = [];
+ if ($entry->{subtitles}->[0])
+ {
+ for my $subtitle(@{$entry->{subtitles}->[0]->{subtitle}})
+ {
+ push @{$result{subt}}, [$subtitle];
+ }
+ }
+ $result{time} = $entry->{'running-time'}->[0];
+ $result{synopsis} = $entry->{plot}->[0];
+ $result{synopsis} =~ s{(<|&lt;)br/>}{\n}g;
+
+ $result{rating} = $self->convertRating($entry->{rating}->[0]);
+ #$result{borrower} = 'none' if (! $entry->{loaned});
+ $result{borrower} = 'Unknown' if ($entry->{loaned}->[0] eq 'true');
+ $result{comment} = $entry->{comments}->[0];
+
+ #Picture management
+ $result{image} = $self->getPicture($collection, $entry->{cover}->[0], $result{title});
+
+ return \%result;
+ }
+
+ sub getGCgamesItem
+ {
+ my ($self, $entry, $collection) = @_;
+
+ my %result;
+
+ $result{name} = $entry->{title}->[0];
+ $result{platform} = $entry->{platform}->[0];
+ $result{released} = $entry->{year}->[0];
+ $result{genre} = [];
+ if ($entry->{genres}->[0])
+ {
+ for my $genre(@{$entry->{genres}->[0]->{genre}})
+ {
+ push @{$result{genre}}, [$genre];
+ }
+ }
+ if ($entry->{publishers}->[0])
+ {
+ for my $editor(@{$entry->{publishers}->[0]->{publisher}})
+ {
+ $result{editor} .= $editor.', ';
+ }
+ $result{editor} =~ s/, $//;
+ }
+ if ($entry->{developers}->[0])
+ {
+ for my $developer(@{$entry->{developers}->[0]->{developer}})
+ {
+ $result{developer} .= $developer.', ';
+ }
+ $result{developer} =~ s/, $//;
+ }
+ $result{description} = $entry->{description}->[0];
+ $result{rating} = $self->convertRating($entry->{rating}->[0]);
+ $result{completion} = 100 if $entry->{completed}->[0] eq 'true';
+ $result{borrower} = 'Unknown' if ($entry->{loaned}->[0] eq 'true');
+ $result{boxpic} = $self->getPicture($collection, $entry->{cover}->[0], $result{name});
+ return \%result;
+ }
+
+ sub getGCbooksItem
+ {
+ my ($self, $entry, $collection) = @_;
+
+ my %result;
+
+ $result{title} = $entry->{title}->[0];
+ $result{isbn} = $entry->{isbn}->[0];
+ $result{authors} = [];
+ if ($entry->{authors}->[0])
+ {
+ for my $author(@{$entry->{authors}->[0]->{author}})
+ {
+ push @{$result{authors}}, [$author];
+ }
+ }
+ $result{publisher} = $entry->{publisher}->[0];
+ $result{publication} = $entry->{pub_year}->[0];
+ if ($entry->{languages}->[0])
+ {
+ for my $language(@{$entry->{languages}->[0]->{language}})
+ {
+ $result{language} .= $language.', ';
+ }
+ $result{language} =~ s/, $//;
+ }
+ $result{serie} = $entry->{series}->[0];
+ $result{rank} = $entry->{series_num}->[0];
+ $result{edition} = $entry->{edition}->[0];
+ $result{format} = $entry->{binding}->[0];
+ $result{description} = $entry->{comments}->[0];
+ $result{pages} = $entry->{pages}->[0];
+ $result{read} = 1 if ($entry->{read}->[0] eq 'true');
+ $result{acquisition} = $entry->{pur_date}->[0];
+ $result{genre} = [];
+ if ($entry->{genres}->[0])
+ {
+ for my $genre(@{$entry->{genres}->[0]->{genre}})
+ {
+ push @{$result{genre}}, [$genre];
+ }
+ }
+ $result{rating} = $self->convertRating($entry->{rating}->[0]);
+ $result{borrower} = 'Unknown' if ($entry->{loaned}->[0] eq 'true');
+ $result{cover} = $self->getPicture($collection, $entry->{cover}->[0], $result{title});
+ return \%result;
+ }
+
+ sub getGCmusicsItem
+ {
+ my ($self, $entry, $collection) = @_;
+
+ my %result;
+
+ $result{title} = $entry->{title}->[0];
+ $result{format} = $entry->{medium}->[0];
+ if ($entry->{artists}->[0])
+ {
+ for my $artist(@{$entry->{artists}->[0]->{artist}})
+ {
+ $result{artist} .= $artist.', ';
+ }
+ $result{artist} =~ s/, $//;
+ }
+ if ($entry->{labels}->[0])
+ {
+ for my $label(@{$entry->{labels}->[0]->{label}})
+ {
+ $result{label} .= $label.', ';
+ }
+ $result{label} =~ s/, $//;
+ }
+ $result{release} = $entry->{year}->[0];
+ $result{genre} = [];
+ if ($entry->{genres}->[0])
+ {
+ for my $genre(@{$entry->{genres}->[0]->{genre}})
+ {
+ push @{$result{genre}}, [$genre];
+ }
+ }
+ if ($entry->{tracks}->[0])
+ {
+ my $trackNum = 1;
+ for my $track(@{$entry->{tracks}->[0]->{track}})
+ {
+ push @{$result{tracks}}, [$trackNum,
+ $track->{column}->[0],
+ $track->{column}->[2]];
+ $trackNum++;
+ }
+ }
+ $result{comment} = $entry->{comments}->[0];
+ $result{rating} = $self->convertRating($entry->{rating}->[0]);
+ $result{borrower} = 'Unknown' if ($entry->{loaned}->[0] eq 'true');
+ $result{cover} = $self->getPicture($collection, $entry->{cover}->[0], $result{title});
+ return \%result;
+ }
+
+ sub getGCcoinsItem
+ {
+ my ($self, $entry, $collection) = @_;
+
+ my $i = 0;
+ my %result;
+
+ #$result{name} = $entry->{title}->[0];
+
+ $result{currency} = $entry->{type}->[0];
+ $result{value} = $entry->{denomination}->[0];
+ $result{year} = $entry->{years}->[0]->{year}->[0];
+ $result{country} = $entry->{country}->[0];
+ $result{type} = ($entry->{set}->[0] eq 'true') ? 'coin' : 'banknote';
+ # TODO: Import grade
+ $result{added} = $entry->{pur_date}->[0];
+ $result{estimate} = $entry->{pur_price}->[0];
+ $result{location} = $entry->{location}->[0];
+
+ $result{comments} = $entry->{comments}->[0];
+
+ $result{name} = $result{currency}.' '.$result{value}.' ('.$result{year}.')';
+
+ $result{picture} = $self->getPicture($collection, $entry->{obverse}->[0], $result{name});
+ $result{front} = $self->getPicture($collection, $entry->{obverse}->[0], $result{name}.'_front');
+ $result{back} = $self->getPicture($collection, $entry->{reverse}->[0], $result{name}.'_back');
+ return \%result;
+ }
+
+ sub getPicture
+ {
+ my ($self, $collection, $imageId, $title) = @_;
+
+ my $result = undef;
+ if ($imageId && (ref($imageId) ne 'HASH'))
+ {
+ (my $suffix = $imageId) =~ s/.*?(\.[^.]*)$/$1/;
+ my $fileName = $self->{options}->{parent}->getUniqueImageFileName($suffix, $title);
+ if ((exists $collection->{images}->[0]->{image}->{$imageId}) &&
+ (exists $collection->{images}->[0]->{image}->{$imageId}->{content}))
+ {
+ # Picture is embedded
+ my $data = MIME::Base64::decode_base64($collection->{images}->[0]->{image}->{$imageId}->{content});
+ open PIC, ">$fileName";
+ print PIC $data;
+ close PIC;
+ }
+ else
+ {
+ if ($self->{type} eq 'T')
+ {
+ # Only zipped file may have external pictures
+ my $picName = 'images/'.$imageId;
+ $self->{zip}->extractMember($picName, $fileName);
+ }
+ else
+ {
+ $fileName = '';
+ }
+ }
+ $result = $self->{options}->{parent}->transformPicturePath($fileName);
+ }
+ return $result;
+ }
+
+ sub convertRating
+ {
+ my ($self, $rating) = @_;
+ return 10 if $rating =~ /^5/;
+ return 7 if $rating =~ /^4/;
+ return 3 if $rating =~ /^2/;
+ return 0 if $rating =~ /^1/;
+ return 5; #if ($rating =~ /^3/) || ($rating == undef);
+ }
+
+}
+
+
+
+
+1;